APU Mixer: Difference between revisions
(Games believed to use $4011 as volume) |
(The formula at top is also an approximation, as MDFourier reveals) |
||
Line 2: | Line 2: | ||
The [[APU|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 [[APU|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 calculates the audio output level within the range of 0.0 to 1.0. It is the sum of two sub-groupings of the channels: | The following formula 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 | output = pulse_out + tnd_out | ||
Line 18: | Line 18: | ||
The values for [[APU Pulse|pulse1]], [[APU Pulse|pulse2]], [[APU Triangle|triangle]], [[APU Noise|noise]], and [[APU DMC|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. | The values for [[APU Pulse|pulse1]], [[APU Pulse|pulse2]], [[APU Triangle|triangle]], [[APU Noise|noise]], and [[APU DMC|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|lookup table]], or even rougher with a [[#Linear Approximation|linear formula]]. | |||
The NES hardware follows the DACs with a [http://nesdev.org/NESAudio.gif surprisingly involved circuit] that adds several low-pass and high-pass filters: | The NES hardware follows the DACs with a [http://nesdev.org/NESAudio.gif surprisingly involved circuit] that adds several low-pass and high-pass filters: |
Revision as of 19:38, 1 May 2021
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 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