A Django site.
July 10, 2008

Hans Fugal
no nic
The Fugue :
» k20

I finished the promised K-20 meter. I imaginatively called it k20, and you can find it at http://hans.fugal.net/src/k20. Here's a screenshot:

k20 screenshot

From left to right, read average (VU), peak (instantaneous with 26 dB / 3 sec falloff), maximum peak, and overs.

This is pure unadulterated printf() abuse. No ncurses. Not that I have anything against ncurses, just that I'm lazy. Of course you need an ANSI capable terminal, but I'm sure you can find one lying around.

June 11, 2008

Hans Fugal
no nic
The Fugue :
» My Studio

Well, I've spent two days doing actual work in my studio and I can now confidently report my settings for the benefit of Linux-running MacBook users (and other related hoodlums).

I won't go into the detail that I did in the previous posts, most of which is still relevant.

I pass the option position_fix=3 to the module snd-hda-intel. I did this by creating /etc/modprobe.d/local, containing: options snd-hda-intel position_fix=3

then running sudo update-initramfs -uk all.

I set up my Gnome session to run QJackCtl, which is in turn configured to start JACK on startup. My JACK settings (from ~/.jackdrc) are: /usr/bin/jackd -R -t2000 -dalsa -dhw:0 -r48000 -p1024 -n2 -s

JACK is extremely stable. I've had 2, maybe 3 xruns through two days of work, and those were when starting up applications, not when actually using them.

Now, since we have only one audio device and JACK has monopolized it, and we want to hear other than JACK, we need more configuration. Here is my ~/.asoundrc:

# Set the default device to PulseAudio for all well-behaved ALSA applications
pcm.!default {
        type plug
        slave.pcm "pulse"
}
ctl.!default {
        type plug
        slave.pcm "pulse"
}

# This device can come in handy, but I mostly don't use it.
pcm.jack {
        type plug
        slave {
                pcm {
                        type jack
                        playback_ports {
                                0 alsa_pcm:playback_1
                                1 alsa_pcm:playback_2
                        }
                        capture_ports {
                                0 alsa_pcm:capture_1
                                1 alsa_pcm:capture_2
                        }
                }
                rate 48000
        }
}
ctl.jack {
        type hw
        card 0
}

# The acutal PulseAudio device
pcm.pulse {
        type pulse
}
ctl.pulse {
        type pulse
}

Now all well-behaved ALSA programs will use the default ALSA device, i.e. PulseAudio. PulseAudio needs to be configured now to use JACK. You'll need to get the pulseaudio-module-jack package, which probably means you'll need to build it yourself. I show you how to do that and how to configure PulseAudio in a previous post. Incidentally you need to do the same for libasound2-plugins if you want to use the JACK plugin for ALSA as in my asoundrc above.

