Author: Michael Minn <michael@michaelminn.com>
Version 0.2001.06.02 - June 2, 2001
The options for getting MIDI into and out of a Linux laptop are still relatively limited as of this writing. Laptop computers do not have PCI slots for connecting sound cards and most internal sound chips no longer have FM synthesis. Software synthesis is common, but relatively limited in quality. USB MIDI products are available for Windows, but Linux drivers are just beginning to emerge since manufacturers are loathe to release specs so the open source community can develop drivers.
However, the RS-232 serial port that is still incorporated into most laptops can be used for MIDI output and input. Although an unmodified PC RS-232 cannot operate at the MIDI speed of 31.2 Kbaud, there are two simple hardware options for MIDI with an external sound module via the serial port:
If you have ALSA (www.alsa-project.org), there is supposedly support for serial port MIDI in ALSA. I've never tried it, but you may want to investigate this if you've got ALSA and you're using a Roland Sound Canvas or Yamaha MU sound module. The connecting cable information given below may be of value.
The NOTEMIDI device driver (kernel module) was conceived with notebook computers in mind, since even the most rudimentary desktop soundcards provide MIDI output in some form. However, the NOTEMIDI device driver can be used with any computer running Linux that has an 9-pin RS-232 serial port.
I would appreciate notification of any bugs, problems or successes using NOTEMIDI.
I am deeply indebted to John Stone for pointing me in the right direction in this project. He has written MIDID, another method (with a daemon and message queues) of accessing the MS-124W. Use of his software is described later in this document.
The current version of NOTEMIDI is written for Red Hat Linux 7.1. Older versions work on Red Hat Linux 7.0 and 6.2. I cannot guarantee that it will operate or even compile under any other kernel version or distribution.
The following is a version history and links to downloadable source tarballs.
Compiles under Red Hat 7.1 (2.4 kernel)
Fixed bugs in OSS registration that caused /dev/sequencer to crash OSS when opened and that caused "Aiee, killing interrupt handler" system crash.
MIDI input from /dev/midiXX. No MIDI input through /dev/sequencer.
Compiles under Red Hat 7.0
Integrated into the Linux Sound System: accessible via /dev/midi00 and /dev/midi01 and displays under /dev/sndstat.
Uses serial port (tty) write function directly.
Compiles under Red Hat 7.0
Bug fixes from previous version.
For some unknown reason, MIDI input no longer works under Red Hat 7.0
Working version for Red Hat 6.2
Added port configuration (termios) code to noteplay and noterecord so they can be used directly with the serial port (/dev/ttyS0).
Changed NOTEPLAY & NOTERECORD command line options to enable routing to a port with or without MS-123W protocol
Added SETUID bit to "make install" option so a non-superuser can use noteplay, noterecord directly to the serial port.
Added a "make uninstall" option
Initial buggy release for Red Hat 6.2
If you have a Roland Sound Canvas or Yamaha XG Sound Module you can connect them directly to the RS-232 serial port via a cable that connects a 8-pin MINI DIN (aka Macintosh serial cable) to 9-Pin D-SUB (RS-232). I haven't seen a commercially available cable but I believe you can connect a Macintosh serial cable with a 25-pin RS-232 via a NULL modem connector to a 25-pin to 9-pin convertor. You CAN NOT use a Mac modem cable with gender convertors to RS-232...the pins are wired backwards.
If you have a soldering iron and a Radio Shack handy, I would just get a Mac serial cable, cut the end off, get a 9-pin female plug from Radio Shack and connect the wires like this.
DIN pin 1 = D-SUB pin 8 (CTS)
DIN pin 2 = D-SUB pin 7 (RTS)
DIN pin 3 = D-SUB pin 2 (RxD)
DIN pin 4 & 8 = D-SUB pin 5 (GROUND)
DIN pin 5 = D-SUB pin 3 (TxD)
The pin numbers for the DIN (Mac) plug should be barely visible in small raised letters under good light.
Once you've bought or created your cable, connect the sound module to the PC. On a Roland sound module, set the MIDI select switch on the back panel to PC, (not Mac, MIDI, or USB). On a Yamaha sound module, set MIDI input to PC-2 (38,400 baud) NOT PC-1 (Mac). After changing the sound module switch to/from MIDI/PC, you should restart the sound module (turn off and turn on again).
If you're in the market for a sound module (tone generator), I highly recommend the Roland SC-8850, sold in the United States by Edirol. It's a bit expensive ($900) but worth it...although the string sounds aren't great.
If you visit the Edirol site, you might also e-mail them with a request that they write Linux drivers for their UA-100 USB sound interface. It's a wonderfully clean 20-bit A/D, D/A with built-in effects and MIDI in/out. In an e-mail in July, 2000, a rep indicated that they were not ruling out the creation of Linux drivers but were not planning on writing them anytime soon. Perhaps a little expression of market interest will nudge them in our direction.
If you're using something other than a Roland or Yamaha sound module (or some other module that has a serial input port) you can use the MIDIator MS-124W. The MIDIator MS-124W is available from Midiator Systems.
Note that this is NOT the plain MS-124 (a lower end and cheaper product) or the MS-124T (which is slower, has no MIDI input, and has no addressable MIDI output). The baud rates are different and therefore will not work with the NOTEMIDI driver...although you might be able to hack my code and get it to work.
This box costs around $200 with cables and shipping. On my Toshiba 2555DVD the module was successfully parasitically powered, so I didn't need the power adapter...you may want to get it just in case. You should also get the connecting cable just to make sure you get a cable with the right pin assignments.
The MODE switches on the MS-124W should be set to "M" and "B" (multiple burst mode).
Download the source tarball and gunzip/tar it. This will create a NOTEMIDI directory:
$ tar -zxvf notemidi-0.2001.05.21.tar.gz
Because NOTEMIDI is a kernel module, you must be logged in as SUPERUSER (root) to compile and load.
You will need to install the kernel source (i.e. the RPM from your Red Hat distribution disk) in order to compile NOTEMIDI. Because the Linux Sound System (OSS) cannot normally recognize drivers loaded as modules, NOTEMIDI directly calls OSS kernel functions that are only defined in the source code headers. While this opens the possibility of problems with future changes to the kernel, this seems to be the only way of registering driver functions in a way that they display on /dev/sndstat and use the /dev/midi* devices.
When you have the source installed, compile and install NOTEMIDI:
$ make install
If the compilation and installation succeeds, you will have a loaded notemidi.o module. You can verify this with:
$ cat /proc/modules
You should also verify that the module successfully registered itself with the Linux Sound System:
$ notemidiecho
Assuming you have no other MIDI devices registered on your system, you should get the following listing in the middle of the output:
Midi devices: 0: NOTEMIDI 1: MS-124W
This indicates that you have two devices for sending MIDI. If you have other MIDI devices attached, the numbers may be different. For the example given above:
/dev/midi00 (NOTEMIDI) is the device you should use if you are connecting a sound module such as the Yamaha MU series or Roland Sound Canvas series MIDI module directly to the serial port. Writing to this device sends the data directly to the serial port with no protocol modification.
/dev/midi01 (MS-124W) is the device you should use if you are using an MS-124W. It sends a "burst byte" prior to each MIDI byte.
You should now be able to play MIDI files from any Linux MIDI player, such as KMID or playmidi (with the -e option).
NOTEMIDI permits MIDI input through /dev/midiXX, where XX is the number of one of the two MIDI devices assigned to NOTEMIDI. Since there is no input protocol associated with the MS-124W, input can come through either device.
Because /dev/sequencer implements MIDI output with a kernel timer, I could not find a way to implement a second timer to poll the input port for incoming data. Therefore, no midi input is available through /dev/sequencer and any attempt to read from /dev/sequencer will simply block.
If you have a Roland Sound Canvas or Yamaha MU-XX series sound module, if connected as described above, any MIDI input sent to the module's MIDI IN ports will be echoed to the serial connection and therefore will be available to NOTEMIDI.
I have not tested this feature extensively and would appreciate any feedback on it's success or failure.
NOTEMIDI is extremely simple. If all you want to do is play simple MIDI files, the instructions given above should be sufficient. However, the following information is provided for those who want or need to know more about this software. A thorough examination of the source code may also be helpful.
Since the serial port device /dev/ttyS0 can only be directly accessed by the superuser (or a kernel module), NOTEMIDI permits any user to send data to the serial port. NOTEMIDI is loaded at boot time so MIDI access is available instantly when the user logs in.
Because the standard UNIX open/write/read/close functions are not available to kernel modules, I had to use the filp_open() function to access the serial port and then dereferenced the tty_struct driver functions from the file pointer for writing. This is a very non-portable way of solving this problem, but I couldn't figure out any other technique. Unfortunately, there is little module programming information on the web. The best resource for module programming is the book, "Linux Device Drivers" by Alessandro Rubini and published by O'Reilly.
The NOTEMIDI module simply relays MIDI data to the Linux Serial Port device /dev/ttyS0. While this may not be the safest way to deal with the serial port, controlling the serial port is relatively complex and since the code for supporting the serial port is already part of the kernel, I see no reason to reinvent the wheel. More information on the serial port is available in the Serial Port HOWTO.
NOTEMIDI can also handle conversion of MIDI data to MS-124W format through a second device, /dev/midi01.
MIDIator, unlike many hardware vendors, has been extremely helpful in providing information on their products and programming information for the MS-124W is available both as a flyer that comes with the device and online from Midiator Systems.
There are three different modes of operation, selected by the two panel switches on the unit. NOTEMIDI uses the simplest (and the one that requires no complex interrupt handling: MULTIPORT BURST MODE. Each MIDI output byte requires sending two bytes: a BURST BYTE specifying which of the four output ports to use, and a data byte. Although this effectively halves the potential transfer rate, to 19K baud, it avoids the complex handshaking techniques needed for the other two modes.
The BURST BYTE has the format:
pppp1000
where each bit of pppp represents one of the four output ports. /dev/ms124w sends 1111100, therefore routing each data byte to all four ports simultaneously. /dev/ms124w1, /dev/ms124w2, /dev/ms124w3, /dev/ms124w4 send burst bytes 10001000, 01001000, 00101000, and 00011000, respectively. Programmers could easily implement this themselves in their own software by accessing the serial port device file /dev/ttyS0 or the "plain" NOTEMIDI port /dev/notemidi directly.
Since the serial port operates at 38.4 Baud (versus MIDI rate of 31.25) there would be no parallel advantage to operating out of multiple ports to avoid MIDI choke. Therefore, I have not permitted multiple devices to be opened simultaneously. Of course, you could implement this yourself by sending data to /dev/midi00 and handling sending the burst byte yourself.
There is no protocol conversion necessary for the Roland & Yamaha serial interfaces. MIDI data (without delta time information, of course) is simply sent directly to the serial port. NOTEMIDI provides /dev/midi00 for direct access, since a program would have to be run as superuser (or have the setuid bit on) to directly access the Linux serial port device /dev/ttyS0.
For modules with multiple internal "parts" (i.e. separate 16-channel synths), such as the SC-8850 with four (yielding 64 possible channels), Roland implements the undefined MIDI code F5 as a two-byte MIDI command for part selection. F5 should be sent, followed by a byte that selects the part: F500 for no selection, F501 for part 1, F502 for part 2, etc. All subsequent MIDI data will be played by the selected part.
The Linux Open Sound System (OSS) does not provide a convenient standard API for dynamically loading drivers as loadable modules. Simple use of the register_sound_midi() function will reserve a /dev/midiXX device but will not register any information that can be read from /dev/sequencer. Therefore, a user cannot know which device is connected to which /dev/midi port.
Therefore, NOTEMIDI is integrated into OSS by directly calling OSS kernel functions and directly using OSS kernel variables. Since the necessary declarations are only defined in include files that are part of the kernal source tree, the kernel source must be loaded before NOTEMIDI can be compiled.
The comments in the source code attempt to explain what I've done. It's a rather embarrasing kludge, and if you know a better way I'd welcome suggestions.
You can uninstall NOTEMIDI by typing "make uninstall" in the source directory. You will need to make a minor change to the /etc/rc.d/rc.local file. Remove the following lines. They should be somewhere near the bottom of the file.
/sbin/insmod soundlow /sbin/insmod sound /sbin/insmod -f notemidi
There are a number of sites on the web offering other options for MIDI output. However, most of them involve building hardware and that led me to the MS-124W. Hopefully, USB MIDI drivers will be available in the near future, making NOTEMIDI obsolete.
John Stone has written MIDID, another method (with a daemon and message queues) of accessing the MS-124W. It seems a bit complex for my tastes, but if you're not having any success with NOTEMIDI, or you're trying to get MIDI out of another UNIX platform, you may want to investigate this further.
He has provided instructions for installation. I have not tried the most recent version, but I am including my experiences with a previous version in case you need further guidance.
Download the software into your home directory from:
http://jedi.ks.uiuc.edu/~johns/projects/midid/
Gunzip and un-tar creates a "midid" directory. Make creates the executables quickly and flawlessly.
gunzip midid.tar.gz tar -xfv midid.tar cd midid make
Create a text file with a single line. This maps the Midiator interface to the serial port (i.e. /dev/ttyS0 or COM1). I named it "/home/michael/.midid"
"Midiator-MS-124W" "/dev/ttyS0"
Kick off the midi daemon with the config file you just created.
cd daemon ./midid /home/michael/.midid
You can then play midi files with midiplay:
seq/midiplay [your_file].mid
The version of midiplay I got from an outdated site had problems with tempos and type 0 files (which is what I use exclusively). John has stated that the current version of MIDID has fixed these problems.