diff --git a/src/gba/gba-audio.c b/src/gba/gba-audio.c index 8d40af5b3..c2e0cc8e4 100644 --- a/src/gba/gba-audio.c +++ b/src/gba/gba-audio.c @@ -6,6 +6,7 @@ #include "gba-thread.h" #include +#include const unsigned GBA_AUDIO_SAMPLES = 512; const unsigned GBA_AUDIO_FIFO_SIZE = 8 * sizeof(int32_t); @@ -419,6 +420,41 @@ unsigned GBAAudioCopy(struct GBAAudio* audio, void* left, void* right, unsigned return read; } +void GBAAudioResampleNN(struct GBAAudio* audio, float ratio, float* drift, struct GBAStereoSample* output, unsigned nSamples) { + int32_t left[GBA_AUDIO_SAMPLES]; + int32_t right[GBA_AUDIO_SAMPLES]; + + // toRead is in GBA samples + // TODO: Do this with fixed-point math + unsigned toRead = ceilf(nSamples / ratio); + while (nSamples) { + unsigned currentRead = GBA_AUDIO_SAMPLES; + if (currentRead > toRead) { + currentRead = toRead; + } + unsigned read = GBAAudioCopy(audio, left, right, currentRead); + toRead -= read; + unsigned i; + for (i = 0; i < read; ++i) { + *drift += ratio; + while (*drift >= 1.f) { + output->left = left[i]; + output->right = right[i]; + ++output; + --nSamples; + *drift -= 1.f; + if (!nSamples) { + return; + } + } + } + if (read < currentRead) { + memset(output, 0, nSamples * sizeof(struct GBAStereoSample)); + return; + } + } +} + static int32_t _updateSquareChannel(struct GBAAudioSquareControl* control, int duty) { control->hi = !control->hi; int period = 16 * (2048 - control->frequency); diff --git a/src/gba/gba-audio.h b/src/gba/gba-audio.h index 1a058cd23..0215aea45 100644 --- a/src/gba/gba-audio.h +++ b/src/gba/gba-audio.h @@ -7,7 +7,7 @@ struct GBADMA; -const unsigned GBA_AUDIO_SAMPLES; +extern const unsigned GBA_AUDIO_SAMPLES; struct GBAAudioEnvelope { union { @@ -204,6 +204,11 @@ struct GBAAudio { int32_t sampleInterval; }; +struct GBAStereoSample { + int16_t left; + int16_t right; +}; + void GBAAudioInit(struct GBAAudio* audio); void GBAAudioDeinit(struct GBAAudio* audio); @@ -229,6 +234,7 @@ void GBAAudioWriteFIFO(struct GBAAudio* audio, int address, uint32_t value); void GBAAudioSampleFIFO(struct GBAAudio* audio, int fifoId, int32_t cycles); unsigned GBAAudioCopy(struct GBAAudio* audio, void* left, void* right, unsigned nSamples); +void GBAAudioResampleNN(struct GBAAudio*, float ratio, float* drift, struct GBAStereoSample* output, unsigned nSamples); struct GBASerializedState; void GBAAudioSerialize(const struct GBAAudio* audio, struct GBASerializedState* state); diff --git a/src/gba/gba.h b/src/gba/gba.h index b3d498c13..6d0fd806a 100644 --- a/src/gba/gba.h +++ b/src/gba/gba.h @@ -7,7 +7,7 @@ #include "gba-video.h" #include "gba-audio.h" -const uint32_t GBA_ARM7TDMI_FREQUENCY; +extern const uint32_t GBA_ARM7TDMI_FREQUENCY; enum GBAIRQ { IRQ_VBLANK = 0x0,