Now we have a bit of a chicken and egg problem. PulseAudio starts when you log in, and so does JACK (by way of QJackCtl in your Gnome session). But PulseAudio will fail to start if JACK isn't already running. What's more, if you decided you wanted to restart JACK for whatever reason, you'd have to restart PulseAudio too. So here's how I solved it. I leave ESD enabled in the Gnome sound settings, knowing that it will fail to start (and I won't get the really cool Ubuntu Studio startup ditty, but oh well). It needs to be checked if you want Gnome to make nifty system sounds. Now, in QJackCtl setup, on the options tab, check the box for "Execute script after Startup" and put "pulseaudio -D" in the box. Now PulseAudio will start whenever JACK starts, and it will stop/crash/whatever whenever JACK stops.

Now, you need to install libflashsupport to get Flash working with PulseAudio. Even so you might find occasional sites that crash it.

That about covers it. If you do much work with audio applications using complicated JACK graphs, don't overlook the power of QJackCtl's patchbay, which will automatically hook things up. I have a patch that will connect Aeolus to system output 3&4 (headphones/external speakers), and hook my MIDI keyboard to Aeolus. So all I have to do is start Aeolus and pull some stops and I'm ready to play.

Which reminds me, there's still the annoying thing about JACK having 8 outputs (for surround sound) and the internal speakers are on outputs 1&2, and the headphone jack is outputs 3&4. If you're not getting sound from a JACK app and you think you should be, that's the first thing to check. Someday I plan to figure out the .asoundrc magic needed to set up JACK so that it's a regular stereo device sending sound to both the internal speakers and headphones. If you know how, please enlighten us in the comments. I know it can be done, I just haven't put in the time to figure it out and test it.

June 4, 2008

Hans Fugal
no nic
The Fugue :
» PulseAudio as a JACK Client

I spoke too soon about not being able to get PulseAudio working as a JACK client. I found this post that tells you how to do it.

The key I think is chmod -s `which pulseaudio`. I didn't have to start the JACK transport rolling, so that may be antiquated information. I did have to build some packages from source, though:

sudo apt-get build-dep pulseaudio
sudo apt-get install libjack-dev
fakeroot apt-get source -b pulseaudio

This creates a bunch of .debs, including pulseaudio-module-jack*.deb. I just installed them all, but you can probably just install the jack module deb. Make the changes permanent by putting them in ~/.pulse/default.pa or in /etc/pulse/default.pa and you're in business.

» JACK on the MacBook

I spent the better part of two days fine tuning my linux audio setup on my MacBook, so maybe I can save anothe MacBook user some time with this post.

The sound card in this thing is an Intel HDA Controller, driven by the kernel module snd-hda-intel. Intel HDA cards (usually onboard cards) are looked down upon and generally derided, and I can testify with good reason. Like all sorry excuses for an audio card, it has only one subdevice which means only one application can use the card at a time. (If you want to know if your audio card is cheap, this is a good indicator—just look in /proc/asound/card0/pcm0p/info for subdevices_count)

Luckily in these modern times, the default ALSA device does software mixing (dmix), so even on a cheap card you can usually hear more than one application just fine. No, no, you do not need PulseAudio for this. In fact, PulseAudio steals the audio card in its default configuration (at least on Ubuntu 8.04). So if PulseAudio is running, applications that aren't PulseAudio aware (or ESD aware) will simply not be able to make sound. There are other misbehaved kids on the block, but they're fairly rare. The difference is that a well-behaved application will grab the default ALSA device, instead of the first audio card in the system explicitly, hw:0. PulseAudio in fact advises the use of this trick, to set PulseAudio as the default ALSA device, which I suppose explains why PulseAudio grabs hw:0 by default. Unfortunately Ubuntu is only halfhearted here—it enables PulseAudio but does not set up the default ALSA device to point to it. So in Ubuntu you need to either set up the default ALSA device with an ~/.asoundrc that looks like this

pcm.!default {
    type pulse
}
ctl.!default {
    type pulse
}

or you need to configure PulseAudio to use the default device instead of hw:0. If you are going to be using JACK too (and you want to hear other applications outside the JACK pipeline when JACK is running), I recommend the latter, though if you're twisted enough you might try JACK as a PulseAudio client.

JACK also by default grabs hw:0, because JACK is all about low latency and high performance and going through dmix adds a layer of overhead. If you're using JACK, you may be enough of a snob that you're ok with leaving those non-JACK applications out in the cold while JACK is running. In fact you may not want to hear Pidgin sounds (for example) at all while you're doing audio work. Semisnobs like myself, though, might want a compromise. Setting up my studio just the way I want is enough of a pain, I really don't want to quit all my JACK applications just so I can listen to Last.fm or watch sb_email.

Now at this point I would be remiss if I didn't mention the very cool JACK plugin for ALSA. It allows you to make well-behaved ALSA applications (the ones that use the default device or allow you to configure which device is used) go through JACK. I modified my .asoundrc in a manner slightly different from the example given:

pcm.jack {
        type plug
        slave {
                pcm {
                        type jack
                        playback_ports {
                                0 alsa_pcm:playback_1
                                1 alsa_pcm:playback_2
                        }
                        capture_ports {
                                0 alsa_pcm:capture_1
                                1 alsa_pcm:capture_2
                        }
                }
                rate 48000
        }
}

Then if you want to make the JACK plugin the default, you add

pcm.!default {
    type plug
    slave.pcm "jack"
}

I tried configuring PulseAudio to use the JACK plugin, but it would crash on startup. Last.fm's client also had issues—it will play fine for one song and then crash jackd when the second song starts. So unfortunately it doesn't look like the JACK plugin for ALSA is quite ready for prime time, but you can certainly use it from time to time in applications that let you choose the ALSA device.

Unfortunately, the JACK plugin isn't found in Ubuntu's libasound2-plugins package where it belongs. It's an easy remedy, however, just install libjack-dev and fakeroot, then build the package from source (you don't even have to patch it):

