MIDI BLE Tutorial
Encapsulating MIDI Data
Paraphrased from the MIDI Tutorial,
Bytes of MIDI messages are divided into 2 major categories, based on the setting of the most significant bit. If a byte's MSB is a 0, it is a data byte with 7 usable bits of data. If the MSB is a 1, it's a status byte (or could be a special case if SysEx messages are used, but they are ignored here).
A serial MIDI packet is started with a status byte, then contains a number of data bytes depending on what type of packet is indicated by the status byte (see Summary of MIDI Messages for more information).
In the world of BLE, data is thought of in terms of characteristics, which is just a size of data that can be written to, and is available on both ends of the connection by the unseen negotiations of the link.
The Bluetooth LE MIDI Specification serves as the source material for the next section. Go register with midi.org to download it for free, and it helps them see who's using the information. They're a great organization and are allowing direct reprinting of their copyrighted material for this tutorial.
The specification allows a few types of MIDI packets to exist within a characteristic.
BLE Packet with One Full MIDI Message
The most basic type of MIDI BLE packet, or characteristic value, is one containing a single MIDI message.
The first and second bytes are overhead to the actual midi payload.
- The first byte describe the upper 6 bits of the timestamp and has the MSB set.
- The second byte describes the lower 7 bits of the timestamp and also has the MSB set.
- The remaining bytes are the payload. It's the original midi message that is being encapsulated.
Shown here, a MIDI message of 3 bytes is appended to a timestamp to create a BLE packet. If the midi message was only 2 bytes long, the BLE packet size would be 4 bytes, and so on.
Also notice that the MSB is set for any byte that isn't data. This will be useful when parsing out MIDI messages of other forms.
BLE Packet with Multiple Full MIDI Messages
A BLE characteristic can be written to a variable size, and can contain more than 1 MIDI message. When two or more MIDI messages are concatenated, the upper 6 bits of timestamp can be omitted because it can't rollover twice per BLE packet. All contained messages share the same upper timestamp bits and have their own lower bits.
Here two MIDI messages are contained in a single characteristic. The second message has the same header byte and so it's omitted to reduce overhead.
Look at the output from the basic BLE Peripheral example.
This has been hand decoded in the following table.
This is an NRPN message. It's three controller change commands sent sequentially. Just as the MIDI specification indicates, the packet is formed with single Header and unique timestamps for each message (although they all seemed to originate simultaneously).
BLE Packet with Running Status MIDI Messages
The last type of BLE packet that can exist is a running status message. In a message like this many MIDI messages all have the same timestamp and MIDI status, so the timestamp and status are only sent once followed by a block of data. The MIDI status indicates what size the data will be (by message type) and the data can be parsed accordingly.
From the previous example, the MacBook Air sent 3 messages that did have the same timestamp and status. It's unusual that it was instructed to send these as full messages rather than running status messages.