Move audio resampling out of SDL code

This commit is contained in:
Jeffrey Pfau 2014-01-28 23:52:28 -08:00
parent 2e2ca19220
commit a79a592c1e
3 changed files with 44 additions and 2 deletions

View File

@ -6,6 +6,7 @@
#include "gba-thread.h" #include "gba-thread.h"
#include <limits.h> #include <limits.h>
#include <math.h>
const unsigned GBA_AUDIO_SAMPLES = 512; const unsigned GBA_AUDIO_SAMPLES = 512;
const unsigned GBA_AUDIO_FIFO_SIZE = 8 * sizeof(int32_t); 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; 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) { static int32_t _updateSquareChannel(struct GBAAudioSquareControl* control, int duty) {
control->hi = !control->hi; control->hi = !control->hi;
int period = 16 * (2048 - control->frequency); int period = 16 * (2048 - control->frequency);

View File

@ -7,7 +7,7 @@
struct GBADMA; struct GBADMA;
const unsigned GBA_AUDIO_SAMPLES; extern const unsigned GBA_AUDIO_SAMPLES;
struct GBAAudioEnvelope { struct GBAAudioEnvelope {
union { union {
@ -204,6 +204,11 @@ struct GBAAudio {
int32_t sampleInterval; int32_t sampleInterval;
}; };
struct GBAStereoSample {
int16_t left;
int16_t right;
};
void GBAAudioInit(struct GBAAudio* audio); void GBAAudioInit(struct GBAAudio* audio);
void GBAAudioDeinit(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); void GBAAudioSampleFIFO(struct GBAAudio* audio, int fifoId, int32_t cycles);
unsigned GBAAudioCopy(struct GBAAudio* audio, void* left, void* right, unsigned nSamples); 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; struct GBASerializedState;
void GBAAudioSerialize(const struct GBAAudio* audio, struct GBASerializedState* state); void GBAAudioSerialize(const struct GBAAudio* audio, struct GBASerializedState* state);

View File

@ -7,7 +7,7 @@
#include "gba-video.h" #include "gba-video.h"
#include "gba-audio.h" #include "gba-audio.h"
const uint32_t GBA_ARM7TDMI_FREQUENCY; extern const uint32_t GBA_ARM7TDMI_FREQUENCY;
enum GBAIRQ { enum GBAIRQ {
IRQ_VBLANK = 0x0, IRQ_VBLANK = 0x0,