diff --git a/CHANGES b/CHANGES index d1ec9224b..ab86dde0a 100644 --- a/CHANGES +++ b/CHANGES @@ -17,6 +17,7 @@ Emulation fixes: - GBA: Unhandled bkpt should be treated as an undefined exception - GBA Audio: Fix sample timing drifting when changing sample interval - GBA Audio: Fix initial channel 3 wave RAM (fixes mgba.io/i/2947) + - GBA Audio: Fix sample position issues when rate changes (fixes mgba.io/i/3006) - GBA GPIO: Fix tilt scale and orientation (fixes mgba.io/i/2703) - GBA BIOS: Fix clobbering registers with word-sized CpuSet - GBA SIO: Fix normal mode SI/SO semantics (fixes mgba.io/i/2925) diff --git a/src/gba/audio.c b/src/gba/audio.c index ed4ea8474..66f0fb3e4 100644 --- a/src/gba/audio.c +++ b/src/gba/audio.c @@ -253,13 +253,14 @@ void GBAAudioWriteSOUNDCNT_X(struct GBAAudio* audio, uint16_t value) { } void GBAAudioWriteSOUNDBIAS(struct GBAAudio* audio, uint16_t value) { - GBAAudioSample(audio, mTimingCurrentTime(&audio->p->timing)); + int32_t timestamp = mTimingCurrentTime(&audio->p->timing); + GBAAudioSample(audio, timestamp); audio->soundbias = value; int32_t oldSampleInterval = audio->sampleInterval; audio->sampleInterval = 0x200 >> GBARegisterSOUNDBIASGetResolution(value); if (oldSampleInterval != audio->sampleInterval) { - audio->lastSample += oldSampleInterval * audio->sampleIndex; - audio->sampleIndex = 0; + timestamp -= audio->lastSample; + audio->sampleIndex = timestamp >> (9 - GBARegisterSOUNDBIASGetResolution(value)); if (audio->p->stream && audio->p->stream->audioRateChanged) { audio->p->stream->audioRateChanged(audio->p->stream, GBA_ARM7TDMI_FREQUENCY / audio->sampleInterval); }