Looking at a-Pac

Since currently there’s a preparation phase for the next Ukrainian counteroffensive and I don’t know what other features to add to NihAV (beside improving video player), I was bored enough to do this.

After a comment from Paul, I’ve looked at some random lossless audio codec from 90’s, namely a-Pac. While the codec by itself it very simple (no LPC or IIR filter, no variable-length codes except in block header, no arithmetic coder either) as you can see from its description in the Wiki, it was a bit tricky to RE.

The main issues being: apac.exe is in NE format (which means 16-bit code and Ghidra sucks at figuring out which segment registers should be used when) and, which is worse, written in Delphi with all the quirks of its object model implementation. So it’s after some search I’ve found the virtual table corresponding to the APAC format handler (both coding and decoding) and after trying one function after another I’ve finally found the one responsible for encoding—after which finding a decoder function was easy.

The code itself (beside the weirdness introduced by Delphi compiler like using both positive and negative offsets in vtable calls) is very old-fashioned too: bit reading is done by keeping bitreader state as global variables, reading n-bit values by reading a single bit in a loop and refilling that bit buffer every byte (with a callback function).

It’s still fun to see how we’ve moved from simple formats like this to overcomplicated formats like LA or OptimFrog while settling down on in-between complexity FLAC, Monkey’s Audio and WavPack.

Leave a Reply