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 you are using an Arduino board, simplest will be to use Arduino MIDI library, as described in the following sections. You may also use less sophisticated ardumidi library that is provided with ttymidi download package. 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 9600
Where /dev/ttyS0
is the serial port you want to read from,
and 9600
is the bitrate. For Arduino with serial connection
runnning at 115200bps (the default rate for ttymidi)
the command would be:
Arduino Diecimila:
ttymidi -s /dev/ttyUSB0 -v
Arduino UNO:
ttymidi -s /dev/ttyACM0 -v
Where the -v
gives me verbose output, which helps
me when I'm debugging.
ttymidi creates an ALSA MIDI input and output ports 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.
If you are using automated patchbay connecting application, such as
the patchbay feature of qjackctl or
aj-snapshot you might want to rename the name of ttymidi client created by using
-n
flag.
ttymidi -s /dev/ttyUSB0 -v -n my_weird_controller
Programming your serial device
Arduino MIDI library
ttymidi is nowadays compatible with
Arduino MIDI library
and we strongly recommend using it when communicating from Arduino to ttymidi.
You only need to remember to call Serial.begin(int baud_rate)
immediately after MIDI.begin(int channel)
on your patch as
the serial port of your computer is not able to operate at MIDI baud rate
that MIDI library is using. For example:
void setup() { MIDI.begin(4); // will listen incoming MIDI at channel 4 Serial.begin(115200); // will change baud rate of MIDI traffic from 31250 to 115200 }
You'll find MIDI library examples with these changes made in ttymidi download package.
Arduino interface
This chapter explains how to use deprecated (but still functional) ardumidi library instead of Arduino MIDI library. To interface to ttymidi, the serial-attached device must send data in MIDI-format. 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); // Check if a MIDI message has arrived from the PC int midi_message_available(); // Get a MIDI message from the PC MidiMessage read_midi_message(); // Get the pitch bend value from a MIDI message int get_pitch_bend(MidiMessage msg); // 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). The center position of the pitch-bend wheel is 8192.
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.
Similarly, when receiving MIDI messages from the PC, you can use constants to figure out type of the incoming message:
if (midi_message_available() > 0) { MidiMessage msg = read_midi_message(); if (msg.command == MIDI_NOTE_ON && msg.channel == 0) { /* Since this is a "Note On" command, we know that - msg.param1 is the MIDI note - msg.param2 is the "velocity" of the note How do we know this? See the table below. */ } }
There are a couple of things to keep in mind when using MIDI in features of
ardumidi. Firstly midi_message_available()
will always
flush the incoming Serial buffer of all non-MIDI data. In practice this
means that you can't mix using the Serial library and
ardumidi
(unless you know what you are doing). Secondly the incoming Serial buffer
of arduino can store at most 42 MIDI commands so you have to take care
that buffer does not overflow. However this does not cause your patch to crash,
only couple MIDI messages are lost.
To install the ardumidi library, just copy its folder
into Arduino's sketchbook/libraries
directory.
Also note that an example Arduino sketches are included in the
ttymidi package. They should appear under Examples
in Arduino IDE after you have succesfully installed the library.
For instance, ardumidi_test
, will play one 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 MIDI specification. To sum this up, most of the commands sent to ttymidi are comprised of 3 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 | - |
channel pressure | 0xD0-0xDF | value | - |
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). For channel pressure and program change you
should send only one data byte.
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
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 (or 1) 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, examples
for Arduino MIDI library 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
- Arduino MIDI library
- 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
Authors
- Thiago Teixeira
Changelog
- 0.60