Stereo samples are stored interleaved - left, right, left, right - but to work on one channel at a time you need them split apart. Today you de-interleave a flat sample stream into per-channel slices.
Split an interleaved sample stream into one slice per channel.
In a multi-channel WAV the samples are interleaved: one sample per channel for
the first instant (a frame), then one per channel for the next instant, and so
on. Stereo is L R L R L R.... That layout is right for streaming to hardware, but
wrong for processing - to fade the left channel or average two channels you want
each channel as its own contiguous slice.
De-interleaving walks the flat stream and routes sample index i to channel
i mod numChannels. So [100, 200, 300, 400] at 2 channels becomes left
[100, 300] and right [200, 400]. With one channel it is a no-op - a single
slice equal to the input. This per-channel form is what the sample-math chapter
operates on, and interleaving (the reverse) is how you will lay samples back down
before writing. Together with decoding, this is the second half of turning raw
bytes into usable audio.
// sample i belongs to channel (i mod numChannels), frame (i div numChannels)func deinterleave(samples []int, channels int) [][]int {out := make([][]int, channels)for i, s := range samples {ch := i % channelsout[ch] = append(out[ch], s)}return out}