Akai EWI USB and Linux, part 2

Part 1 of my Akai saga ended with the EWI producing sound, a disappearing symlink and a shocking latency. This was unacceptable.

To get a flavor of how things should work, I did something I hadn't done in months: boot into Windows. I dutifully installed the software from EWI's companion CD and tried a few tones. The software itself was nice, polished and simple enough, except that the latency was pretty much the same as under Linux! Google said one should install a different audio stack, "winaudio" or something, but I had no such inclination.

I pulled out the big guns instead. I installed 64studio on a spare partition. It's a specialized multimedia-production Linux with pre-configured JACK low-latency audio server etc. and I was certain that it would help. Except it wouldn't talk to my graphics card. Next up was Ubuntu Studio - same purpose, different vendor. It installed beautifully, had tons of pre-installed audio software including JACK and QSynth and... exhibited the same latency problem as my regular aptosid and Windows. It was back to the drawing board.

I knew it wasn't a hardware problem - when I ran fluidsynth in verbose mode it would print MIDI events very swiftly, only the sound was lagging. CPU load was negligible so it wasn't any slowness on my computer's part, either. I tried the only thing I could think of - further tweaking fluidsynth's options, this time on the output (audio) side. Lo and behold, when I chose the legacy OSS output driver the system started reacting like a caffeine-doped squirrel. Sound was coming out almost before I touched the pads. I had reached the Akai EWI nirvana.

The utterly perplexing aspect of this outcome is that I don't even have true OSS on my system; virtually no-one has these days. OSS on my notebook is just a special legacy emulation mode of ALSA, yet it performs better than ALSA proper. Go figure...

I had basically two options to resolve the disappearing symlink from /dev/snd/midiC1D0 to /dev/snd/midiC0D0. I could either automate its creation in a start-up script or I could remove the need for it, i.e. make fluidsynth talk to midiC1D0 as it should. The latter was obviously a cleaner solution so I started pursuing it. Tweaking the command line had been useless before, hence I downloaded the source code (apt-get source fluidsynth) and started looking around the error messages I was getting ("Unknown RawMidi" etc.).

It turned out that when fluidsynth documentation says I should specify a MIDI device, it doesn't really mean "a path to a device file" but rather "an ALSA device ID", at least when alsa_raw is specified as the MIDI driver. ALSA device IDs have a special syntax that looks like "hw0,0", with the first number identifying a sound card and the second one determining a feature of that sound card one wants to work with. I tried to formulate a device ID for midiC1D0 but couldn't figure it out.

Looking through the code, I noticed that when no MIDI device is explicitly specified fluidsynth deduces an ID from various ALSA settings, mainly the default sound card. It occurred to me that I could set the EWI as the default sound card. I remembered that ALSA reads user-specific configuration from ~/.asoundrc and a short trip to Google yielded this incantation: defaults.rawmidi.card 1. Having that line in my .asoundrc finally let fluidsynth talk to the EWI without a symlink hack. This wasn't as exciting as doing away with the latency but I felt satisfied that things were finally set up the way they should be.

In summary, all I had needed from the start was that single line in .asoundrc and a simple fluidsynth -m alsa_raw -a oss TimGM6mb.sf2 (I use the soundfonts provided on EWI's companion CD). It took a while to get there but I finally had a straightforward way to play the EWI through my notebook.

Once I knew what to set in fluidsynth I configured QSynth with the same settings to get a nice graphical UI for switching sounds and tweaking the effects (fluidsynth has built-in reverb and chorus). This was really comfortable and I became spoiled after a while. It started bugging me that I had to launch QSynth by hand each time I wanted to play. I knew that the computer should be able to do it automatically when the EWI gets plugged in. It should even be able to exit QSynth when the EWI gets unplugged. I decided to tackle that one as well to make my playing truly comfortable. It's a story for another post, however...

Proudly powered by Pelican, which takes great advantage of Python.