Playing audio CDs, part 11 – Why isn’t my sample ready for prime time?

As I mentioned in my previous post, the code I've provided will play back audio CDs.  But it's not ready for prime time yet.

There are four major problems with the code.

First off, the error handling isn't 100% up-to-snuff.  In particular, there are several error checks that are missing (if an allocation fails in the constructor of the CDRomReadData function, for example).  The error handling in general isn't robust enough for production code, and if there are failures during the read loop, the memory used to hold buffers is leaked.  That was an intentional omission to keep the size of the code down.

Next, the code totally ties up the callers thread.  That means it can't easily be adopted for use except in very limited scenarios.  And it's totally unsuitable for use in a Windows application (or a non windows application that uses STA apartment model COM objects).  For production systems that almost always a complete non starter.

Third, the code as written is utterly laptop unfriendly.  Laptops have a rather different power consumption profile than desktop systems.  For a laptop, battery life is king.  And, because of the laws of physics, that means that anything that involves moving parts is bad.  The bigger the moving part, the worse it is.  So writing code that involves moving heads on a hard disk is bad, but writing code that keeps a relatively heavy CD spinning in a CD drive is even worse.  For a laptop, it's far better to either spin the CD up once and transfer the entire audio data into memory, or to read the CD at 1x - slowly stepping the heads forward.  The absolute worst thing you can do is to spin up the drive and let it spin down again repeatedly - it doesn't take that much power to keep the disc spinning, but starting the disc up is horribly expensive.

The final version of this sort-of does the 1x read thingy - it moves the heads slowly forward.  But that means that the CD is spinning for the entire length of the track, which leads to increased power consumption.  With two or three buffers, this isn't that bad (again, it doesn't take too much power to keep the drive spinning).  But if you increase the CDROM_READAHEAD_DEPTH too high, you can actually get into a situation where playing back the audio samples takes so long that the CD drive decides to spin down the disk.  And that means that the next read, the drive spins up again.   And that's bad.  On a laptop, the "read it all into memory" version may actually be better from a power standpoint (it may cause the system to page however, which is bad - there are always trade-offs).

The fourth reason that this code isn't ready for prime time is what is known as "stitching".

You see, audio CDs were never designed to be played in a computer.  Instead, they were intended to be played back in a commercial CD player, with a simple track next/track previous command.  On those devices, it wasn't critical that data be able to be read reliably.

So it turns out that if you ask a CD-ROM drive to read bytes on the audio CDfrom block 253962 to 253972, you might actually get the contents of blocks 253961 to 253971, or the contents of blocks 253963 to 253973.  You can't predict what the actual data that's read from the disk will be. This limitation doesn't happen to CD-ROM disks because CD-ROMs were designed for accurate location.

Because you can't reliably read the data, you need to "stitch" together the samples you read with the samples that you last read.  That involves DSP and sample matching logic that's beyond my ability to describe in the context of a blog post.  But essentially the idea is that you match the samples at the start of the incoming data block with the samples at the end of the previous data block and look for overlaps.  If you find overlaps, then you slide the incoming block over until the overlapped samples line up.

If you don't really care about full fidelity rendering, then this probably doesn't matter.  But if you do, then you need to care about this issue.

Apple's got a pretty good description of their implementation of DAE and stitching (which showed up in Mac OS9) in their Tech Note 1187

And to be fair - Anonymous posted a pretty good description of the stitching issue in their comment on the first post in this series.

Comments (7)

  1. Anonymous says:

    Can we assume that in LH you can do DAE with just opening a Stream to the CD and then using CdReader or whatever?

  2. Anonymous says:

    Is it the stiching behaviour that the CD copy protection schemes deliberatly mess around with. Do they change the data slighly so that it can’t find where to stich or stiches in the wrong place?

  3. Joku,

    Since I don’t know what CDReader is, I don’t know the answer.


    I have absolutely no idea. I have no idea how CD copy protection schemes work.

  4. Anonymous says:

    "Do they change the data slighly so that it can’t find where to stich or stiches in the wrong place?"

    Several variations on the theme are used — having two blocks labelled the same, missing some blocks out, adding a second session with invalid data, and generally screwing with the layout in subtle but critical ways.

    (One side effect of this, of course, is that CDs protected in this manner don’t adhere to the standards, and therefore aren’t really allowed to have the "Compact Disc Digital Audio" logo on them.)

    A bit OT from here on, I’m afraid:

    More ‘sophisticated’ protection schemes are cropping up, but without the TCP (nee Palladium) there’s no surefire way to create a disc that will play on a regular CD player but will resolutely refuse to be "ripped" on a PC.

    CD-ROMs used to use a similar copy protection method but now the battle has been stepped up a couple of notches, most notably by StarForce; it’s a heinous system that installs a bunch of mini-drivers (which in some instances can cause HIDEOUS file I/O slowdown), and thus far the only sure fire way to evade it is to use a USB CD-ROM and/or disable all your ATAPI devices in the BIOS, or via tools such as the swearingly named StarForceFucker. Of course it’s only a matter of time until someone breaks it "properly", at which point (if I were a publisher or developer) I’d be inclined to stop throwing away good money on doomed DRM/copy protection.

    (Of course when (if) TCP rears its ugly head, and assuming it catches on, the story will be completely different. I for one hope that day never arises!)

  5. Anonymous says:

    Larry> Since I don’t know what CDReader is, I don’t know the answer

    I meant it would be a new manager wrapper doing, for example, DAE or reading ISO9660 image.

  6. Joku,

    I don’t know what the CLR teams plans are for managed access to multimedia.

    There may very well be teams doing just what you described, but I’m not aware of them (this doesn’t mean they don’t exist, btw).

  7. Anonymous says:

    Well, this year I didn’t miss the anniversary of my first blog post.

    I still can’t quite believe it’s…

Skip to main content