A copy of the DDJ Cover from January, 2000, here for decorative purposes only.i Dr. Dobb's Journal
January, 2000
by Charlie Munro and Mark Nelson

This summer a remarkable thing happened in Dallas, and for once it didn’t have anything to do with triple digit temperatures or the Dallas Cowboys. In fact, this story didn’t even make the front page of the newspaper; it was buried in a garish Fry’s insert. What was it that made this advertisement newsworthy? Simply the news that an 18 GByte disk drive could be had for the price of $180.

What makes this price point so interesting is that it means we have now reached the point where a Megabyte of hard disk space can be had for the grand total of one cent. Doing The math led us to an inescapable conclusion: the ultimate home jukebox was now within our reach.

Laying down tracks

After a quick trip to Fry’s, followed by a few hours of rehab work on some older PCs, we had inexpensive home music servers that were ready to be loaded with our personal collections. The format of choice for recording music from CDs is MPEG-1 audio layer 3, popularly known as MP3. We found that most CDs can be digitally converted to MP3 format at a rate of 160 Kbps with no great loss of fidelity. (Trained ears or high quality audio gear might require higher rates.) This meant that our new 18Gbyte drives could hold up to 300 CDs, enough for a good-sized personal collection!

Creating MP3 recordings on your PC involves two steps: ripping and encoding. Ripping refers to the process of extracting the music from the CD itself. Ideally this is done digitally, reading the actual bits directly from disk. We were able to do digital ripping on most machines, most of the time, but in some situations had to fall back to analog ripping. This less-desirable method involves playing the CD tracks through your sound card, then digitizing its analog output. The slight loss of fidelity may be minimal, but it human psychology seems to magnify the loss out of proportion.

Once the tracks have been ripped to your hard disk, usually as WAV files, the encoder converts them to MP3 files. The MP3 files can be encoded at rates as low as 16 KBps ranging up to 320 Kbps. Our selected rate of 160 Kbps reduces the WAV file size by roughly 9 to 1.

Integrated programs that rip and encode generally also take advantage of online CD track databases. These databases keep playlists for as many titles as possible, and can be accessed via the Internet. (See www.cddb.com for more information on these databases.) The encoder can embed this track information in the MP3 file in an information element known as the ID3 tag.

A typical ripping session in progress is shown in Figure 1. The program in question, AudioCatalyst, is an integrated ripper/encoder from Xing, a company that is known for their multimedia compression and rendering engine.

A screen capture of the AudioCatalyst app in the process of ripping a CD.
Figure 1 — A rip/encode session in progress

Getting organized

The whole point of putting your entire CD collection on a hard drive is ease of access. Being able to play what you want, when you want, is like being the program director of your own radio station.

Making the database of music easy to work with involved a couple of different design decisions. The first decision we made was the naming scheme for the files and directories that would hold the music repository. Each CD was placed in its own directory, which fell under a virtual root using the directory naming scheme of Artist/Title. The individual songs were named according to the scheme Track Number — Title.mp3. A shot of the resulting organization is shown in Figure 2.

This shows a file explorer view from Windows, which demonstrates that the music storage system relies on a specific directory structure. The top level directory is the group name, then the album name. The song files are stored in the album directory, and are named with a numeric prefix indicating the position in the album.
Figure 2 — The Music Repository Naming Scheme

This naming scheme was really designed for the human navigation. Regardless of the software we used to play our music, we knew we could find individual CDs or tracks quickly and easily. Using Windows drag and drop, it’s easy to quickly select individual tracks from a CD and drag them Onto a player. This gives us the convenience of a simple database without any real programming.

This directory structure is good, but scanning it when looking for music can be time consuming. Asking the operating system to traverse the structure with a library of several hundred CDs can mean minutes of disk activity. To avoid doing this constantly, we also created a single directory of M3U playlists. By making our Playlist folder a Virtual Directory on the web server, we’ll have an easy way to link to these files from a web page.

Most popular MP3 players (including Windows Media Player) support the M3U format, which is actually just an ASCII list of files. A typical M3U file is shown in Figure 3.

\\mark\d\My Music\Radiohead\The Bends\1_Planet Telex.mp3
\\mark\d\My Music\Radiohead\The Bends\2_The Bends.mp3
\\mark\d\My Music\Radiohead\The Bends\3_High And Dry.mp3
\\mark\d\My Music\Radiohead\The Bends\4_Fake Plastic Trees.mp3
\\mark\d\My Music\Radiohead\The Bends\5_Bones.mp3
\\mark\d\My Music\Radiohead\The Bends\6_(Nice Dream).mp3
\\mark\d\My Music\Radiohead\The Bends\7_Just.mp3
\\mark\d\My Music\Radiohead\The Bends\8_My Iron Lung.mp3
\\mark\d\My Music\Radiohead\The Bends\9_Bullet Proof..I Wish I Was.mp3
\\mark\d\My Music\Radiohead\The Bends\10_Black Star.mp3
\\mark\d\My Music\Radiohead\The Bends\11_Sulk.mp3
\\mark\d\My Music\Radiohead\The Bends\12_Street Spirit (Fade Out).mp3
Figure 3 — Contents of Radiohead - The Bends.m3u

