NES Audio
Sound on the NES comes from the Audio Processing Unit (APU), built into the CPU. It has five channels: two pulse waves, a triangle, a noise source and a sample player (DMC). Each channel is a small block of registers in the CPU’s I/O range, and a status register and frame counter tie them together.
Overview
The five channels each occupy four bytes of the APU register range from $4000 upward, apart from a shared status and frame-counter pair. The pulse channels play square waves with selectable duty, a volume envelope and a pitch sweep. The triangle plays a fixed-shape wave an octave low, the noise channel makes pitched hiss for percussion, and the DMC streams 1-bit delta samples for drums and speech.
| Channel | Registers | Role |
|---|---|---|
| Pulse 1 | $4000–$4003 | Square wave, duty, envelope, sweep. |
| Pulse 2 | $4004–$4007 | Second square wave, same features. |
| Triangle | $4008–$400B | Fixed triangle wave, no volume control. |
| Noise | $400C–$400F | Pseudo-random noise, envelope. |
| DMC | $4010–$4013 | 1-bit delta sample playback. |
The pulse channels
Each pulse channel is four registers. The first sets the duty cycle (which of four pulse widths), whether the length counter is held, and either a constant volume or an envelope rate. The second controls the sweep unit, which slides the pitch up or down over time. The last two hold the 11-bit timer period, the low 8 bits in one register and the top 3 bits plus a length-counter load in the next.
| Register | Bits | Contents |
|---|---|---|
| $4000 / $4004 | DDLC VVVV | Duty, length halt / envelope loop, constant-volume flag, volume or envelope rate. |
| $4001 / $4005 | EPPP NSSS | Sweep enable, period, negate, shift. |
| $4002 / $4006 | TTTT TTTT | Timer period, low 8 bits. |
| $4003 / $4007 | LLLL LTTT | Length counter load, timer period high 3 bits. |
The duty bits select a pulse that is 12.5%, 25%, 50% or 75% high, giving each channel its tone colour. The timer period sets the pitch: a smaller value is a higher note.
Triangle and noise
The triangle channel plays a 32-step triangle wave at the pitch set by its 11-bit timer. It has no volume control, so it is either on or off, and it is clocked twice as often as the pulses, which puts it an octave lower for a given period. It is gated by a linear counter as well as the length counter.
| Register | Bits | Contents |
|---|---|---|
| $4008 | CRRR RRRR | Length halt / linear-counter control, linear-counter reload value. |
| $400A | TTTT TTTT | Timer period, low 8 bits. |
| $400B | LLLL LTTT | Length counter load, timer period high 3 bits. |
The noise channel makes a pseudo-random square from a shift register. Its first register holds volume or envelope like the pulses; the next picks one of 16 period values and a mode bit that switches between a tonal buzz and a broad hiss.
| Register | Bits | Contents |
|---|---|---|
| $400C | --LC VVVV | Length halt / envelope loop, constant-volume flag, volume or envelope rate. |
| $400E | M--- PPPP | Mode flag, period index (0–15). |
| $400F | LLLL L--- | Length counter load. |
The DMC channel
The delta modulation channel plays back samples as a stream of 1-bit deltas: each bit nudges the output level up or down by two, tracing a waveform. It reads sample bytes straight from CPU memory, can loop, and can raise an interrupt when a sample ends. It is used for drums, bass and rough speech.
| Register | Bits | Contents |
|---|---|---|
| $4010 | IL-- RRRR | IRQ enable, loop flag, playback rate index. |
| $4011 | -DDD DDDD | Direct 7-bit output level. |
| $4012 | AAAA AAAA | Sample start address (×64, offset from $C000). |
| $4013 | LLLL LLLL | Sample length (×16, plus 1 bytes). |
Status and frame counter
The status register at $4015 enables and disables channels and reports which are still sounding. Writing it turns each channel’s length counter on or off; reading it tells which channels are active and whether the frame or DMC interrupt has fired. The frame counter at $4017 clocks the envelopes, sweeps and length counters at a steady rate and chooses a 4-step or 5-step sequence, optionally raising a frame interrupt.
| Register | Role |
|---|---|
| $4015 (write) | Enable pulse 1, pulse 2, triangle, noise, DMC (bits 0–4). |
| $4015 (read) | Channel-active flags and interrupt status. |
| $4017 | Frame counter: 4- or 5-step mode, interrupt inhibit. |