[sdiy] MIDI Clock sync advice

brianw brianw at audiobanshee.com
Sat Mar 16 23:10:47 CET 2024


I suspect that hard-sync / reset could cause some hiccups, but maybe only at the start ... and when there are tempo changes.

I still have not entirely figured out how a PLL works, especially not in software (even with timers and interrupts to help) as opposed to a pure hardware PLL. However, the hardware PLL automatically syncs like a DJ who is trying to beat match: they speed up or slow down one record until the other is both the same tempo and same phase of the beats. For a software PLL, you'd need some way to know which clock is ahead of the other. With timer interrupt assist, that probably means reading the timer when MIDI Clock arrives, and some method of determining where the timer is in its period at that moment. Spiros' implementation might work with the addition of some way to "look at" the internal clock to see where it's at in its period when the MIDI Clock is received.

Measuring the period and matching that will get the tempo right, but with no sync. Comparing the state of the two clocks (external versus internal divided) will phase lock the two, but that's more challenging in software than in hardware. Sure, hard-sync is not difficult, but the smoother phase lock is what I'm saying would be more challenging.

Perhaps a higher internal clock rate - more than double speed - would reduce the fluctuation of the PFD values. That's just a guess, though. How much resolution do you have, Spiros? Are we talking about a fluctuation of one LSB? ... or does the measurement fluctuate more than that?

Your USB-MIDI without interrupts is interesting, because I assume that the Device must be using interrupts to receive the USB data. Then again, maybe the USB peripheral uses DMA to put the data directly in memory, and then the client code just polls the registers to see when something shows up. I recall that the USB Device libraries that I use sometimes allow a choice between interrupt-based and polled. In any case, USB-MIDI is going to be somewhat different from classic asynchronous serial MIDI.

As Roman mentioned, you can implement the serial MIDI interrupt as a hybrid: Handle MIDI System Real Time events inside the interrupt, but queue the rest. This is effectively filtering out System Real Time messages from the stream that ends up in the queue, and perhaps your MIDI parser can be slightly simpler with the knowledge that there will never be any System Real Time events in the queue.

Regarding the new generation of programmers, I'm both happy and sad. Having more people exciting about programming is great. However, when new stuff gets prototyped by amateurs; hyped into a startup; and result in commercial products that are poorly engineered but "good enough" ... I just find it tedious to sift through the cruft. Lots of consumers get excited by the newness, and when things work poorly they cry for open source (even though few can program any better) or dismiss the problem as the fault of "MIDI" - in contrast, it's amazing what can be done when there is no waste.

I hope some of this makes sense,

Brian


On Mar 16, 2024, at 7:38 AM, Amos wrote:
> PS) I just re-read the end of your message and saw that you were thinking of exactly the mechanism I suggested (hard-syncing the output every quarter note). I don't know whether it seems wrong or not, but I can confirm that it does the job. :)
> 
> On Sat, Mar 16, 2024 at 9:34 AM Amos <controlvoltage at gmail.com> wrote:
>> One small thought I’d add is that once you’re happy with your clock-frequency detection, one way to handle phase is to every so often do a hard-reset of your output timer phase on receipt of an incoming clock, so that you output a clock at the next possible instant. I suppose you could be fancy and keep track of the time delta by which your output leads/lags incoming clocks, and reset phase when this drifts beyond an acceptable measure, but in practice I think I’ve just done this every quarter note or something like that (it’s been a while).
>> 
>> In any case, adding some mechanism like this can ensure that your clock output stays pretty well in sync with the beat.
>> 
>> On Saturday 16 March 2024, Spiros Makris via Synth-diy <synth-diy at synth-diy.org> wrote:
>>> On Fri, 15 Mar 2024 at 17:47, Roman Sowa via Synth-diy <synth-diy at synth-diy.org> wrote:
>>>> If I may just add - maybe it's just my impression, but I think that new
>>>> generations of programmers educated today have absolutely no idea how
>>>> microprocessor works.
>>> 
>>> That feels true, but we should keep in mind that "programmer" has been a continuously expanding group of people, and you can now be a programmer starting from a wild variety of disciplines, most of which don't start from the bottom, as is customary in electrical engineering and (sometimes) computer science degrees. Most programs I know of have computers and operating systems as a standard class, but microcontrollers and embedded systems as an elective. That is, you can't become an embedded programmer "by accident", unlike python, java and others, which any STEM major will have some knowledge of.
>>> 
>>> I gave it a quick try on a teensy 4. I used USB-MIDI and fed a clock from Ableton, without using interrupts. I made all the wrong choices, I know.
>>> So my strategy was to create something that resembles a phase frequency detector: I created an internal clock that will run at double the speed of the incoming clock, and implemented a /2 divider. I am listening for clocks from either USB or the internal clock, and switch between decreasing and increasing a count variable based on the lead-lag relationship of the incoming messages. The result resembles the functionality of a PFD coupled with a charge pump/integrator filter, and it does lock to the incoming tempo. It will follow abrupt tempo changes reasonably fast, but then sync between beats is lost. Furthermore, I can see the PFD values fluctuating, which does happen in such a configuration, but I would expect less of a ripple under a good lock. I suspect Ableton clocks are fairly jittery through USB, so I'll give it another go using a more stable clock and figure out if the ripple is system instability or Ableton acting up.
>>> Another approach I intend to try is simply measuring the incoming frequency using a reference timer and then assigning the value (multiplied by a factor) to a second timer to act as a clock. I know it will more or less work, but doesn't really have any syncing mechanism; I expect the resulting beats will be out of sync.
>>> I am contemplating adding a syncing mechanism that keeps track of the number of incoming beats and introducing a secondary feedback mechanism following the quarter notes. It feels like a wrong approach though.
>>> 
>>>  
>>> On Fri, 15 Mar 2024 at 17:47, Roman Sowa via Synth-diy <synth-diy at synth-diy.org> wrote:
>>>> W dniu 2024-03-15 o 13:57, René Schmitz pisze:
>>>> > 
>>>> > 
>>>> > The speed of processors roughly keeps up with programmers ability to 
>>>> > waste it.
>>>> 
>>>> Yes, that's my feeling exactly
>>>> 
>>>> > 
>>>> > My gripe is that, for beginner programmer, it does not necessarily teach 
>>>> > good practices, and even for a seasoned one it proliferates some bad 
>>>> > habits.  (How often is everything in loop()...)
>>>> > 
>>>> > It's like giveing you a nice sugar coated piece of cake, so you might 
>>>> > never be motivated to learn how to bake a better one.
>>>> 
>>>> hell yeah!
>>>> 
>>>> If I may just add - maybe it's just my impression, but I think that new 
>>>> generations of programmers educated today have absolutely no idea how 
>>>> microprocessor works.
>>>> 
>>>> 
>>>> > Back to MIDI: generally, when using the serial interrupt you have two 
>>>> > choices:
>>>> > 
>>>> > Either make the ISR short, and for example just throw the data into a 
>>>> > buffer.
>>>> > 
>>>> > Or do all the processing (which could take some time) there. Risk is 
>>>> > that you might block other ISRs, such as timers, which is of course bad.
>>>> 
>>>> If I need a buffer, I usually process only MIDI clock inside ISR and put 
>>>> all other messages into the buffer. Less than 20 cycles worst case. But 
>>>> for example in my MIDI note decoder there's no buffer at all. The work 
>>>> is done before next byte comes in, so there's no chance of cluttering or 
>>>> missing a message.
>>>> 
>>>> Roman
>>> 



More information about the Synth-diy mailing list