Pan Docs — Audio Registers
The register-by-register specification of the game-boy-apu: the NRxy naming scheme (x = channel, 5 = global; NRx1 length/duty, NRx2 volume/envelope, NRx3 period low, NRx4 trigger, length enable and period high), then every register with its bit fields, formulas and warnings, many backed by a SameSuite test ROM. Part of pan-docs; the overview is s-pandocs-audio-overview, the internals s-pandocs-audio-details.
Key claims#
Global registers
NR52($FF26): bit 7 switches the APU on/off — off "drains less power (around 16%)", clears every APU register (not wave RAM, not the DIV-APU counter) and makes them read-only; bits 0–3 are read-only "channel on" flags — writing them does nothing, "despite many emulators behaving as if". A channel turns on by triggering (NRx4bit 7, ineffective if the DAC is off) and off when its enabled length timer expires, when CH1's sweep overflows, or when its DAC is switched off. "The envelope reaching a volume of 0 does NOT turn the channel off!"NR51($FF25): bits 7–4 send CH4…CH1 to the left output, bits 3–0 to the right — each channel "hard left, center, hard right, or ignored entirely"; changing a bit for a channel whose DAC is on causes a pop.NR50($FF24): bits 7 and 3 route VIN left/right (keep 0 without external hardware); bits 6–4 and 2–0 are the left/right master volume — "0 is treated as a volume of 1 (very quiet), and a value of 7 is treated as a volume of 8 (no volume reduction)"; "the amplifier never mutes a non-silent input."
CH1 — pulse with period sweep
NR10($FF10): bits 6–4 pace in 128 Hz ticks (7.8 ms; 0 disables iterations; a new value is only read when an iteration completes or the channel is retriggered), bit 3 direction (0 = addition, the period value increases; 1 = subtraction), bits 2–0 individual step: L(t+1) = L(t) ± L(t) ÷ 2^step, written back toNR13/NR14on every iteration. In addition mode a result above$7FFturns the channel off — "even if sweep iterations are disabled by the pace being 0"; a period value of 0 can never be changed by the sweep, and it cannot underflow.NR11($FF11): bits 7–6 duty —0012.5 %,0125 %,1050 %,1175 %; "there is no audible difference between the 25 % and 75 % duty cycle settings"; the duty setting also alters the phase, "hardly noticeable except in combination with other channels". Bits 5–0: initial length timer, write-only — "the higher this field is, the shorter the time before the channel is cut."NR12($FF12): bits 7–4 initial volume (readable but "not updated by the envelope functionality"), bit 3 direction (0 = decrease, 1 = increase), bits 2–0 sweep pace — the envelope ticks at 64 Hz and moves one step every pace ticks; 0 disables it. Bits 3–7 all zero switches the DAC (and the channel) off, "which may cause an audio pop". "Writes to this register while the channel is on require retriggering it afterwards."NR13/NR14($FF13/$FF14): an 11-bit period value. The period divider counts up and is reloaded from the register on overflow, so the value acts as a negative period — "the higher the period value in the register, the lower the period, and the higher the frequency." Pulse dividers clock at 1048576 Hz with 8 samples per cycle: sample rate = 1048576 ÷ (2048 − value), tone frequency = 131072 ÷ (2048 − value) Hz;$500→ 170.67 Hz,$740→ 682.67 Hz (two octaves higher, because 2048 − value is a quarter). Period changes only take effect after the current sample ends.NR14: bit 7 trigger (write-only) — enables CH1, resets an expired length timer, reloads the period divider, resets the envelope timer, sets the volume fromNR12and restarts the sweep; bit 6 length enable (takes effect immediately); bits 2–0 the period's upper 3 bits.
CH2 — pulse: NR21–NR24 at $FF16–$FF19, identical to CH1 without the sweep.
CH3 — wave output
- A "voluntary wave" channel: the wave is fixed at 32 four-bit samples, the read speed is free; "shorten" it by repeating a pattern or doubling each sample and the rate, "lengthen" it by loading a new wave as soon as the buffer has been read — "sometimes used for full-on sample playback".
NR30($FF1A) bit 7: DAC on/off — off turns the channel off and may pop; usually switched off before writing wave RAM.NR31($FF1B): 8-bit initial length timer.NR32($FF1C) bits 6–5, output level:00mute,01100 %,1050 % (samples shifted right once),1125 % (twice) — "a much coarser volume control", no envelope.NR33/NR34($FF1D/$FF1E): the divider clocks at 2097152 Hz with 32 samples per cycle: tone frequency = 65536 ÷ (2048 − value) Hz —$500→ 85.333 Hz,$740→ 341.33 Hz; "given the same period value, the tone frequency of the wave channel is generally half that of a pulse channel, or one octave lower." Changes take effect at the next wave RAM read. Trigger resets the wave RAM index "but its not refilled"; on monochrome consoles retriggering while a byte is being read corrupts wave RAM "in a generally unpredictable manner"; triggering does not start playback immediately — the last sample ever read is output until the next read.- Wave RAM
$FF30–$FF3F: 16 bytes of two samples each, read left to right, upper nibble first; the first sample read after starting is index 1, the lower nibble of the first byte. While CH3 is active accesses misbehave: on AGB reads return$FFand writes are ignored; on monochrome consoles access only works on the same cycle as CH3's own read; on other consoles the byte CH3 is currently reading is accessed whatever the address. With the DAC on but the channel inactive, wave RAM is accessible normally.
CH4 — noise
- Noise is made "by randomly switching the amplitude between two levels fairly fast"; a lower frequency sounds "harder", a higher one "softer"; the random function can be manipulated to be "more regular, sounding closer to a pulse than noise".
NR41($FF20) bits 5–0 initial length;NR42($FF21) works likeNR12.NR43($FF22): bits 7–4 clock shift, bit 3 LFSR width (0 = 15-bit, 1 = 7-bit — "more regular output; some frequencies sound more like pulse than noise"), bits 2–0 clock divider (0 counts as 0.5). The LFSR is clocked at 262144 ÷ (divider × 2^shift) Hz; shift 14 or 15 stops it. The bit shifted out selects 0 or theNR42volume. Lock-up: switching from 15- to 7-bit mode in a certain LFSR state silences CH4, "avoided by retriggering CH4, which resets the LFSR".NR44($FF23): bit 7 trigger (enable, reset an expired length timer, reset the envelope timer, volume fromNR42, reset the LFSR), bit 6 length enable.
Practical takeaways#
For a lsdj user the register map explains the instrument screen: WAVE = the two duty bits, LENGTH = the length timer, the hardware part of ENV = NRx2, SWEEP = NR10, wave VOLUME = NR32, NOISE 7/15-bit = NR43 bit 3, OUTPUT = NR51, M = NR50. Three formulas to remember: pulse tone = 131072 ÷ (2048 − v), wave tone = 65536 ÷ (2048 − v), noise clock = 262144 ÷ (divider × 2^shift).
Notable quotes#
"It's worth noting that there is no audible difference between the 25 % and 75 % duty cycle settings."
"The envelope reaching a volume of 0 does NOT turn the channel off!"
Relevance#
The register/feature table of game-boy-apu comes from here; it confirms the four fixed duties, the 32 × 4-bit wave RAM, the 7/15-bit LFSR and the 16-step envelope that were (unverified) on that page and on pulse-width-modulation.
Pages touched#
game-boy-apu · pulse-width-modulation · wavetable-programming · adsr-envelope · retrigger · stereo-panning · pitch-slide-and-portamento · instrument-design · lsdj · game-boy · pan-docs