Nerdy Nights: APU overview
Music and sound effects on the NES are generated by the APU (Audio Processing Unit), the sound chip inside the CPU. The CPU "talks" to the APU through a series of I/O ports, much like it does with the PPU and joypads.
The APU has 5 channels: Square 1, Square 2, Triangle, Noise and DMC. The first four play waves and are used in just about every game. The DMC channel plays samples (pre-recorded sounds) and is used less often.
The square channels produce square waveforms. A square wave is named for its shape. It looks like this:
+-----------+ | | | | | | | | | . . . . . | . . . . . | | | | | | | | | +-----------+
As you can see the wave transitions instantaneously from its high point to its low point (where the lines are vertical). This gives it a hollow sound like a woodwind or an electric guitar.
The triangle channel produces triangle waveforms. A triangle wave is also named for its shape. It looks like this:
/\ / \ / \ / \ / . . . .\ . . . ./ \ / \ / \ / \/
The sound of a triangle wave is smoother and less harsh than a square wave. On the NES, the triangle channel is often used for bass lines (in low octaves) or a flute (in high octaves). It can also be used for drums.
The noise channel has a random generator, which makes the waves it produces sound like.. noise. This channel is generally used for percussion and explosion sounds.
The delta modulation channel plays samples, which are pre-recorded sounds. It is often used to play voice recordings ("Blades of Steel") and percussion samples. Samples take up a lot of ROM space, so not many games make use of the DMC channel.
Before you can use the channels to produce sounds, you need to enable them. Channels are toggled on and off via port $4015:
7654 3210 APUFLAGS ($4015) | |||| | |||+- Square 1 (0: disable; 1: enable) | ||+-- Square 2 | |+--- Triangle | +---- Noise +------ DMC
Here are some code examples using $4015 to enable and disable channels:
lda #%00000001 sta $4015 ;enable Square 1 channel, disable others lda #%00010110 sta $4015 ;enable Square 2, Triangle and DMC channels. Disable Square 1 and Noise. lda #$00 sta $4015 ;disable all channels lda #$0F sta $4015 ;enable Square 1, Square 2, Triangle and Noise channels. Disable DMC. ;this is the most common usage.
Try opening up some of your favorite games in FCEUXD SP and set a breakpoint on writes to $4015. Take a look at what values are getting written there. If you don't know how to do this, follow these steps:
- Open FCEUXD SP
- Load a ROM
- Open up the Debugger by pressing F1 or going to Tools->Debugger
- In the top right corner of the debugger, under "BreakPoints", click the "Add..." button
- Type "4015" in the first box after "Address:"
- Check the checkbox next to "Write"
- Set "Memory" to "CPU Mem"
- Leave "Condition" and "Name" blank and click "OK"
Now FCEUX will pause emulation and snap the debugger anytime your game makes a write (usually via STA) to $4015. The debugger will tell you the contents of the registers at that moment, so you can check what value will be written to $4015. Some games will write to $4015 every frame, and some only do so once at startup. Try resetting the game if your debugger isn't snapping.
What values are being written to $4015? Can you tell what channels your game is using?