Birds Linux jukebox

Background

Leisa & I have somewhere around 200 audio CD's. They are semi-organised into 4 compact carousels (40 in each) with the rest just piled up in various places around the hifi cabinet. We have a serious problem finding a particular CD, and as we slowly buy more CD's the problem is getting worse. We have contemplated some sort of computerised "system" to keep track of them, but it all seems like too much effort, and would need constant attention to keep up to date.

The better solution seemed like a simple enough idea - build a linux based PC to sit in the bottom of my home hifi cabinet and load it up with all the tracks off our audio CD's. Stick a wireless network card in the back and let it join my existing home wireless network, with a "jukebox" network service to allow other client PC's to connect and ask for tracks to be played.

Leisa thought this was a great idea - she would be able to command the Jukebox to play music from her notebook computer (a sony Vaio) without leaving her chair. Soon after suggesting this, I was presented with a list of required features - the system must support user-defined playlists, a command history (a-la GNU readline), a locate command for searching for particular tracks and so on...

Well, I got there in the end. It has taken about a month from start to finish, and I have found a few surprises along the way. I thought it was interesting enough to write this summary page for anyone else who wants to try doing this.

Audio Data Format

A major design decision revolved around what format to use for the stored audio tracks. They come off the discs in raw PCM, and the three main choices seemed to be:
  1. Store them "as-is" in raw PCM format
  2. Store them as WAV files (PCM + a small header)
  3. Convert them to something like MP3 or one of the other lossy formats.
I discarded option 3 pretty quickly. A rough calculation showed that I could fit all my audio discs onto a 120Gb hard disk without any loss of quality, and 120Gb drives are available for a reasonable cost in Australia. I had recently read a review of a nice-sounding, quiet and cool-running 120Gb drive from Samsung. Exactly what I wanted for this project (model number SV1204H).

In the end I decided to store the data as WAV files, so that I had more options for playback. I experimented briefly with using gzip to compress the files, but decided against it because it made seeking around on the input files a bit trickier (and I am conscious of the amount of CPU time needed by the player. Too much wasted CPU cycles and the audio will skip.)

There are a few lossless audio compressors around (e.g. FLAC) which can reduce the size of the audio data by around 50 percent or so - I might try one of them in the future, but I have enough space to do without and I am still wary of CPU usage.

S/PDIF "digital" playback

Here is an interesting tale...

My home hifi unit can take a digital S/PDIF audio input, so I planned to feed the digitally sampled audio tracks out to the hifi unit (a Yamaha RX-V2095) via a sound card with S/PDIF ouptut. This turned out to be a surprisingly difficult goal to achieve without losing sound quality - my opinion of various sound card manufacturers has dropped quite a bit as a result of this experience.

As a complete neophyte to digital audio, I had assumed that the "digital" connectors on soundcards were able to output the raw PCM audio in my sound files without any processing, giving my Jukebox the same sound quality as I get when playing audio discs through my DVD player (44.1kHz PCM sounds clearly better than the audio coming out the analogue RCA connectors on my existing CD player). My first attempt at a proof-of-concept used my existing Soundblaster Live! card. The S/PDIF digital output was at 48kHz, and sounded awful. It turns out that the SBLive! always resamples its input signal up to 48kHz, and the algorithm that it uses for this is not very good. Maybe it's ok for small computer speakers or something, but it's a complete waste of time for home hifi use.

This, as I then discovered, is part of the "AC97 sound specifiction". The S/PDIF output will always be at 48kHz regardless of the input on cards which are "AC97 compliant". This means that audio CD samples at 44.1kHz will always be resampled up to 48kHz, probably with audible loss of quality.

AC97 is very popular among the manufacturers of soundcards and motherboards. It is also hopeless for use in this kind of hifi jukebox.

I have found only one sound chip which is able to pass through audio samples at 44.1kHz unchanged via S/PDIF - the C-Media CM8738-MX. There may be others, but after a couple of days of R&D this was the only candidate that I could find. Various motherboards by ASUS use this as their onboard sound, and it is also used as the basis for a number of soundcards. It is perfect for use in the jukebox, and comes with good Linux support.

There are many nice things to like about this chip - for example the S/PDIF output is disabled when it is not in use (unlike many other chips, where the 48kHz carrier is permanently on), so it integrates nicely into my hifi system. My amplifier can auto-sense whether the "CD" audio is coming from the analogue or S/PDIF input, so it is important that the jukebox shut up when it's not in use.

In the end I found a sound card with this chip (Leadtek WinFast 6X Sound). They are cheap - this cost me $60 Australian (about US$30 or so). I think this series is actually discontinued, so you might have trouble finding one of these. I bought a spare just in case :-)

This card is also nice enough to provide the optical and coaxial S/PDIF connectors, saving me the trouble of building an adaptor.

