build-a-wav-pcm-toolkit / lesson-02.md
Lesson 02 · The RIFF/WAVE container

Little-endian integers

Every numeric field in a WAV file - sizes, sample rates, channel counts - is stored little-endian, least significant byte first. Today you decode those bytes into integers, the second half of everything the container is made of.

The goal

Decode a little-endian uint16 and uint32 from their bytes.

Start here - the target
TO DO
Scenario: Little-endian bytes decode to integers
Giventhe four bytes 0x2C 0x00 0x00 0x00
Whenthey are read as a little-endian uint32
Thenthe value is 44
Andthe two bytes 0x10 0x00 read as a little-endian uint16 give 16, and 0x44 0xAC give 44100
Background

RIFF stores every multi-byte number in little-endian order: the least significant byte comes first. So the four bytes 2C 00 00 00 are not the number 0x2C000000 - they are 0x0000002C, which is 44. You rebuild the value by taking each byte, shifting it left by eight bits per position, and combining them: b[0] | b[1]<<8 | b[2]<<16 | b[3]<<24.

The two sizes you will use constantly are the 16-bit fields (channel count, block align, bits per sample) and the 32-bit fields (chunk sizes, sample rate, byte rate). 0x44 0xAC little-endian is 0xAC44 = 44100, the most common sample rate in the wild. With chunk ids from last lesson and integers today, you have every primitive the container is built from.

Make it work
// little-endian: byte 0 is the low 8 bits, byte 1 the next 8, and so on
func u16(b []byte) uint16 {
return uint16(b[0]) | uint16(b[1])<<8
}
func u32(b []byte) uint32 {
// combine four bytes, each shifted 8 more bits than the last
}
CheckpointDONE
You can decode little-endian 16- and 32-bit integers. Commit and stop here.