diff --git a/CHANGES b/CHANGES index 5dc7c52c4..7a7b0cb24 100644 --- a/CHANGES +++ b/CHANGES @@ -8,6 +8,8 @@ Emulation fixes: - GBA Memory: Fix STM/LDM to invalid VRAM - GB: Fix savedata initialization (fixes mgba.io/i/1473, mgba.io/i/1478) - GB Printer: Reset printer buffer index after printing + - GBA Audio: Fix channel 4 aliasing (fixes mgba.io/i/1265) + - GB Audio: Improve channel 4 supersampling Other fixes: - Switch: Fix threading-related crash on second launch - Qt: Fix FPS target maxing out at 59.727 (fixes mgba.io/i/1421) diff --git a/src/gb/audio.c b/src/gb/audio.c index ce8791308..96eb5e1eb 100644 --- a/src/gb/audio.c +++ b/src/gb/audio.c @@ -37,7 +37,7 @@ static bool _updateSweep(struct GBAudioSquareChannel* sweep, bool initial); static void _updateSquareSample(struct GBAudioSquareChannel* ch); static int32_t _updateSquareChannel(struct GBAudioSquareChannel* ch); -static int8_t _coalesceNoiseChannel(struct GBAudioNoiseChannel* ch); +static int16_t _coalesceNoiseChannel(struct GBAudioNoiseChannel* ch); static void _updateFrame(struct mTiming* timing, void* user, uint32_t cyclesLate); static void _updateChannel1(struct mTiming* timing, void* user, uint32_t cyclesLate); @@ -630,8 +630,11 @@ void GBAudioSamplePSG(struct GBAudio* audio, int16_t* left, int16_t* right) { } } + sampleLeft <<= 3; + sampleRight <<= 3; + if (audio->playingCh4 && !audio->forceDisableCh[3]) { - int8_t sample = _coalesceNoiseChannel(&audio->ch4); + int16_t sample = audio->style == GB_AUDIO_GBA ? (audio->ch4.sample << 3) : _coalesceNoiseChannel(&audio->ch4); if (audio->ch4Left) { sampleLeft += sample; } @@ -641,9 +644,6 @@ void GBAudioSamplePSG(struct GBAudio* audio, int16_t* left, int16_t* right) { } } - sampleLeft <<= 3; - sampleRight <<= 3; - *left = sampleLeft * (1 + audio->volumeLeft); *right = sampleRight * (1 + audio->volumeRight); } @@ -766,12 +766,12 @@ static int32_t _updateSquareChannel(struct GBAudioSquareChannel* ch) { } } -static int8_t _coalesceNoiseChannel(struct GBAudioNoiseChannel* ch) { +static int16_t _coalesceNoiseChannel(struct GBAudioNoiseChannel* ch) { if (!ch->nSamples) { return ch->sample; } // TODO keep track of timing - int8_t sample = ch->samples / ch->nSamples; + int16_t sample = (ch->samples << 3) / ch->nSamples; ch->nSamples = 0; ch->samples = 0; return sample;