Archive for the ‘Scala’ Category

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

Friday, October 21st, 2011

Java MIDI driver for OS X

The Java MIDI driver for Apple OS X is getting shape. Now the driver can:

  • Register itself as a MIDI driver
  • Enumerate endpoints from Apple CoreMidi
  • Separate inputs from outputs

It still can not send or receive messages. The driver project is open sourced (MIT license) and shared on the Github page. As this is the first project where I used Java Native Interface, Objective C or Apple Core Foundation classes, I’m more than happy to get any feedback and suggestions how to improve any part of the code.

Friday, September 9th, 2011

Mac OS X Lion MIDI sysex problems with Java

Happiness of easy MIDI programming with Scala didn’t last too long. Almost everything is fine with my pair of DaScratch controllers. I can switch the led’s and read the touch interfaces easily, but there is one small thing. The mode of round touch interface is switched by using MIDI system exclusive or sysex command. This is easy with javax.sound.midi in theory, but in OS X the sysex command doesn’t get transmitted.

This can be worked around by using mmj drivers. With mmj sending sysex messages from Scala console is a bliss. However, if there’s a pair of identical controllers just like I have, I can not access the second controller because of a bug in mmj.

So, I filed two bugs:

  • to Apple about sysex commands. I’ve got problem ID 10016703, but no response.
  • to Humatic about accessing two similar devices with mmj. Nils from Humatic responded very fast, but he didn’t promise fix soon.

Well, seems that my first project creating router for a pair of DaScratches is spinning off another project creating Java MIDI drivers for OS X.

Sunday, September 4th, 2011

Scala console MIDI hands-on

As Scala console, Interactive Interpreter or REPL was one of my selling points for programming MIDI with Scala, I show what can be done with it. I do not show how to install Scala or how to access console.

First things first: Import Midi libraries to save typing later on.

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

Enumerate devices attached.

scala> MidiSystem.getMidiDeviceInfo
res0: Array[javax.sound.midi.MidiDevice.Info] = Array(Bus 1, SCS.3d, SCS.3d, FastTrack Pro, Bus 1, SCS.3d, SCS.3d, FastTrack Pro, Real Time Sequencer, Java Sound Synthesizer)

We are interested in two Stanton SCS.3d DaScratch controllers attached directly to USB ports, so let’s filter them using res0 from previous evaluation.

scala> res0.filter(_.getName == "SCS.3d")
res1: Array[javax.sound.midi.MidiDevice.Info] = Array(SCS.3d, SCS.3d, SCS.3d, SCS.3d)

Now there are four MidiDevice infos: Two inputs and two outputs – one for each physical device.

Let’s map those information blocks to actual devices.

scala> res1.map(MidiSystem.getMidiDevice)
res2: Array[javax.sound.midi.MidiDevice] = Array(com.sun.media.sound.MidiInDevice@503f0b70, com.sun.media.sound.MidiInDevice@5b080f38, com.sun.media.sound.MidiOutDevice@6e1f5438, com.sun.media.sound.MidiOutDevice@4ad26103)

Let’s filter out the inputs and outputs in two separate lists. Again we use result from previous evaluation, but now we are storing the lists to named variables:

scala> val ins = res2.filter(_.getMaxTransmitters != 0)  
ins: Array[javax.sound.midi.MidiDevice] = Array(com.sun.media.sound.MidiInDevice@503f0b70, com.sun.media.sound.MidiInDevice@5b080f38)

scala> val outs = res2.filter(_.getMaxReceivers != 0)
outs: Array[javax.sound.midi.MidiDevice] = Array(com.sun.media.sound.MidiOutDevice@6e1f5438, com.sun.media.sound.MidiOutDevice@4ad26103)

Get the first output device and open it.

scala> val out = outs.head
out: javax.sound.midi.MidiDevice = com.sun.media.sound.MidiOutDevice@6e1f5438

scala> out.open

Send note on message for key number 0×72 on channel 1 with velocity 1 to light a deck indicator on DaScratch.

scala> val m = new ShortMessage()
m: javax.sound.midi.ShortMessage = javax.sound.midi.ShortMessage@7f7ef0a7

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

scala> out.getReceiver.send(m, -1)

That’s it. Using Scala REPL is very fast way to check how the MIDI works with JVM.

Wednesday, August 24th, 2011

Programming MIDI with Scala

I’ve got a pair of Stanton SCS.3d DaScratch controllers and a Native Instruments Traktor Pro DJ software. They are connected using DaRouter software which is based on Bome Midi Translator. It runs pretty well, but there’s one small issue. Traktor has four decks, and there is no way to control more than two decks using the two DaScratches with this setup. There is “deck” button on the controller, but it is only used to change between two decks if there’s only one DaScratch. The button has no effect with a pair of controllers. I believe Stanton SCS.3m mixer would solve this, but I don’t have one.

I could buy SCS.3m mixer, but it doesn’t offer a lot of value. To be honest, I’d rather use my iPad with TouchOSC for the controls outside the DaScratches. Not owning SCS.3m mixer I’m pretty much forced to use DaRouter. I could also buy a Bome Midi Translator and try to make a patch for four decks. As no-one has done it, I suppose it may be impossible to do with Bome. So, it is time to start a programming project. However, even if I develop software as my job, my MIDI programming skills are dated 10 years ago. Back then I used Windows low level MIDI API with Delphi.

For DJ’ing I use MacBook, so the first option came in to my mind was to use Xcode and Objective-C, but after looking examples, it really didn’t felt my thing. It is pretty verbose, and OOP paradigm is not too interesting for me. More interesting Haskell isn’t too mature to use with Xcode yet, and the learning curve is still pretty high. So, I turned to trusty Scala running on Java Virtual Machine. After my experience with Windows API and Delphi, I immediately noticed the following advantages:

  • Comparing to Xcode, the project is not cluttered with numerous files
  • With REPL, it is very easy to prototype any code
  • Scala is very productive when enumerating lists

I can admit the following disadvantages

  • Java Virtual Machine doesn’t start too fast – although it doesn’t matter now
  • Fading support of Java on Macintosh – but it is still supported
  • Performance – the application is not too hungry for that, and the performance decrease is not actually very high
  • Java UI tools are slightly out-fashioned – let’s see if this application is getting any user interface