MIDI Protocol
This page documents the MIDI specifications that Timbre implements: MIDI 1.0 (1983), MPE (2018), and USB-MIDI (1999). Use it as a development reference when writing firmware. For Timbre-specific mappings and design decisions, see the concept pages: MIDI & MPE and On the Wire. For Timbre’s consolidated spec sheet, see MIDI Implementation.
Serial Transport
Section titled “Serial Transport”The MIDI 1.0 electrical specification defines a current-loop serial interface at 31,250 baud, 8-N-1 (8 data bits, no parity, 1 stop bit). Each byte on the wire takes 320 microseconds.
Every MIDI byte is either a status byte (bit 7 = 1, range 0x80–0xFF) or a data byte (bit 7 = 0, range 0x00–0x7F). This single-bit distinction is the foundation of the entire protocol — a receiver can always determine whether it is looking at a command or a parameter.
Running Status
Section titled “Running Status”Running status allows a sender to omit the status byte when consecutive messages share the same status. The rules:
| Rule | Detail |
|---|---|
| Applies to | Channel messages only (0x80–0xEF) |
| Canceled by | System Common (0xF0–0xF7) and System Exclusive |
| Not affected by | System Real-Time (0xF8–0xFF) — these may be interleaved freely |
| Receiver behavior | Store the last received channel status byte; apply it to subsequent data bytes until a new status arrives |
Running status is a bandwidth optimization from the era of 31,250-baud serial links. Over USB it saves nothing meaningful, but receivers must handle it correctly because controllers still use it.
Channel Voice Messages
Section titled “Channel Voice Messages”Channel Voice messages carry performance data. The low nibble of the status byte encodes the channel (0–15).
| Status Byte | Binary | Data Bytes | Description |
|---|---|---|---|
0x8n | 1000nnnn | 2: note, velocity | Note Off — velocity often ignored but part of the spec |
0x9n | 1001nnnn | 2: note, velocity | Note On — velocity 0 = Note Off (running status optimization) |
0xAn | 1010nnnn | 2: note, pressure | Polyphonic Aftertouch — per-key pressure |
0xBn | 1011nnnn | 2: CC#, value | Control Change — see CC table below |
0xCn | 1100nnnn | 1: program | Program Change — patch selection |
0xDn | 1101nnnn | 1: pressure | Channel Pressure — single pressure value for the whole channel |
0xEn | 1110nnnn | 2: LSB, MSB | Pitch Bend — 14-bit value, center = 8192 (0x2000) |
Key Reference Values
Section titled “Key Reference Values”| Constant | Value | Note |
|---|---|---|
| Middle C | Note 60 | MIDI standard (some DAWs display as C3, others C4) |
| A440 | Note 69 | Concert pitch reference |
| Pitch Bend center | 8192 (0x00, 0x40) | LSB first, then MSB |
| Velocity range | 1–127 | 0 = Note Off when sent as Note On |
Control Change Numbers
Section titled “Control Change Numbers”CC messages (0xBn) use the second byte as a controller number (0–127) and the third byte as the value (0–127). The MIDI specification assigns specific functions to most of these numbers.
CC 0–31: MSB Controllers
Section titled “CC 0–31: MSB Controllers”These 32 controllers support 14-bit resolution when paired with their LSB counterparts (CC 32–63).
| CC | Name | Typical Use |
|---|---|---|
| 0 | Bank Select MSB | Bank switching (paired with Program Change) |
| 1 | Modulation Wheel | LFO depth, vibrato |
| 2 | Breath Controller | Wind controller input |
| 4 | Foot Controller | Expression pedal |
| 5 | Portamento Time | Glide speed |
| 6 | Data Entry MSB | Sets value for selected RPN/NRPN |
| 7 | Channel Volume | Main volume for the channel |
| 8 | Balance | Stereo balance |
| 10 | Pan | Stereo position (64 = center) |
| 11 | Expression | Sub-volume (scales within Volume) |
| 12–15 | Effect Control 1–4 | General purpose |
| 16–19 | General Purpose 1–4 | Undefined by default |
| 20–31 | Undefined | Available for custom use |
CC 32–63: LSB Controllers
Section titled “CC 32–63: LSB Controllers”Fine adjustment for 14-bit resolution. CC 32 is the LSB of CC 0, CC 33 is the LSB of CC 1, and so on.
| CC | Name |
|---|---|
| 32 | Bank Select LSB |
| 33 | Modulation Wheel LSB |
| 38 | Data Entry LSB |
| 34–63 | LSBs for CC 2–31 |
CC 64–69: On/Off Switches
Section titled “CC 64–69: On/Off Switches”Values 0–63 = off, 64–127 = on.
| CC | Name | Notes |
|---|---|---|
| 64 | Sustain Pedal | The most common CC after Mod Wheel |
| 65 | Portamento On/Off | Enables glide between notes |
| 66 | Sostenuto | Sustains only notes held at pedal-down |
| 67 | Soft Pedal | Reduces volume/brightness |
| 68 | Legato Footswitch | Enables legato mode |
| 69 | Hold 2 | Extended sustain variation |
CC 70–79: Sound Controllers
Section titled “CC 70–79: Sound Controllers”| CC | Name | Common Assignment |
|---|---|---|
| 70 | Sound Variation | Timbre variation |
| 71 | Resonance / Timbre | Filter Q / resonance |
| 72 | Release Time | Amplitude envelope release |
| 73 | Attack Time | Amplitude envelope attack |
| 74 | Brightness / Cutoff | Filter cutoff frequency |
| 75 | Decay Time | Amplitude envelope decay (GM2) |
| 76 | Vibrato Rate | LFO rate |
| 77 | Vibrato Depth | LFO depth |
| 78 | Vibrato Delay | LFO onset delay |
| 79 | Sound Controller 10 | Undefined |
MPE note: In MPE mode, CC 74 is the per-note Slide dimension — the third axis of expression alongside Pitch Bend and Channel Pressure. On Timbre, Slide controls oscillation mode morphing rather than simple filter cutoff. See MIDI & MPE.
CC 80–95: General Purpose and Effects
Section titled “CC 80–95: General Purpose and Effects”| CC | Name | Notes |
|---|---|---|
| 80–83 | General Purpose 5–8 | Undefined by default |
| 84 | Portamento Control | Source note for portamento |
| 85–90 | Undefined | |
| 91 | Reverb Send | Effects depth 1 |
| 92 | Tremolo Depth | Effects depth 2 |
| 93 | Chorus Send | Effects depth 3 |
| 94 | Celeste Depth | Effects depth 4 (detune) |
| 95 | Phaser Depth | Effects depth 5 |
CC 96–101: Data and Parameter Selection
Section titled “CC 96–101: Data and Parameter Selection”| CC | Name | Function |
|---|---|---|
| 96 | Data Increment | Bump RPN/NRPN value up by 1 |
| 97 | Data Decrement | Bump RPN/NRPN value down by 1 |
| 98 | NRPN LSB | Non-Registered Parameter Number (LSB) |
| 99 | NRPN MSB | Non-Registered Parameter Number (MSB) |
| 100 | RPN LSB | Registered Parameter Number (LSB) |
| 101 | RPN MSB | Registered Parameter Number (MSB) |
CC 102–119: Undefined
Section titled “CC 102–119: Undefined”All 18 controllers in this range are unassigned by the MIDI specification and available for custom use.
CC 120–127: Channel Mode Messages
Section titled “CC 120–127: Channel Mode Messages”These are sent as Control Change messages but function as mode commands.
| CC | Name | Function |
|---|---|---|
| 120 | All Sound Off | Immediately silence all voices on this channel |
| 121 | Reset All Controllers | Return all CCs to default values |
| 122 | Local Control On/Off | Connect/disconnect keyboard from internal sound engine |
| 123 | All Notes Off | Release all held notes (respects sustain pedal) |
| 124 | Omni Mode Off | Respond only to assigned channel |
| 125 | Omni Mode On | Respond to all channels |
| 126 | Mono Mode On | One voice per channel (+ optional voice count) |
| 127 | Poly Mode On | Normal polyphonic operation |
Registered Parameter Numbers (RPN)
Section titled “Registered Parameter Numbers (RPN)”RPNs provide a standardized way to control parameters that do not fit into the 128-controller CC space. The protocol uses four CC messages in sequence:
- CC 101 (RPN MSB) — selects the parameter (MSB)
- CC 100 (RPN LSB) — selects the parameter (LSB)
- CC 6 (Data Entry MSB) — sets the value (MSB)
- CC 38 (Data Entry LSB) — sets the value (LSB, optional for 7-bit parameters)
After setting a parameter, transmit RPN NULL (CC 101 = 127, CC 100 = 127) to deselect and prevent accidental data entry changes from affecting the wrong parameter.
Standard RPN Table
Section titled “Standard RPN Table”| RPN (MSB, LSB) | Name | Data Entry Value | Range |
|---|---|---|---|
| 0, 0 | Pitch Bend Sensitivity | MSB = semitones, LSB = cents | Typically 2 (standard) or 48 (MPE) |
| 0, 1 | Fine Tuning | 14-bit, center = 8192 | ±100 cents |
| 0, 2 | Coarse Tuning | MSB only, center = 64 | ±64 semitones |
| 0, 3 | Tuning Program Change | MSB = program | 0–127 |
| 0, 4 | Tuning Bank Select | MSB = bank | 0–127 |
| 0, 5 | Modulation Depth Range | MSB = semitones, LSB = cents | MPE-defined |
| 0, 6 | MPE Configuration | MSB = member channel count | See MPE section |
| 127, 127 | RPN NULL | — | Deselects active RPN |
System Messages
Section titled “System Messages”System messages are not channel-specific — they apply globally to the MIDI bus.
System Exclusive (SysEx)
Section titled “System Exclusive (SysEx)”| Byte Position | Value | Description |
|---|---|---|
| 1 | 0xF0 | Start of Exclusive |
| 2 | Manufacturer ID | 1 byte (0x01–0x7C) or 3 bytes (0x00 + 2 bytes) |
| 3…N | Data | Payload — all bytes must be 0x00–0x7F (7-bit) |
| N+1 | 0xF7 | End of Exclusive |
7-bit encoding constraint: Every data byte inside a SysEx message must have bit 7 = 0. To transmit 8-bit binary data (firmware images, patch dumps), it must be packed into 7-bit form — typically by splitting each group of 7 bytes into 8 bytes, with the high bits collected in a prefix byte.
Reserved Manufacturer IDs
Section titled “Reserved Manufacturer IDs”| ID | Purpose |
|---|---|
0x7D | Development / non-commercial — free use, no registration required |
0x7E | Universal Non-Real Time (MIDI-CI, sample dumps, tuning) |
0x7F | Universal Real Time (MTC, notation, device control) |
Identity Request / Reply
Section titled “Identity Request / Reply”Any MIDI device should respond to a Universal SysEx Identity Request:
Request: F0 7E 7F 06 01 F7
(Universal Non-Real Time, broadcast, General Information, Identity Request)
Reply: F0 7E DD 06 02 MM FF FF DD DD SS SS SS SS F7
(DD = device ID, MM = manufacturer, FF FF = family, DD DD = model, SS SS SS SS = version)
System Common
Section titled “System Common”| Status | Bytes | Name | Description |
|---|---|---|---|
0xF1 | 1 data | MTC Quarter Frame | SMPTE timecode fragment |
0xF2 | 2 data | Song Position Pointer | 14-bit beat count (MIDI beat = 6 clocks) |
0xF3 | 1 data | Song Select | Select song/sequence number |
0xF4 | — | Undefined | |
0xF5 | — | Undefined | |
0xF6 | 0 | Tune Request | Trigger analog oscillator tuning |
0xF7 | 0 | End of Exclusive | Terminates SysEx message |
System Real-Time
Section titled “System Real-Time”Single-byte messages with no data. May be interleaved anywhere in the byte stream — even between the status byte and data bytes of another message, or within a SysEx transfer. Receivers must handle this.
| Status | Name | Description |
|---|---|---|
0xF8 | Timing Clock | 24 pulses per quarter note (ppqn) |
0xF9 | Undefined | |
0xFA | Start | Begin playback from song position 0 |
0xFB | Continue | Resume from current song position |
0xFC | Stop | Halt playback |
0xFD | Undefined | |
0xFE | Active Sensing | Heartbeat — once started, must arrive within 300 ms or receiver assumes disconnect |
0xFF | System Reset | Return device to power-on state |
MPE — MIDI Polyphonic Expression
Section titled “MPE — MIDI Polyphonic Expression”MPE (adopted by the MMA in January 2018) assigns each sounding note to its own MIDI channel, enabling per-note continuous control of multiple expression dimensions simultaneously.
Zone Architecture
Section titled “Zone Architecture”MPE defines up to two zones, each with a Manager Channel and one or more Member Channels:
| Zone | Manager Channel | Member Channels | Direction |
|---|---|---|---|
| Lower Zone | Channel 1 | Channels 2 upward | Ascending |
| Upper Zone | Channel 16 | Channels 15 downward | Descending |
The Manager Channel carries zone-wide controls (sustain pedal, volume, program change). Member Channels carry per-note data (note on/off, pitch bend, pressure, CC 74).
MPE Configuration Message (MCM)
Section titled “MPE Configuration Message (MCM)”Zone setup is performed via RPN 6 on the Manager Channel. The Data Entry MSB specifies how many Member Channels to allocate. Setting it to 0 deactivates the zone.
Lower Zone — 15 member channels:
B0 65 00 CC#101 = 0 (RPN MSB) on channel 1B0 64 06 CC#100 = 6 (RPN LSB) on channel 1B0 06 0F CC#6 = 15 (Data Entry) on channel 1Upper Zone — 7 member channels:
BF 65 00 CC#101 = 0 (RPN MSB) on channel 16BF 64 06 CC#100 = 6 (RPN LSB) on channel 16BF 06 07 CC#6 = 7 (Data Entry) on channel 16Deactivate Lower Zone:
B0 65 00 CC#101 = 0 (RPN MSB) on channel 1B0 64 06 CC#100 = 6 (RPN LSB) on channel 1B0 06 00 CC#6 = 0 (Data Entry) on channel 1Default Pitch Bend Sensitivity
Section titled “Default Pitch Bend Sensitivity”After MCM, the MPE specification sets default pitch bend ranges:
| Channel Type | Default Range | RPN 0 Value |
|---|---|---|
| Manager Channel | ±2 semitones | 2 |
| Member Channels | ±48 semitones | 48 |
The wide ±48 range on member channels gives expressive controllers (Linnstrument, Seaboard, Continuum) full pitch-slide capability across the playing surface.
Per-Note Expression Dimensions
Section titled “Per-Note Expression Dimensions”| Dimension | MIDI Message | Typical Controller Gesture |
|---|---|---|
| Strike velocity | Note On velocity | Initial key/pad impact |
| Pitch | Pitch Bend (per-channel) | Horizontal slide on playing surface |
| Pressure | Channel Pressure (per-channel) | Vertical force after initial strike |
| Slide | CC 74 (per-channel) | Vertical position on playing surface |
| Lift velocity | Note Off velocity | Release speed |
Note Sharing
Section titled “Note Sharing”When the number of sounding notes exceeds available member channels, the MPE specification permits note sharing — multiple notes on the same channel. Per-note expression is degraded for shared notes (they receive the same pitch bend and pressure). Instruments should avoid this by voice-stealing the oldest or quietest note before resorting to channel sharing.
USB-MIDI
Section titled “USB-MIDI”The USB Device Class Definition for MIDI Devices (1999) defines how MIDI travels over USB, built on top of the USB Audio Class.
USB-MIDI Event Packet
Section titled “USB-MIDI Event Packet”Every USB-MIDI transaction is composed of 32-bit packets:
| Bits | Field | Description |
|---|---|---|
| 31–28 | Cable Number | Virtual cable / port index (0–15) |
| 27–24 | Code Index Number (CIN) | Identifies the message type and packet size |
| 23–16 | MIDI_0 | First MIDI byte (usually status) |
| 15–8 | MIDI_1 | Second MIDI byte (or 0x00 if unused) |
| 7–0 | MIDI_2 | Third MIDI byte (or 0x00 if unused) |
CIN Table
Section titled “CIN Table”| CIN | MIDI Bytes Used | Message Type |
|---|---|---|
0x0 | 1, 2, or 3 | Miscellaneous (reserved) |
0x2 | 2 | Two-byte System Common |
0x3 | 3 | Three-byte System Common |
0x4 | 3 | SysEx starts or continues (3 bytes) |
0x5 | 1 | Single-byte System Common or SysEx end |
0x6 | 2 | SysEx ends with 2 bytes |
0x7 | 3 | SysEx ends with 3 bytes |
0x8 | 3 | Note Off |
0x9 | 3 | Note On |
0xA | 3 | Polyphonic Aftertouch |
0xB | 3 | Control Change |
0xC | 2 | Program Change |
0xD | 2 | Channel Pressure |
0xE | 3 | Pitch Bend |
0xF | 1 | Single Byte (Real-Time) |
The Cable Number field allows a single USB connection to carry up to 16 independent virtual MIDI cables (ports), each with its own 16-channel MIDI stream. Timbre uses a single cable in Phase 1–2, with dual cable (performance + configuration) planned for Phase 3.
Key Constants
Section titled “Key Constants”Quick-lookup table for firmware development:
| Constant | Value | Hex | Notes |
|---|---|---|---|
| A440 | Note 69 | 0x45 | Concert pitch reference |
| Middle C | Note 60 | 0x3C | |
| Pitch Bend center | 8192 | 0x2000 | 14-bit, LSB first on wire |
| Max channel | 15 | 0x0F | 0-indexed (channels 0–15 = display 1–16) |
| Baud rate | 31,250 | — | Serial MIDI |
| Byte time | 320 us | — | At 31,250 baud, 10 bits per byte |
| SysEx Start | — | 0xF0 | |
| SysEx End | — | 0xF7 | |
| Velocity range | 1–127 | — | 0 = Note Off (in Note On context) |
| 14-bit max | 16,383 | 0x3FFF | Pitch bend, 14-bit CCs |
| 7-bit max | 127 | 0x7F | Standard CC/velocity/note range |
| MIDI Clock ppqn | 24 | — | Pulses per quarter note |
| Active Sensing timeout | 300 ms | — | After first 0xFE received |
Sources
Section titled “Sources”| Resource | URL |
|---|---|
| MIDI 1.0 — Summary of Messages | midi.org/summary-of-midi-1-0-messages |
| MIDI Message Quick Reference | michd.me/jsmidgen/midi-message-reference |
| MPE Specification | midi.org/midi-polyphonic-expression-mpe |
| USB-MIDI Class Definition | usb.org/document-library/usb-midi-devices-10 |
| MIDI 2.0 Specification | midi.org/midi-2-0 |