ACIDCAT . FILE FORMAT REFERENCE

WAV Anatomy

RIFF / WAVEPCM + metadata
rev 2026.06
magic "RIFF"
endian little
container chunked
order fmt before data

A WAV is a RIFF container: the 12-byte RIFF header, then a sequence of chunks, each an id, a 32-bit little-endian size, and that many payload bytes (plus a pad byte if the size is odd). Regions below list the chunks; the fmt and acid chunks are drawn byte by byte. Hover a field to light its bytes, click a field with a + for its table. Color marks kind (see the key).

chunk regions

Order varies by writer; only fmt-before-data is guaranteed. Reads are bounded and every declared size is checked against the bytes that remain.

RIFF header0x00 . 12 bytes
magic"RIFF"
riff_sizeu32 LE = file size - 8 (often stale; linted, not trusted)
form type"WAVE"
fmtformat . drawn below

The audio encoding. 16 bytes for PCM (the byte map below), 18 with a cb_size field at 0x10, 40 for extensible (tag 0xFFFE), which appends:

cb_sizeu16 extension byte count, 22 for extensible
valid_bits_per_sampleu16, real precision inside the container word
channel_masku32 speaker bitmask, low bit first: FL FR FC LFE BL BR FLC FRC BC SL SR TC TFL TFC TFR TBL TBC TBR
sub_format16-byte GUID: 2-byte format tag + fixed tail 00000000-1000-8000-00AA00389B71; a non-standard tail is warned
factsample count . 4 bytes
sample_lengthu32 samples per channel; the authoritative count for non-PCM codecs
0xFFFFFFFFRF64 sentinel, resolved via the ds64 sample_count; warned if ds64 is absent
datathe audio payload

Interleaved PCM samples. duration = data_size / (rate * channels * bytes_per_sample). A declared size past EOF is linted, and acidcat derives duration from the bytes present, not the claim.

acidloop metadata . drawn below

The project's namesake: Sonic Foundry ACID tempo, beats, meter, and root note. No official spec; layout field-verified against real ACIDized packs. See the byte map below.

smplsampler root + loops
midi_unity_noteroot key; 0 = unset sentinel, not C-1
num_sample_loopseach loop is 24 bytes: start/end in sample frames
instinstrument tuning . 7 bytes
base_noteMIDI root, usually duplicates the smpl unity note
detune / gaini8 cents (-50..+50) and i8 dB adjustment
note / velocity rangelow..high playable keys and trigger velocities, one u8 each
cue / LISTmarkers, text
cueu32 count (clamped to payload), then 24-byte points
LIST/INFOINAM title, IART artist, ICMT, IGNR, ...
bextbroadcast wave . 602-byte fixed area
description256-byte free text
originator32-byte creator name
originator_reference32-byte unique reference
time_referenceu64 sample count since midnight, two u32 halves
version0, 1, or 2; the fixed area is 602 bytes in every version
umid64-byte SMPTE ST 330 identifier at 0x15C, v1+
loudnessv2: five i16 at 0x19C in hundredths of LUFS/LU/dBTP; 0x7FFF = unset
coding_historyASCII EBU R98 rows from 0x25A to the end of the chunk
RF64 / ds6464-bit sizes . EBU Tech 3306
header"RF64" replaces "RIFF"; the 32-bit size holds the 0xFFFFFFFF sentinel
ds64 fixed area28 bytes, must be the first chunk: riff_size u64, data_size u64, sample_count u64, table_length u32
override tabletable_length records of 4-byte chunk id + u64 size, for non-data chunks carrying the sentinel
resolutiondata takes data_size, others read the table; a sentinel with no override is linted
fmt chunk

16 bytes for PCM. Example: 16-bit stereo at 44100 Hz.

acid chunk

24 bytes. Example: an 8-beat 4/4 loop at 120 BPM, root C4, root-set flag.