MIDI Protocol and MIDI Messages

MIDI Protocol

MIDI PROTOCOL : Part 2 – MIDI Messages

The MIDI Message specification (or “MIDI Protocol”) is the most important part of MIDI.

Originally intended for use over MIDI Cables to connect twoor more keyboards, MIDI messages are now used inside computers, smartphones and tablets to generate music, and transported over professional and consumer interfaces (USB, FireWire, etc.) to a wide variety of MIDI-equipped devices.

As said in the overview, MIDI is a music description language in digital (binary) form. It was designed for use with keyboard-based musical instruments, so the message structure is oriented to performance events, such as picking a note and then striking it, or setting typical parameters available on electronic keyboards.

For example, to sound a note in MIDI you send a “Note On” message, and then assign that note a “velocity“, which determines how loud it plays relative to other notes. You can also adjust the overall loudness of all the notes with a Channel Volume message. Other MIDI messages include selecting which instrument sounds to use, stereo panning, and many more settings and events.

The first specification (1983) did not define every possible “word” that can be spoken in MIDI , nor did it define every musical instruction that might be desired in an electronic performance. So over the past 20 or more years the original MIDI specification has been improved and enhanced by defining additional performance control messages, and creating additional specifications which include:

  • MIDI Machine Control
  • MIDI Show Control
  • MIDI Time Code
  • General MIDI
  • Downloadable Sounds
  • Scalable Polyphony MIDI

Alternate Applications MIDI Machine Control and MIDI Show Control are interesting extensions because instead of addressing musical instruments they address studio recording equipment (like tape decks for example) and theatrical control (lights, smoke machines, scenic effect, etc.).

MIDI is also being used for control of devices like audio mixing console.

We have said that the MIDI messages are used to transmit real time information for the playback of a piece of music describing what should be played like a music score would do for the performer.

It’s important to understand that “Real time” means that each message is sent exactly at the moment it must be interpreted by the target instrument/synthesizer (which can be a hardware synthesizer or software synthesizer).

The important point is that the MIDI language does not define the sound itself, but only the sequence of instructions to create the sound in the target instrument/synthesizer.

The MIDI messages are sent as a time sequence of one or more bytes (8 bits). Each message is composed by one or more bytes and the first byte is always a so called STATUS byte, often followed by DATA bytes with additional parameters. To keep things simple the STATUS bytes and DATA bytes are recognized by the bit 7, the left most bit, that is set (1) in STATUS bytes and is clear (0) in DATA bytes.

The STATUS byte determines the type of the message. The number of DATA bytes that follow depend on the type of the message.

Except for some system MIDI messages, the STATUS byte contains the MIDI channel number.

There are 16 possible MIDI channels, numbered from 0 to 15. In practice, musicians and software refer to the MIDI channels by counting them from 1 to 16, so that there is a difference of 1 when you program them in hexadecimal notation:

Channel numbers
– Decimal notation : 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
– Hexadecimal notation : 0, 1, 2, 3, 4, 5, 6 ,7 ,8 ,9 ,A, B, C, D, E, F

In the same MIDI cable, up to 16 MIDI channels may be used to control up to 16 different instruments playing independently.

DATA bytes can be transmitted or received even if they are not preceded by a STATUS byte, in this case the STATUS byte associated is the las one that was received (or transmitted). This is perfectly legal and the last STATUS byte active is commonly known as MIDI RUNNING STATUS.



MIDI Messages : NOTE Messages

The main MIDI messages are the NOTE ON and NOTE OFF messages.

The NOTE ON message is sent when the performer hits a key of the music keyboard. It contains parameters to specify the pitch of the note as well as the velocity (intensity/loudness of the note when it is hit).

When an instrument receives this message, it starts playing that note with the correct pitch and force level.

When the NOTE OFF message is received, the corresponding note is switched off by the instrument. So every NOTE ON messages requires its coresponding NOTE OFF message or the note will play forever! This is not true for percussion instruments where it can happen that only NOTE ON messages are sent just because the percussion sound terminates itself automatically (think about the difference between a note played by a trumpet and a note played by a snare drum).

The NOTE ON message is structured as follows:

  • Status byte : 1001 CCCC
  • Data byte 1 : 0PPP PPPP
  • Data byte 2 : 0VVV VVVV


  • CCCC is the MIDI channel (0 – 15)
  • PPP PPPP is the note pitch (0 – 127)
  • VVV VVVV is the velocity (0 – 127)

The pitch value determines the frequency of the note to be played.

It goes from 0 to 127, with the middle C note being represented by the value of 60, The value is represented

Middle C
Middle C

in half steps, so that C# will be 61, D will be 62,…

Note velocity in music notation
Note velocity in music notation

