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).











craig@ccrma.stanford.edu