NOTEMIDI - Linux MIDI Interface For Notebook Computers
Author: Michael Minn (see michaelminn.com for contact info)
October 10, 2002
NOTEMIDI is a Linux interface for MIDI output via the RS-232 serial port on notebook (laptop) computers. NOTEMIDI can be used with external MIDI keyboards/sound modules that have a serial interface (such as the Roland Sound Canvas or Yamaha MU-x series sound modules) or the the MIDIator MS-124W Serial-to-MIDI interface.
1. Introduction
NOTEMIDI has been deprecated for a very long time and I no longer support it.
However, I will continue to make the code available on my site. Laptop users needing MIDI I/O should look into acquiring a USB midi module which can be accessed with the USB-MIDI MIDI driver. I would specifically recommend the Roland UM-1 or UM-2 MIDI interfaces or (if you want high-quality digital audio) the UA-100 from Edirol. You should consult my MMUSBAUDIO page for information on my MIDI/Audio interface for the Roland MIDI products.
If you absolutely must use the serial port, ALSA (Advanced Linux Sound Architecture) provides support for serial port MIDI (with the snd-serial module) and permits access to many internal sound chips and sound cards. I have never tried using ALSA (and from a programming side it looks like a real mess), but at least it is actively supported.
You are welcome to contact me directly with any concerns or questions regarding NOTEMIDI in particular or MIDI/Linux in general: michaelminn.com.
NOTEMIDI is a Linux kernel module that emulates /dev/sequencer and /dev/midi to permits MIDI input/output to/from an external sound module via the standard 9-pin PC RS-232 (modem) serial port. It is specifically appropriate for notebook computers that do not have expansion slots for sound cards with MIDI ports. NOTEMIDI is extremely simple and does not have the confusing overhead and associated with OSS or ALSA. NOTEMIDI is, however, a bit of a kludge in the way it access the serial port code in the kernel, and this may cause problems with future kernel versions.
Because NOTEMIDI implements /dev/sequencer separately from OSS, it does not have the capability to handle MIDI devices other than the serial port. OSS (Open Sound System) does not and (based on my correspondence with them) will not support MIDI via the serial port. If installed correctly, NOTEMIDI should not conflict with OSS and should not affect OSS support for any digital audio (/dev/dsp) devices on your computer.
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.
2. Version History & Download
The current version of NOTEMIDI is written for Red Hat Linux 7.1 and compiles on Red Hat 7.0 (2.2 kernel) as well. Older versions compile on Red Hat Linux 7.0 and 6.2. I cannot guarantee that NOTEMIDI will operate or even compile under any other kernel version or distribution.
The following is a version history and links to downloadable source tarballs.
Modified README.html to reflect no further support
Probably the last official release
Moved tarballs to different directory on michaelminn.com
Major upgrade to emulate /dev/sequencer and /dev/sequencer2 directly without using any OSS kernel sound functions. Also retains raw MIDI device (/dev/midi) capability.
Compiles under Red Hat 7.1 (2.4 kernel) and 7.0 (2.2 kernel).
Works with Jazz++.
Compiles under Red Hat 7.1 (2.4 kernel) or Red Hat 7.0 (2.2 kernel).
Otherwise, identical to version 0.2001.06.02.
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
3. Hardware Installation
Although an unmodified PC RS-232 cannot operate at the MIDI speed of 31.2 Kbaud, the serial port can be used for MIDI I/O either with a sound module/keyboard that provides a serial connection, or using a convertor like the Midiator MS-124W.
3.1 Sound Modules With Serial Port Connections
If you have a keyboard or sound module with a serial port connection (such as the Roland Sound Canvas or Yamaha XG Sound Modules) 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). Such cables are commercially available, but you can also easily 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).
3.2 MIDIator MS-124W
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. This box costs around $200 with cables and shipping. If you have a USB port, you would be much better off using a USB MIDI interface.
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.
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).
4. Software Installation
4.1 Module Installation
Because NOTEMIDI is a kernel module, you must be logged in as SUPERUSER (root) to compile, load and install
Download source tarball (source links are listed above) and gunzip/tar it. This will create a NOTEMIDI source directory.
If you are using an MS124W, you will need to edit notemidi.c prior to compiling and change the NOTEMIDI_IS_MS124W_PROTOCOL from 0 to 1. Otherwise, leave the code alone.
#define NOTEMIDI_IS_MS124W_PROTOCOL 1
Compile and install:
$ cd notemidi $ tar -zxvf notemidi-0.2001.08.17.tar.gz $ cd notemidi $ make install
The standard Linux sound devices all use the OSS sound.o module and therefore have the same "major number" of 14. To have NOTEMIDI connect to these devices, you must make new device nodes. The old devices should be renamed for your convenience in case you need to go back to OSS or ALSA in the future.
mv /dev/sequencer /dev/sequencer-old mv /dev/midi03 /dev/midi03-old mknod --mode=0777 /dev/sequencer c 80 0 mknod --mode=0777 /dev/midi03 c 80 1
The raw MIDI device /dev/midi03 is specifically given above so any other MIDI devices registered with OSS will use /dev/midi00 - /dev/midi02. You can chose any name you want. However, because /dev/sequencer is reconfigured, any OSS MIDI devices that normally use /dev/sequencer will not be able to access any other MIDI devices registered with OSS.
The major number of 80 was arbitrarily chosen for NOTEMIDI and is used in the mknod commands listed above. In case this number is already in use, you can change the NOTEMIDI_MAJOR_NUMBER constant in notemidi.c to another number.
The NOTEMIDI module can be loaded manually with the modprobe command. You can then verify loading by listing /proc/modules:
$ /sbin/modprobe notemidi $ cat /proc/modules
If you want the NOTEMIDI module to load when you access /dev/sequencer or /dev/midi03, add the following line to the bottom of /etc/modules.conf. This file is a cross-reference used by the kernel to determine what module should be loaded to support a given resource - in this case the NOTEMIDI devices you defined earlier with major number 80 which are handled by the NOTEMIDI module.
alias char-major-80 notemidi
4.2 Application Software
NOTEMIDI emulates /dev/sequencer, /dev/sequencer2 and /dev/midi. As such, it should work with any legacy MIDI software that uses /dev/sequencer or new software that provides backwards compatibility to OSS.
NOTEMIDI works with playmidi, the console command (e.g. playmidi -e midi_file.mid) and with kmid, the MIDI/Karaoke player that comes standard with the KDE desktop.
NOTEMIDI underwent a major redesign to work with Jazz++, an excellent MIDI sequencer that also provides support for playing sampled digital audio. The primary configuration issue is changing the ".driver" entry in the jazz.cfg configuration file (in your home directory) to 1 so it uses OSS instead of ALSA or MPU-401 MIDI capability.
.driver 1
I cannot guarantee operation with any other MIDI software. However, I would appreciate any reports of success or failure and will attempt to deal with bug fixes as quickly as possible.
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 through /dev/sequencer or /dev/midi03. MIDI input to the MS-124 input port will also be available. Consult your module documentation for specific details.
4.3 NOTEMIDI Utilities
NOTEMIDI also comes with some simple console command line utilities
notemiditest
Tests NOTEMIDI output by playing a simple 5 note scale to the serial device (/dev/ttyS0), the raw midi port (/dev/midi03) and the sequencer (/dev/sequencer).
notemidiecho [-l] <midi or audio device file>
Echoes MIDI or digital audio input from a device back to the device. Useful for testing connection of a keyboard to a sound module. -l option gives hexadecimal echo to the console
notemidihexdump <output device name>
lists output from a device file in hexadecimal form on the screen. Useful for debugging MIDI input.
notemidiioctl
Lists the numeric IOCTL values used for controlling standard Linux OSS devices. Needed because values listed in /usr/include/linux/soundcard.h are defined with macros that are very difficult to interpret visually.
notemidilist
Lists the status of standard Linux sound device files
notemidiplay <MIDI file name> [<midi device name>]
Plays type 0 MIDI files to a /dev/midi device (default /dev/midi03). Does not use /dev/sequencer. Use the Linux standard playmidi command (with the -e option) if you want to play MIDI files on /dev/sequencer.
notemidiplaywave <wave file name> [<audio device name>]
Plays 44khz stereo .wav files to an audio device (default /dev/dsp). Provided primarily as source code to demonstrate use of the standard Linux OSS DSP commands. Normally the standard "play" command or an X Windows player should be used instead.
notemidiscale <midi device name>
Tests MIDI output by playing a brief five-tone scale to a device
notemiditone [-q] <audio device name> <frequency> <# of samples>
Plays a test tone in 44khz PCM stereo to the specified audio device. -q option gives square wave instead of sine wave. The main audio device is normally /dev/dsp on Linux. Data is sent in .wav file format a header so this option can also be used to create a test tone .wav file.
notemidiwavehead <wave file 1>...
Writes a 44.1 Khz 16bit stereo wave file header to the beginning of each file. Simply uses the file size and does no error checking to validate the actual format of the file contents. Useful for making a corrupted wave file listenable.
5. Implementation Details
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.
5.1 The NOTEMIDI Kernel Module
The serial port device /dev/ttyS0 can only be directly accessed by the superuser (or a kernel module). Also, in order to communicate with a sound module or convertor, the serial port parameters must be set to the correct protocol. NOTEMIDI permits any user to send data to the serial port and handles the setting of parameters. NOTEMIDI can be loaded on demand (by configuring /etc/modules.conf) or manually (with modprobe).
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.
5.2 /dev/sequencer
By far, the messiest part of NOTEMIDI is emulation of the OSS /dev/sequencer device. The Linux Open Sound System (OSS) does not provide a convenient standard API for dynamically loading drivers as loadable modules. Also, because of the way OSS uses interrupts, I found use of the Linux kernel TTY functions impossible. Therefore, the basic capabilities of /dev/sequencer were completely reimplemented.
/dev/sequencer is the multiplexed main device for MIDI I/O with OSS/Free. Unfortunately, this interface is extremely cumbersome and poorly documented, so implementing emulation of this was rather difficult. The definitions for accessing /dev/sequencer in /usr/include/linux/soundcard.h. are basically a set of wrappers for write(), read() and ioctl() calls. All the nonsense with having to define specific buffer variables is unnecessary. Writes and reads to /dev/sequencer need to be in a specific message format that also contains timing information - hence the name sequencer. The supported message formats and ioctl commands may be explored by reviewing the source code in notemidi.c.
Developers are advised to use raw MIDI devices (e.g. /dev/midi01) and provide their own timing mechanisms (e.g. gettimeofday()) rather using /dev/sequencer for future development.
5.3 MS-124 Protocol
NOTEMIDI can also handle conversion of MIDI data to MS-124W format when the NOTEMIDI_IS_MS124W_PROTOCOL is set to 1 at compilation time. 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.
5.4 Direct Module Connection
There is no protocol conversion necessary for modules that are connected directly to the port. MIDI data (without delta time information) is simply sent directly to the serial port. With the configuration specified above, NOTEMIDI provides /dev/midi03 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.
6. Uninstalling NOTEMIDI
You can uninstall NOTEMIDI by typing
make uninstallThis deletes the module file and the NOTEMIDI utilities. If you modified your /etc/module.conf file to load the module on demand, you will want to remove the aliasing line you added.
Dizzy taught me that if you want to just play whatever you want to play without considering the audience, fine. But if you want to get paid, you're now in a different ballgame. (Chuck Mangione)