After the header come the seek table, any data kept from the original file, and the compressed frames. The order depends on the version.
File layout
| Version 3980 and later | Before version 3980 |
|---|---|
| Junk (optional) | Junk (optional) |
| Descriptor | Old header, with the peak level and seek count if flagged |
| Header | WAV header, unless flag 32 is set |
| Seek table | Seek table |
| Header data (WAV header) | Bit table, below version 3810 |
| Frames | Frames |
| Terminating data | Terminating data |
| Tag | Tag |
The first frame starts at the sum of the junk, descriptor, header, seek table and header data sizes, plus one byte per frame for a bit table below version 3810.
Seek table
The table is an array of 32-bit little-endian values, normally one for each frame. FFmpeg
discards the first entry and places the first frame by the sum above. Every other entry
plus the junk length is a frame’s position in the file. In version 3980 and later the
table’s size is nSeekTableBytes; older files use the seek element count, or one
entry per frame.
Frames start on 32-bit boundaries measured from the first frame. When a position does not,
the remainder, (position − first frame) & 3, is a count of bytes to skip
after reading from the boundary below it.
Bit table
Files below version 3810 have one byte per frame after the seek table. Each byte is a count
of bits to skip at the start of its frame, combined with the byte skip above as
skip × 8 + bits. A nonzero count also adds four bytes to the previous frame’s
size.
Data from the original file
Monkey’s Audio keeps the source file’s non-audio bytes, so that decoding can restore the file exactly. The header data is everything before the audio, typically the WAV header; the terminating data is anything after the audio. With format flag 32 no WAV header is stored, and the decoder creates one.
The frames’ total size is held in two words, so files can exceed 4 GB. The history records repeated work on large files, up to version 10.65.
Frames
Every frame has nBlocksPerFrame blocks, except the last, which has
nFinalFrameBlocks. A frame’s bytes are a series of 32-bit little-endian words
that together form a big-endian stream: FFmpeg swaps each word’s bytes before decoding.
A frame in that swapped order begins:
| Size | Field | Meaning |
|---|---|---|
| 4 | CRC | Big-endian. Above version 3820, the top bit set means frame flags follow; the other 31 bits are the CRC |
| 4 | Frame flags | Only if that bit is set |
| 1 | Skipped byte | Version 3900 and later: one byte, then the range coder |
| varies | Compressed audio | See entropy coding |
Before version 3900 the frame is read through a bit reader instead, so these fields are read as bits.
Frame flags
| Value | Name | Meaning |
|---|---|---|
| 1 | APE_FRAMECODE_MONO_SILENCE | A silence bit. FFmpeg names it but tests only the mask of 3 |
| 3 | APE_FRAMECODE_STEREO_SILENCE | Both silence bits: a stereo frame is entirely silent, with no audio data |
| 4 | APE_FRAMECODE_PSEUDO_STEREO | A stereo frame holds one channel, copied to the other |
In a mono stream, FFmpeg treats either silence bit as a silent frame. In a stereo stream, it needs both.
The frame CRC
The CRC covers the decoded audio, not the compressed bytes. FFmpeg verifies it from version 3900 on, when asked: it computes an IEEE CRC-32, starting from 0xFFFFFFFF, over the little-endian bytes of each decoded sample in turn, one channel after another, using three bytes for 24-bit audio. The stored value is the complement of the result shifted right by 1.