Archive for November, 2011

Monday, November 21st, 2011

Sending MIDI system exclusive messages from Scala console

Apple OS X gets updated once a while, and I hope the problem with sending system exclusive message will be fixed. In the previous article I’ve shown how to send a MIDI note using Scala console. Here I’ll show how to send system exclusive messages, to ensure the bug I’ve reported is still present.

Tools I’ll use:

Now start the Scala console, and import the MIDI libraries first.

scala> import javax.sound.midi._
import javax.sound.midi._

Enumerate the output devices:

scala> MidiSystem.getMidiDeviceInfo.map(MidiSystem.getMidiDevice).filter(_.getMaxReceivers != 0)
res0: Array[javax.sound.midi.MidiDevice] = Array(de.humatic.mmj.spi.CoreMidiDeviceImpl@65d174f, com.sun.media.sound.MidiOutDevice@53281264, com.sun.media.sound.RealTimeSequencer@49a546cc, com.sun.media.sound.MixerSynth@1cb20da)

Separate the MMJ and Apple drivers. I just get the first output device which is Bus 1 loopback device.

scala> val mmj = res0.filter(_.isInstanceOf[de.humatic.mmj.spi.CoreMidiDeviceImpl]).head
mmj: javax.sound.midi.MidiDevice = de.humatic.mmj.spi.CoreMidiDeviceImpl@65d174f

scala> val osx = res0.filter(_.getClass.toString.endsWith("MidiOutDevice")).head
osx: javax.sound.midi.MidiDevice = com.sun.media.sound.MidiOutDevice@53281264

Note that class com.sun.media.sound.MidiOutDevice cannot be accessed here, so we need to kludge the driver out using class string.

Open the drivers:

scala> mmj.open; osx.open

Now connect the MIDI Monitor to listen the MIDI loopback device. Test it out by sending some notes:

scala> val note = new ShortMessage() 
note: javax.sound.midi.ShortMessage = javax.sound.midi.ShortMessage@52dce479

scala> note.setMessage(0x90, 0x72, 0x01) 

scala> osx.getReceiver.send(note, -1)

scala> mmj.getReceiver.send(note, -1)

Lines should appear in MIDI Monitor. Now send some system exclusive messages:

scala> val sysex = new SysexMessage
sysex: javax.sound.midi.SysexMessage = javax.sound.midi.SysexMessage@410e4a33

scala> val bytes = Array(0xF0, 0x00, 0x01, 0x60, 0x01, 0x00, 0xF7).map(_.toByte).toArray
bytes: Array[Byte] = Array(-16, 0, 1, 96, 1, 0, -9)

scala> sysex.setMessage(bytes, bytes.size)

scala> osx.getReceiver.send(sysex, -1)                                                 

scala> mmj.getReceiver.send(sysex, -1)

By looking MIDI Monitor you should now see that only messages sent using MMJ driver are getting through. We still hope that Apple can get the thing fixed.

Finally, close the devices.

scala> mmj.close; osx.close