# APU Mixer

The NES APU mixer takes the channel outputs and converts them to an analog audio signal. Each channel has its own internal digital-to-analog convertor (DAC), implemented in a way that causes non-linearity and interaction between channels, so calculation of the resulting amplitude is somewhat involved. In particular, games such as *Super Mario Bros.* and *StarTropics* use the DMC level ($4011) as a crude volume control for the triangle and noise channels.

The following formula^{[1]} calculates the approximate audio output level within the range of 0.0 to 1.0. It is the sum of two sub-groupings of the channels:

output = pulse_out + tnd_out 95.88 pulse_out = ------------------------------------ (8128 / (pulse1 + pulse2)) + 100 159.79 tnd_out = ------------------------------------------------------------- 1 ----------------------------------------------------- + 100 (triangle / 8227) + (noise / 12241) + (dmc / 22638)

The values for pulse1, pulse2, triangle, noise, and dmc are the output values for the corresponding channel. The dmc value ranges from 0 to 127 and the others range from 0 to 15. When the values for one of the groups are all zero, the result for that group should be treated as zero rather than undefined due to the division by 0 that otherwise results.

Faster but less accurate approximations are also possible: using an efficient lookup table, or even rougher with a linear formula.

The NES hardware follows the DACs with a surprisingly involved circuit that adds several low-pass and high-pass filters:

- A first-order high-pass filter at 90 Hz
- Another first-order high-pass filter at 440 Hz
- A first-order low-pass filter at 14 kHz

See also:

The Famicom hardware instead ONLY specifies a first-order high-pass filter at 37 Hz, followed by the unknown (and varying) properties of the RF modulator and demodulator.

## Emulation

The NES APU Mixer can be efficiently emulated using a lookup table or a less-accurate linear approximation.

### Lookup Table

The APU mixer formulas can be efficiently implemented using two lookup tables: a 31-entry table for the two pulse channels and a 203-entry table for the remaining channels (due to the approximation of tnd_out, the numerators are adjusted slightly to preserve the normalized output range).

output = pulse_out + tnd_out pulse_table [n] = 95.52 / (8128.0 / n + 100) pulse_out = pulse_table [pulse1 + pulse2]

The tnd_out table is approximated (within 4%) by using a base unit close to the DMC's DAC.

tnd_table [n] = 163.67 / (24329.0 / n + 100) tnd_out = tnd_table [3 * triangle + 2 * noise + dmc]

### Linear Approximation

A linear approximation can also be used, which results in slightly louder DMC samples, but otherwise fairly accurate operation since the wave channels use a small portion of the transfer curve. The overall volume will be reduced due to the headroom required by the DMC approximation.

output = pulse_out + tnd_out pulse_out = 0.00752 * (pulse1 + pulse2) tnd_out = 0.00851 * triangle + 0.00494 * noise + 0.00335 * dmc

## References

- ↑ apu_ref.txt by blargg