Reading Cart Chunk with PowerShell

Look at the audio files in any professional radio playout system. They’ll likely be linear WAVE files with the associated metadata stored in the cart chunk format. With this information it’s usually enough to successfully share audio between stations and systems (there are some issues around time markers but they can be worked round).

With that in mind, a recent project required me to read the cart chunk data from an existing playout system using PowerShell. It might not seem an obvious option for this but as the ubiquitous scripting language on the Windows platform, it should be possible and require a lot less work than writing and maintaining a full .NET application.

Before we crack into the code, it’s worth taking a look at how a WAVE file is broken down. At the top level it’s a single “chunk” called the RIFF chunk. The header of this chunk is made up of two 4 byte values – the tag (“RIFF” in this case) and the length of the chunk content. As this is the top level chunk, the length is the length of the rest of the file.

Within this top level chunk, you’ll see a number of smaller chunks. Some are required (e.g. data and fmt), others not so much (e.g. cart and bext). These chunks all use the same header format as the top level chunk. That means it should be simple enough to skip through the file looking for the chunk you want rather than reading the whole file into memory.

If you want a bit more information about the technical details of how the chunks are formatted, check out this site. The fmt and data chunks are of most interest if you’re planning to read or write the audio data from the files.

That’s the entire thing ready to go. Admittedly it only reads the title and artist fields but it wouldn’t take much to extend it into any of the other fields you need.

Either way, let’s take a closer look. One of the first lines to jump out would be:

$encoder = [System.Text.Encoding]::UTF7

The WAVE format (and cart chunk) is old enough that it’s specified the fields should be ASCII format. As that has no support for accented characters, you’ll often see UTF7 encoding used instead. This is one of those real world vs. specification things.

A little further down you’ll see we read the file in as a binary and look for the RIFF tag we talked about earlier.

Assuming we’re all good, we shift past the initial header and enter the main loop. This loop is constructed so that we check every chunk in the file until we see the one we want. The location of the cart chunk in a WAVE file is not explicitly defined. You’ll find that playout systems vary between placing it ahead of and after the audio data.

This is one of the reasons skipping through the file rather than reading it in wholesale is a nicer approach. While we’re on the topic of skipping through the file, we calculate the length of our next skip using the following code:

From this bigger buffer we can now read in the cart chunk contents. In this example, we’re only extracting the artist and title which we then present back to the user as an object. It’s here that you’ll want to add any code of processing further fields.

And that’s all you need to read cart chunk in PowerShell. Turns out it’s much simpler than I thought it would be.