apt-get install libjack-dev fakeroot
apt-get build-dep libasound2-plugins
fakeroot apt-get source -b libasound2-plugins
sudo dpkg -i libasound2-plugins*.deb

Getting Ubuntu to not annoy you constantly about "upgrading" that package is another story.

Ok, so now to the meat of this post. JACK does not work well on this sound card with its default settings. It either has an insane number of xruns, or it sounds terrible. For quite some time I chased the red herring of the position_fix parameter to the snd-hda-intel module, and I can report with confidence that on this hardware you don't want to change it from the default (0, which is auto). However, if you are only concerned with JACK, you will want to change it to position_fix=3, which gives rock-solid JACK with the default settings on hw:0. However, although JACK or other direct-to-hw:0 applications sound fine, dmix sounds crackly using position_fix=3. So it's probably not a good all-around solution if you're interested in more than just JACK.

The first order of business in good JACK performance (on any system) is to enable realtime. Edit /etc/security/limits.conf and add something like this:

@audio - memlock unlimited
@audio - nice -10
@audio - rtprio 99

Now (after logging out and back in) you should be able to pass the -R option to jackd and get realtime.

If you do jackd -R -d alsa (unless you use position_fix=3) you will get lots of xruns. The best I have been able to do is jackd -R -d alsa -p 512 -n 4, as it seems that the trick is getting at least 3 periods (and to do that with hw:0 you have to reduce the period size). This works well but qjackctl reports lots of xruns still. Actually, they're mysterious messages like this

delay of 5152.000 usecs exceeds estimated spare time of 4071.000; restart ...

which don't actually cause an audio blip (but you will get an occasional real xrun). I still need to try the realtime kernel (linux-image-rt package) to see if that might help here. In my early tests (mostly playing with position_fix) the realtime kernel was actually doing worse than the generic kernel, but that was before I learned the number of periods should be at least 3, so I need to test again.

If you run jackd -R -d alsa -d default you will theoretically be able to use JACK and other applications at the same time via dmix/dsnoop. JACK will complain

You appear to be using the ALSA software "plug" layer, probably a result of using the "default" ALSA device. This is less efficient than it could be. Consider using a hardware device instead rather than using the plug layer. Usually the name of the hardware device that corresponds to the first soun

[sic] but pay it no heed, we're doing this on purpose, and actually are able to get better performance than the hw:0 route (with position_fix=0). That command will not actually work, though. It will crash within a minute even without any clients. Again the fix seems to be the number of periods, but this time we can avoid the excess delay by leaving the period size at 1024 (at the cost of some latency, of course). So, jackd -R -d alsa -d default -n 4. This is rock solid. It went all night without a single xrun. (But it wasn't doing much, though Ardour, Aeolus, and Hexter were "running". I was able to play around with them for a half hour or so with no xruns before I went to bed.) However, sometime down the road it will miss a deadline and it will crash. This crashing seems to be specific to using dmix, usually you'll just get an xrun. The workaround is to use softmode with the -s switch. Now you can run JACK 24/7 with excellent performance and without locking other applications out of the soundcard.

So in summary, if you don't care about dmix but only JACK (or any other application using hw:0, which can be all of them if you change your .asoundrc, but only one at a time), set position_fix=3 for snd-hda-intel e.g. in a file in /etc/modprobe.d/ with a line like this: options snd-hda-intel position_fix=3, and do update-initramfs -uk all. If you want a more balanced setup, where you can have JACK running and other well-behaved ALSA applications can use the sound card, leave the module parameters alone and set up realtime and use the following command to start JACK (or equivalent settings in QJackCtl):

