This article shows how a Blue Gecko can be used as a MIDI controller over Bluetooth Low Energy. At first we give some basic info about the MIDI standard then on the Apple Bluetooth Low Energy MIDI Specification. Finally, we highlight and explain the most important code snippets from the attached sample application which implements a very basic MIDI controller.
The protocol
MIDI is an industry standard music technology protocol that connects products from many different companies including digital musical instruments, computers, tablets and smartphones. MIDI is used everyday around the world by musicians, DJs, producers, educators, artists and hobbyists to create, perform, learn and share music and artistic works. Nearly every hit album, film score, TV show and theatrical production uses MIDI to connect and create. MIDI information is transmitted in "MIDI messages", which can be thought of as instructions which tell a music synthesizer how to play a piece of music. The synthesizer receiving the MIDI data must generate the actual sounds.
Physical layer
The MIDI specification for the electrical interface is based on a fully isolated current loop. The MIDI OUT port nominally sources a +5 volt source through a 220 ohm resistor out through pin 4 on the MIDI OUT DIN connector, in on pin 4 of the receiving device's MIDI IN DIN connector, through a 220 ohm protection resistor and the LED of an optoisolator. The current then returns via pin 5 on the MIDI IN port to the originating device's MIDI OUT port pin 5, again with a 220 ohm resistor in the path, giving a nominal current of about 5 milliamperes. Despite the cable's appearance, there is no conductive path between the two MIDI devices, only an optically isolated one. The data rate on this system is a relatively slow (by today standards) 31,250 bits per second, logic 0 being current ON. The MIDI data stream is a unidirectional asynchronous bit stream with 10 bits transmitted per byte (a start bit, 8 data bits, and one stop bit). The MIDI data stream is usually originated by a MIDI controller, such as a musical instrument keyboard.
MIDI controller and sound module
A MIDI controller is a device which is played as an instrument, and it translates the performance into a MIDI data stream in real time (as it is played). The MIDI data output from a MIDI controller is transmitted via the devices' MIDI OUT connector. The recipient of this MIDI data stream is commonly a MIDI sound generator or sound module, which will receive MIDI messages at its MIDI IN connector, and respond to these messages by playing sounds.
MIDI messages
There are a number of different types of MIDI messages. See the https://www.midi.org for details.
In the example code attached we implemented only Note On and Note Off messages. The Note On message is used for turning on MIDI notes. This is typically sent when a key pressed on keyboard. The Note Off message is used for turning off MIDI notes. This is typically sent when a key released on keyboard.
MIDI over BLE
There are number of solutions where the standard DIN connector and physical layer changed to a more modern medium like USB or Ethernet. Apple defined a custom BLE service for MIDI support. This is now part of the MIDI standard.
To support MIDI over BLE the accessory has to fulfill a set requirements collected below.
Connection interval
The accessory shall request a connection interval of 15 ms or less. Apple recommends starting with a request for a connection interval of 11.25 ms and going to 15 ms if the connection request is rejected by the Apple product. Intervals higher than 15 ms are unsuitable for live playback situations.
MTU negotiation
The accessory shall support MTU negotiation. See the MTU Size section in the Bluetooth Low Energy chapter of the Bluetooth Accessory Design Guidelines for Apple Products for implementation details.
Multiple packet transmissions
The accessory shall support sending and receiving the maximum number of Bluetooth Low Energy packets that can fit into the connection interval. MIDI minimum bandwidth requirements may not be met otherwise.
Custom MIDI Service and Characteristic
The GATT should contain the following service and characteristic
Name
UUID
MIDI Service
03B80E5A-EDE8-4B33-A751-6CE34EC4C700
MIDI I/O Characteristic
7772E5DB-3868-4112-A1A9-F2669D106BF3
The MIDI I/O characteristics
Name
Type
Security
Properties
Comment
MIDI I/O
blob
Read, Write, Notify
Pairing required
Shall require encryption. Writes must not expect a response.
Header and Timestamp fields
Additional Header and Timestamp fields has to be added before the standard MIDI message format
Header bit 7 is start bit and set to 1
Header bit 6 is reserved and set to 0
Header bits 0-5 are upper 6 bits of 13 bit timestamp
Timestamp bit 7 is start bit and set to 1
Note that the actual timestamp value is splitted between the Header and Timestamp fields.
The 13-bit timestamp for a MIDI event in any given Bluetooth Low Energy packet is formed from the bottom 6 bits of the Header field and the bottom 7 bits of the Timestamp filed. Timestamps are in expressed in milliseconds, implying that the maximum timestamp range is 8192 ms. Timestamps shall be sent in monotonically increasing order.
Example application
The attached application act as a very basic MIDI controller. It can send MIDI note on and MIDI note off messages when a button pressed or released on the WSTK. Pressing PB0 button repeatedly will play the Imperial March from Star Wars. Pressing PB1 is resetting the sequence so the melody can start from the beginning.
The application is built upon the Simplicity Studio Bluetooth SDK ver. 2.11 and tested with the BGM13S Starter Kit (SLWSTK4305A) but it should work with other EFR32 based Bluetooth enabled targets with minimal changes.
We going to highlight the most important steps which are needed for building a MIDI over BLE compatible device.
GATT definition
The GATT.xml file has to contain the MIDI service definition as it is showed below.
Set the connection interval to the required 15 ms.
void midi_ble_connected(uint8_t connection)
{
/* store the connection ID */
connectionId = connection;
/* connection parameter constrains for ble MIDI */
gecko_cmd_le_connection_set_timing_parameters(connection, 0x12, 0x12, 0, 0x64, 0, 0xFFFF);
}
Setup CRYOTIMER for creating 1ms timer for the timestamp
This timestamp has to be included to the MIDI message.
void midi_init_timer(void)
{
CRYOTIMER_Init_TypeDef cryoInit = CRYOTIMER_INIT_DEFAULT;
/* General settings */
cryoInit.enable = 1;
cryoInit.debugRun = 0;
cryoInit.em4Wakeup = 0;
/* Clocking settings */
/* With a frequency of 1000Hz on ULFRCO, this will result in a 1.00 ms timeout */
cryoInit.osc = cryotimerOscULFRCO;
cryoInit.presc = cryotimerPresc_1;
cryoInit.period = cryotimerPeriod_1;
CRYOTIMER_Init(&cryoInit);
}
Setup GPIO interrupt for button press
Here is the PBB0_pressed function registered as a GPIO interrupt service routine and will be triggered for both rising and falling edges. The function is reading the GPIO state and sends a note on or note off message accordingly. The code snippet below shows the recommended way for registering the ISR.
The midi_note_on() function prepare and send a note on message. First the function gets the timestamp from the CRYOTIMER. The CRYTIMER provides a 32 bit counter but according to the specification we need only the lower 13 bit, so the rest of the bits are masked. Then the function fills the header and timestamp fields. The header byte is 0b10xxxxxx where xxxxxxx is top 6 bits of timestamp. The timestamp byte is 0b1xxxxxxx where xxxxxxx is lower 7 bits of timestamp.
The status byte is 0x90 is 0b1sssnnnn where sss is message type and nnnn is the MIDI channel.
The last two bytes contains the 2 byte long event field in this case it is the note and velocity.
Finally the function sends the message with the gecko_cmd_GATT_server_send_characteristic_notification API function.
void midi_note_on(uint8 note, uint8 velocity)
{
static midi_data_t note_on;
/* Get the timestamp from the CRYOTIMER */
uint32 temp = CRYOTIMER_CounterGet();
/* Mask it - only the lower 13 bit needed */
temp = temp & 0x00001fff;
/* Header byte = 0b10xxxxxx where xxxxxxx is top 6 bits of timestamp */
note_on.midi_event.header = 0x80 | (temp >> 7);
/* Timestamp byte = 0b1xxxxxxx where xxxxxxx is lower 7 bits of timestamp */
note_on.midi_event.timestamp = 0x80 | (temp & 0x003f);
/* Status byte = 0b1sssnnnn where sss is message type and nnnn is channel */
note_on.midi_event.status = 0x90;
/* setting the note parameter */
note_on.midi_event.note = note;
/* setting the velocity parameter */
note_on.midi_event.velocity = velocity;
/* sending the assembled MIDI message */
gecko_cmd_GATT_server_send_characteristic_notification(connectionId, GATTdb_xGATT_MIDI, 5, (uint8 const *) ¬e_on);
}
Testing
Once the application flashed to kit it starts advertise itself. After connection it pairs and bonds with just work method. The application tested with the following IOS apps:
Bluetooth Knowledge Base
KBA_BT_0911: MIDI over BLE
MIDI basics
This article shows how a Blue Gecko can be used as a MIDI controller over Bluetooth Low Energy. At first we give some basic info about the MIDI standard then on the Apple Bluetooth Low Energy MIDI Specification. Finally, we highlight and explain the most important code snippets from the attached sample application which implements a very basic MIDI controller.
The protocol
MIDI is an industry standard music technology protocol that connects products from many different companies including digital musical instruments, computers, tablets and smartphones. MIDI is used everyday around the world by musicians, DJs, producers, educators, artists and hobbyists to create, perform, learn and share music and artistic works. Nearly every hit album, film score, TV show and theatrical production uses MIDI to connect and create. MIDI information is transmitted in "MIDI messages", which can be thought of as instructions which tell a music synthesizer how to play a piece of music. The synthesizer receiving the MIDI data must generate the actual sounds.
Physical layer
The MIDI specification for the electrical interface is based on a fully isolated current loop. The MIDI OUT port nominally sources a +5 volt source through a 220 ohm resistor out through pin 4 on the MIDI OUT DIN connector, in on pin 4 of the receiving device's MIDI IN DIN connector, through a 220 ohm protection resistor and the LED of an optoisolator. The current then returns via pin 5 on the MIDI IN port to the originating device's MIDI OUT port pin 5, again with a 220 ohm resistor in the path, giving a nominal current of about 5 milliamperes. Despite the cable's appearance, there is no conductive path between the two MIDI devices, only an optically isolated one. The data rate on this system is a relatively slow (by today standards) 31,250 bits per second, logic 0 being current ON. The MIDI data stream is a unidirectional asynchronous bit stream with 10 bits transmitted per byte (a start bit, 8 data bits, and one stop bit). The MIDI data stream is usually originated by a MIDI controller, such as a musical instrument keyboard.
MIDI controller and sound module
A MIDI controller is a device which is played as an instrument, and it translates the performance into a MIDI data stream in real time (as it is played). The MIDI data output from a MIDI controller is transmitted via the devices' MIDI OUT connector. The recipient of this MIDI data stream is commonly a MIDI sound generator or sound module, which will receive MIDI messages at its MIDI IN connector, and respond to these messages by playing sounds.
MIDI messages
There are a number of different types of MIDI messages. See the https://www.midi.org for details.
In the example code attached we implemented only Note On and Note Off messages. The Note On message is used for turning on MIDI notes. This is typically sent when a key pressed on keyboard. The Note Off message is used for turning off MIDI notes. This is typically sent when a key released on keyboard.
MIDI over BLE
There are number of solutions where the standard DIN connector and physical layer changed to a more modern medium like USB or Ethernet. Apple defined a custom BLE service for MIDI support. This is now part of the MIDI standard.
This specification can be found here:
https://www.midi.org/specifications/item/bluetooth-le-midi
To support MIDI over BLE the accessory has to fulfill a set requirements collected below.
Connection interval
The accessory shall request a connection interval of 15 ms or less. Apple recommends starting with a request for a connection interval of 11.25 ms and going to 15 ms if the connection request is rejected by the Apple product. Intervals higher than 15 ms are unsuitable for live playback situations.
MTU negotiation
The accessory shall support MTU negotiation. See the MTU Size section in the Bluetooth Low Energy chapter of the Bluetooth Accessory Design Guidelines for Apple Products for implementation details.
Multiple packet transmissions
The accessory shall support sending and receiving the maximum number of Bluetooth Low Energy packets that can fit into the connection interval. MIDI minimum bandwidth requirements may not be met otherwise.
Custom MIDI Service and Characteristic
The GATT should contain the following service and characteristic
The MIDI I/O characteristics
Header and Timestamp fields
Additional Header and Timestamp fields has to be added before the standard MIDI message format
Note that the actual timestamp value is splitted between the Header and Timestamp fields.
The 13-bit timestamp for a MIDI event in any given Bluetooth Low Energy packet is formed from the bottom 6 bits of the Header field and the bottom 7 bits of the Timestamp filed. Timestamps are in expressed in milliseconds, implying that the maximum timestamp range is 8192 ms. Timestamps shall be sent in monotonically increasing order.
Example application
The attached application act as a very basic MIDI controller. It can send MIDI note on and MIDI note off messages when a button pressed or released on the WSTK. Pressing PB0 button repeatedly will play the Imperial March from Star Wars. Pressing PB1 is resetting the sequence so the melody can start from the beginning.
The application is built upon the Simplicity Studio Bluetooth SDK ver. 2.11 and tested with the BGM13S Starter Kit (SLWSTK4305A) but it should work with other EFR32 based Bluetooth enabled targets with minimal changes.
We going to highlight the most important steps which are needed for building a MIDI over BLE compatible device.
GATT definition
The GATT.xml file has to contain the MIDI service definition as it is showed below.
Enable the bonding before connection
Set the connection interval to the required 15 ms.
Setup CRYOTIMER for creating 1ms timer for the timestamp
This timestamp has to be included to the MIDI message.
Setup GPIO interrupt for button press
Here is the PBB0_pressed function registered as a GPIO interrupt service routine and will be triggered for both rising and falling edges. The function is reading the GPIO state and sends a note on or note off message accordingly. The code snippet below shows the recommended way for registering the ISR.
Function to send a note on message
The midi_note_on() function prepare and send a note on message. First the function gets the timestamp from the CRYOTIMER. The CRYTIMER provides a 32 bit counter but according to the specification we need only the lower 13 bit, so the rest of the bits are masked. Then the function fills the header and timestamp fields. The header byte is 0b10xxxxxx where xxxxxxx is top 6 bits of timestamp. The timestamp byte is 0b1xxxxxxx where xxxxxxx is lower 7 bits of timestamp.
The status byte is 0x90 is 0b1sssnnnn where sss is message type and nnnn is the MIDI channel.
The last two bytes contains the 2 byte long event field in this case it is the note and velocity.
Finally the function sends the message with the gecko_cmd_GATT_server_send_characteristic_notification API function.
Testing
Once the application flashed to kit it starts advertise itself. After connection it pairs and bonds with just work method. The application tested with the following IOS apps:
References
[1] https://www.midi.org
[2] https://www.midi.org/specifications/item/bluetooth-le-midi
[3] https://en.wikipedia.org/wiki/MIDI