.... for Linux, anyway. (It may or may not be possible under other systems.
Personally I'm using BeOS/Haiku as one end of the link, but that's only because
I have my own module to translate the internal MIDI stream format into serial
bytes.) The rest of this note is highly Linux-specific, so skip it if you're
using something else.
I thought it might be interesting to post a piece about this, because the
possibility -- or rather the ease of doing it -- didn't occur to *me* until
recently! It doesn't require any custom software, just a couple of readily
The nice thing about Linux is that it is easy to tap into the raw MIDI byte
stream, as passed to or from external instruments. (Remember that the 'Sequencer'
format, that most Linux apps prefer to use, is not in the least 'raw'.) And
passing a raw byte stream across an internet connection is trivial if you
have the right app.
The "right app" is 'netcat' (usually abbreviated to 'nc'). A program that
I was inexplicably ignorant of for many years of its existence, but turns out
to be useful for all sorts of odd jobs (not all of them quite honourable (:-/).
If you're on Ubuntu, you can get it from the usual repository, but it's
widely available on the web. There are several lineages around. I'm using
the 'traditional' one descended from the original '96 source, because the
current Debian/Ubuntu version (1.10-36)seems the most versatile, but they
should all be compatible.
Essentially to use it, you start a 'listener' instance at one end of the
connection, and a 'client' at the other (same program, different options).
Then anything sent to standard-in on one pops out the standard-out of the
other. It's symmetrical, so it doesn't matter which end is which, except
that you have to start the listener first.
As a simplest example, suppose you have one machine -- let's give it the
hostname 'kbdhost' (you can also use numeric IP-addresses of course) --
connected through MIDI to your keyboard, and another, 'synhost', driving
a (hardware) synth. I'll assume the MIDI port is the basic one on both
machines. We'll arbitrarily select net port '5555' to communicate through,
and start the listener on kbdhost:
nc -l -p 5555 </dev/midi
Then, on synhost:
nc kbdhost 5555 >/dev/midi
Play your keyboard, and the synth at the other end plays along...
(You could equally well use the '/dev/snd/...' raw alsa ports, which we'll
have to do in the next step.)
To connect to anything but external hardware, you'll need another facility
which may or may not already be on your system. (I seem to remember it came
with my Ubuntu installation, but had to be enabled before I could use it.
I'm afraid I've completely forgotten the details by now.) This is the alsa
'Virtual MIDI' module, which pretends to be a hardware port in /dev/snd,
but is a Sequencer port -- accessible through aconnect etc. -- on the other
side. Thus you can feed a serial raw MIDI stream to one of its ports and
connect the other end of the same VirMIDI to a soft synth, sequencer, or
whatever. Or you can drive it from a sequencer, and get the raw midi to
send off through nc. If you have VirMIDI enabled, you should see the ports
if you do 'aconnect -oil'. If it's not there, do a 'find' for 'snd-virmidi*'
to see if the modules are present. Get it from the repository if they're not.
As this example, we'll play a midi file on kbdhost, and on synhost we'll
just start a copy of 'aseqdump' to see the MIDI events. (I really don't
want to get into the horrors of, say, a fluidsynth command line. You'll
have to make that journey on your own!) It's more convenient to have the
listener on synhost this time. We also have to separate netcat and the MIDI
supplier or consumer into separate processes on each machine; I'll assume you
can run them in separate Terminal windows, to avoid background processes.
First, in a Terminal on synhost, we run aseqdump, connected to sequencer
source-port 24 (which is the first Virtual MIDI on my machine):
aseqdump -p 24
In another Terminal on the same machine, run a netcat listener to drive
that same port on the raw-MIDI end:
nc -l -p 5555 >/dev/snd/midiC2D0
On kbdhost, run netcat client that *takes* raw_MIDI from a VirMIDI port
(it doesn't have to be the same one on both machines -- just keeping it
nc synhost 5555 </dev/snd/midiC2D0
And finally, start aplaymidi to drive the sequencer end of the port:
aplaymidi -p 24 favouritetune.mid
You should see the MIDI-events print out in the aseqdump window.
In practice, one would probably write short shell scripts to encapsulate
the above, putting the netcat instances into the background. There is one
annoyance, though. Netcat will quit (and tell the other end to quit as well)
when you use ctrl-C, or in many versions of netcat when you use the '-q' option
and send it an EOF. Unfortunately, you can't use ctrl-C on a background process,
and raw MIDI never seems to pass an EOF, so the only way to terminate the
connection may be to explicitly kill one end by process-ID.
Remember, though, that the connection is bidirectional, so it might be useful
to pipe remarks made by your synth back to kbdhost, for example. (This way,
you don't need the second Terminal either.) Then if the synth sends an EOF
when you quit it, it closes the connection neatly. [I would have illustrated
by piping aseqdump's output, but it can't be piped...! Sigh. Ain't Linux
As an actual personal example, I'm using a net link to drive a Csound Hammond
simulation. (It's a CPU hog, so it's nice to run it on a separate machine.)
The Csound command line is itself encapsulated in a script, so the connection
script (note the '-q0' option to tell it to quit immediately on EOF) is just:
hammondvt 2>&1|nc -q0 kbdhost 2424 >/dev/snd/midiC2D0
I start the script via telnet (as it's a local net) and the program accepts
keyboard commands, so when I tell it to quit everything shuts down.
As a final note, being able to send a raw MIDI stream through stdin and
stdout can be very useful. I have some Ruby scripts that take MIDI on stdin,
and do things like add harmony. Very convenient for quick experiments.
Hope all that was interesting to someone...
-- Pete --
The address in the header is a Spam Bucket -- replies will not be seen...
(If you do need to email, replace the account name with my true name.)