Sending MIDI data (Linux)
by Richard Russell, May 2018
Unlike Windows, Linux does not incorporate a software MIDI synthesiser as a standard feature. If you want to output MIDI data you will need to install a synthesiser such as amSynth or Timidity. For example to install amSynth you would typically do:
sudo apt-get install amsynth
You will also need to create a virtual MIDI port to which to output the data:
sudo modprobe snd-virmidi
The next step is to run the synthesiser and connect its input to the virtual MIDI port. Since the port numbers may vary depending on your system the safest thing to do is to list them to the console (note that the parameter is the letter L not the figure 1):
amsynth & aconnect -l
This should output something similar to the following:
client 24: 'Virtual Raw MIDI 2-0' [type=kernel,card=2] 0 'VirMIDI 2-0 ' client 25: 'Virtual RAW MIDI 2-1' [type=kernel,card=2] 0 'VirMIDI 2-1 ' client 26: 'Virtual RAW MIDI 2-2' [type=kernel,card=2] 0 'VirMIDI 2-2 ' client 27: 'Virtual RAW MIDI 2-3' [type=kernel,card=2] 0 'VirMIDI 2-3 ' client 128: 'amsynth' [type=user,pid=930] 0 'MIDI IN ' 1 'MIDI OUT '
Having discovered the port numbers you can connect the virtual MIDI port to the synth input as follows (substitute different port numbers as appropriate):
aconnect 24:0 128:0
With the synthesiser running and the connections established you should be able to run BASIC programs which output raw MIDI data. For example here is a trivial example which outputs just a single note (you may need to change portname$ to correspond to the port you are using):
SND_RAWMIDI_SYNC = 4 portname$ = "hw:2,0" SYS "snd_rawmidi_open", 0, ^midiout%, portname$, SND_RAWMIDI_SYNC TO status% IF status% < 0 ERROR 100, "snd_rawmidi_open failed: " + FN_strerror(status%) DIM noteon&(2), noteoff&(2) noteon&() = &90, 60, 100 noteoff&() = &90, 60, 0 SYS "snd_rawmidi_write", midiout%, ^noteon&(0), 3 TO status% IF status% < 0 ERROR 100, "snd_rawmidi_write failed: " + FN_strerror(status%) WAIT 100 SYS "snd_rawmidi_write", midiout%, ^noteoff&(0), 3 TO status% IF status% < 0 ERROR 100, "snd_rawmidi_write failed: " + FN_strerror(status%) SYS "snd_rawmidi_close", midiout% END DEF FN_strerror(S%) LOCAL T% SYS "snd_strerror", S% TO T% = $$T%