MIDI Messages
With the foundation from the previous chapters, it is time to move into the more animated part of our journey.
Until now, we have talked about MIDI messages in very general sense, we touched bits, bytes, number systems, and how MIDI data is structured. You now understand why MIDI uses 7-bit values, how status and data bytes are distinguished, and how multi-byte values are assembled. In this chapter, we will put that knowledge to work.
If you have an Electra One controller, open the web editor and create a new, empty project:
[ IMAGE OF EMPTY PROJECT ]
Do not worry if you are completely new to this. We will move step by step.
Earlier in this book, we described MIDI messages conceptually. Note On, Control Change, Program Change, Pitch Bend, and so on. Now we will look at them from a more technical perspective. For each message type, we will:
- Identify the status byte
- Decode the data bytes
- Examine their binary and hexadecimal forms
- Send them manually
- Observe what happens
Instead of only reading about MIDI messages, you will see the exact bytes being transmitted and interpreted. To do so we will use two tools:
- The Electra One hardware controller
- The MIDI Console in the Electra One web editor
The MIDI Console allows you to type and send raw MIDI data directly and observe incoming messages in real time.
[ MIDI Console ]
How MIDI Data Is Sent
MIDI data is transmitted as a sequence of bytes, each consisting of 8 bits. Every MIDI message is composed of a Status byte, which identifies the type of message and, in most cases, the MIDI channel, followed by zero or more Data bytes, which carry the actual parameters of that message.
A Status byte is easy to recognize: its msb is always set to 1. This means its numeric value falls within the range 128 to 255 (0x80 to 0xFF in hexadecimal). Because the most significant bit is 1, the receiving device immediately understands that a new message is beginning. For channel messages, the Status byte encodes both the message type, such as Note On or Control Change, and the channel number. We will decode this structure in detail shortly.
Data bytes, on the other hand, always have their msb set to 0. This limits their numeric range to 0 – 127 (0x00–0x7F in hexadecimal). The remaining seven bits carry the actual MIDI value, whether that is a note number, a velocity, a controller number, or a pressure value. Since data bytes can never have their msb set to 1, they can never be confused with a Status byte. This is precisely what makes the MIDI protocol self-synchronizing: the receiver can always detect where a new message begins.
The number of Data bytes depends entirely on the type of message being sent. Some messages consist of only a single Status byte and carry no Data bytes at all. Real-Time messages such as Start, Stop, or Clock are examples of this. Other messages contain one or two Data bytes. A Note On message, for instance, carries two: the first indicates which note (which key) was pressed, and the second specifies the velocity—how strongly it was struck.
SysEx messages are a special case. They begin with a Status byte but can contain a variable number of Data bytes, sometimes forming quite long messages. These are used for device-specific communication, and we will explore them in detail later in this chapter.
MIDI Channels in Status Bytes
Status byte format for channel messages:
[ message type ][ channel ]Example:
- Channel 1 → 0
- Channel 16 → 15 (0x0F)
Note On
Purpose: Start playing a note Status byte: Decimal: 144–159 Hex: 0x90–0x9F Byte sequence:
[ Status ] [ Note Number ] [ Velocity ]Example (Note On, channel 1):
144 60 100
0x90 0x3C 0x64Description: Plays note 60 (Middle C) with velocity 100.
Note Off
Purpose: Stop playing a note Status byte: Decimal: 128–143 Hex: 0x80–0x8F Byte sequence:
[ Status ] [ Note Number ] [ Velocity ]Example:
128 60 64
0x80 0x3C 0x40Note On with Velocity 0 (Alternate Note Off)
Status byte: same as Note On Velocity: 0
144 60 0
0x90 0x3C 0x00Description: Treated identically to Note Off.
Control Change
Purpose: Change a continuous or switch parameter Status byte: Decimal: 176–191 Hex: 0xB0–0xBF Byte sequence:
[ Status ] [ Controller Number ] [ Value ]Example (CC 7 Volume):
176 7 100
0xB0 0x07 0x64Program Change
Purpose: Select preset or instrument Status byte: Decimal: 192–207 Hex: 0xC0–0xCF Byte sequence:
[ Status ] [ Program Number ]Example:
192 10
0xC0 0x0ANote: Only 2 bytes, no value byte.
Pitch Bend
Purpose: Smooth pitch control Status byte: Decimal: 224–239 Hex: 0xE0–0xEF Byte sequence:
[ Status ] [ LSB ] [ MSB ]Value range: 14-bit (0–16383), center = 8192 Example (center):
224 0 64
0xE0 0x00 0x40Channel Pressure (Channel Aftertouch)
Purpose: Pressure affecting entire channel Status byte: Decimal: 208–223 Hex: 0xD0–0xDF Byte sequence:
[ Status ] [ Pressure ]Example:
208 80
0xD0 0x50Polyphonic Key Pressure
Purpose: Pressure per individual note Status byte: Decimal: 160–175 Hex: 0xA0–0xAF Byte sequence:
[ Status ] [ Note Number ] [ Pressure ]Example:
160 60 90
0xA0 0x3C 0x5ASystem Exclusive (SysEx)
Purpose: Manufacturer-specific data Status bytes: Start: 240 (0xF0) End: 247 (0xF7) Byte sequence:
0xF0 [ Manufacturer ID ] [ Data... ] 0xF7Example:
240 67 16 76 0 247
0xF0 0x43 0x10 0x4C 0x00 0xF7MIDI Clock
Purpose: Tempo synchronization Status byte: Decimal: 248 Hex: 0xF8 Byte sequence:
248
0xF8Sent 24 times per quarter note.
Start
Purpose: Start playback Status byte: Decimal: 250 Hex: 0xFA
250
0xFAContinue
Purpose: Resume playback Status byte: Decimal: 251 Hex: 0xFB
251
0xFBStop
Purpose: Stop playback Status byte: Decimal: 252 Hex: 0xFC
252
0xFCActive Sensing
Purpose: Connection monitoring Status byte: Decimal: 254 Hex: 0xFE
254
0xFESystem Reset
Purpose: Reset all devices Status byte: Decimal: 255 Hex: 0xFF
255
0xFFSummary
MIDI communication is based on small byte sequences where the status byte defines the message type and channel, followed by one or two data bytes carrying parameters. Understanding the decimal and hexadecimal values of MIDI messages — and their byte order — is essential for low-level MIDI programming, debugging, and working with MIDI APIs such as Electra One’s Lua Extension.