To transpose a note one octave higher we have to add 12 to its pitch value because each octave is composed by 12 half-tones. By using MIDI, transposition is very simple as it is done simply by adding or subtracting a fixed value.

The velocity value normally goes from 1 to 127, covering the range from a practically inaudible note up to the maximum note level. It basically corresponds to the scale of nuances found in music notation, like you can see on the right box.

In basic synthesizers, the velocity value is used only to determine the force with which the note is played, the only effect being a note that is louder or softer in volume.

In more sophisticated synthesizer, this value will also affect the sound quality. Indeed, on a real piano, hitting a note harder will not only affect its loudness but also the quality of the sound itself, the timber. This is practically the case with any real instrument.

There is a special case if the velocity is set to zero. The NOTE ON message then has the same meaning as a NOTE OFF message, switching the note off.

The NOTE OFF message is structured as follows:

  • Status byte : 1000 CCCC
  • Data byte 1 : 0PPP PPPP
  • Data byte 2 : 0VVV VVVV

where CCCC and PPP PPPP have the same meaning as the NOTE ON message. The VVV VVVV instead is the release velocity, which is very rarely used and by default it is set to zero.

MIDI Messages : Playing notes and chords

When you send a NOTE ON message to an instrument, this note starts playing. Immediatly after this event, you can send other NOTE ON messages, with different note pitch to create a chord. The ability to play simultaneous notes for a digital instrument is called polyphony. This value depends on the digital instrument quality and the voice used to reproduce the note because sometime multiple layers of sound are used to generate a voice and so the total polyphony is reduced, but we will cover this argument when we will talk about synthesizers.


MIDI Messages : Selecting Instruments

There is a MIDI Message to specify an instrument from a predefined list of 128 sounds, this 128 sounds group is called bank and generally a mordern digital instrument have 2 or more bank of instruments.

In theory, each instrument could have its own custom list of instruments, but the “General Midi (GM)” standard defines a list of 128 instruments that simplifies compatibility. Most synthesizer have at least a compatibility mode with the GM standard, for your reference here is the list of General MIDI instrumentsGeneral MIDI standard.

The MIDI message used to specify the instrument is called a “program change” message.
It has one STATUS byte and one DATA byte :

  • Status byte : 1100 CCCC
  • Data byte 1 : 0XXX XXXX

where CCCC is the MIDI channel (0 to 15) and XXXXXXX is the instrument number from 0 to 127.

Similarly to MIDI channels, you will often see that the instrument numbers in synthesizers and in GM lists, are numbered from 1 to 128 so you also need to add or subtract 1 for the conversion.

For instance, the trumpet instrument has number 57 in the GM list, so in the above MIDI message you must set XXXXXXX = 56 to get the correct instrument in the target synthesizer.

The notes sent to the synthesizer after that message will be played with a trumpet sound.


Drum instruments

Drum instruments are a special case, as they do not have a specific pitch like on a piano or trumpet (even if there are the so called chromatic percussions that do have a pitch). A specific MIDI channel is used to transmit the playback of drum instruments. In General Midi, it is channel 10, but you will find synthesizers that can be programmed to receive drums on any channel.

In the case of a channel assigned to drum instruments (and also for special sound effects often included in synthesizers), the NOTE ON and NOTE OFF message information for the pitch is in fact used to select which drum or sound effect will play.

For example, to play a bass drum instrument on channel 10, send the NOTE ON message as follows:

  • 0x99 0x23 0x40

0x99 is the STATUS byte for the NOTE ON message, using channel 10 (coded 9). 0x23 is decimal 35 which is the note number used for the acoustic bass drum. 0x40 is decimal 64 for a velocity around the mezzo forte nuance. You should then send the NOTE OFF message as follows:

  • 0x89 0x23 0x00

Using MIDI Channels

The MIDI protocol handles up to 16 different MIDI channels and each channel has its own status, for instance the current instrument defined, the notes that are currently playing, as well as other values like the volume and so on…

By using different MIDI channels, you can define a specific instrument for each one and by sending notes on the corresponding MIDI channels, these notes will sound with the given instruments.

MIDI Controllers

There are 128 MIDI controllers defined, but only a few of them are used in practice.

The purpose of a MIDI controller is to set a value of a parameter in the synthesizer playing the notes, like the volume, the panning, the level of reverberation, and many others.
The message is built as follows:
  • Status byte : 1011 CCCC
  • Data byte 1 : 0NNN NNNN
  • Data byte 2 : 0VVV VVVV

