Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Port "Gameboy sound hardware" from the old wiki #562

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
13 changes: 12 additions & 1 deletion src/Audio.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,17 @@ It refuses to run on the GBA for a different reason: the developer couldn't figu

:::

Each channel contains components that control different aspects of sound generation:

| Channel | Sweep | Frequency | Wave Form | Length Timer | Volume |
|----------|-------|----------------|-----------|--------------|----------|
| Square 1 | Sweep | Period Counter | Duty | Length Timer | Envelope |
| Square 2 | | Period Counter | Duty | Length Timer | Envelope |
| Wave | | Period Counter | Wave | Length Timer | Volume |
| Noise | | Period Counter | LFSR | Length Timer | Envelope |

These components are controlled by writing to the [audio registers](<#Audio Registers>).

[^speaker_mono]:
The speaker merges back the two channels, losing the stereo aspect entirely.

Expand Down Expand Up @@ -70,7 +81,7 @@ Internally, all envelopes are ticked at 64 Hz, and every 1–7 of those ticks, t
All channels can be individually set to automatically shut themselves down after a certain amount of time.

If the functionality is enabled, a channel's **length timer** ticks up[^len_cnt_dir] at 256 Hz (tied to [DIV-APU](<#DIV-APU>)) from the value it's initially set at.
When the length timer reaches 64, the channel is turned off.
When the length timer reaches 64 (CH1, CH2, and CH4) or 256 (CH3), the channel is turned off.

### Frequency

Expand Down
48 changes: 36 additions & 12 deletions src/Audio_Registers.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ One of the pitfalls of the `NRxy` naming convention is that the register's purpo

- **Audio on/off** (*Read/Write*): This controls whether the APU is powered on at all (akin to [`LCDC` bit 7](<#LCDC.7 — LCD enable>)).
Turning the APU off drains less power (around 16%), but clears all APU registers and makes them read-only until turned back on, except `NR52`[^dmg_apu_off].
Turning the APU off, however, does not affect [Wave RAM](<#FF30–FF3F — Wave pattern RAM>), which can always be read/written, nor the [DIV-APU](<#DIV-APU>) counter.

- **CH<var>n</var> on?** (*Read-only*): Each of these four bits allows checking whether channels are active[^nr52_dac].
Writing to those does **not** enable or disable the channels, despite many emulators behaving as if.

Expand All @@ -32,7 +34,7 @@ One of the pitfalls of the `NRxy` naming convention is that the register's purpo
- The channel's [length timer](<#Length timer>) is enabled in `NRx4` and expires, or
- *For CH1 only*: when the [period sweep](<#FF10 — NR10: Channel 1 sweep>) overflows[^freq_sweep_underflow], or
- [The channel's DAC](#DACs) is turned off.

The envelope reaching a volume of 0 does NOT turn the channel off!

<hr>
Expand Down Expand Up @@ -202,7 +204,15 @@ Period changes (written to `NR13` or `NR14`) only take effect after the current
"NR14" 7:"Trigger" 6:"Length enable" 2-0:"Period"
}}

- **Trigger** (*Write-only*): Writing any value to `NR14` with this bit set [triggers](<#Triggering>) the channel.
- **Trigger** (*Write-only*): Writing any value to `NR14` with this bit set [triggers](<#Triggering>) the channel, causing the
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can improve this wording a bit? "triggering a channel"

following to occur:
* Ch1 is enabled.
* If length timer expired it is reset.
* The period divider is set to the contents of `NR13` and `NR14`.
* Envelope timer is reset.
* Volume is set to contents of `NR12` initial volume.
* Sweep does [several things](<#Pulse channel with sweep (CH1)>).

- **[Length](<#Length timer>) enable** (*Read/Write*): Takes effect immediately upon writing to this register.
- **Period** (*Write-only*): The upper 3 bits of the period value; the lower 8 bits are stored in [`NR13`](<#FF13 — NR13: Channel 1 period low \[write-only\]>).

Expand Down Expand Up @@ -256,7 +266,7 @@ This channel lacks the envelope functionality that the other three channels have
}}

- **Output level**: Controls the channel's volume as follows:

Bits 6-5 (binary) | Output level
-----------------:|--------------
00 | Mute (No sound)
Expand Down Expand Up @@ -295,20 +305,27 @@ Period changes (written to `NR33` or `NR34`) only take effect after the followin
"NR34" 7:"Trigger" 6:"Length enable" 2-0:"Period"
}}

- **Trigger** (*Write-only*): Writing any value to `NR34` with this bit set [triggers](<#Triggering>) the channel.
- **Trigger** (*Write-only*): Writing any value to `NR34` with this bit set [triggers](<#Triggering>) the channel, causing the
following to occur:
* Ch3 is enabled.
* If the length timer expired it is reset.
* The period divider is set to the contents of `NR33` and `NR34`.
* Volume is set to contents of `NR32` initial volume.
* Wave RAM index is reset, but its *not* refilled.

:::warning RETRIGGERING CAUTION
:::warning RETRIGGERING CAUTION

On monochrome consoles only, retriggering CH3 while it's about to read a byte from wave RAM causes wave RAM to be corrupted in a generally unpredictable manner.
On monochrome consoles only, retriggering CH3 while it's about to read a byte from wave RAM causes wave RAM to be corrupted in a generally unpredictable manner.

:::
:::

:::warning PLAYBACK DELAY
:::warning PLAYBACK DELAY

Triggering the wave channel does not immediately start playing wave RAM; instead, the *last* sample ever read (which is reset to 0 when the APU is off) is output until the channel next reads a sample.
([Source](https://github.com/LIJI32/SameSuite/blob/master/apu/channel_3/channel_3_delay.asm))
Triggering the wave channel does not immediately start playing wave RAM; instead, the *last* sample ever read (which is reset to 0 when the APU is off) is output until the channel next reads a sample.
([Source](https://github.com/LIJI32/SameSuite/blob/master/apu/channel_3/channel_3_delay.asm))

:::

:::
- **[Length](<#Length timer>) enable** (*Read/Write*): Takes effect immediately upon writing to this register.
- **Period** (*Write-only*): The upper 3 bits of the period value; the lower 8 bits are stored in [`NR33`](<#FF1D — NR33: Channel 3 period low \[write-only\]>).

Expand Down Expand Up @@ -395,5 +412,12 @@ If the bit shifted out is a 0, the channel emits a 0; otherwise, it emits the vo
"NR44" 7:"Trigger" 6:"Length enable"
}}

- **Trigger** (*Write-only*): Writing any value to `NR14` with this bit set [triggers](<#Triggering>) the channel.
- **Trigger** (*Write-only*): Writing any value to `NR14` with this bit set [triggers](<#Triggering>) the channel, causing the
following to occur:
* Ch4 is enabled.
* If the length timer expired it is reset.
* Envelope timer is reset.
* Volume is set to contents of `NR42` initial volume.
* [LFSR bits](<#Noise channel (CH4)>) are reset.

- **[Length](<#Length timer>) enable** (*Read/Write*): Takes effect immediately upon writing to this register.
71 changes: 71 additions & 0 deletions src/Audio_details.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,35 @@ A channel can be deactivated in one of the following ways:
- Its [length timer](<#Length timer>) expiring
- (CH1 only) [Frequency sweep](<#FF10 — NR10: Channel 1 sweep>) overflowing the frequency

### Pulse channel with sweep (CH1)

The first square channel has a frequency sweep unit, controlled by `NR10`. This internally has a "sweep timer", "enabled flag",
and a period/frequency "shadow register". The "enabled flag" controls if the sweep unit is active,
the "sweep timer" is clocked at 128 Hz by the [DIV-APU](#DIV-APU), and the "shadow register" holds the current output period.

During a [trigger event](#Triggering), several things occur:

- CH1 [period value](<#FF13 — NR13: Channel 1 period low \[write-only\]>) is copied to the "shadow register".
- The "sweep timer" is reset.
- The "enabled flag" is set if either the [sweep pace or individual step](<#FF10 — NR10: Channel 1 sweep>) are non-zero, cleared otherwise.
- If the individual step is non-zero, _frequency calculation_ and _overflow check_ are performed immediately.

_Frequency calculation_ consists of taking the value in the frequency "shadow register", shifting it right by the individual step,
optionally negating the value, depending on the [direction](<#FF10 — NR10: Channel 1 sweep>), and summing this with the frequency "shadow register" to produce a new frequency.
What is done with this new frequency depends on the context.

The _overflow check_ simply calculates the new frequency and if it is greater than 2047, or $7FF, CH1 is disabled.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor: this section may enjoy a flow diagram?


When the "sweep timer" is [clocked](#DIV-APU) if the "enabled flag" is set and the sweep pace is not zero,
a new frequency is calculated and the overflow check is performed.
If the new frequency is 2047 or less and the individual step is not zero, this new frequency is written back to the
"shadow register" and CH1 frequency in `NR13` and `NR14`, then frequency calculation and overflow check
are run _again_ immediately using this new value, but this second new frequency is not written back.

CH1 frequency can be modified via `NR13` and `NR14` while sweep is active,
but the "shadow register" won't be affected so the next time the "sweep timer" updates the channel's frequency,
this modification will be lost. This can be avoided by triggering the channel.

### Pulse channels (CH1, CH2)

Each pulse channel has an internal "duty step" counter, which is used to index into [the selected waveform](<#FF11 — NR11: Channel 1 length timer & duty cycle>) (each background stripe corresponds to one "duty step")[^pulse_lut].
Expand Down Expand Up @@ -199,3 +228,45 @@ The APU was reworked pretty heavily for the GBA, which introduces some slightly
None of the additional features (more wave RAM, digital FIFOs, etc.) are available to CGB programs.

[`NR51`]: <#FF25 — NR51: Sound panning>

## Obscure Behavior

- The volume envelope and sweep timers treat a period of 0 as 8.
- Just after powering on, the first duty step of Ch1 and Ch2 after they are triggered for the first time is played
as if it were 0. Also, the duty cycle clocking is disabled until the first trigger.
- 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*.
The first nibble from the wave table is thus not played until the waveform loops.
- When triggering Ch1 and Ch2, the low two bits of the frequency timer are NOT modified.
- 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.
- 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).
- 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.
- Using a noise channel clock shift of 14 or 15 results in the LFSR receiving no clocks.
- 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.
- 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.
- "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:
* 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.
* If the mode was changed (increase to decrease or decrease to increase), volume is set to 16-volume.
* Only the low 4 bits of volume are kept after the above operations.

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.

- 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):

```c
static double capacitor = 0.0;

double high_pass( double in, bool dacs_enabled )
{
double out = 0.0;
if ( dacs_enabled )
{
out = in - capacitor;

// capacitor slowly charges to 'in' via their difference
capacitor = in - out * 0.999958; // use 0.998943 for MGB&CGB
}
return out;
}
```

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.
Loading