Every lesson is one concrete spec with exact bytes or exact integer samples: the RIFF header pinned byte for byte, a 16-bit little-endian sample 00 80 decoding to -32768, the even-size padding byte after an odd data chunk, gain that clips at +32767 instead of wrapping, a mix sum that clamps, byteRate equal to sampleRate times blockAlign, a sine sample at a known phase with the rounding stated, and mono duplicated to stereo then averaged back with rounding. No real audio hardware, no external files - just bytes and samples you can assert.
Over 31 lessons you build a working WAV/PCM toolkit from scratch: a library that reads and writes real WAV files and transforms raw PCM samples, with a small command-line tool on top. Everything is pinned to exact bytes and exact integer samples, so the toolkit you write behaves identically in any language and needs no audio hardware or sample files to test.
You begin at the container level, walking the RIFF/WAVE format one chunk at a time - a four-byte id, a little-endian size, a payload - parsing the fmt chunk's fields, skipping chunks you do not recognise, and honouring the even-size padding byte. Then you decode PCM samples for every common depth (8-bit unsigned with its 128 bias, 16-bit and 24-bit signed little-endian, and 32-bit float), de-interleave stereo into per-channel slices, and turn the whole thing around to write valid files, proven correct by round-trip equality. On that foundation you add the sample math - gain with clipping, mixing with clamping, normalization to a target peak, linear fades, reversing, and channel conversions - then synthesize sine, square, and sawtooth tones, shape them with an ADSR-lite envelope, and add a delay echo. The capstone synthesizes a two-tone stereo signal, applies gain, a fade, and a mix, writes a 16-bit stereo WAV, and reads it back to confirm the exact samples and header.
This is a teaching-grade toolkit built around uncompressed PCM in the classic RIFF/WAVE container. It decodes 8/16/24-bit integer and 32-bit float PCM and writes 16-bit PCM, but it deliberately stops short of the wider format: writing is 16-bit only, no compressed or ADPCM codecs, no WAVE_FORMAT_EXTENSIBLE channel masks, no cue/list/metadata chunk authoring, and no resampling or filtering beyond the effects you build. That honest core is exactly what production libraries like libsndfile and dr_wav extend with more codecs, formats, and streaming.
A WAV file is built out of chunks, and every chunk starts with a four-byte ASCII tag that names it. Today you read those four bytes back as text, the smallest possible first step into the format.
Read four bytes and return them as a four-character ASCII string.
The WAV format is a specific use of a general container called RIFF (Resource
Interchange File Format). A RIFF file is a sequence of chunks, and every chunk
begins with a four-character code - four raw ASCII bytes that name what the
chunk is. RIFF, WAVE, fmt , and data are the ones you will meet first.
These tags are stored as plain bytes, big-endian in the sense that byte order is
just reading order - the first byte is the first character. Note that fmt is
four characters including a trailing space (0x20); the format is strict about
the count, so the space is real and required. Today is deliberately tiny: turn four
bytes into a string. Every chunk you parse from here on starts exactly this way.
// a chunk id is just four ASCII bytes, read in orderfunc readID(b []byte) string {return string(b[0:4])}
The toolkit reads and writes real 16-bit PCM WAV files end to end (verified against macOS's afinfo) with a working synthesize, transform, and inspect CLI, but write is 16-bit only, 32-bit float read is decoded yet not wired in, and there is no metadata, cue, or compressed-format support.
The single clearest one-page description of the canonical 44-byte WAV header - every field, its offset, size, and endianness, with the exact byte layout this project pins lesson by lesson.
Microsoft's authoritative definition of the fmt chunk fields (wFormatTag, nChannels, nSamplesPerSec, nAvgBytesPerSec, nBlockAlign, wBitsPerSample) and the derived-value rules the writing chapter reproduces.
A free, exceptionally readable DSP textbook - quantization, sampling, gain, mixing, and the math behind the synthesis and effects chapters, without assuming a signals background.
A short primer on the two numbers that define PCM audio - sample rate and bit depth - and what quantization and clipping actually mean, useful orientation before the decoding chapter.
The original RIFF container specification: chunk structure, the four-byte id plus little-endian size plus payload, and the word-alignment padding rule that the container chapter implements.