Move audio resampling out of SDL code
Jeffrey Pfau jeffrey@endrift.com
Tue, 28 Jan 2014 23:52:28 -0800
3 files changed,
44 insertions(+),
2 deletions(-)
M
src/gba/gba-audio.c
→
src/gba/gba-audio.c
@@ -6,6 +6,7 @@ #include "gba-serialize.h"
#include "gba-thread.h" #include <limits.h> +#include <math.h> const unsigned GBA_AUDIO_SAMPLES = 512; const unsigned GBA_AUDIO_FIFO_SIZE = 8 * sizeof(int32_t);@@ -417,6 +418,41 @@ read = read >= readR ? read : readR;
} GBASyncConsumeAudio(audio->p->sync); 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) {
M
src/gba/gba-audio.h
→
src/gba/gba-audio.h
@@ -7,7 +7,7 @@ #include <stdint.h>
struct GBADMA; -const unsigned GBA_AUDIO_SAMPLES; +extern const unsigned GBA_AUDIO_SAMPLES; struct GBAAudioEnvelope { union {@@ -204,6 +204,11 @@
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);
M
src/gba/gba.h
→
src/gba/gba.h
@@ -7,7 +7,7 @@ #include "gba-memory.h"
#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,