Note that the file names are given as network shared drives. This is critical for making your music playable on any system in your home network. It also allows us to expand our collection across disks or even machines. M3U files can be created using the command line DIR command, or using most popular players. We usually use WinAmp’s playlist editor to create ours.

The Friendly Front End

Once you’ve gone to the trouble of setting up a home music server, you probably are already thinking about serving up HTML pages from the same system. We thought it would be nice to have a web page that listed all your music in a somewhat organized form. Better yet, the web page ought to be able to dynamically create the index based on the contents of an M3U directory.

It takes a bit more than plain HTML to accomplish this, but nothing too sophisticated. Since we decided to implement our directory using Active Server Pages we were committed to using Microsoft’s servers. We’ve used both IIS and Microsoft’s Personal Web Server with good results.

Figure 4 shows a screen shot of the web page that organizes the music. Having the titles organized by artist, having all the artists in alphabetical order, and then having links that let you move quickly through the page all contribute to making it quick and easy to choose your selections. Each album name you see is a hot link to an M3U file. Clicking on it automatically launches your MP3 player and begins playing the CD.

A view of the web page, showing a listing of artists and albums.
Figure 4 — The Dynamically Generated Web Page

The Script Behind the Page

The web page that generates the screen in Figure 4 is not a static HTML page. Nearly all of the HTML for the page is generated when the page is loaded using some simple JavaScript. Listing 1, default_js.asp, contains all the code used by this page.

The routine that sets up all the data for this page to display is function GetFileList(). It uses an instance of the ASP FileSystemObject to create a list of all the M3U files our Playlist directory. The Server.MapPath() method lets us get the path to the M3U files from the virtual directory name. One thing to notice in the GetFileList() function is the way we loop through the files. Unlike VBScript, where you can iterate through members of a files collection using For Each Item In CollectionObject, JavaScript requires you to explicitly create an Enumerator object for the files collection. We then use the object.item() method to set a variable to the current file object in the collection.

These file names are stored in array fileList[] when the function is called near the top of the page. The list of files is then sorted using JavaScript’s array.sort() method. Since the file names start with the artist, this clumps all the files for a given artist together in the list. One note of caution: Since the JavaScript array.sort() method uses ASCII sorting (A-Z before a-z) by default, it’s important to have all your file names start with uppercase letters.

After generating the HTML for the very start of the page, we create a dynamic list of hot links to each of the possible first letters in the artists in the collection. Once the index of single letter links has been written out, the rest of the page is created in a simple loop that iterates over each file in the fileList[] array. For every file in the list, we are going to create a link on the web page that has the name of the CD (with the artist name stripped off) and points to the M3U file. The code that does that is at the bottom of the loop:

idx = fileName.indexOf(" - "); // find the delimiter separating artist 
title = fileName.substring(idx + 3, fileName.length - 4);
title = jTrim(title);
    
href = rootPath + pathSeparator + Server.URLPathEncode(fileName);
Response.Write("<DD><A HREF=\"" + href + "\">" + title + "</A></DD>\n");

In this part of the code, the title variable gets the album title portion of the file name, and it is what is displayed. The full path name is used as the actual link, but this is simply our virtual directory name and the file name. The formatting for the whole listing is accomplished using Definition List block elements (<DL>) for each letter, with each artist as a defined term (<DT>) and each title as a definition (<DD>).

We open and close the definition list elements using code executed conditionally at the top of the loop. For each title, we check to see if the Artist has changed by comparing lastArtist and artist. If the Artist has changed, we check to see if that artist is the first to start with a new letter. If it is the first, we call doNextLetter() which closes out the current list (<DL>) of titles, inserts a new anchor, starts the next definition list, and returns. For each new artist, we insert the artist name as a Defined Term (<DT>). If the artist for the current file is the same as lastArtist, then we write just the title as a definition (<DD>).

References

MP3’ Tech at www.mp3tech.org provides a great deal of technical and programming information regarding the MP3 format. MP3.com at mp3.com has links to popular freeware, shareware, and commercial players and track rippers. A few of the programs we’ve had success with are listed below.

Commercial Ripper/Player
AudioCatalyst 2.x Xing Technology Corporation www.xingtech.com (Link is no longer available)

Free Ripper
CDex 1.2 (beta) ALFA Technologies www.surf.to/cdex (Link is no longer available)

Shareware Player
WinAmp 2.x Nullsoft, Inc. www.winamp.com

Commercial Player
(Free download) Windows Media Player v 6.x Microsoft www.microsoft.com

Commercial Ripper/Player
(Crippled version is free) RealJukebox Plus Real Networks www.real.com

Listing

The listing file contains default_js.asp, the javascript page that was created for this article.

listing.zip