Saturday, January 23, 2010

Max for Live, Java, MIDI, Windows and Sysex

Recently, I have spent some of my free time hacking some Java to provide Max for Live patchers direct access to the MIDI ports of my machine. Usually, one would be restricted to the MIDI data that Live has previously processed, which restricts it in many ways.

I have not spent too much time hacking Java in my life, but the times I have done it for various smaller hacks, it was a nice overall experience. This time, I was particularily impressed by Eclipse for its automated source code formatting facility that is widely configurable. I tweaked the settings a little to match my prefered squirly brace style, and then had Eclipse beautify my (and imported) source code with a single key stroke. Also, I like Eclipse's ability to automatically locate unknown classes and add required import statements with a single click. This makes working with examples from documentation rather easy. I still like Emacs, but I must admit that it is rather baroque when compared to what Eclipse can do.

Getting the Max external to interface to the MIDI subsystem that Java provides was rather easy, and I was mostly done after 2-3 hours of hacking. Sadly, sending Sysex strings to the MIDI controller that I used for testing did not work reliably. Naturally, I thought that the problem was with my lack of MIDI, Java and Max skills, so I spent quite some time trying out various implementation strategies, without success.

Finally, I figured that what did not work was sending Sysex messages, and only sometimes (i.e. it appeared as if the first message came through and then some following messages where not transmitted). Google finally pointed me to a web page by Thorsten Klose where, at the end, he describes the behavior as being a bug in the Java MIDI library. The problem is that when sending Sysex messages, the Java library remembers the size of largest Sysex message sent and uses that for all subsequent Sysex messages, even if they are shorter. My workaround is to close and re-open the MIDI device if a Sysex string to be sent is shorter than the previous one. This is kind of ugly, but it works for me. The workaround that Thorsten suggest has the problem that it does not stop Java from sending long messages, which reduces MIDI throughput to a point that was unacceptable for me.

I'm posting this in the hopes that it saves the next person seeing the problem some time. If you are interested in the Max for Live MIDI external, it is available here.