[sdiy] Techniques for Multiplying MIDI Clock frequency?

Benjamin Tremblay btremblay at me.com
Mon Dec 20 14:05:20 CET 2021


But wait! There’s more.

With the KPR-77 I wanted to leverage the nice HKA MIDI interface, so I put a DFRobot beetle in the clock signal path and tried to make a clock doubler.  That was a total failure, but maybe due to a lack of time to work it out.

> On Dec 20, 2021, at 7:46 AM, Benjamin Tremblay via Synth-diy <synth-diy at synth-diy.org> wrote:
> 
> @Roman
> Yes I believe your theory is correct; it’s an issue with not handling a tangled bunch of messages. But I can’t prove it, and I if it’s true I don’t know what to do about.
> 
> The history of this goes back to the middle of the summer. 
> I was working on MIDI interface for a Roland CR-5000 and experienced these problems while trying to generate the 24ppq clock.
> This is when I first experienced this issue while testing using the DR-202.
> After spending many hours twiddling the code, I decided I wanted to try this with a Teensy 4, so I could see if it was a speed issue, and also so I could get good logging over the USB port.
> The issue was exactly the same on the Teensy.  I was surprised it was not an Arduino speed issue at all.
> The logs showed the code I was using to measure the time between MIDI clock events was varying wildly when I played a house music or latin groove on the 202. 
> As if the MIDI parser was choking on nearly-simultaneous events.
> My code’s pretty simple, it looks like a boilerplate Arduino MIDI Library code example using MIDI clock, start/stop/resume.
> I simply measure microseconds and generate the clock pulses when micros() exceeds the estimated clock pulse duration.
> 
> #define CLOCK_LENGTH 3333  // microseconds
> 
> void setupMidi() {
>   if (USE_SERIAL) {
>     Serial.println("setupMidi");
>   }
>   MIDI.begin(RECEIVE_CHANNEL);
>   MIDI.setHandleNoteOn(handleNoteOnMidi);
>   MIDI.setHandleClock(myClock);
>   MIDI.setHandleStart(onClockStart);
>   MIDI.setHandleContinue(onClockStart);
>   MIDI.setHandleStop(onClockStop);
>   if (USE_SERIAL) {
>     Serial.println("setupMidi DONE");
>   }
> }
> 
> void myClock() {
>   if (CLOCK_RUNNING) {
>     digitalWrite(CLOCK_OUT, LOW);
>     clockFuture = micros(); // *
>   }
> }
> 
> // *In previous iterations I tired to recalculate CLOCK_LENGTH by averaging, etc. It simply won’t work if its’ far from 3000µs.
> 
> void loop() {
>   MIDI.read();
>   if (CLOCK_RUNNING) {
>     if (clockFuture > 0 && (micros() - clockFuture) > CLOCK_LENGTH) {
>       digitalWrite(CLOCK_OUT, HIGH);
>       clockFuture = 0;
>     }
>   } … etc
> 
> // ** If I subtract micros() from clockFuture, this number goes crazy when I play a thick loop on the 202.
> 
> In spite of my avoidance of delayMicroseconds(), this code is sensitive to timing because CLOCK_LENGTH (is a constant here, but I have tried to make it dynamic in other builds) is inflexible.
> 
> I have seen some GitHub projects that use interrupts for the MIDI clock and time calculations. I have never written my own interrupt code but would gladly go that way if I was certain it could fix this problem.  But, it seems like I am hitting a hard limitation of 5 pin MIDI… The folks who write fast code with MIDI clock seem to skip ahead to using USB for real-time messages, etc.
> 
> When I was playing with the awesome cheerful.nl <http://cheerful.nl/> OPL2 Audio Board, the author provided some lean MIDI parsing code and skipped the MIDI library. (Especially a no-op for sysex.) So I forked that and tried a lean implementation. Same problem! Lag when the 202 go busy with CC messages and snare rolls.
> 
> So I reverted my code back to Arduino MIDI Library, cleaned up the source, removed dead code, and tested it using everything I learned. It runs OK when I use a dumb drum machine like an SR-16. It chokes on the floofy beats of 1998 in my DR-202. 
> 
> Finally after months, I ported the code back to Arduino Mega and runs virtually the same as on the Teensy 4.
> 
> What I don’t know is, when the 202 gets busy, how can I ditch all the MIDI events I don’t care about without waiting a long time to get the ones I do care about? As bad as the DR-202’s MIDI implementation may be, I have to assume there are many boxes (including a Yamaha QY-22 I was also testing) which send out these swooshing sweeping resonant filter CC events and sysex param tweaks in their drum-and-bass patterns.
> 
> I am assuming that someone, somewhere has mitigated this problem. I want to know how she or he did it.
> 
> Ben
> 
>> On Dec 20, 2021, at 5:30 AM, Roman Sowa <modular at go2.pl <mailto:modular at go2.pl>> wrote:
>> 
>> When you say "complex pattern" I see a lot of MIDI messages, and then the clock messages like to be trapped between bytes of single note message. So maybe, just maybe your Arduino code, or library you've used are not capable to see a MIDI clock message trapped inside a note message, or simply get overloaded.
>> 
>> Is it Arduino doing or KPR itself is best to check on a scope with trigger set to timeout on decoded clock byte.
>> 
>> Roman
>> 
>> W dniu 2021-12-18 o 21:12, Benjamin Tremblay via Synth-diy pisze:
>>> Interesting topic!
>>> I have been wanting to write some code like this for a KPR-77. Goal would be MIDI clock in, TTL-ish clock out. 24ppq>48ppq.
>>> The first challenge is converting 24ppq computer signals to 24 HIGH/LOW pin state transitions per quarter note.
>>> One thing that discouraged me was MIDI clock coming from my Boss DR-202.  When I play a complex pattern on that thing, I start losing clock steps. I could not figure out why, so I gave up on multiplying the clock.
>>> If I use a plain vanilla drum machine (as opposed to a groove box), it seems to work okay.
>>> I wrote this code for Arduino Mega, and then tried it with Teensy, but either way it has the same problems.
>>> So, two different problems.
>>> 1) MIDI clock dropping out on groove boxes.
>>> 2) I wish I understood the theory of clock multipliers. I have seen code that measures the period between clock pulses and dead reckons the double-time pulse as an average of the recent periods. But why? Why can’t I just fire another extra HIGH-LOW pulse whenever I get a MIDI clock event? Why does timing of the extra ticks matter?  I’m assuming 48 PPQ divides the clock down to individual sequencer steps on the KPR-77. As long as the divided clock is coming in on the beat, what does it matter if some of the synthetic pulses are a little off? (They’re just shadows of the main tempo clock). It’s not like the KPR-77 is inferring something or trying to calculate BPM from the external clock… So… Anyway I just wish I knew what I was aiming for, and then maybe I could hit the target.
> 
> _______________________________________________
> Synth-diy mailing list
> Synth-diy at synth-diy.org
> http://synth-diy.org/mailman/listinfo/synth-diy
> Selling or trading? Use marketplace at synth-diy.org

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://synth-diy.org/pipermail/synth-diy/attachments/20211220/bb4439ea/attachment.htm>


More information about the Synth-diy mailing list