where CCCC is the MIDI channel, NNNNNNN is the controller number (from 0 to 127) and VVVVVVV is the value assigned to the controller (also from 0 to 127).The most common controller numbers are the following:

  • 0 = Sound bank selection (MSB)
  • 1 = Modulation wheel, often assigned to a vibrato or tremolo effect.
  • 7 = Volume level of the instrument
  • 10 = Panning (0 = left; 64 = center; 127 = right)
  • 11 = Expression (sometimes used also for volume control or similar, depending on the synthesizer)
  • 32 = Sound bank selection (LSB)
  • 64 = Sustain pedal (0 = no pedal; >= 64 => pedal ON)
  • 121 = All controllers off (this message clears all the controller values for this channel, back to their default values)
  • 123 = All notes off (this message stops all the notes that are currently playing)

Volume and velocity

For instance, if you want to set the volume to a value of 100 (in the 0 to 127 range of values, 100 = 0x64) for the instrument playing on channel 1 (coded 0), you can send the following message:
  • 0xB00x07 0x64

The volume change has an impact on all notes currently playing as well as the notes that will start playing later.

The synthesizer keeps that volume level until another volume level is sent.
Remember that the velocity of a note is sent with the NOTE ON message itself and that the velocity cannot be changed once the note has been started, so you can use the volume controller to change the level of the note after it has been started.
To create a crescendo, you need to send a sequence of increasing volume values.
Instrument selection
As we have seen before, you can select a sound on a synthesizer with the 128 values of the program change message. The sound bank selection messages (LSB Least Significant Byte and MSB Most Significant Byte) are used in addition to the program change message.
A digital instrument may contain one or more sound banks, each one with 128 sounds. If you want to use a specific sound bank of the synthesizer, you must first activate the new bank and then send the program change message.
As an example, if you want to use sound number 3 (encoded 2) on channel 1 (coded 0) in the bank with specification LSB=1; MSB=5, you must send the following sequence of MIDI messages:
  • 0xB00x00 0x05 (MSB sound bank selection)
  • 0xB0 – 0x20 – 0x01 (LSB sound bank selection)
  • 0xC0 – 0x02 (sound selection in the current sound bank)

After receiving these messages, the synthesizer will play the following notes with that specific sound.

As the MSB and LSB can range from 0 to 127, there is a total of 128 x 128 = 16384 possible sound bank to be selected.

Pitch Bend

The Pitch Bend message is used to vary the pitch of the notes that are playing on the current MIDI channel. The message is the following:

  • Status byte : 1110 CCCC
  • Data byte 1 : 0LLL LLLL
  • Data byte 2 : 0MMM MMMM

where CCCC is the MIDI channel, LLL LLLL is the LSB of the pitch bend value and MMM MMM is the MSB. The 14 bit value of the pitch bend is defined so that a value of 0x2000 is the center corresponding to the normal pitch of the note (no pitch change). Using numbers above 0x2000 (up to 0x3FFF) will increase the pitch and using numbers below (down to 0x0000) will decrease the pitch. The range of pitch change is symmetric (up and down) and can often be adjusted in the synthesizer itself.

The most common range value is +/- 2 semitones around the standard note pitch.
Pitch bend is often used to create glissando and guitar bend effects. To achieve this, you must send a continuous sequence of pitch bend messages, to vary the pitch in real time, often enough so that the ear does not hear too much steps in the curve.
For instance, to “bend” a note of a semitone higher, you must send a value of 0x3000, which will be sent as:
  • 0xE0 – 0x00 – 0x60

Indeed, the value 0x3000 must be split into two 7-bit values, giving 0x60 and 0x00 for the MSB and LSB parts.

Resetting notes

There are some cases where you want to reset whatever notes are playing. There are basically 4 ways to do this.

Some synthesizer do not accept them all, so it is interesting to offer the different possibilities.
  1. Using MIDI controller 123
    If you send a MIDI controller 123 on one MIDI channel, the synthesizer will stop all notes playing on that channel. To reset all MIDI channels, send that message for each channel.
    Please note that some synthesizer do not respond to this message.
  2. MIDI Reset message
    This is a one status byte message 0xFF, without data bytes. It should reset the synthesizer to its power-on default, so it also stops all notes playing.
    Use this message sparingly, as it reset the full synthesizer, not only the notes playing.
    You can also send, for each channel (0 to 15) and each note pitch (0 to 127) one MIDI NOTE OFF message.
    This is the total solution, but requires a lot of MIDI messages to be sent, which may have some reaction time according to the MIDI hardware system you use.
  4. MIDI NOTE OFF – Optimized
    In this case, use a table to keep track of the NOTE ON and OFF messages you send for each channel. A buffer of 128 bytes for each channel, representing the number of NOTE ON messages sent to that note, should be incremented by a NOTE ON and decremented by a NOTE OFF.
    Then, when you want to reset every note, simply go through that table and send a NOTE OFF to each note that is still playing.



Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.