Monday, October 13, 2008

Streaming iTunes Music to my Squeezebox Duet Receivers

Apple's "Remote" iPhone (or iPod Touch 16GB in my case) application for controlling iTunes is so great that I wanted to see if I could use it to control my music in other rooms around my house. Buying an Apple Airport Express extender with its audio output would've been one means to that end. That hardware device costs $99 which isn't terribly expensive, but I already have Squeezebox Duet receivers in both my living room and master bedroom. Adding Yet Another Digital Music Receiver to both rooms seems like overkill (and would exhaust the inputs on one of my stereo receivers), so I decided to figure out how to control the music playing on those existing devices from an iPod Touch. (Yes, it really is a nicer UI than the SqueezeBox Duet controllers that are meant to be so great for this... sorry Logitech.)

Several possibilities occurred to me:

1) Reverse engineer the airport express protocol and improve the duet receiver firmware to make it look like an airport express to iTunes directly. This would be a great solution and Johansen (of DeCSS fame) appears to have done some of the reverse engineering and built some tools to stream data to an airport express. However, that's the wrong direction for my needs: I want something that emulates an airport express in software/firmware. (See also AirFoil that sends Mac audio output to an airport express; also the wrong direction.) This might be possible, but is more than a day's hacking.

2) Find a plug-in for iTunes that streams in a format accessible to my SqueezeBox Duet receivers. If iTunes would broadcast a URL of a streaming mp3, e.g., all would be great. Alas, no such luck.

3) Capture the iTunes audio output somehow (software or hardware) and use another piece of software to do #2.

4) Forego iTunes altogether and figure out a way to approximate Apple's Remote software for Squeezebox Duet's software, the SqueezeCenter (configured using the iTunes plugin so it uses the same library). The downside of this is that any DRM protected songs won't play, but my collection is predominantly ripped off of CDs rather than bought from iTunes (and I've been paying extra for DRM-free music whenever convenient). This approach is tempting, and Google-searching led me to iPeng which is a SqueezeCenter plug-in that skins the HTML it generates to be iPhone/Safari friendly. It's pretty nice, but way slower than Apple Remote because it's going over WiFi chattily and the SqueezeCenter server and the iPeng app apparently weren't written with latency in mind.

#4 might be a cool weekend (and more) project, though my underpowered Mac Mini makes me dread the thought of compile/download/test cycles on it. It's certainly more than a day's hack, too, but would be broadly useful in general (presuming Apple deems the App suitable for their store). The iPeng source might provide a useful starting place.

In any case, I ended up getting #3 working, and that's what I describe below. Note that I did all this work on a Windows XP PC, not the Mac mini I mention above and have blogged about previously.

The basic mechanism ends up being pretty simple and involves only a few components:

1) iTunes plays music, controlled remotely (over WiFi in my house) by Apple Remote running on my iPod touch;
2) Virtual Audio Cable (VAC) 4.0.9 from http://www.ntonyx.com/vac.htm ($30 from https://www.regsoft.net/regsoft/vieworderpage.php3?productid=76825, free trial) to capture iTunes output and loop it back to a virtual input device that is available to other Windows programs on the same machine (note that the free trial has a voiceover of "trial" every five seconds or so);
3) edCast DSP v3 plug-in for WinAmp v5.52 to connect to the icecast32 broadcast server;
4) the icecast win32 port to stream the data it gets from the edCast WinAmp plug-in.

At one point, I thought I needed the LineIn plugin v1.80 for WinAmp and I'm actually using it, but the edCast DSP plug-in allows you to transmit to icecast via a microphone on a selected device. That lets me just configure it to record from the Virtual Cable's SPDIF output directly.

The way I currently have it configured, though, is Winamp is playing from the virtual device "line://" (not its built-in linein:// -- that didn't work for me). My default audio output device is set to a Virtual Audio Cable before I start iTunes (it uses the default output device at startup for playback).

icecast32 is running as a server, I copied the lame mp3 encoder DLL and its ini file into the "Program Files\WinAmp" directory, restarted edCast, and configured an encoder to encode in MP3 and connect to icecast32 running on port 8070, creating a stream called "/stream.mp3". I then set my squeezecenter to playback the "streaming radio station" http://192.168.0.xx:8070/stream.mp3.

In the end, this results in about 4 seconds of lag between pausing on Apple Remote and the music actually pausing (or restarting, or whatever). A little over 3 seconds of that appears to be in the icecast server (for contrast, shoutcast server had over 30 seconds of lag -- unacceptable). I also tried the jetCast dsp PlugIn for WinAmp -- it's a simpler set up since it doesn't require a separate running broadcast server, but it was pretty flakey for me and I gave up on it after finding it just too inconsistent.

I do think I can avoid Virtual Audio Cable, too, by just using a coupler cable to connect my sound-card's audio output to one of its line-inputs, but that would involve an extra gratuitous D->A and A->D conversion pair (but save $30). Another downside of this approach is that it ties up my soundcard more, making it hard to listen to music at my PC while different music is playing around the house.