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).
Radium in Ubuntu
My Radium 61 MIDI controller (read: MIDI keyboard that doesn't make any sound of its own accord) has worked great in Linux from day one, but it was always a bit of a pain to get set up.
When the keyboard is plugged in (USB), it needs firmware uploaded to it before it will show up as a USB MIDI device. In the past the way this is done has changed several times. In the devfs days you did one thing. Then someone wrote a package that made it even simpler. Then udev came along and messed everything up. Then udev changed and messed everything up. Then it happened again (stupid udev). Then I brought my keyboard to school and only used it with OS X for a year or so, and now here we are.
Now Ubuntu 8.04 has a package midisport-firmware which installs the firmware and the udev rules. Awesome! Except, it doesn't work. It turns out that the midisport-firmware package (which obviously must be coming from Debian unstable, or it would probably work) depends on usbfs, and apparently Ubuntu has disabled it. Or broken it. Or something. The fix is quite easy: uncomment the four lines under the comment "Magic to make /proc/bus/usb work" in /etc/init.d/mountdevsubfs.sh, then issue /etc/init.d/mountdevsubfs.sh start. It should Just Work™ in the future after reboots.
Linux on the MacBook
So now that I'm done with comps, it's time to start doing real research. In my case, that means playing with audio and MIDI.
Specifically, I'm going to be generating preliminary data by recording chromatic scales and musical works on Aeolus, an absolutely fantastic pipe organ synthesizer. I did get it ported to OS X (feel free to contact me about that, or just wait until the next release, he is integrating my patches), and Ardour works in OS X as well. But realizing that I wanted to record the same things with many different registrations (stop choices), I needed a MIDI sequencer, like Rosegarden. Frankly, there just doesn't seem to be anything even close available on OS X that doesn't cost an arm and a leg (at least from a student's perspective). Combined with the fact that the OS X driver for my Radium 61 seems to be buggy, I decided I need to go Linux.
OS X is supposedly the darling of multimedia types, but in my experience there is nothing like the wealth of interesting software available, for free, on the Linux Audio scene. And when it comes to audio stability and low-latency performance, there is nothing like a well-tuned Linux box. In short, I can't imagine doing serious audio work in anything but Linux.
So there are many guides out there for installing Linux on a MacBook, and I won't try to duplicate that information here. What I would like to do is detail what I had to do, and which choices I made.
The first choice is that of partitioning. In the end I decided to share the internal hard drive, giving 10G to linux. It looked like the easiest way to do that was with Boot Camp, although it appears possible without it. But Boot Camp Assistant just would not resize my OS X volume. It would either complain about files that couldn't be moved, or running out of disk space. I thought it might be running programs, so I shut them down. I thought it might be swap space so I rebooted. I thought it might work if I did it from the installation DVD. I thought maybe it needed more free space to do the shuffle. None of these fixed it. So I googled around and found that it might be possible for a file to be locked in position. So I needed to figure out what files were entrenched at the end of my HDD and see if I couldn't do something about that. I came across a not-free defragmenter, iDefrag and fired up the demo. It processed the disk and eventually showed me a map of the sectors of the drive, and mousing over them I was able to see the files using those sectors. Near the end of the drive there were a lot of red sectors that all belonged to Google Desktop. I assumed red sectors probably meant stuff that couldn't be moved, but I couldn't be bothered to look it up. Google Desktop seemed like a logical lead, though. So I uninstalled it and gave the repartitioning a try, and it worked like a charm. Incidentally I like Google Desktop, as also Quicksilver and Spotlight (I use all three, depending on what I want to do), so I'll probably reinstall it. Oh, and I didn't defragment with iDefrag since the demo only defragments drives smaller than 100M. But just try finding that information on their website or in the README.
I then installed rEFIt, which although not necessary is a nice way to bootload a dual-boot system.
I rebooted and chose to boot from CD in rEFIt. Odd, I just get a blank screen and no activity. I know this Ubuntu CD works on this very laptop because I had already tried it. So I rebooted and held down alt, which gave me the Apple boot chooser, and I chose the CD, and it worked fine.
I installed Ubuntu in the usual way. I manually partitioned, formatting the partition Boot Camp made for Windows as ext3 and not bothering with swap (I made a swapfile after installation). I told it to install the bootloader (GRUB) on the partition instead of the disk (the partition is sda3).
When I rebooted, I did the gptsync thing using the rEFIt "Partitioning Tool", which synchronized the legacy MBR with the newfangled GPT. Then I tried to boot into Linux, and again rEFIt gave me a blank screen. I booted into OS X and googled it, finally stumbling across something that said that happened once or twice and then stopped happening. So I rebooted and sure enough, it worked the second time. That's odd, and not the end of booting troubles. Sometimes when booting Linux you get a kernel panic talking about APIC. I remembered this from early experiments last year, so I didn't panic. You just try try again until it works.
I will adorn this blog with a flurry of posts on the rest of my adventures soon, but for now suffice it to say I had Linux installed, and it has come a long way. Ubuntu 8.04 had wireless, multi-finger trackpad tapping (though I prefer two fingers to be the right button not the middle button), basic sound, video acceleration, and even suspend working out of the box. It's beginning to look like I could not only do my research in Linux, but maybe even make it the primary OS on my laptop the rest of the time too.
PhD Candidate
A couple weeks back I finished my PhD comprehensive examination, which means I am officially a "PhD Candidate".
The comprehensive exam is a literature survey paper in my area of research and an oral presentation of that survey. You're welcome to read/peruse both at http://hans.fugal.net/comps.
Mad Scientist Wanted
If any of you out there into whose RSS feeds my blog has infiltrated have some way to measure pH, I call upon you to perform an experiment and report back for the benefit of mankind.
Measure the pH of 1 cup milk. I reckon it would be about 6.5. Then, add 1/8 teaspoon baking soda, stir well, give it a minute, and measure the pH. Repeat until you have added a total of 2 teaspoons of baking soda. You will get a warm fuzzy feeling for helping.
XvMC
I bought an MSI NX6200AX-TD256H D2 video card (It's an NVIDIA GeForce 6200 256MB 8x AGP card) to drive the MythTV frontend, since MythTV can't manage to play even the most modest content using my trusty old Radeon 7000 (MythTV doesn't support VIDIX, only XVideo). I hoped that the upgrade would allow me to watch live HD television, which means XvMC.
Before I go any further, the other relevant stats: the computer I'm using (for the purposes of this post, anyway) is an 64-bit AMD Athlon 2800+ running 32-bit Ubuntu 8.04. The motherboard is a VIA K8T800. I'm actually using TwinView to share the Desktop computer with MythTV, but I tested everything with a single-screen (the CRT) to avoid confounding, and using TwinView doesn't seem to make a difference one way or the other.
All the normal stuff works great, but XvMC does not though it should. Whenever I try to use XvMC, the client (mythfrontend or mplayer, for example) freezes up and must be killed. I tried all the standard tweaks that Google could suggest: enable/disable sync on vblank, enable/disable OpenGL vsync, various xorg.conf settings. I tried just about everything I could think of and then some, and the only thing to make any difference at all is this setting in xorg.conf:
Option "NVAGP" "0"
That is, I disabled AGP. When I do this, XvMC works as it should. After a little research, it perhaps shouldn't be too surprising that AGP is the problem on a VIA motherboard. At least it's a lead.
Interestingly, when I downgraded the driver from the latest (173.14.05) to the newer legacy driver (96.43.05), XvMC works fine with AGP enabled. As one would expect, it outperforms the newer driver with AGP disabled. Here's a performance table:
(% CPU when playing SD/HD in MythTV)
Driver Xv Xv+linear XvMC+bob
173.14.05 (AGP disabled) 20/100+ 30/100+ 12/60+ (OSD is too much)
96.43.05 20/100+ 30/100+ 8/45
There's a few caveats to XvMC, either way I get it to work. When deinterlacing is on, the OSD gets deinterlaced too. This isn't a pretty sight, though it's functional. The OSD is always grayscale, in spite of setting XvmcUsesTextures to false in xorg.conf and choosing chromakey. But that doesn't bother me much, I don't much like the color schemes of the OSD themes I've seen.
I have one more straw to grasp before I consign myself to using the legacy driver (which I may do if it runs FlightGear and X-Plane ok) or crossing my fingers for a fixed driver before the Olympics (I intend to submit a bug report). I'm going to try poking around with AGP driving strength settings in the BIOS. I tried 0xEA and X wouldn't start at all, but with the same symptoms I get with XvMC. That hints at the same cause, so maybe with some kind of binary search I can stumble on a compatible setting.
So in conclusion, I'm going to try using the legacy driver even though my card is supported by the newer driver, and for OSD reasons only use XvMC for HD.
Thermometer Reference Card
Next to a digital scale, I'd say a good probe thermometer is the most important kitchen tool that nobody has. If you're not everybody, then you might find this reference card handy.
Pain Perdu
I grew up eating french toast once every week or two. Delicious stuff, and easy too. Some eggs, a little milk, dip the bread and cook like a pancake.
Then I got married, and my wife did the same thing but ruined it by adding cinnamon. Well, to each her own. We started dividing the egg stuff before she added the cinnamon to her mix.
One day I watched the Good Eats episode Toast Modern where AB goes through this complicated process to get some kind of "perfect" french toast. It sure didn't look worth the effort to me, so I promptly forgot all about it.
Then I visited New Orleans for a conference. The hotel I stayed at had complimentary breakfast (and not that lame cover-up people call "continental breakfast"). One day I ordered the french toast, unwittingly changing my life forever.
What they served was, as AB says, crispy on the outside and soft and creamy on the inside. It tasted less eggy than what I was used to. It was lightly dusted with powdered sugar before I put some syrup on, but I knew it went deeper than condiments. This was fundamentally different french toast to what I had been accustomed to. And I loved it. Truly incredible. More than anything else about that trip to New Orleans, I will remember the french toast.
Fast forward again, and I came across the same Good Eats episode. This time I paid closer attention and due respect to AB. Then I tried the recipe faithfully, but with mediocre results. First, the homemade artisan bread I was using had curled up while staling, making it very difficult to get a good browning in the pan. It also was quite holey. Second, I just didn't get much of a crisp. So again I chalked the recipe up to too complicated and not really worth it.
Yesterday I again had the hankering for some french toast like what I had in New Orleans. So I decided to follow AB's recipe again, but also to take some insurance out. I did some surfing and found that New Orleans french toast is apparently famous. Most recipes that seemed credible had the same basic structure: custard, pan-fry in butter, maybe put in the oven for the final crisping (I get the feeling some just use more butter or butter/oil mixture and fry it to crisp instead). So I grabbed french bread from the store (for reproduceability) and the rest of AB's ingredients. I mixed the custard and set out sliced bread the night before. In the morning, I followed his instructions to the T, except that I used the toaster oven and I included baking in the toaster oven in the pipeline (since I couldn't fit all 8 slices in at once anyway). It worked well, and wasn't too complicated.
The toaster oven really cuts down on the wait for preheat and the wasted heat. I actually set it to 400°F instead of the 375°F he recommended, and it worked well (5 minutes in). I may even toy with using the toast setting instead of the bake setting.
The rack and cookie sheet are, I believe, an unnecessary complication. If properly staled, the toast loses very little custard while resting, so i wouldn't worry about pooling. Instead I plan to use foil, or maybe just a cookie sheet, to cut down on the cleanup.
The french bread didn't curl, and tasted alright. As good as Albertson's french bread could be expected to taste. Next time I'll use my own artisan bread again (one with a bit more even crumb), and make sure to not lay it out in a way that bends the bread. I expect the results will be fantastic.
I feel like I'm working with the same principles that the hotel chef was working with. It is close to what I had, and I think perfection is within my grasp. What's more, it's no harder than the old way though it does take just a hair more planning and a less-common ingredient (half and half).
Sound Card Indices
I have two soundcards in my desktop: the built-in soundcard which uses the snd-via82xx module, and the nice soundcard which uses the snd-cs46xx module. Naturally, the speakers are plugged into the nice card.
When I installed Ubuntu 8.04 from scratch, the VIA card started showing up as the first card, and therefore the default card. (You can tell by looking at /proc/asound/cards.) I created the following /etc/asound.conf to remedy that problem:
pcm.!default {
type hw
card CS46xx
}
ctl.!default {
type hw
card CS46xx
}
Ok, so now all programs using ALSA's default device automatically go to the right soundcard. But apparently using the default device is too much to ask of some software, which apparently hardcodes hw:0 or (even nuttier) hw:0,0.
So what I really wanted was to fix the order problem, so that the VIA card doesn't steal index 0. On Ubuntu at least, the fix is:
echo 'options snd-via82xx index=2' >> /etc/modprobe.d/alsa-base
Now my /proc/asound/cards always looks like this:
0 [CS46xx ]: CS46xx - Sound Fusion CS46xx
Sound Fusion CS46xx at 0xfb122000/0xfb000000, irq 20
1 [UART ]: MPU-401 UART - MPU-401 UART
MPU-401 UART at 0x330, irq 10
2 [V8237 ]: VIA8237 - VIA 8237
VIA 8237 with ALC655 at 0xec00, irq 21
Stuff StuffIt!
I wish StuffIt would just die, already. I'm sick of running into .sit and .hqx files. Thankfully these are quite rare, and usually an indication that the project is ancient and unmaintained. If you ever find you do need to open one, though, head on over to The Unarchiver. Do not under any circumstances even visit the StuffIt website. Only you can prevent StuffIt fires!
I'm sick of Firefox asking me if I want to open archive files (zip, tar, etc.) with "StuffIt Expander (Default)". Earth to Firefox! StuffIt Expander hasn't been included with the OS for several versions now. It is not and never will be installed on my computer. Incidentally, it works just fine—opening files with the appropriate application. In other words, Firefox is a big fat liar. But we knew that.
I applaud Apple for finally dropping StuffIt a few years back. There has never, ever been a good reason (other than "I'm stuck in the 1990s OS 9 mac scene") to use StuffIt on OS X. Please join us in the 21st century. Use zip, tar+gzip, or tar+bzip2. Even better (for OS X recipients) use a .dmg. For the love of all that is green, do not do .dmg.sit! You won't get any more compression over a compressed disk image, and you will only make rational people foam at the mouth.
Die. Die. DIE.
