How to send MIDI bytes to an external synthesizer from Linux
The Open Sound System (OSS) drivers for Linux has two ways of sending MIDI
bytes out to external synthesizers:
- Output Method 1:
- for sending raw MIDI bytes with the write() function,
using the devices "/dev/midi??", where ?? is the
numbering from "00" to "04" usually.
"/dev/midi" is a device which is a symbolic link to one
of the midi?? devices (usually to "/dev/midi00")
intended as a default MIDI device.
- Output Method 2:
- for sending raw MIDI bytes via packets with the write() function
using the device "/dev/sequencer". The packet for sending a
MIDI byte with "/dev/sequencer" consists of four unsigned
characters:
- byte 0:
- device command byte tells the sequencer device what type of
packet is being written. For example, writing a MIDI byte
would use the MIDI_PUTC (5) command.
- byte 1:
- the actual MIDI byte to be sent.
- byte 2:
- the internal device number of /dev/sequencer which
specifies which MIDI output device connected to the sequencer
driver to which you can send MIDI output to.
- byte 3:
- always is 0.
Here is a short example of how to send a Middle C note-on MIDI message with Method 1.
This example assumes that /dev/midi is a valid MIDI output device.
Example 1: using /dev/midi to send a MIDI message.
(method1.c).
|
#include <linux/soundcard.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
int main(void) {
char* device = "/dev/midi" ;
unsigned char data[3] = {0x90, 60, 127};
// step 1: open the OSS device for writing
int fd = open(device, O_WRONLY, 0);
if (fd < 0) {
printf("Error: cannot open %s\n", device);
exit(1);
}
// step 2: write the MIDI information to the OSS device
write(fd, data, sizeof(data));
// step 3: (optional) close the OSS device
close(fd);
return 0;
}
|
|
When I run this program, the note Middle C is played on the external
synthesizer, and lasts for one second (since the driver turns it off
one second after closing the device it seems).
With Method 1, it does not seem possible to access the MIDI synthesizers
available on the internal soundcard.
Using only method 1, you could figure out how many MIDI output devices are
available by searching the /dev directory for devices that start
with "midi" and end in a two-digit number, e.g. "00".
You could then try to open each one of the listed devices to see if they
are allowable. If you open with the open() function and the
returned file descriptor is -1, then you know that the devices
is already open somewhere else, or it is not a valid MIDI output.
Shown below is a short example using Method 2. This example assumes
that device 0 is a valid MIDI output device. This example does the same
thing as Example 1 (sends out one MIDI note-on message).
Example 2: using /dev/sequencer to send a MIDI message.
(method2.c).
|
#include <linux/soundcard.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
int main(void) {
char* device = "/dev/sequencer";
unsigned char devnum = 0;
unsigned char packet[4] = {SEQ_MIDIPUTC, 0, devnum, 0};
// step 1: open the OSS device for writing
int fd = open(device, O_WRONLY, 0);
if (fd < 0) {
printf("Error: cannot open %s\n", device);
exit(1);
}
// step 2: write the note-on message as done in prior example.
packet[1] = 0x90; // note-on command
write(fd, packet, sizeof(packet));
packet[1] = 60; // middle c
write(fd, packet, sizeof(packet));
packet[1] = 127; // attack velocity
write(fd, packet, sizeof(packet));
// step 3: (optional) close the device
close(fd);
return 0;
}
|
|
The only difference between Example 2 and Example 1 is that when Example 2 finishes
executing the driver's note off for middle C is send immediately (total duration about 100 ms
as opposed to around 1000 ms for Example 1 code).