The Game Boy’s third sound channel does something the other three cannot: it plays a waveform you supply. Channels 1 and 2 are pulse generators locked to four duty settings. Channel 4 is a linear-feedback shift register producing noise. Channel 3 — the wave channel — reads from a 32-entry table of 4-bit samples that lives in memory you control. That table is the instrument. The entire timbre is whatever 16 bytes you write to $FF30–$FF3F.
This is a register-level walkthrough of that budget: what the bytes hold, how the playback pipeline reads them, and which hardware quirks shape what a composer can actually do with 32 samples.
The data layout: 32 samples, 16 bytes
The wave channel plays a 32-entry wave table made up of 4-bit samples. Each byte encodes two samples, the first in the high bits. So the full waveform occupies 16 bytes, mapped to $FF30 through $FF3F. The gbdev wiki documents this layout directly, and the register table in the same reference lists the wave table as FF30–FF3F, with FF30 holding samples 0 and 1 and FF3F holding samples 30 and 31.
Each sample is a 4-bit value, 0 to 15. The channel’s DAC converts that to a proportional voltage: an input of 0 generates −1.0 and an input of 15 generates +1.0, using arbitrary voltage units. So the waveform is a sequence of 32 discrete amplitude steps, each one of 16 possible levels. That is the raw material.
Compare this to the pulse channels. Their timbre is fixed by four duty settings — 12.5%, 25%, 50%, 75% — and the only shaping available is the volume envelope. On CH3, there is no preset. The design problem is not “which waveform” but “how do I spend 32 samples.”
The playback pipeline
The wave channel’s frequency timer period is set to (2048 − frequency) × 2. When the timer generates a clock, the position counter advances one sample in the wave table, looping back to the beginning when it goes past the end, then a sample is read into the sample buffer from this new position. The DAC receives the current value from the upper or lower nibble of the sample buffer, shifted right by the volume control.
That shift is the entire volume system on this channel. The volume codes in NR32 ($FF1C) are:
00= 0% (silent)01= 100%10= 50%11= 25%
Four steps. No envelope. The squares and noise each have a volume envelope unit to help with fading notes and sound effects, while the wave channel has only limited manual volume control. If you want a fade on CH3, you either rewrite the waveform data or re-trigger the channel with a different volume code. There is no automatic ramp.
The length timer is the one piece of automatic shaping the channel shares with the others. When the length timer reaches 256 (CH3’s limit, versus 64 for the other channels), the channel is turned off. That gives you a note-off mechanism, but not a volume curve.
The trigger quirk
Triggering the wave channel does not do what you might expect. Writing to NR34 ($FF1E) with bit 7 set causes the channel to enable, reloads the frequency timer, and sets the wave channel’s position to 0 — but the sample buffer is not refilled.
The consequence is documented in the gbdev wiki: when triggering the wave channel, the first sample to play is the previous one still in the high nibble of the sample buffer, and the next sample is the second nibble from the wave table. The first nibble from the wave table is not played until the waveform loops. The wiki notes this is because the hardware doesn’t load the first byte on trigger the way it “should.”
This means the audible start of a note depends on whatever was left in the buffer from the previous playback. If you are designing an instrument, the buffer state is part of the instrument. A note that starts on a fresh trigger may begin with a sample from the last note’s waveform if you swapped tables between triggers. The practical implication is that the first sample of your table is deferred: it plays on the loop, not on the attack.
Wave RAM access
Wave RAM can only be properly accessed when the channel is disabled. This is not a soft recommendation; it is a hardware restriction documented in the gbdev wiki’s wave channel section. The 16 bytes at $FF30–$FF3F are a resource you load between notes, not a buffer you stream during playback.
That reframes the budget. If you want multiple distinct waveforms in a piece, you are not swapping them mid-note. You disable the channel, write new bytes, re-enable, and trigger. The cost is the silence between notes and the CPU time to write 16 bytes. The benefit is that 16 bytes is small enough to reload quickly — but the access window is the constraint, not the byte count.
Power-on state and hardware variation
When the Game Boy is switched on, before the internal boot ROM executes, the values in the wave table depend on the model. On the DMG, they are somewhat random, though the particular pattern is generally the same for each individual Game Boy unit. The game R-Type does not initialize wave RAM and thus relies on these values. One documented set is 84 40 43 AA 2D 78 92 3C 60 59 59 B0 34 B8 2E DA.
This is a concrete case where the instrument is literally the unit’s power-on state. The same ROM on a different DMG may produce a different waveform because the uninitialized RAM differs. That is not a bug in the game; it is a documented hardware behavior that the game’s sound code depends on.
On the Game Boy Color, the power-on wave RAM values are consistently 00 FF 00 FF 00 FF 00 FF 00 FF 00 FF 00 FF 00 FF 00 FF, per the gbdev wiki.
What the budget actually means
The 32-nibble table is the entire instrument. There is no filter, no resonance, no second oscillator layered underneath. The waveform is 32 amplitude steps, and the only real-time control is a four-step volume shift and the frequency timer.
That produces a specific design surface. A sine wave needs enough samples per cycle to avoid sounding stepped; 32 samples gives you one cycle of a reasonably smooth sine, but if you want a lower pitch, the same 32 samples stretch over a longer period and the steps become audible. A complex waveform with harmonics needs more samples per cycle to represent the harmonics, which means fewer cycles fit in the table. The trade-off is between waveform complexity and pitch range.
The coarse volume steps mean that expressive dynamics on CH3 come from the waveform data itself — you can build an amplitude envelope into the 32 samples, but then you have committed those samples to that envelope and cannot reuse them for a sustained tone. Alternatively, you re-trigger with different volume codes, which costs the buffer-refill quirk on every note.
The access restriction means that swapping waveforms is a between-notes operation. A piece that cycles through many distinct timbres is limited by how often the channel can be disabled, rewritten, and re-enabled without disrupting the rhythm.
None of this is a limitation to lament. It is the set of constraints that define the channel. The pulse channels have their own constraints — four duty settings, an envelope that ticks at 64 Hz, a sweep unit on CH1 only. The wave channel’s constraint is that you get 32 samples and four volume steps, and everything else is your problem. That is the hack: not fitting an instrument into 32 bytes as a compromise, but treating 32 bytes as the instrument.
FAQ
Can I change the waveform while a note is playing?
Wave RAM can only be properly accessed when the channel is disabled. So no, not during playback. You disable the channel, write the new bytes, and re-enable.
Why does my note start with the wrong sample?
Because triggering the wave channel sets the position to 0 but does not refill the sample buffer. The first sample played is whatever was left in the buffer from the previous playback. The first nibble of your table is not played until the waveform loops.
How do I fade a wave channel note?
There is no envelope on CH3. You can re-trigger with a different volume code (100%, 50%, 25%, silent), or you can build the fade into the waveform data itself — but then those samples are committed to that shape.
What is the frequency formula?
The wave channel’s frequency timer period is (2048 − frequency) × 2. The frequency value is written across NR33 ($FF1D) and the low bits of NR34 ($FF1E).
Does the wave channel have a length timer?
Yes. When the length timer reaches 256, the channel is turned off. That is the CH3 limit, versus 64 for the other channels.
Sources
- gbdev wiki, “Gameboy sound hardware”: https://gbdev.gg8.se/wiki/articles/Gameboy_sound_hardware
- Pan Docs, “Audio”: https://gbdev.io/pandocs/Audio.html
- Pan Docs repository: https://github.com/gbdev/pandocs