Paul, Yes I have noticed this too. The clock is being generated by a PC with the obvious overheads of a huge OS. In the music world we know that a computer does not provide a rock solid clock, and products exist to address this. One of my pending projects is to offer a stable midi clock. In the real world, these micro differences could be considered a good thing as they give music a more "human feel". Its up to the music producer to decide.Another observation. This is how the MIDI Clock messages look over time. The timing between clocks is less stable than I would expect.
View attachment 32354
@snowsh Does this pose a problem for you or are you doing some averaging?
Paul
I think there's a bit of confusion over what's happening in the [USB] MIDI interrupt handler. As far as I can see it'll just queue messages until the application is ready for them. The application may attach a callback handler to the event types it wants to deal with, and wheneverOK. So In summary:
The process of using midi with interrupts must hand off all recieved messages to the relevant interrupt handler. Whatever library is dealing with this takes all messages buffered in the midi library, and takes over. This is why without the midi.read() loop before we attach the interuupt handlers had no effect. We also see that while(USBmidi.read() {}) had no effect, as already mentioned there is a delay so @PaulStoffregen was correct and indeed the timed loop functions.
Is the fix a bit hacky? maybe. But it does indeed solve the issue. However does this present a problem that may be wider reaching? In any project that uses interrupts do we care about events that have been buffered during setup? I would be keen to understand in more detail how the interrupts are setup. @PaulStoffregen thoughts? Is there anything in the interrupt routines we could call at the end of setup to flush out any buffered events?
usbMIDI.read()
is called, if there's a handler, then it gets called automatically from within the .read
. Alternatively you can query the content of the result and process it, if .read
returns true
..read
can return false
, implying the pending queue is empty, when this is in fact not the case. Spinning the while()
loop for some apparently arbitrary timeout "fixes" this, for a given value of "fixes".setup()
{
// run setup code
// at the end of setup:
elapsedMillis msec = 0;
while (msec < 250) // increase this value if needed
{
usbMIDI.read(); // consume all recieved MIDI messages for 1/4 second. Increase the timer value if a rush of clocks is experienced at the first loop.
};
usbMIDI.setHandleRealTimeSystem(RealTimeSystem);
// add other interrupt handlers as needed.
// end setup
}