[sdiy] Techniques for Multiplying MIDI Clock frequency?

Roman Sowa modular at go2.pl
Mon Dec 20 17:53:32 CET 2021

To make sure where the clocks are swallowed, why don't you check it on a 
scope? Reviewing code hundreds of times will not give you answers that 
single hardware test will do. Especially since you use library not 
written by yourself, so you can't really tell what's going on there.

IMHO you are not reaching hard limitation of DIN MIDI. To entirely fill 
DIN MIDI with clock it requires nearly 1000 bpm at 192ppq

If so many various platforms gave you same results, then maybe the 
DR-202 and QY-22 and KPR-77 are really skipping a few clocks here and there.

First thing I do in UART interrupt routine is to check if received byte 
is MIDI clock or whatever else. If it's clock, the program branches to 
clock handling and work is finished, clock is not needed anywhere else 
so MIDI processing is not even bothered. If received byte is not clock, 
it goes to regular full bunch of chunky MIDI processing, now obviously 
stripped from any clocks already.
This way even if MIDI is totally filled with data, back to back, 
interlaced with notes, CC and other multi-byte messages, there's not a 
single clock lost, ever. And output pulse delay appears about 45us on 
average after last bit of MIDI clock received.
BTW, it's not Arduino or Teensy, so may not be relevant.


W dniu 2021-12-20 o 13:46, Benjamin Tremblay pisze:
> @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.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.

More information about the Synth-diy mailing list