diff --git a/include/mgba/internal/gba/audio.h b/include/mgba/internal/gba/audio.h index 2bf6c14a6..65336b299 100644 --- a/include/mgba/internal/gba/audio.h +++ b/include/mgba/internal/gba/audio.h @@ -16,6 +16,7 @@ CXX_GUARD_START #include #define GBA_AUDIO_FIFO_SIZE 8 +#define GBA_MAX_SAMPLES 16 #define MP2K_MAGIC 0x68736D53 #define MP2K_MAX_SOUND_CHANNELS 12 @@ -34,7 +35,7 @@ struct GBAAudioFIFO { uint32_t internalSample; int internalRemaining; int dmaSource; - int8_t samples[8]; + int8_t samples[GBA_MAX_SAMPLES]; }; DECL_BITFIELD(GBARegisterSOUNDCNT_HI, uint16_t); diff --git a/include/mgba/internal/gba/serialize.h b/include/mgba/internal/gba/serialize.h index 20d0719ab..6ab814859 100644 --- a/include/mgba/internal/gba/serialize.h +++ b/include/mgba/internal/gba/serialize.h @@ -225,8 +225,8 @@ mLOG_DECLARE_CATEGORY(GBA_STATE); * 0x00324 - 0x00327: Interruptable BIOS stall cycles * 0x00328 - 0x00367: Matrix memory mapping table * 0x00368 - 0x0036F: Reserved (leave zero) - * 0x00370 - 0x00377: Audio FIFO A samples - * 0x00378 - 0x0037F: Audio FIFO B samples + * 0x00370 - 0x0037F: Audio FIFO A samples + * 0x00380 - 0x0038F: Audio FIFO B samples * 0x00380 - 0x003FF: Reserved (leave zero) * 0x00400 - 0x007FF: I/O memory * 0x00800 - 0x00BFF: Palette @@ -387,11 +387,11 @@ struct GBASerializedState { uint32_t reservedMatrix[2]; struct { - int8_t chA[8]; - int8_t chB[8]; + int8_t chA[16]; + int8_t chB[16]; } samples; - uint32_t reserved[32]; + uint32_t reserved[28]; uint16_t io[SIZE_IO >> 1]; uint16_t pram[SIZE_PALETTE_RAM >> 1]; diff --git a/src/gb/audio.c b/src/gb/audio.c index 7a1fe60bf..19f265c47 100644 --- a/src/gb/audio.c +++ b/src/gb/audio.c @@ -566,29 +566,28 @@ void GBAudioRun(struct GBAudio* audio, int32_t timestamp, int channels) { cycles <<= audio->ch4.frequency; cycles *= 8 * audio->timingFactor; - int32_t last = 0; int32_t diff = timestamp - audio->ch4.lastEvent; - int samples = 0; - int positiveSamples = 0; - int lsb; - int coeff = 0x60; - if (!audio->ch4.power) { - coeff <<= 8; - } - for (; last + cycles <= diff; last += cycles) { - lsb = audio->ch4.lfsr & 1; - audio->ch4.lfsr >>= 1; - audio->ch4.lfsr ^= lsb * coeff; - ++samples; - positiveSamples += lsb; - } - if (samples) { + if (diff >= cycles) { + int32_t last; + int samples = 0; + int positiveSamples = 0; + int lsb; + int coeff = 0x60; + if (!audio->ch4.power) { + coeff <<= 8; + } + for (last = 0; last + cycles <= diff; last += cycles) { + lsb = audio->ch4.lfsr & 1; + audio->ch4.lfsr >>= 1; + audio->ch4.lfsr ^= lsb * coeff; + ++samples; + positiveSamples += lsb; + } audio->ch4.sample = lsb * audio->ch4.envelope.currentVolume; audio->ch4.nSamples += samples; audio->ch4.samples += positiveSamples * audio->ch4.envelope.currentVolume; + audio->ch4.lastEvent += last; } - - audio->ch4.lastEvent += last; } } diff --git a/src/gba/audio.c b/src/gba/audio.c index 8cd58dc78..00c20bd46 100644 --- a/src/gba/audio.c +++ b/src/gba/audio.c @@ -25,7 +25,7 @@ mLOG_DEFINE_CATEGORY(GBA_AUDIO, "GBA Audio", "gba.audio"); const unsigned GBA_AUDIO_SAMPLES = 2048; const int GBA_AUDIO_VOLUME_MAX = 0x100; -static const int SAMPLE_INTERVAL = GBA_ARM7TDMI_FREQUENCY / 0x8000; +static const int SAMPLE_INTERVAL = GBA_ARM7TDMI_FREQUENCY / 0x4000; static const int CLOCKS_PER_FRAME = 0x800; static int _applyBias(struct GBAAudio* audio, int sample); @@ -305,14 +305,11 @@ void GBAAudioSampleFIFO(struct GBAAudio* audio, int fifoId, int32_t cycles) { } } int32_t until = mTimingUntil(&audio->p->timing, &audio->sampleEvent) - 1; - int bits = 1 << GBARegisterSOUNDBIASGetResolution(audio->soundbias); + int bits = 2 << GBARegisterSOUNDBIASGetResolution(audio->soundbias); until += 1 << (9 - GBARegisterSOUNDBIASGetResolution(audio->soundbias)); until >>= 9 - GBARegisterSOUNDBIASGetResolution(audio->soundbias); int i; for (i = bits - until; i < bits; ++i) { - if (i < 0 || i >= bits) { - abort(); - } channel->samples[i] = channel->internalSample; } if (channel->internalRemaining) { @@ -333,8 +330,8 @@ static int _applyBias(struct GBAAudio* audio, int sample) { static void _sample(struct mTiming* timing, void* user, uint32_t cyclesLate) { struct GBAAudio* audio = user; - int16_t samplesLeft[8]; - int16_t samplesRight[8]; + int16_t samplesLeft[GBA_MAX_SAMPLES]; + int16_t samplesRight[GBA_MAX_SAMPLES]; int32_t timestamp = mTimingCurrentTime(&audio->p->timing) - cyclesLate - SAMPLE_INTERVAL; int sample; for (sample = 0; sample * audio->sampleInterval < (int32_t) SAMPLE_INTERVAL; ++sample) {