Well, actually, there are 3 libraries.
The main one is
e/midi, which defines all the necessary types, abstractions (and also some helpers for common use cases).
And there are also
e/usb-midi, which implement actual MIDI I/O communications over Serial and USB.
Here is how to use them.
Creating MIDI messages
You can create a message by specifying a type, channel and data bytes using a
e/midi/message node. There are also helper nodes for common message types like
pitch-bend. And, of course, you can create other ones yourself!
Sending and receiving messages
e/midi only defines generic
There are a few other alternative transport methods besides the good old 5-pin DIN, and I want to make message processing logic be as decoupled from them as possible.
For now, two are supported:
e/serial-midi for communication on the serial ports and
e/usb-midi for communication over USB. The next one should probably be a wrapper around something like Arduino-AppleMIDI-Library (and I would love if someone would help with that ).
Let’s say you want to make a simple controller that will act a a mod wheel:
If you have a board with native USB support (like Arduino Leonardo) and want to make a USB controller, place a
e/usb-midi/usb-midi node and connect it to
MIDI input. And it you want to switch it for an old-school 5-pin DIN connection over serial, just replace
usb-midi with one of
serial-midi nodes from
e/serial-midi. Generic nodes are awesome!
Unpacking and processing messages
To extract status and data bytes from
e/midi has a
filter-by-channel node that only lets through messages with a specified channel (and is an example on how to deal with messages in C++)
e/midi also includes some helper nodes that extract data from specific messages and ignore the rest (
Here is how to control a servo with ModWheel CC messages sent over the 1st channel:
As with message-creating nodes, the included message-processing helpers are absolutely not meant to cover all the possible use cases. But as long you use
e/midi/message type, all additional helper libraries will be compatible with each other (and with future additional/alternative transport implementations)!