ttymidi

In a nutshell
ttymidi is a GPL-licensed program that allows external serial devices to interface with ALSA MIDI applications. The main motivation behind ttymidi was to make Arduino boards talk to MIDI applications without the need to use (or build) any extra hardware.
Usage
If are using an Arduino board, you must first program it with the provided MIDI library, as described in the next section. If you are using another device, you should read the rest of this page to see how your device should communicate. Once your device is programmed and connected to your PC, ttymidi is executed in the following manner:
ttymidi -s /dev/ttyS0 -b 2400
Where /dev/ttyS0
is the serial port you want to read from,
and 2400
is the bitrate. For my Arduino, I use the USB port
at 115200bps (the default rate for ttymidi):
ttymidi -s /dev/ttyUSB0 -v
Where the -v
gives me verbose output, which helps
me when I'm debugging.
ttymidi creates an ALSA MIDI output port that can be interfaced to any compatible program. This is done in the following manner:
# start ttymidi ttymidi -s /dev/ttyUSB0 & # start some ALSA compatible MIDI # program (timidity, in this case) timidity -iA & # list available MIDI input clients aconnect -i # list available MIDI output clients aconnect -o # connect aconnect 128:0 129:0 # ...where 128 and 129 are the client # numbers for ttymidi and timidity, # found with the commands above
If you would like to use a graphical interface to connect your MIDI clients, you can use something like qjackctl. As for the program that will consume the MIDI data, there are many out there (other than timidity, which was used in the previous example). Some crowd pleasers are fluidsynth, puredata, sooperlooper and ardour, to cite a few.
Programming your serial device
Arduino interface
To interface to ttymidi, the serial-attached device must send data in a specific MIDI-like format, which has only a few small differences from the MIDI specification. In the case of Arduino boards, a library is provided that abstracts all the nitty-gritty details away. Below is a list of the available functions:
// Start/stop playing a certain note: midi_note_on(byte channel, byte key, byte velocity); midi_note_off(byte channel, byte key, byte velocity); // Change pressure of specific keys: midi_key_pressure(byte channel, byte key, byte value); // Change controller value (used for knobs, etc): midi_controller_change(byte channel, byte controller, byte value); // Change "program" (change the instrument): midi_program_change(byte channel, byte program); // Change key pressure of entire channels: midi_channel_pressure(byte channel, byte value); // Change pitch-bend wheel: midi_pitch_bend(byte channel, int value); // Send a comment: midi_comment(char* str); // Send a series of bytes (to be interpreted by another program): midi_printbytes(char* bytes, int len);
Where the parameters are in the range: channel (0–15), pitch-bend value (0–16383), all other values (0–127).
Since MIDI uses numbers to represent notes, a few useful constants are defined in this library. With them, it is much easier to deal with MIDI nodes. For example:
midi_note_on(0, MIDI_C + MIDI_SHARP - 2*MIDI_OCTAVE, 127)
All notes refer to the 4th octave by default. So the line above
plays a C#2. As a shortcut to the 1st octave, constants such as
MIDI_C0
can be used.
To install the ardumidi library, just copy its folder
into Arduino's hardware/libraries
directory.
Also note that an example Arduino sketch is included in the
ttymidi package. The file is called
ardumidi_test
, and is ready to be uploaded to your
Arduino board. If everything works well, you should hear a C-minor
chord every second.
General interface
If you are using another serial device in place of the Arduino, you'll need to program it to follow the specification described here. Every command sent to ttymidi is comprised of 3 bytes (whereas in the MIDI spec some commands consist of 2 bytes):
byte 1 byte 2 byte 3 status parameter #1 parameter #2
Where status
is a combination of a command
and a
channel
. Why is it called status? I haven't a clue, but that's
the name in the MIDI spec. The table below describes the codes for each
command as well as their associated parameters.
code | parameter #1 | parameter #2 | |
---|---|---|---|
note off | 0x80-0x8F | key | velocity |
note on | 0x90-0x9F | key | velocity |
pressure | 0xA0-0xAF | key | pressure |
controller change | 0xB0-0xBF | controller | value |
program change | 0xC0-0xCF | program | 0 |
channel pressure | 0xD0-0xDF | value | 0 |
pitch bend | 0xE0-0xEF | range LSB | range MSB |
bytes | 0xFF | 0 | 0 |
Most of these commands and parameters are self-explanatory. All parameters
are given as a number in the range 0–127. That is, they're all 7-bit
numbers with a 0 padded to their left (i.e. 0xxxxxxx
) in order
to make up 1 full byte (8 bits).
One odd MIDI command is the pitch bend
, whose parameter is a
14-bit number. For this reason, it is split into two parts: a least
significant byte (LSB) and a most significant byte (MSB). These can be
easily computed by quick logical and shift operations:
int range = 12345; byte range_lsb = range & 0x7F; byte range_msb = range >> 7;
The bytes
command provides a way to send non-MIDI data
through the serial port without messing up with ttymidi.
All you need to do is send 0xFF 0x00 0x00 len data[0] data[1] ...
,
where len
is the number of data[•]
in
the message. When seeing such messages, ttymidi will
just print them to the screen (but not parse them), so you can use this
to print comments from your serial device. You can also use it with
sprintf
for debugging.
You may have noticed that, for all commands, the 1st byte always has a 1 as the most-significant bit, while the other 2 bytes always have a 0. This comes from the MIDI spec, and is used by ttymidi for data alignment purposes. Do not try to change that in your serial device's program, or it will royally mess things up.
Downloads
The archive includes the ttymidi program as
well as the ardumidi libraries for Arduino. Also, don't
forget to read the README
file in that is included in the
archive. It has important information about compiling ttymidi.
It is possible that a more recent version is available at the project's trunk series.
Found a Bug?
If you find a bug, please report it! I especially like when the report comes with a patch :) but that's not a requirement.
Links
- Arduino
- How does MIDI work? — by Indiana University's CECM
- Arduino MIDI output board — a physical alternative to ttymidi
- Matthias Nagorni's website — examples for ALSA programming
- QJackCtl
- Timidity++
- Fluidsynth
- Puredata
- Sooperlooper
- Ardour
Changelog
- 0.30