USBMIDI
USBMIDI class hierarchy
You can use the USBMIDI interface to send and receive MIDI messages over USB using the standard USB-MIDI protocol.
Examples of tasks you can perform using this library include sending MIDI messages to a computer (such as to record in a sequencer, or trigger a software synthesiser) and receiving messages from a computer (such as actuating things based on MIDI events).
USBMIDI class reference
Public Member Functions | |
USBMIDI (bool connect_blocking=true, uint16_t vendor_id=0x0700, uint16_t product_id=0x0101, uint16_t product_release=0x0001) | |
Basic constructor. More... | |
USBMIDI (USBPhy *phy, uint16_t vendor_id, uint16_t product_id, uint16_t product_release) | |
Fully featured constructor. More... | |
virtual | ~USBMIDI () |
Destroy this object. More... | |
bool | ready () |
Check if this class is ready. More... | |
void | wait_ready () |
Block until this device is configured. More... | |
bool | write (MIDIMessage m) |
Send a MIDIMessage. More... | |
bool | readable () |
Check if a message can be read. More... | |
bool | read (MIDIMessage *m) |
Read a message. More... | |
void | attach (mbed::Callback< void()> callback) |
Attach a callback for when a MIDIEvent is received. More... | |
void | init () |
Initialize this instance. More... | |
void | deinit () |
Power down this instance. More... | |
bool | configured () |
Check if the device is configured. More... | |
void | connect () |
Connect a device This method can also be used to resume USB operation when USB power is detected after it was suspended via USBDevice::deinit. More... | |
void | disconnect () |
Disconnect a device. More... | |
void | sof_enable () |
Enable the start of frame interrupt. More... | |
void | sof_disable () |
Disable the start of frame interrupt. More... | |
bool | endpoint_add (usb_ep_t endpoint, uint32_t max_packet, usb_ep_type_t type, mbed::Callback< void()> callback=nullptr) |
Add an endpoint. More... | |
template<typename T > | |
bool | endpoint_add (usb_ep_t endpoint, uint32_t max_packet, usb_ep_type_t type, void(T::*callback)()) |
Add an endpoint. More... | |
void | endpoint_remove (usb_ep_t endpoint) |
Remove an endpoint. More... | |
void | endpoint_remove_all () |
Remove all non-zero endpoints. More... | |
void | endpoint_stall (usb_ep_t endpoint) |
Stall an endpoint. More... | |
void | endpoint_unstall (usb_ep_t endpoint) |
Un-stall an endpoint. More... | |
uint32_t | endpoint_max_packet_size (usb_ep_t endpoint) |
Get the current maximum size for this endpoint. More... | |
void | endpoint_abort (usb_ep_t endpoint) |
Abort the current transfer on this endpoint. More... | |
bool | read_start (usb_ep_t endpoint, uint8_t *buffer, uint32_t size) |
start a read on the given endpoint More... | |
uint32_t | read_finish (usb_ep_t endpoint) |
Get the status of a read. More... | |
bool | write_start (usb_ep_t endpoint, uint8_t *buffer, uint32_t size) |
Write a data to the given endpoint. More... | |
uint32_t | write_finish (usb_ep_t endpoint) |
Get the status of a write. More... |
Protected Member Functions | |
virtual void | callback_state_change (DeviceState new_state) |
Called when USB changes state. More... | |
virtual void | callback_request (const setup_packet_t *setup) |
Called by USBDevice on Endpoint0 request. More... | |
virtual void | callback_request_xfer_done (const setup_packet_t *setup, bool aborted) |
Called by USBDevice on data stage completion. More... | |
virtual void | callback_power (bool powered) |
Called by USBDevice layer on power state change. More... | |
virtual void | callback_sof (int frame_number) |
Called by USBDevice layer on each new USB frame. More... | |
virtual void | callback_reset () |
Called by USBDevice layer on bus reset. More... | |
void | complete_request (RequestResult result, uint8_t *data=NULL, uint32_t size=0) |
Called to complete the setup stage of a callback request. More... | |
void | complete_request_xfer_done (bool success) |
Called to complete the data stage of a callback request. More... | |
void | complete_set_configuration (bool success) |
Called to complete a set configuration command. More... | |
void | complete_set_interface (bool success) |
Called to complete a set interface command. More... | |
uint8_t * | find_descriptor (uint8_t descriptor_type, uint8_t index=0) |
Find a descriptor type inside the configuration descriptor. More... | |
const usb_ep_table_t * | endpoint_table () |
Get the endpoint table of this device. More... | |
virtual void | start_process () |
Callback called to indicate the USB processing needs to be done. More... | |
virtual void | lock () |
Acquire exclusive access to this instance USBDevice. More... | |
virtual void | unlock () |
Release exclusive access to this instance USBDevice. More... | |
virtual void | assert_locked () |
Assert that the current thread of execution holds the lock. More... |
The two examples below use a program called "Anvil Studio 32-bit" to play MIDI notes from an Mbed board through the host PC. You can play back the MIDI notes through headphones or speakers by following the steps below:
- Flash the board, and ensure the target's USB is plugged into the PC.
- Open Anvil Studio.
- Click View > Synthesizers, MIDI + Audio Devices.
- Uncheck Synth is too slow to echo incoming events.
- Click View > Composer (Staff Editor) to see notes from the board being mapped to the sheet music.
USBMIDI example
Below is an example to send a series of MIDI notes to the host PC:
/*
* Copyright (c) 2006-2020 Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*/
#include "mbed.h"
#include "USBMIDI.h"
USBMIDI midi;
int main()
{
while (1) {
for (int i = 48; i < 83; i++) { // send some messages!
midi.write(MIDIMessage::NoteOn(i));
ThisThread::sleep_for(250);
midi.write(MIDIMessage::NoteOff(i));
ThisThread::sleep_for(500);
}
}
}
Play "Take Me Out to the Ball Game" example
You can use USBMIDI to play an entire song, not just a series of notes. "Take Me Out to the Ball Game" is a popular song in the public domain. To play "Take Me Out to the Ball Game" (public domain) using MIDI over USB on the host PC:
/*
* Copyright (c) 2006-2020 Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*/
#include "mbed.h"
#include "USBMIDI.h"
#define REST -1
#define C 0
#define Cs 1
#define D 2
#define Ds 3
#define E 4
#define F 5
#define Fs 6
#define G 7
#define Gs 8
#define A 9
#define As 10
#define B 11
#define OCTAVE0 0
#define OCTAVE1 12
#define OCTAVE2 24
#define OCTAVE3 36
#define OCTAVE4 48
#define OCTAVE5 60
#define OCTAVE6 72
#define OCTAVE7 84
#define WHOLE_NOTE 1150
#define HALF_NOTE (WHOLE_NOTE / 2)
#define QUARTER_NOTE (WHOLE_NOTE / 4)
#define EIGHTH_NOTE (WHOLE_NOTE / 8)
#define SIXTEENTH_NOTE (WHOLE_NOTE / 16)
#define THREE_EIGHTHS_NOTE (EIGHTH_NOTE * 3)
#define THREE_FORTHS_NOTE (QUARTER_NOTE * 3)
USBMIDI midi;
void PlayNote(int note, int octave, uint32_t duration)
{
if (note == REST) {
ThisThread::sleep_for(duration);
} else {
midi.write(MIDIMessage::NoteOn(note + octave));
ThisThread::sleep_for(duration);
midi.write(MIDIMessage::NoteOff(note + octave));
}
}
void TakeMeOutToTheBallGame()
{
//https://www.bethsnotesplus.com/2012/09/take-me-out-to-ball-game.html
PlayNote(C, OCTAVE5, HALF_NOTE);
PlayNote(C, OCTAVE6, QUARTER_NOTE);
PlayNote(A, OCTAVE5, QUARTER_NOTE);
PlayNote(G, OCTAVE5, QUARTER_NOTE);
PlayNote(E, OCTAVE5, QUARTER_NOTE);
PlayNote(G, OCTAVE5, THREE_FORTHS_NOTE);
PlayNote(D, OCTAVE5, THREE_FORTHS_NOTE);
PlayNote(C, OCTAVE5, HALF_NOTE);
PlayNote(C, OCTAVE6, QUARTER_NOTE);
PlayNote(A, OCTAVE5, QUARTER_NOTE);
PlayNote(G, OCTAVE5, QUARTER_NOTE);
PlayNote(E, OCTAVE5, QUARTER_NOTE);
PlayNote(G, OCTAVE5, THREE_FORTHS_NOTE);
PlayNote(G, OCTAVE5, HALF_NOTE);
PlayNote(REST, 0, QUARTER_NOTE);
PlayNote(A, OCTAVE5, QUARTER_NOTE);
PlayNote(Gs, OCTAVE5, QUARTER_NOTE);
PlayNote(A, OCTAVE5, QUARTER_NOTE);
PlayNote(E, OCTAVE5, QUARTER_NOTE);
PlayNote(F, OCTAVE5, QUARTER_NOTE);
PlayNote(G, OCTAVE5, QUARTER_NOTE);
PlayNote(A, OCTAVE5, HALF_NOTE);
PlayNote(F, OCTAVE5, QUARTER_NOTE);
PlayNote(D, OCTAVE5, THREE_FORTHS_NOTE);
PlayNote(A, OCTAVE5, HALF_NOTE);
PlayNote(A, OCTAVE5, QUARTER_NOTE);
PlayNote(A, OCTAVE5, QUARTER_NOTE);
PlayNote(B, OCTAVE5, QUARTER_NOTE);
PlayNote(C, OCTAVE6, QUARTER_NOTE);
PlayNote(D, OCTAVE6, QUARTER_NOTE);
PlayNote(B, OCTAVE5, QUARTER_NOTE);
PlayNote(A, OCTAVE5, QUARTER_NOTE);
PlayNote(G, OCTAVE5, QUARTER_NOTE);
PlayNote(E, OCTAVE5, QUARTER_NOTE);
PlayNote(D, OCTAVE5, QUARTER_NOTE);
PlayNote(C, OCTAVE5, HALF_NOTE);
PlayNote(C, OCTAVE6, QUARTER_NOTE);
PlayNote(A, OCTAVE5, QUARTER_NOTE);
PlayNote(G, OCTAVE5, QUARTER_NOTE);
PlayNote(E, OCTAVE5, QUARTER_NOTE);
PlayNote(G, OCTAVE5, THREE_FORTHS_NOTE);
PlayNote(D, OCTAVE5, HALF_NOTE);
PlayNote(D, OCTAVE5, QUARTER_NOTE);
PlayNote(C, OCTAVE5, HALF_NOTE);
PlayNote(D, OCTAVE5, QUARTER_NOTE);
PlayNote(E, OCTAVE5, QUARTER_NOTE);
PlayNote(F, OCTAVE5, QUARTER_NOTE);
PlayNote(G, OCTAVE5, QUARTER_NOTE);
PlayNote(A, OCTAVE5, THREE_FORTHS_NOTE);
PlayNote(A, OCTAVE5, QUARTER_NOTE);
PlayNote(A, OCTAVE5, QUARTER_NOTE);
PlayNote(B, OCTAVE5, QUARTER_NOTE);
PlayNote(C, OCTAVE6, THREE_FORTHS_NOTE);
PlayNote(C, OCTAVE6, THREE_FORTHS_NOTE);
PlayNote(C, OCTAVE6, QUARTER_NOTE);
PlayNote(B, OCTAVE5, QUARTER_NOTE);
PlayNote(A, OCTAVE5, QUARTER_NOTE);
PlayNote(G, OCTAVE5, QUARTER_NOTE);
PlayNote(Fs, OCTAVE5, QUARTER_NOTE);
PlayNote(G, OCTAVE5, QUARTER_NOTE);
PlayNote(A, OCTAVE5, THREE_FORTHS_NOTE);
PlayNote(B, OCTAVE5, THREE_FORTHS_NOTE);
PlayNote(C, OCTAVE6, THREE_FORTHS_NOTE);
PlayNote(C, OCTAVE6, HALF_NOTE);
PlayNote(REST, 0, QUARTER_NOTE);
}
int main()
{
while (1) {
TakeMeOutToTheBallGame();
}
}