Saturday, September 3, 2011

Fun with WAV

Last year, a "Fun with wav" post got a lot of visibility. The author was trying to extract the header from a audio file in the WAV format and output the sum of the remaining data in the file. He gives the disclaimer several times that this was a specific hack and not a generalized solution.

Although the original solution was in C, he received other possible solutions on Reddit. The "winner" by code golf rules is probably Ruby:

Each WAV file begins with a "master RIFF chunk" followed by format information and the sampled data. We could read each field specifically, or we can capture this header information directly into a packed structure (I added support for these in January and recently merged it into the main Factor repository).

PACKED-STRUCT:header{idchar[4]}{totallengthint}{wavefmtchar[8]}{formatint}{pcm short }{channels short }{frequencyint}{bytes_per_secondint}{bytes_by_capture short }{bits_per_sample short }{datachar[4]}{bytes_in_dataint};

We can easily read from an input stream directly into this structure:

:read-header(--header)header[heap-size read ][memory>struct] bi ;

The original solution then produced a sum of the remaining file, treated as a sequence of shorts (16-bit integers).

It might be useful to add some validation to this example (much like the original C version) for such things as endianness and the 16-bit WAV format. Alternatively, we could improve it to be more general to handle 8-bit or 24-bit encodings, as well as other header formats (not just the "extended WAV" format).