midi

Beware of the dreadful MIDI running status!

This is a problem you may encounter when writing a program that receive MIDI messages. I know I did, reading this post could have saved me many hours of troubleshooting.

Sometimes, I did not receive the MIDI status byte (note on, note off, cc etc). I recieved the data bytes, but the status byte seemed to be dropped. I did all kinds of troubleshooting, built different kinds of circuits with different optocouplers, and I thought it was an electrical problem, but finally Trash80 pointed me the problem:

The MIDI spec allows something called “running status”, which means that the status byte does not have to be sent if it is the same as the previous status (in order to save bandwidth). This may or may not be implemented in MIDI gear, so you never know.

So, for example, two note on messages following each other may look like this:

0x90 NOTE ON
0x3C NOTE
0x7F VELOCITY
0x3C NOTE
0x7F VELOCITY

In this example, the device sending MIDI does not send NOTE ON for the second note.

So, any code reading MIDI should never expect a status byte, but read the bytes below 128 and re-use the last received status byte. So, for example I think the post in the Arduino forums with midi-in schematics and code may be incorrect.

  • http://blog.henrikcarlsson.se Henrik Carlsson

    Thank you!!!!

    I’ve been struggling with this problem for weeks now and would’ve likely kept struggling without this blog post.

    I owe you a beer or five.

  • cornbeast

    😀

  • Tony S

    I owe you a beer too. You have saved me from tearing the rest of my hair out… I’ve been fighting with this damn synth for 3 weeks now trying to get it to pick up all the damn messages, now I know why.

  • cornbeast

    Hahaha, glad I can help 😀

  • J

    I struggled for hours. I started code development using a cheap USB-Midi converter that *always* sends the status byte. My program always worked, until I switched to a Roland UM-ONE, that skips the status byte when commands happen faster than about… ohh… 100mS. Thanks for the code tip (always read data bytes & use last RX’ed status byte)