Why MIDI Note On Velocity 0 Means Note Off
In the MIDI 1.0 specification, transmitting a Note On command with a
velocity value of zero is universally recognized as a Note Off event.
This article provides a technical explanation of why byte sequence
0x90 0x3C 0x00 stops Middle C from sounding instead of
playing it silently, detailing the historical bandwidth constraints and
data optimization techniques that shaped this protocol rule.
The Breakdown of the Bytes
To understand the command, examine each byte in the sequence
0x90 0x3C 0x00:
0x90(Status Byte): Specifies a Note On event on MIDI Channel 1. The high nibble (9) defines the message type (Note On), and the low nibble (0) indicates Channel 1 (indexed from 0 to 15).0x3C(Data Byte 1): Specifies the note number in hexadecimal, which corresponds to 60 in decimal—standard Middle C (C4).0x00(Data Byte 2): Specifies the key velocity, ranging from 0 to 127. Here, the velocity is 0.
Standard Note Off commands use the status byte 0x80.
However, when a synthesizer or MIDI receiver receives 0x90
with a velocity of 0x00, it immediately executes a Note Off
routine for that specific note.
The Purpose: MIDI Running Status
The primary reason for this behavior is data transmission efficiency over serial connections. When the MIDI standard was established in 1983, it was designed to run over a serial cable at a fixed baud rate of 31,250 bits per second (31.25 kbaud). Because musical performances generate high volumes of data in real time, reducing the byte count was essential to prevent audible latency and timing jitter.
To minimize data transfer, the MIDI specification introduced Running Status. Under Running Status rules:
- When a status byte (such as
0x90) is sent, the receiving device remembers it as the active status. - Subsequent messages that share the same status do not need to resend the status byte.
- The sender only transmits the two data bytes (note number and velocity).
The Inefficiency
of the Standard Note Off (0x80)
If a synthesizer relied exclusively on standard Note Off commands
(0x80), playing and releasing notes would require
constantly alternating between status bytes:
- Press Note:
0x90 0x3C 0x40(3 bytes: Note On, Note 60, Velocity 64) - Release Note:
0x80 0x3C 0x40(3 bytes: Note Off, Note 60, Velocity 64) - Press Next Note:
0x90 0x3E 0x40(3 bytes: Note On, Note 62, Velocity 64)
Because the status byte toggles between 0x90 and
0x80, Running Status is broken continuously. Every single
note start and end requires a full 3-byte transmission.
How Velocity 0 Solves the Problem
By defining a Note On with velocity 0 as a Note Off, the status byte
can remain 0x90 indefinitely for an entire sequence of
pressed and released keys:
- Press Middle C:
0x90 0x3C 0x64(3 bytes: Status byte sets Running Status to0x90) - Release Middle C:
0x3C 0x00(2 bytes: Note Off via velocity 0 under Running Status) - Press D:
0x3E 0x64(2 bytes: Note On under Running Status) - Release D:
0x3E 0x00(2 bytes: Note Off via velocity 0 under Running Status)
This technique eliminates the need to transmit the status byte for every release event, saving 33% of the bandwidth on subsequent messages.
Note Off
(0x80) vs. Note On Velocity Zero
(0x90 0x00)
The only functional difference between a dedicated Note Off message
(0x80) and a Note On with velocity zero
(0x90 ... 0x00) relates to release
velocity:
0x80 [Note] [Velocity]allows a device to send a release velocity value between 1 and 127, indicating how quickly the key was released. Some advanced synthesizers and sample libraries use release velocity to modulate key-release sounds or envelope release times.0x90 [Note] 0x00cannot convey variable release velocity because the velocity byte is fixed at zero to trigger the off command. Synthesizers assume a default release velocity (typically 64) when this method is used.