Skip to content

Commit c17d184

Browse files
Port Obscure Behavior section from old wiki
1 parent 1bd39c0 commit c17d184

File tree

1 file changed

+42
-0
lines changed

1 file changed

+42
-0
lines changed

src/Audio_details.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,3 +228,45 @@ The APU was reworked pretty heavily for the GBA, which introduces some slightly
228228
None of the additional features (more wave RAM, digital FIFOs, etc.) are available to CGB programs.
229229

230230
[`NR51`]: <#FF25 — NR51: Sound panning>
231+
232+
## Obscure Behavior
233+
234+
- The volume envelope and sweep timers treat a period of 0 as 8.
235+
- Just after powering on, the first duty step of Ch1 and Ch2 after they are triggered for the first time is played
236+
as if it were 0. Also, the duty cycle clocking is disabled until the first trigger.
237+
- When triggering Ch3, the first sample to play is the previous one still in the high nibble of the sample buffer, and the next sample is the second nibble from the wave table. This is because it doesn't load the first byte on trigger like it *should*.
238+
The first nibble from the wave table is thus not played until the waveform loops.
239+
- When triggering Ch1 and Ch2, the low two bits of the frequency timer are NOT modified.
240+
- Extra length clocking occurs when writing to NRx4 when the DIV-APU next step is one that doesn't clock the length timer. In this case, if the length timer was PREVIOUSLY disabled and now enabled and the length timer is not zero, it is decremented. If this decrement makes it zero and trigger is clear, the channel is disabled. On the CGB-02, the length timer only has to have been disabled before; the current length enable state doesn't matter. This breaks at least one game (Prehistorik Man), and was fixed on CGB-04 and CGB-05.
241+
- If a channel is triggered when the DIV-APU next step is one that doesn't clock the length timer and the length timer is now enabled and length is being set to 64 (256 for wave channel) because it was previously zero, it is set to 63 instead (255 for wave channel).
242+
- If a channel is triggered when the DIV-APU next step will clock the volume envelope, the envelope's timer is reloaded with one greater than it would have been.
243+
- Using a noise channel clock shift of 14 or 15 results in the LFSR receiving no clocks.
244+
- Clearing the sweep direction bit in NR10 after at least one sweep calculation has been made using the substraction mode since the last trigger causes the channel to be immediately disabled. This prevents you from having the sweep lower the frequency then raise the frequency without a trigger inbetween.
245+
- Triggering the wave channel on the DMG while it reads a sample byte will alter the first four bytes of wave RAM. If the channel was reading one of the first four bytes, the only first byte will be rewritten with the byte being read. If the channel was reading one of the later 12 bytes, the first FOUR bytes of wave RAM will be rewritten with the four aligned bytes that the read was from (bytes 4-7, 8-11, or 12-15); for example if it were reading byte 9 when it was retriggered, the first four bytes would be rewritten with the contents of bytes 8-11. To avoid this corruption you should stop the wave by writing 0 then $80 to NR30 before triggering it again. The game Duck Tales encounters this issue part way through most songs.
246+
- "Zombie" mode: the volume can be manually altered while a channel is playing by writing to NRx2. Behavior depends on the old and new values of NRx2, and whether the envlope has stopped automatic updates. The CGB-02 and CGB-04 are the most consistent:
247+
* If the old envelope period was zero and the envelope is still doing automatic updates, volume is incremented by 1, otherwise if the envelope was in decrease mode, volume is incremented by 2.
248+
* If the mode was changed (increase to decrease or decrease to increase), volume is set to 16-volume.
249+
* Only the low 4 bits of volume are kept after the above operations.
250+
251+
Other models behave differently, especially the DMG units which have crazy behavior in some cases. The only useful consistent behavior is using increase mode with a period of zero in order to increment the volume by 1. That is, write $V8 to NRx2 to set the initial volume to V before triggering the channel, then write $08 to NRx2 to increment the volume as the sound plays (repeat 15 times to decrement the volume by 1). This allows manual volume control on all units tested.
252+
253+
- When all four channel DACs are off, the master volume units are disconnected from the sound output and the output level becomes 0. When any channel DAC is on, a high-pass filter capacitor is connected which slowly removes any DC component from the signal. The following code applied at 4194304 Hz implements these two behaviors for one of the DMG output channels (unoptimized floating point for clarity):
254+
255+
```c
256+
static double capacitor = 0.0;
257+
258+
double high_pass( double in, bool dacs_enabled )
259+
{
260+
double out = 0.0;
261+
if ( dacs_enabled )
262+
{
263+
out = in - capacitor;
264+
265+
// capacitor slowly charges to 'in' via their difference
266+
capacitor = in - out * 0.999958; // use 0.998943 for MGB&CGB
267+
}
268+
return out;
269+
}
270+
```
271+
272+
The charge factor can be calculated for any output sampling rate as 0.999958^(4194304/rate). So if you were applying high_pass() at 44100 Hz, you'd use a charge factor of 0.996.

0 commit comments

Comments
 (0)