MIDI 2 Part 2: Per-Note Expression, Channel Voice Messages and System Messages
New Message Types in MIDI 2.0
MIDI 2.0 not only extends existing messages to higher resolution, but also introduces new categories of messages that had no direct equivalent in MIDI 1.0. These new messages focus on per-note control, new controller semantics, and enhanced management of performance data. Below we explore these new message types and their bit-level structure, including Per-Note Controllers, expanded Channel Voice messages, and new System messages for timing and more.
Per-Note Controllers and Per-Note Expression
While MIDI 1.0 did have polyphonic key pressure (per-note aftertouch) and the later MPE extension (which used separate channels per note to simulate per-note control), MIDI 2.0 formalizes and greatly expands per-note expression. In MIDI 2.0, each note can have multiple independent control values associated with it, not just pressure. This is a game-changer for expressiveness: it’s like giving each note its own set of controllers (pitch, timbre, etc.), rather than only having channel-wide controllers.
MIDI 2.0 defines several new Per-Note message types as part of the Channel Voice category (MT = 0x4):
- Registered Per-Note Controllers (RPNC): a standardized set of per-note controllers with specific defined meanings. These are analogous to Registered Parameter Numbers in MIDI 1.0, but they apply per note instead of per channel. For example, the spec might define “Per-note Modulation” or “Per-note Brightness” as specific RPNC numbers.
- Assignable Per-Note Controllers (APNC): an open set of per-note controllers for custom or manufacturer-specific use. Like NRPN in MIDI 1.0, these allow 14-bit identifiers (128 banks of 128 controllers, giving 16384 possible per-note controller IDs). They can be mapped to whatever a device wants (vibrato depth per note, filter cutoff per note, etc.) if no standard RPNC exists for that.
- Per-Note Pitch Bend: independent pitch bend for each note. This lets you bend one note in a chord without affecting others, which was only possible in MIDI 1.0 by using multiple channels (MPE).
- Per-Note Management: a special message to manage the state of per-note controls when notes overlap (discussed below).
These messages use the 64-bit MIDI 2.0 voice message format. Let’s break down their bit structure using an example:
- Registered Per-Note Controller message – Status opcode might be, say, 0x0 (just hypothetical, since 0xA is poly pressure, 0xB is CC, maybe 0x0 or 0x2 are used for per-note controllers in the new scheme as these were unused in MIDI 1.0 status nibbles). The 16-bit Index field carries two pieces of info: the Note Number (so the target note 0–127) and the controller number (the RPN per-note number). According to one reference, in a MIDI 2.0 Note On message, the 16-bit index is split into 8-bit note and 8-bit attribute type. By analogy, for a per-note controller message, the 16-bit index could be split into 7 or 8 bits of Note Number and 8 or 9 bits of Controller ID. It is likely 8 bits for note (since note numbers remain 0–127) and 8 bits for controller number (allowing 0–255 per-note controller identifiers, where 0–127 might be RPN and 128–255 might denote a bank extension for assignable controllers). The 32-bit Data field is the controller value (0–0xFFFFFFFF). So a message might look like: “On channel 5, for note number 60, set Registered Per-Note Controller 3 to value 0x50000000.”
- Assignable Per-Note Controller message – This would be similar, but it would indicate an assignable controller number (likely a two-part number combining bank and index if needed). Possibly the opcode or a flag in the index distinguishes RPNC vs APNC. The spec likely defines that if the controller number (in the index) is 0x00–0x7F, it’s a registered per-note controller, and if it’s 0x80–0xFF, it denotes an assignable per-note controller with bank (just an educated guess, as they might reuse the 8-bit attribute as bank for APNC). They could also have separate opcodes for RPNC vs APNC; indeed Appendix A lists “MIDI 2.0 Registered Per-Note Controllers” and implies separate handling.
- Per-Note Pitch Bend message – The spec specifically lists “MIDI 2.0 Per-Note Pitch Bend” as a new message. This likely has its own opcode or is treated as a particular RPNC (some documents imply RPNC #3 is per-note pitch. Regardless, in the UMP it will carry the note number in the index and a 32-bit pitch value in the data (in 7.25 format). So if you want to bend note 64 up a whole tone, you send a per-note pitch message with note=64 and data = corresponding offset (maybe 0xXXXXXX depending on range).
- Poly Pressure (Per-Note Aftertouch) – Though not “new” (MIDI 1.0 had poly aftertouch), in MIDI 2.0 it is extended to 32-bit data. It is essentially a per-note controller itself (pressure for that note). The MIDI 2.0 Poly Pressure message uses the note in the index and a 32-bit pressure value in data. It was given its own status in MIDI 1.0 (0xA), and MIDI 2.0 likely retains opcode 0xA for “Per-Note Pressure” with extended data.
The Per-Note Management (PNM) message is interesting and new. It deals with situations where multiple instances of the same note number are sounding on one channel (e.g., two C4 notes). In MIDI 1.0, if you sent a poly aftertouch for that note number, both instances would respond identically (because they share the note ID). MIDI 2.0’s solution is the PNM message which has a Detach (D) and Reset (S) flag. When you send a PNM with D=1 for a given note number, it means “detach any currently sounding note(s) of this pitch from per-note controls.” Those already playing notes will continue sounding but ignore further per-note controllers. The next Note On of that pitch will start a fresh context where per-note controllers apply only to it. Essentially, it creates a new “instance” for per-note control purposes. The S (reset) flag instructs the receiver to reset all per-note controller values for that note to default (useful if you want to clear bend or modulation from a previous note before triggering a new one). So typically, before playing an overlapping note, a controller might send PNM (D=1, S=maybe 1) for that note number, then do the Note On for the new note. This way the new note can be modulated independently of the tail of the old note. A PNM message itself would contain the note number in the index and perhaps the two flags in the 32-bit data word (with the rest of the bits reserved/zero). It doesn’t carry a “value” like other messages, just options.
In summary, per-note messages allow what MPE did (per-note pitch, per-note Y-axis, etc.) but within a single channel and with more structure and resolution. The bit fields ensure you always specify which note you’re targeting (via the 16-bit index). The data is 32-bit, so even something like per-note filter cutoff can be very smooth and continuous.
From a usage perspective:
- A MIDI 2.0 controller can send independent vibrato depth for each note in a chord by using an Assignable Per-Note controller for vibrato and sending separate values for note 60 vs note 64, etc.
- A synth receiving this will apply those differences to each voice playing that note.
- Per-note pitch means things like strumming a chord on a MIDI guitar – each string’s bend can be transmitted on one channel (no more channel-per-string needed), simply referencing the note ID.
It’s worth noting that Channel Controllers still exist and function as before (and at 32-bit). So, for example, Channel Volume (CC#7) is still a channel message affecting the whole channel. Per-note controllers are in addition – they typically handle expressive modulation that you want separate for each note. The design is such that if a per-note controller is not used by a device, it can ignore those messages. And if a device isn’t doing anything polyphonic, it might never send them. But for multi-dimensional controllers or advanced synths, this opens up a new world. Essentially, MIDI 2.0’s per-note messages are a built-in, more powerful successor to MPE.
Expanded Channel Voice Messages
All the traditional Channel Voice messages from MIDI 1.0 exist in MIDI 2.0, but some have new formats or related new messages to simplify extended functionality:
- Control Change (CC): MIDI 2.0 keeps CC numbers 0–127 but the value is 32-bit. This means a standard CC message is just higher resolution – e.g., CC74 (timbre) now sends a 32-bit value. In addition, as mentioned, some CC numbers (like 98–101 for NRPN/RPN in MIDI 1.0) are no longer needed for their old purpose because RPN and NRPN have dedicated messages now. The spec designates those controllers as “reserved for MIDI 1.0 compatibility” in MIDI 2.0 mode.
- Registered Controllers (RPN) and Assignable Controllers (NRPN): In MIDI 1.0, setting an RPN (like pitch bend range or fine tuning) required sending CC101/100 (to select RPN number), then CC6/38 (Data Entry MSB/LSB). In MIDI 2.0, there are new Channel Voice messages to handle these in one go. The spec likely defines a “Registered Controller” message (maybe using an opcode beyond 0xB, or a special controller number) to directly send a 32-bit value for a specific 14-bit RPN number. For example, to set RPN 0 (Pitch Bend Range) to ±2 semitones, a MIDI 2.0 device might send a single message that contains RPN=0 and value=0x00020000 (2 semitones in 14-bit, if they encode semitone and cents). Appendix B of the spec lists “Special Control Change Messages” which probably includes “Registered Controller” and “Assignable Controller” messages. So effectively, NRPN (98/99) similarly gets collapsed into one message with a 14-bit identifier and a 32-bit value. This makes parameter changes more atomic and far higher resolution.
- Relative Controllers: MIDI 2.0 adds the concept of relative (increment/decrement) controller messages. This is useful for endless encoders. A relative message might carry a signed 32-bit value indicating the amount of change. The spec likely assigns a range or separate status for relative controllers. For instance, there might be a “Relative CC” message type or a flag in the high bits of the 32-bit value to indicate it’s relative. Some hints in the spec tables show entries like “Relative” and “Rel NRPN”. An example: turning an endless knob could send “Relative Controller #16 = +5” to increase something by 5 units, rather than an absolute position.
- Program Change: MIDI 2.0 Program Change messages are expanded to optionally include bank information in one message. In MIDI 1.0, to change presets you often send CC0 (Bank MSB), CC32 (Bank LSB), then Program Change. In MIDI 2.0, a Program Change can be sent as a 64-bit message where the 32-bit data field could be partitioned into Bank MSB, Bank LSB, and Program Number. The MMA has defined a Bank Select mechanism in MIDI 2.0 that uses 14-bit for bank (128*128 banks) and 7-bit for program, all in one message. Likely the 16-bit index might carry the bank number and the 8-bit program is in the data field, or vice versa. The exact division aside, the result is one message can specify both bank and program. If a device only cares about program (and stays in current bank), it can ignore the bank part.
- Channel Pressure (Aftertouch): Channel Pressure is now a 64-bit message with a 32-bit pressure value. No new semantics, just higher res.
- Pitch Bend: Channel Pitch Bend remains, but now with a 32-bit value (where 0x8000_0000 is center) instead of a 14-bit value. The message is 64-bit but functionally it’s the same concept, just more precise.
New System Messages (Real-Time and Sync)
MIDI 2.0’s system messages include a crucial enhancement for timing: Jitter Reduction Timestamps. This mechanism, described earlier, effectively time-stamps MIDI messages for more precise scheduling. These are not “System Common” or “Real-Time” messages in the old categorization, but rather belong to the Utility/Stream category in UMP.
To recap in a bit-level fashion:
- JR Clock Message: This is a periodic message that carries the current time of the sender in a high-resolution format (likely 32-bit). It does not align with MIDI beat clock; it’s more like a continuously running clock. The format (from MMA materials) might be 4 bytes where, for example, the least significant 7 bits of each byte are used (to keep it compatible as a SysEx payload if needed). The resolution is 31.25 µs per tick (which is 32 kHz tick rate). So the 32-bit clock wraps roughly every ~9.6 minutes. The important part: the JR Clock message is sent regularly (e.g. every 5–10 ms or on significant time changes) to sync the receiver’s notion of time with the sender.
- JR Timestamp Message: This is a small message (probably one byte after the header) that gives a delta-time offset for the immediately following MIDI message. How it works: The sender, say a sequencer, will send a JR Clock at time 1000 (just an example). Then it wants to send two notes that are supposed to strike together 5 ms later. It sends a JR Timestamp message specifying an offset of +5 ms (in that 32 kHz tick format, 5 ms ≈ 160 ticks). Then it sends the first Note On, then another JR Timestamp of 0 (for same time as last offset, meaning simultaneous), then the second Note On. The receiver will queue those notes until the local clock (kept in sync by JR Clock messages) reaches the specified time, then play them. This way, if there was any jitter in the USB transmission (maybe one Note On arrived a millisecond late), the timestamp ensures it’s corrected – the synth knows they were meant to be together. Technically, JR Timestamp could be a 2-byte value giving the number of 31.25µs ticks offset (so 0–0x3FFF maybe, allowing up to ~2 ms offset with high precision if one byte, or more if two bytes).
- The JR Clock and JR Timestamp messages work in tandem and are optional. If a device or host doesn’t implement them, MIDI still works, just without the jitter improvement. They are designed such that they can apply to both MIDI 1.0 and 2.0 messages over UMP. This means even if you’re driving an old module through a MIDI 2.0 interface, the interface could use JR timestamps to schedule the outgoing 1.0 bytes more accurately.
- These messages are categorized as Utility (MT=0x0) in UMP with specific status codes. For instance, one code might indicate “JR Clock” and include the 32-bit time, and another indicates “JR Timestamp” with the offset.
MIDI 2.0 did not fundamentally change other system messages like MIDI Clock, Start/Stop, Song Position Pointer – those are still present (because you need them for backward compatibility and sync with older gear). However, because of JR timestamps, a MIDI 2.0 device could transmit MIDI Clock messages with high precision timing. In fact, the MMA suggests that even MIDI 1.0 devices can benefit: “major timing improvements in MIDI 2.0 can apply to MIDI 1.0 devices”, referring to the JR timestamp mechanism working in UMP format.
System Exclusive 8 and Mixed Data Set messages we already covered in format – functionally, SysEx8 allows things like sending full 8-bit binary data (useful for non-musical data, like lighting commands or just more efficient sample dumps). Mixed Data Set could be used for new system-level purposes like bundling MIDI with other info, but as of now it’s more of a placeholder for future expansion.
Endpoint Discovery and Function Blocks: Not exactly musical messages, but MIDI 2.0 defines system-exclusive messages for discovering devices and their “function blocks.” For instance, a MIDI 2.0 device can have multiple function blocks (like a synth engine, a separate drum machine engine, etc.) each on different group IDs. There are messages to inquire this structure, perhaps in the Property Exchange domain or specialized SysEx. These allow systems to map out what a device contains (for example, a keyboard might tell the computer “I have a keyboard controller block on Group1 and a sound engine block on Group2”). This helps routing and UI representations but is mostly behind-the-scenes.
To list new system-level messages introduced:
- JR Clock (for high-res timing sync).
- JR Timestamp (prepended event timing).
- Endpoint Info messages (part of MIDI-CI or system exclusive, giving info like device name, manufacturer, etc., similar to USB descriptors).
- Function Block Discovery and Configuration messages (so a host can query what blocks a device has, and possibly enable/disable them or set their MIDI Group routing).
- (Potentially in the future, new real-time messages could be added thanks to the expandable UMP types, but as of the current spec, MIDI Clock etc. remain as is).
Overall, MIDI 2.0’s new messages provide finer control at every level: per-note expression for performance, easier parameter management for sound design (no more multi-byte RPN sequence hassle), and tighter synchronization for timing. The protocol improvements in encoding these messages (bits for note indices, bigger data fields, etc.) ensure that devices and software have a clear and robust way to implement features that previously required awkward workarounds or proprietary extensions.
Backward Compatibility with MIDI 1.0
MIDI 2.0 extends MIDI 1.0 without breaking what already works. It starts by talking to any device in 1.0 mode. If both sides support MIDI 2.0, they switch automatically. Old gear still gets normal MIDI 1.0 messages, while newer devices can handle higher resolution and advanced features.
In the new UMP format, older messages are simply wrapped in a 32-bit packet. That means a Note On or a CC still looks the same to a 1.0 synth. The backward compatibility extends to system messages, channel modes, and SysEx. The translation rules ensure that 2.0 values scale down to 1.0, and 1.0 values scale up to 2.0.
If your setup mixes 2.0 and 1.0 gear, the operating system or a MIDI interface will handle the conversion. You don’t need special settings for older devices. They keep working as before. New features just become active when both sides support MIDI 2.0.
More about Backward Compatibility
Conclusion
MIDI 2.0 represents a profound evolution of the MIDI protocol, addressing long-standing limitations while preserving the essence of what made MIDI so successful. It introduces a modern, packet-based message format (UMP) that carries both MIDI 1.0 and new MIDI 2.0 messages in a unified way. This format enables features like 32-bit resolution for controllers, per-note expressive control, and precise timing that were unimaginable in the original 1983 specification. Crucially, MIDI 2.0 achieves this without making existing MIDI gear obsolete – through MIDI-CI negotiation and careful design, it ensures seamless backward compatibility with MIDI 1.0 devices.
From a technical perspective, the improvements are significant: the Universal MIDI Packet provides a robust framing with explicit message lengths and categories, eliminating ambiguity and allowing extensibility. The jump from 7-bit to 32-bit data resolution for performance messages gives MIDI 2.0 an almost “HD” quality – parameter changes feel continuous and smooth. The addition of per-note controllers and per-note pitch bend brings polyphonic expression directly into the protocol, enabling richer performances (essentially a high-resolution equivalent to what MPE achieved, but standardized). Timing has been tightened with Jitter Reduction timestamps, which allow synchronization and playback with sub-millisecond accuracy, benefitting both live and recorded MIDI data.
For musicians and producers, these protocol enhancements translate to more expressive instruments and more reliable communication. A single cable or connection can now carry 16 channels × 16 groups = 256 channels of high-resolution data – useful in complex studio setups or large ensemble virtual instruments. A pianist on a MIDI 2.0 keyboard will find that the velocity and per-note nuances of their performance are captured with far greater detail (16-bit velocity, per-note release, etc.), and a guitarist with a MIDI pickup can bend individual strings without complicated multi-channel setups. Electronic analog synths controlled via MIDI 2.0 can receive knob movements that feel continuous, eliminating the “stair-step” artifact of 0–127 CC changes. And in computer-based production, automation lanes can effectively be high-resolution via MIDI 2.0, so slow fades and sweeps recorded as MIDI control changes will replay as smoothly as they were intended.
For manufacturers and software developers, MIDI 2.0 provides a future-proof framework. There is ample space reserved for new messages and extensions, meaning the protocol can grow without a complete overhaul. The introduction of Profiles and Property Exchange means a synth can declare “I’m an analog synth profile” and any controller can auto-map to it, reducing tedious manual mapping. Devices can also communicate metadata (patch names, etc.) in a structured way, simplifying integration with DAWs. All these occur within the MIDI protocol, streamlining what used to require proprietary editors or workarounds.
It’s important to note that MIDI 2.0 is being adopted gradually. As of 2025, major OSes have MIDI 2.0 support in development or released, and some hardware is “MIDI 2.0 ready.” This phased adoption is possible precisely because of backward compatibility – MIDI 2.0 devices work with MIDI 1.0 environments by design. As new MIDI 2.0 features become common, we can expect firmware updates and new products to start leveraging them more. For example, we might see a surge of controllers that send per-note brightness or articulation data for instrument plugins that understand those Profile definitions.