FortySevenEffects / arduino_midi_library

MIDI for Arduino
MIT License
1.59k stars 255 forks source link

MIDI messages received in wrong order #328

Closed amowry closed 1 year ago

amowry commented 1 year ago

Context

Please answer a few questions to help us understand your problem better and guide you to a solution:

Describe your project and what you expect to happen:

I am receiving CC messages from a Web MIDI page. These are used to change settings on my device.

Sometimes the MIDI library is receiving them in a different order from how they were sent. I'm not sure how to tell if this is a TinyUSB problem or a problem with the MIDI library. I thought perhaps this was related to 1byte parsing, but I've turned that off and it didn't make a difference.

Please see the bug referenced below for the full details.

Steps to reproduce

Please see this bug report for TinyUSB MIDI

franky47 commented 1 year ago

Just to rule out the whole device stack, could you run the MIDI stream through a monitor (MIDI-OX on Windows, MIDI Monitor on macOS, not sure on Linux), and make sure the order is correct?

Sending two messages in the same JavaScript event loop tick in WebMIDI may schedule the messages in a different order if not specifying an outgoing timestamp or adding an artificial delay that lets the MIDI driver flush its message queue between commands.

amowry commented 1 year ago

Thanks for your help! I believe you are correct-- my JavaScript is occasionally sending the commands in the wrong order. I made a simpler page that sends the two commands, and they seem to always be received in the correct order.

amowry commented 1 year ago

I believe it was caused by me sending messages from WEB MIDI like this:

o.value.send(cc, window.performance.now());

Instead of like this:

o.value.send(cc);

It seems that adding the current time stamp was occasionally changing the order.

franky47 commented 1 year ago

Privacy-preserving browsers and extensions may introduce some jitter in the performance.now() high resolution timer, to counteract fingerprinters used in surveillance and adtech. This may be the reason why your timestamps came in the wrong order.

If you have a considerable amount of time between two sequences of messages (ie: larger than the introduced jitter), you could ensure an orderly delivery and maintain a relative valid sequence by scheduling later messages in the sequence to be ahead of the previous ones, like so:

let timestamp = window.performance.now();
o.value.send(cc1, timestamp++);
o.value.send(cc2, timestamp++);
// ...