[sdiy] Techniques for Multiplying MIDI Clock frequency?

Tom Wiltshire tom at electricdruid.net
Mon Dec 20 15:26:45 CET 2021


I'm no Arduino coder, but I just had a dig through the code for the Arduino MIDI library and couldn't see any reference to interrupts anywhere.

...which it seems to me is the root of the problem!

I very much doubt this is a "hard limitation of 5 pin MIDI" as you put it. MIDI was *designed* specifically to work on 8-bit processors running at probably only 4 or 8MHz if you were lucky. However, in order to do that, certain things were assumed. One of those assumptions was that Realtime bytes would be dealt with directly in the Rx interrupt, which is why they're easy to filter, and why it doesn't matter that they can appear anywhere: the assumption is that by the time the parser sees the string of incoming bytes, Realtime will already have been removed.

If a Z80 in 1984 can do it, there's no way it's not possible in 2021 on an Arduino. The problem is only the coding, and in this case, it seems like you're fighting against the Arduino MIDI library. The test with the Teensy basically proves that to me.

Tom


> On 20 Dec 2021, at 12:46, 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/151e0c68/attachment.htm>


More information about the Synth-diy mailing list