GB Audio: Fix audio envelope timing resetting too often (fixes #3164)

This commit is contained in:
Vicki Pfau 2024-03-17 19:53:41 -07:00
parent c8c9fcb665
commit 4fdadc585d
4 changed files with 17 additions and 11 deletions

View File

@ -6,6 +6,7 @@ Features:
- New unlicensed GB mappers: NT (older types 1 and 2), Li Cheng, GGB-81 - New unlicensed GB mappers: NT (older types 1 and 2), Li Cheng, GGB-81
- Debugger: Add range watchpoints - Debugger: Add range watchpoints
Emulation fixes: Emulation fixes:
- GB Audio: Fix audio envelope timing resetting too often (fixes mgba.io/i/3164)
- GB I/O: Fix STAT writing IRQ trigger conditions (fixes mgba.io/i/2501) - GB I/O: Fix STAT writing IRQ trigger conditions (fixes mgba.io/i/2501)
- GB Serialize: Add missing Pocket Cam state to savestates - GB Serialize: Add missing Pocket Cam state to savestates
- GB Video: Implement DMG-style sprite ordering - GB Video: Implement DMG-style sprite ordering

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -33,10 +33,10 @@ static void _writeDuty(struct GBAudioEnvelope* envelope, uint8_t value);
static bool _writeEnvelope(struct GBAudioEnvelope* envelope, uint8_t value, enum GBAudioStyle style); static bool _writeEnvelope(struct GBAudioEnvelope* envelope, uint8_t value, enum GBAudioStyle style);
static void _resetSweep(struct GBAudioSweep* sweep); static void _resetSweep(struct GBAudioSweep* sweep);
static bool _resetEnvelope(struct GBAudioEnvelope* sweep); static bool _resetEnvelope(struct GBAudioEnvelope* sweep, enum GBAudioStyle style);
static void _updateEnvelope(struct GBAudioEnvelope* envelope); static void _updateEnvelope(struct GBAudioEnvelope* envelope);
static void _updateEnvelopeDead(struct GBAudioEnvelope* envelope); static void _updateEnvelopeDead(struct GBAudioEnvelope* envelope, enum GBAudioStyle style);
static bool _updateSweep(struct GBAudioSquareChannel* sweep, bool initial); static bool _updateSweep(struct GBAudioSquareChannel* sweep, bool initial);
static void _updateSquareSample(struct GBAudioSquareChannel* ch); static void _updateSquareSample(struct GBAudioSquareChannel* ch);
@ -192,7 +192,7 @@ void GBAudioWriteNR14(struct GBAudio* audio, uint8_t value) {
} }
} }
if (GBAudioRegisterControlIsRestart(value << 8)) { if (GBAudioRegisterControlIsRestart(value << 8)) {
audio->playingCh1 = _resetEnvelope(&audio->ch1.envelope); audio->playingCh1 = _resetEnvelope(&audio->ch1.envelope, audio->style);
audio->ch1.sweep.realFrequency = audio->ch1.control.frequency; audio->ch1.sweep.realFrequency = audio->ch1.control.frequency;
_resetSweep(&audio->ch1.sweep); _resetSweep(&audio->ch1.sweep);
if (audio->playingCh1 && audio->ch1.sweep.shift) { if (audio->playingCh1 && audio->ch1.sweep.shift) {
@ -243,7 +243,7 @@ void GBAudioWriteNR24(struct GBAudio* audio, uint8_t value) {
} }
} }
if (GBAudioRegisterControlIsRestart(value << 8)) { if (GBAudioRegisterControlIsRestart(value << 8)) {
audio->playingCh2 = _resetEnvelope(&audio->ch2.envelope); audio->playingCh2 = _resetEnvelope(&audio->ch2.envelope, audio->style);
if (!audio->ch2.control.length) { if (!audio->ch2.control.length) {
audio->ch2.control.length = 64; audio->ch2.control.length = 64;
@ -383,7 +383,7 @@ void GBAudioWriteNR44(struct GBAudio* audio, uint8_t value) {
} }
} }
if (GBAudioRegisterNoiseControlIsRestart(value)) { if (GBAudioRegisterNoiseControlIsRestart(value)) {
audio->playingCh4 = _resetEnvelope(&audio->ch4.envelope); audio->playingCh4 = _resetEnvelope(&audio->ch4.envelope, audio->style);
audio->ch4.lfsr = 0; audio->ch4.lfsr = 0;
if (!audio->ch4.length) { if (!audio->ch4.length) {
@ -877,9 +877,10 @@ static void _sample(struct mTiming* timing, void* user, uint32_t cyclesLate) {
mTimingSchedule(timing, &audio->sampleEvent, audio->sampleInterval * audio->timingFactor - cyclesLate); mTimingSchedule(timing, &audio->sampleEvent, audio->sampleInterval * audio->timingFactor - cyclesLate);
} }
bool _resetEnvelope(struct GBAudioEnvelope* envelope) { bool _resetEnvelope(struct GBAudioEnvelope* envelope, enum GBAudioStyle style) {
envelope->currentVolume = envelope->initialVolume; envelope->currentVolume = envelope->initialVolume;
_updateEnvelopeDead(envelope); envelope->nextStep = envelope->stepTime;
_updateEnvelopeDead(envelope, style);
return envelope->initialVolume || envelope->direction; return envelope->initialVolume || envelope->direction;
} }
@ -932,7 +933,7 @@ bool _writeEnvelope(struct GBAudioEnvelope* envelope, uint8_t value, enum GBAudi
} }
envelope->currentVolume &= 0xF; envelope->currentVolume &= 0xF;
} }
_updateEnvelopeDead(envelope); _updateEnvelopeDead(envelope, style);
return envelope->initialVolume || envelope->direction; return envelope->initialVolume || envelope->direction;
} }
@ -968,17 +969,21 @@ static void _updateEnvelope(struct GBAudioEnvelope* envelope) {
} }
} }
static void _updateEnvelopeDead(struct GBAudioEnvelope* envelope) { static void _updateEnvelopeDead(struct GBAudioEnvelope* envelope, enum GBAudioStyle style) {
if (!envelope->stepTime) { if (!envelope->stepTime) {
envelope->dead = envelope->currentVolume ? 1 : 2; envelope->dead = envelope->currentVolume ? 1 : 2;
} else if (!envelope->direction && !envelope->currentVolume) { } else if (!envelope->direction && !envelope->currentVolume) {
envelope->dead = 2; envelope->dead = 2;
} else if (envelope->direction && envelope->currentVolume == 0xF) { } else if (envelope->direction && envelope->currentVolume == 0xF) {
envelope->dead = 1; envelope->dead = 1;
} else { } else if (envelope->dead) {
envelope->dead = 0; // TODO: Figure out if this happens on DMG/CGB or just AGB
// TODO: Figure out the exact circumstances that lead to reloading the step
if (style == GB_AUDIO_GBA) {
envelope->nextStep = envelope->stepTime; envelope->nextStep = envelope->stepTime;
} }
envelope->dead = 0;
}
} }
static bool _updateSweep(struct GBAudioSquareChannel* ch, bool initial) { static bool _updateSweep(struct GBAudioSquareChannel* ch, bool initial) {