MIDI specifications for Multidimensional Polyphonic Expression (MPE)
This Revision 1.10 persists for historical reasons and should not be implemented in a new project.
In the meantime, MPE has been adopted by the MIDI association and the published specification is available here: https://www.midi.org/specifications/midi1-specifications/mpe-midi-polyphonic-expression
The most significant alteration addresses a concern about the non-standard use of Poly mode in the Revision 1.10 draft, creating compatibility problems with certain hardware and software. The use of this CC message has been discontinued and replaced with a RPN.
Geert Bevin
February 7th 2022
20th March 2015
Revision 1.10
Amos Gaynes (Moog Music)
Ben Supper (ROLI)
Chris Adam (Apple)
Claes Johanson (Bitwig)
Edmund Eagan (Haken Audio)
Geert Bevin (Roger Linn Design, Moog Music, Eigenlabs, Uwyn)
Gerhard Lengeling (Apple)
Jean-Baptiste Thiebaut (ROLI)
Keith McMillen (Keith McMillen Instruments)
Lippold Haken (Haken Audio)
Markus Sapp (Apple)
Randy Jones (Madrona Labs)
Roger Linn (Roger Linn Design)
Roland Lamb (ROLI)
MPE Mode Activation and Deactivation
Continuous Per-Note Pitch Control
Continuous Per-Note Channel Pressure
Continuous Per-Note Control Change Message 74
Special considerations for DAWs and plug-in instruments
Example VST 2.4 canDo opcode implementation
This set of specifications is a work in progress and may change in the future. We are working towards a finalised version before the end of the Summer 2015.
In the past few years, multi-dimensional controllers have pushed the boundaries of MIDI, and created a hiatus between the degrees of freedom they are unlocking and what DAWs and plug-ins are built to utilise. Multi-dimensional controllers send gestural data that software is not equipped to deal with, which limits the creative use of multi-dimensional controllers.
Music instruments manufacturers and music software editors both share a strong interest to align on a set of specifications that enables an improved user experience of new controllers, allowing to achieve more with electronic music than before.
The objective of this document is to define a concise set of MIDI specifications to open the way to an ubiquitous Multidimensional Polyphonic Expression, requiring only minimal changes for both hardware and software manufacturers and preserving backwards compatibility.
The specifications set in this document are utilising MIDI 1.0 only.
The goal of these specifications is to facilitate the communication of multidimensional data between hardware and software manufacturers. This document proposes a set of rules for using several MIDI channels to each represent one note at a time, and to use per-channel control parameters to represent note changes in three dimensions. (details about channel and voice assignment)
The proposed name for this set of specifications is temporarily MPE. We may name software and hardware that support it “MPE-compatible”. Hardware or software that are MPE-compatible will have an MPE Mode, that can be turned On or Off.
The following summary captures the complete MPE protocol, every product needs to be able to react to these messages and adapt while running:
Enabling/Disabling MPE Mode (details)
Channel Mode Message 127 can be sent on MIDI Channel 1 or 16 with a value bigger than 0 to enable MPE mode (non real-time)
Ex: Channel 1 CC 127 12 turns MPE mode On.
Channel 1 CC 127 0 turns MPE mode Off.
In addition, the value of Channel Mode Message 127 specifies the number of per-note voice channels that are allocated from MIDI Channel 2 onwards when sent on MIDI Channel 1 and from MIDI Channel 15 downwards when sent on MIDI Channel 16.
When Channel Mode Message 127 is sent to MIDI Channel 1, that channel is the Main Channel and MIDI Channels from 2 upwards are Per-Note.
When Channel Mode Message 127 is sent to MIDI Channel 16, that channel is the Main Channel and MIDI Channels from 15 downwards are Per-Note.
Devices should only honour the last Channel Mode Message 127 received.
Per-note channels and Main Channel (details)
The Main Channel (1 or 16) remains a global channel, while channels 2-15 are used for per-note control.
Per-Note channels are assigned to a particular note from its Note On message until its Note Off message.
Messages on the Main Channel apply globally, apart from Polyphonic Key Pressure, which is already the case in the MIDI 1.0 standard.
Expression messages on a Per-Note Channel only apply to the held notes the channel was assigned to.
Any message on a Per-Note Channel could also be sent simultaneously on the Main Channel, an MPE product needs to expect this and behave in a musical fashion when this happens.
Setting the Pitch Bend range (details)
The Pitch Bend Range is by default 48 semitones for each Per-Note Channel.
RPN 00 can be used to set the pitch bend range between 0 and 96 in whole octave intervals (multiples of 12, real-time change, applies to all MIDI messages that arrive afterwards)
ex: RPN 00 24 sets the pitch range to +/- 24 semitones
Pitch Bend Range messages have to be supported on channel 2 when the Main Channel is 1 and on channel 15 when to Main Channel is 16. The range will apply to all Per-Note Channels that belong together, independently of the Main Channel.
Pitch control
The Pitch Wheel message is used independently on each Per-Note Channel. The range that will apply is indicated above and defaults to 48 semitones.
Channel Pressure
The Channel pressure message is used on each Per-Note Channel as an independent controller.
Default third dimension
The Control Change 74 message is used on each Per-Note Channel as an independent controller.
Other Control Changes
Other Control Change messages can be supported on Per-Note Channels, but if they aren’t they should have no influence at all and be ignored.
The following table captures the complete MPE protocol. Every product needs to be able to react to these messages and adapt while running.
MPE mode | Legacy single-channel use for comparison | |
How to select the MPE mode vs MIDI mode | - Channel 1/16 - Must implement CC 127 - CC 127 n [MPE on, n ch used, range 1-15] - Non real-time change - Last received CC 127 takes precedence | - CC 127 0 - Channel choice arbitrary |
MIDI channels used | - Channel 1/16 (global control) | - Single selectable channel n |
Pitch bend range | - Channel 2 (when main channel is 1) - Must implement RPN 0 - Default range is 48 semitones - Range from 0 to 96 semitones - Restricted to multiples of 12 - Symmetrical for up and down bends - Real-time change | - Set using RPN 0 on selected channel - Defaults and range criteria are left to manufacturer |
Pitch bend | - Channel 1/16 (for all notes) - Channels 2-n/15-n (note-specific) - Must implement standard Pitch Bend - Honors the active pitch bend range | - Single selectable channel n - Instrument generates pitch bend by tracking movement of a particular note - DAWs and synths apply this transformation to all playing notes |
Pressure control | - Channel 1/16 (for all notes) - Channels 2-n/15-n (note-specific) - Must implement Channel Pressure - Ignore Poly Aftertouch (per-note channels) | - Single selectable channel n - Instruments, DAWs and synths choose whether to implement Channel Pressure, Poly Aftertouch, or both - If Channel Pressure is supported, controllers sum all notes or track a particular note - DAWs and synths apply the transformation to all playing notes |
Timbre control | - Channel 1/16 (for all notes) - Channels 2-n/15-n (note-specific) - Must implement CC 74 | - Single selectable channel n - Tracks a particular note - CC 1/74 on supported devices |
Global control (sustain pedal, configuration, program change, ...) | - Channel 1/16 | - Single selectable channel n |
MIDI 1.0 provides 16 independent channels for the separation into voices. Practically this is already being adopted as the most popular method to describe per-note expression.
In essence, each note will have its own MIDI channel as soon as the Note On message is generated. This channel will be assigned to that note as long as no corresponding Note Off message was received on this channel. Any expression on that MIDI channel will only apply to the notes it was assigned to. Multiple notes might be active on a given channel for legato playing or when the polyphony is higher than the number of available Per-Note channels.
Below is a selected list of existing products that already adopt this approach:
MIDI 1.0 specifies the Channel Mode Message 127 to enable Poly Mode, but traditionally the value can only be 0.
MPE uses Channel Mode Message 127 with a value bigger than 0 to indicate the number of per-note voice channels that need to be used. All MPE products need to listen to this message and be ready to reconfigure the voices at the earliest appropriate time (non real-time).
This Channel Mode Message will be sent and received on MIDI Channel 1 or 16 to indicate that MPE mode is on with the specified number (non-zero) of MIDI channels that can be used for per-note expression
When sent on MIDI Channel 1, the Per-Note channels are counted from MIDI Channel 2 upwards.
A value of 7 for Channel Mode Message 127 on MIDI Channel 1 will for instance enable MPE mode with MIDI Channel 1 used as the Main Channel and MIDI Channels 2-8 used for per-note expression.
When sent on MIDI Channel 16, the Per-Note channels are counted from MIDI Channel 15 downwards.
A value of 7 for Channel Mode Message 127 on MIDI Channel 16 will for instance enable MPE mode with MIDI Channel 16 used as the Main Channel and MIDI Channels 15-9 used for per-note expression.
Using Channel Mode Message 127 both on MIDI Channels 1 and 16 effectively splits the available MIDI channels into two ranges, making it possible for two splits to be used on MPE controllers. Support for these splits is optional on the controller end, but sound generators and DAWs have to be able to adapt to the main channel that is being used by listening on Channel 1 and 16 for Channel Mode Message 127. The last Channel Mode Message 127 that’s received will determine the active configuration.
Note that the global messages sent on MIDI Channel 1 will only apply to notes on the Per-Note channels that were reserved through Channel Mode Message 127 on MIDI Channel 1 and global messages sent on MIDI Channel 16 will only apply to the Per-Note channels that were reserved for that main channel. Neither MIDI Channel 1 or MIDI Channel 16 can be used for per-note expression when they have been activated as a Main Channel.
Logic Pro X already implements the differentiation between Main Channel and Per-Note Channels through MIDI Mono Mode both on channels 1 and 16, but doesn’t respond to the Channel Mode configuration message.
Real-time musical control can be divided into two main methods:
These two methods of control are natural and should be preserved, they are overlapping concerns that should not intertwine. For the musician, global and per-note interaction are clearly distinct, and established products already integrate these two control methods thanks to the existence of the standard MIDI 1.0 Polyphonic Key Pressure message.
Below are a few examples to illustrate the usefulness of preserving the differentiation of global and per-note control:
To differentiate between global and per-note control, we define a Main MIDI Channel to always be used for global control messages, other MIDI Channels can be used for Per-Note expression.
The Main Channel can still receive Note messages, but other messages like Control Change, Program Change, Pitch Bend Change will apply to everything that was received on this MIDI port. The exception is the Polyphonic Key Pressure message that will still apply to individual notes on MIDI Channel 1. In typical use, MPE-capable controllers will only send note messages on MIDI channels 2-16.
The advantage of this approach is that it clearly separates global and per-note control, while also providing legacy behavior on MIDI Channel 1 that works exactly the same way that MIDI 1.0 has been used over the years with non-MPE devices. Thanks to this, a single implementation will allow manufacturers to cover all devices available.
The primary per-note expression parameter that is missing without MPE, is per-note pitch slides or vibrato. Thanks to Channel and Voice Assignment, each MIDI channel will have individual Pitch Bend Change messages that only apply to the currently held notes that the channel was assigned to. Pitch Bend Change messages on the Main Channel will still apply globally and can be used together with per-note pitch changes.
With pitch changes being specific to individual notes, it’s important to ensure that the intervals expressed by Pitch Bend Change are predictable all the way from the Controller, to the DAW, to the Sound Engine. This is traditionally expressed through a setting in the Sound Engine that defines the pitch bend range, but for MPE to work consistently, every party involved needs to agree on what this range is.
MIDI 1.0 specifies Registered Parameter Number (RPN) 00 as Pitch Bend Sensitivity, expressed in semitones (MSB) and cents (LSB). MPE only uses the MSB message with values in multiples of 12, the LSB for cents is not used at all.
MPE requires all products to listen to RPN 00 on the Per-Note MIDI Channels 2 (for Main Channel 1) and 15 (for Main Channel 16) and to instantly adjust its internal settings based on the values received in real-time (all messages after RPN 00 have to be affected by it). These RPN 00 values can only be expressed in multiples of 12, range from 0 semitones to 96 semitones and will symmetrically apply to upwards and downwards pitch bends. The Pitch Bend Range received through RPN 00 will apply to all Per-Note channels that belong together, independently of the Main channel which has a Pitch Bend Range that is not covered by MPE.
With 14-bit precision for the Pitch Bend Change message, a 48 semitone range still feels acceptable since it has a resolution that is smaller than 1 cent (4800 cents / 8192 units = 0.586 cents/unit).
Any MPE product can send out RPN 00 to indicate that the pitch bend range changed. If no RPN 00 message is received, every product has to default to a range of 48 semitones as soon as MPE mode is enabled.
A minimal implementation of MPE requires a first per-note expression control through the Channel Pressure message. When this message is sent on the Per-Note channels, it only applies to the currently held notes that the MIDI channel was assigned to. Channel Pressure messages on the Main Channel will still apply globally and can be used together with messages on the voice channels.
Channel Pressure was selected instead of Polyphonic Key Pressure to remove ambiguities since it already has a use for per-note expression in the MIDI 1.0 standard. MPE has as guideline that all messages on a Per-Note channel will only apply to the notes that were assigned to that channel. If Polyphonic Key Pressure would be used, this would be the exception where notes still need to be correlated with voices across all the received channels. We prefer to have clarity with one simple guideline.
MPE requires a second per-note expression control through the Control Change Message 74 (Brightness). When this message is sent on the Per-Note channels, it only applies to the notes that the MIDI channel was assigned to. Control Change Message 74 on the Main Channel will still apply globally and can be used together with messages on the voice channels.
Control Change Message number 74 was selected since it is already the default for the Continuum and the LinnStrument for per-note Y-axis control. It also has a meaningful default behavior in many existing synths for timbre or filter cutoff control. The alternative Control Change Message 1 was not selected because it’s traditionally already used for global expression and many MPE controllers will also have dedicated global controls.
From the perspective of a DAW which is not purely recording and playing back an MPE performance as a series of raw MIDI events, but interprets them to an internal higher-level representation, it’s important to know if a specific plug-in is able to deal with MPE data or not. Sending out notes on different MIDI channels would break functionality with plug-ins which doesn’t expect the MIDI data to arrive as specified in MPE.
Querying plug-ins for MPE support
We recommend that VST 2.4 plug-ins which support MPE, implement the canDo opcode so that it returns 1 when passed the “MPE” string. An example implementation can be found in this Appendix.
If you’re knowledgeable in other plug-in formats (AudioUnit, AAX, VST 3, …) we’re interested to hear from you in order to determine what the recommended approach is for querying for MPE support.
/** Example how to query a VST 2.4 plug-in for MPE support. **/ VstInt32 MyVstplug-in::canDo(char* text) { if (!strcmp(text, "MPE")) return 1; // 1 = plug-in supports MPE ... } /** Example how to query a VST 2.4 plug-in for which CC controllers it supports on a note-per-channel basis and their labels. **/ VstInt32 MyVstplug-in::vendorSpecific(VstInt32 lArg1, VstInt32 lArg2, void* ptrArg, float floatArg) { if (lArg1 == 'MPEC') // 4-character literal for MPE (C)ontroller { if (lArg2 == 7) { strcpy((char*)ptrArg, "Gain"); return 1; // 1 = CC supported for MPE } else if (lArg2 == 10) { strcpy((char*)ptrArg, "Pan"); return 1; } else if (lArg2 == 74) { strcpy((char*)ptrArg, "Brightness"); return 1; } return 0; // 0 = CC not supported for MPE } ... } |
Communicate around this document happens at https://groups.google.com/d/forum/mpe-spec
The latest version of this document can always be accessed through http://bit.ly/mpe-spec
March 20th, 2015: removed 14-bit for CC74 as an option; restricted pitch bend range to multiples of 12; detailed split usage on the receiving end; other minor clarifications
March 17th, 2015: clarified that RPN 00 needs to be listened to on any Per-Note channel but applies to all Per-Note channels, independently of the Main Channel; reworded MPE channel to Per-Note channel for clarity; cleaned up implementation overview table
March 16th, 2015: added executive summary and uniformized the detailed specification, removed section about Precise Pitch over Large Ranges and preserved it for a possible later extension
March 14th, 2015: renamed Poly-Legato to Precise Pitch over Large Ranges and clarified it more
March 12th, 2015: added CC106 as LSB for CC74 (MSB), restricted pitch bend range to whole semitones, cleaned up DAW/VST MPE querying, added section about poly-legato
March 4th, 2015: added split mode when sending Channel Mode Message 127 to MIDI Channel 16 and reserving per-note channels from MIDI Channel 15 downwards
February 25th, 2015: summary table of the specification with comparison against legacy single-channel mode
February 24th, 2015: changed MPE pressure support from Polyphonic Key Pressure to Channel Pressure with an explanation of the rationale behind it
February 1st, 2015: changed the RPN 00 pitch bend range from 0-48 to 0-96
January 31st, 2015: clarified that voices are assigned to notes and not reserved by notes, as such it’s possible that multiple notes might be active on a given channel, it’s up to the devices to properly react to this possibility