Note: DO NOT try using the low-end versions of this chip (the 8738-LX and 8738-SX) as they do not provide S/PDIF output. These low-end versions of the cmedia chip are _very_ common on really really cheap soundcards.

Ripping the Audio

I am using cdparanoia to rip the audio tracks. This worked out pretty well - cdparanoia rips all the tracks of an audio CD into files named "track01.cdda.wav", "track02.cdda.wav" etc. The next step was to create a directory hierarchy by artist / album and move the ripped tracks in after renaming them to resemble the title of their respective songs. To help here I grabbed the CDDB-1.08 Perl module (available from CPAN and a program named discid from freshmeat.net. Using these as a guide, I wrote "dotherip.pl" - a perl script which uses a modified discid to identify the disc, cdparanoia to rip the tracks, and the CDDB perl module to connect to the freedb service to get the disc information - artist name, album name and track names. dotherip then renames the tracks and puts them into a semi-sensible hierarchy suitable for use by the jukebox player. As part of the effort to rip about 200 audio CD's, I also wrote a small script named "ripmon" whose task was to monitor the CDROM drive on this PC and call dotherip.pl if it detects a CD has been inserted. This works well, as dotherip will eject a CD after it has ripped it, and also checks for duplicates so that the same CD will not get ripped twice. The result is that it is quite painless to just keep feeding in the audio discs. After each one is ripped it is ejected, the computer beeps to get my attention, and then I just pop in the next one. No interaction via keyboard,monitor or network required. This PC has to live with the hifi equipment in the living room so it is very important that it be quiet and tolerable of claustrophobic conditions. It will be hidden behind a closed panel in the bottom of the hifi unit without much ventilation. For reasons of temperature and noise I chose to use a Samsung 120Gb disc (SV1204H). Various reviews show it to run significantly cooler and quieter than the usual crowd of 7200rpm monsters. It's also a lot cheaper thanks to its 5400rpm rotation speed.

The Hardware

I used one of my spare machines - a P3 running at 550Mhz. This is plenty fast enough. Since I am using Perl for all the software I am mindful that I need a fast-ish CPU so as not to starve the audio device ( there is a bit of time lost in any interpreted language like Perl) but in practice this CPU is fine. I am considering replacing it with a VIA C3 with passive cooling...

The Harddisk is a Samsung SV1204H. This seemed to be to be clearly the best choice. Check out reviews in various places (Toms Hardware for example).

The CDROM drive is a RICOH MP7320A CDROM / CDR / CDRW drive. This drive is almost silent and makes a nice counterpart to the Hard Disk. Has anyone else noticed that CDRW drives are now ridiculously cheap and fast?

It is important to turn on DMA for the Hard disk. This just required editing /etc/sysconfig/harddisks. I also set the readahead to 128 sectors. What the heck - it can't hurt :-)

My motherboard is old, so it only supports up to UDMA2. A newer motherboard will get you better performance (or, more importantly, lower CPU usage). Anyway, the current system sits almost totally idle, even when playing multiple audio streams (locally + across the wireless link) and simultaneously ripping tracks from an audio disc.

The Power Supply was an A-Open "Noise Killer" which runs almost totally silent.

The end result is a system which is very quiet. If I dropped in a VIA C3 CPU with passive cooling then it should be completely silent - all I can hear now is the CPU fan.

The Software

The Linux system was RedHat 7.3. I used a D-Link DWL520 wireless PCMCIA card + PCI adapter to connect it into my home wireless network. This works fairly well, but I'd advise against purchasing this card - I have had much better reliability and performance from my other wireless cards (Lucent "Orinoco" series). The D-Link card works well enough, but it's not ideal.

I am using Samba to make all these tracks visible across the network as a WinDoze mapped drive so that I can also play them on other machines. Now I can access all my stored music even if I am downstairs in my office.

Almost all of the playback and user-interface software is written in Perl (my favourite language). For a while I was using SoX to drive the sound device (/dev/dsp) but in the last couple of days I have figured out how to do that from Perl as well, meaning that my "playback" service is now a single perlscript.

There are two programs that make up the jukebox playback service - one program (playtrack) which is permanently running in memory, and another program (mediaserver) which provides the user interface. These two communicate via shared memory, so there can be many mediaserver clients all talking to the one central "playtrack" server.

In practise this means that I can connect into the jukebox from anywhere in the house and see what it is currently playing, and upload or alter the list of tracks.

There is currently very rough docs, and copies of the source and binaries here.

So there you go - large/cheap harddisks and wireless networking now make buiding a Jukebox system relatively easy. The only trick (if you are interested in "perfect" sound quality) is finding the right sound chip.

Links

I browsed through a LOT of websites over the last few weeks - here are some links that you ought to follow if you want to try something like this: Anthony Wesley awesley@acquerra.com.au