/usr/bin/jackd -R -dalsa -ddefault -r48000 -p1024 -n4 -s

If you want to use PulseAudio in this situation, configure it to use the default ALSA device instead of hw:0.

If you like PulseAudio and JACK both, the ideal situation would be PulseAudio using JACK as a backend, JACK using hw:0 with position_fix=3, and the PulseAudio plugin as the default ALSA device. Unfortunately this is just a theoretical ideal, and doesn't work (yet) because of bugs.

And finally, if you have no or limited use for JACK, but want to use PulseAudio, just change your .asoundrc as above to make PulseAudio the default ALSA device, so that all applications, ESD aware or not, use PulseAudio.

Oh, and I almost forgot to mention the mixer. There's Master, PCM, Front, Surround, Center, LFE, Side, and various toggles. AFAICT the Front controls the internal speakers, and Surround controls the headphone volume. JACK on hw:0 has 8 system ports. The first two correspond to the front speakers and the second two to the headphone jack. When you run JACK on default, it's simply stereo output, and goes to the speakers or the headphones if they're plugged in.

Finally, I regret to report that JACK on default will crash on resume (on hw:0 it won't, at least with position_fix=3).

March 23, 2008

Hans Fugal
no nic
The Fugue :
» CoreMIDI

I'm porting Aeolus to OS X. In the process I'm learning how CoreMIDI works. Naturally you get to hear my opinion on the matter.

CoreMIDI seems like a decent framework, actually. It is callback-based, which is good. It has a pretty reasonable design; physical devices and virtual devices alike communicate with eachother in the same way. They each have endpoints—source endpoints and destination endpoints.

It all looks well and good on the surface, but there's some problems. The first problem is arguably a feature. You can create input/output ports and connect sources/destinations to those ports from within your application. This allows you to make a cute or complicated dialog box where the user can select the MIDI (virtual) device(s) she wants to use. Sounds reasonable right? And so it is, and I wouldn't argue against this ability.

The badness comes in when you consider that every application has to duplicate this functionality. It would be much better to have an external patchbay for connecting applications together. This would be more powerful and flexible and free up application developers to not worry about it. They just have to create the endpoints and then they're done.

Alas, OS X proper has no such patchbay. "Yes it does, silly. It's called Audio MIDI Setup" you say. That's the most infuriating thing—Audio MIDI Setup lets you route between devices in just the sort of way I'm talking about, but it only works for physical devices. Someone needs to be shot.

Luckily, some guy named Pete wrote a MIDI Patchbay. It's serviceable, if quirky and ugly. He also wrote a simple software synthesizer called SimpleSynth (also quirky and ugly) that does what something in OS X (e.g. QuickTime Player) should already be doing: accept MIDI input and use the QuickTime music synthesizer to render it. Kudos to Pete for filling in the gaps, and I'm sorry for calling your children ugly.

While I'm complaining about patchbays, I'm still dumbfounded that JACK doesn't seem to have a command-line application for patching things together. I'm thinking something akin to aconnect for ALSA MIDI, though of course for JACK it would be for audio and MIDI both. qjackctl is absolutely marvelous, and I wouldn't use anything else given the choice, but sometimes you don't have qjackctl handy and it might be quite difficult indeed to get it. This was the case for me the other day. I had the latest greatest JACK installed from source, but qjackctl (which I finally managed to figure out how to build using the QtMac binary, whose qmake refuses to output a real Makefile but instead an XCode project) was choking on it. So I had to downgrade to Jack OS X and rebuild qjackctl (it's still an immense improvement over JackPilot). This is depressing because the newer version of JACK is much more friendly to the CLI user on OS X. The version in Jack OS X 0.76 still requires some ugly workarounds (which JackPilot helps you to do). The latest version of JACK (0.109.2) Just Works™ when you type jackd -R -d coreaudio. So I'm still starting JACK with JackPilot, which I then summarily quit in favor of qjackctl.