Build your own MIDI circuits
Frequently Asked Questions.
MIDI & Music
MIDI and Music Information
MIDI Running Status

Running Status


Since MIDI data is transmitted serially, it is possible that musical events which originally occurred at the same time and must be sent one at a time in the MIDI data stream may not actually be played at exactly the same time. With a data transmission rate of 31.25 Kbit/s and 10 bits transmitted per byte of MIDI data, a 3-byte Note On or Note Off message takes 960µs, about 1 ms to be sent, which is generally short enough that the events are perceived as having occurred simultaneously.


In fact, for a person playing a MIDI instrument keyboard, the time skew between playback of notes when 10 keys are pressed simultaneously should not exceed 10 ms, and this would not be perceptible.


However, MIDI data being sent from a sequencer can include a number of different parts. On a given beat, there may be a large number of musical events which should occur simultaneously, and the delays introduced by serialization of this information might be noticeable. To help reduce the amount of data transmitted in the MIDI data stream, a technique called "running status" may be employed.


Running status considers the fact that it is very common for a string of consecutive messages to be of the same message type. For instance, when a chord is played on a keyboard, 10 successive Note On messages may be generated, followed by 10 Note Off messages. When running status is used, a status byte is sent for a message only when the message is not of the same type as the last message sent on the same Channel. 


The status byte for subsequent messages of the same type may be omitted (only the data bytes are sent for these subsequent messages). The effectiveness of running status can be enhanced by sending Note On messages with a velocity of zero in place of Note Off messages. In this case, long strings of Note On messages will often occur. Changes in some of the MIDI controllers or movement of the pitch bend wheel on a musical instrument can produce a staggering number of MIDI Channel voice messages, and running status can also help a great deal in these instances.


Let's take an example of a device creating a stream of MIDI messages. Assume that the device needs to send 3 Note On messages (for middle C, E above middle C, and G above middle C) on channel 0. Here are the 3 MIDI messages:

0x90 0x3C 0x7F
0x90 0x40 0x7F
0x90 0x43 0x7F
Notice that the Status bytes of all 3 messages are the same (ie, Note On, Channel 0). Therefore the device could implement running status for the latter 2 messages, sending the following bytes:
0x90 0x3C 0x7F
0x40 0x7F
0x43 0x7F
This allows the device to save time since there are 2 less bytes to transmit. Indeed, if the message that the device sent before these 3 also happened to be a Note On message on channel 0, then the device could have omitted the first message's Status too.


Now let's take the perspective of a device receiving this above stream. It receives the first message's Status (ie, 0x90) and thinks "Here's a Note On Status on channel 0. I'll remember this Status byte. I know that there are 2 more data bytes in a Note On message. I'll expect those next". And, it receives those 2 data bytes. 

Then, it receives the data byte of the second message (ie, 0x40). Here's when the device thinks "I didn't expect another data byte. I expected the Status byte of some message. This must be a running status message. The last Status byte that I received was 0x90, so I'll assume that this is the same Status. Therefore, this 0x40 is the first data byte of another Note On message on channel 0".


Remember that a Note On message with a velocity of 0 is really considered to be a Note Off. With this in mind, you could send a whole stream of note messages (ie, turning notes on and off) without needing a Status byte for all but the first message. All of the messages will be Note On status, but the messages that really turn notes off will have 0 velocity. For example, here is how to play and release middle C utilizing running status:

0x90 0x3C 0x7F
0x3C 0x00     <- Note-Off

Real Time Category messages (ie, Status of 0xF8 to 0xFF) do not effect running status in any way. Because a Real Time message consists of only 1 byte, and it may be received at any time, including interspersed with another message, it should be handled transparently. For example, if a 0xF8 byte was received in between any 2 bytes of the above examples, the 0xF8 should be processed immediately, and then the device should resume processing the example streams exactly as it would have otherwise. Because Real Time messages only consist of a Status, running status obviously can't be implemented on Real Time messages.


System Common Category messages (ie, Status of 0xF0 to 0xF7) cancel any running status. In other words, the message after a System Common message must begin with a Status byte. System Common messages themselves can't be implemented with running status. For example, if a Song Select message was sent immediately after another Song Select, the second message would still need a Status byte.


Running status is only implemented for Voice Category messages (ie, Status is 0x80 to 0xEF).


A recommended approach for a receiving device is to maintain its "running status buffer" as so:

  • Buffer is cleared (ie, set to 0) at power up.
  • Buffer stores the status when a Voice Category Status (ie, 0x80 to 0xEF) is received.
  • Buffer is cleared when a System Common Category Status (ie, 0xF0 to 0xF7) is received.
  • Nothing is done to the buffer when a RealTime Category message is received.
  • Any data bytes are ignored when the buffer is 0.