GBA Audio: Change internal audio sample buffer from 32-bit to 16-bit samples
Jeffrey Pfau jeffrey@endrift.com
Sun, 21 Dec 2014 01:14:30 -0800
4 files changed,
84 insertions(+),
25 deletions(-)
M
src/gba/gba-audio.c
→
src/gba/gba-audio.c
@@ -27,8 +27,8 @@ static int _applyBias(struct GBAAudio* audio, int sample);
static void _sample(struct GBAAudio* audio); void GBAAudioInit(struct GBAAudio* audio, size_t samples) { - CircleBufferInit(&audio->left, samples * sizeof(int32_t)); - CircleBufferInit(&audio->right, samples * sizeof(int32_t)); + CircleBufferInit(&audio->left, samples * sizeof(int16_t)); + CircleBufferInit(&audio->right, samples * sizeof(int16_t)); CircleBufferInit(&audio->chA.fifo, GBA_AUDIO_FIFO_SIZE); CircleBufferInit(&audio->chB.fifo, GBA_AUDIO_FIFO_SIZE); }@@ -96,28 +96,28 @@ return;
} GBASyncLockAudio(audio->p->sync); - int32_t buffer[GBA_AUDIO_SAMPLES]; - int32_t dummy; + int16_t buffer[GBA_AUDIO_SAMPLES]; + int16_t dummy; size_t read; size_t i; read = CircleBufferDump(&audio->left, buffer, sizeof(buffer)); CircleBufferDeinit(&audio->left); - CircleBufferInit(&audio->left, samples * sizeof(int32_t)); - for (i = 0; i * sizeof(int32_t) < read; ++i) { - if (!CircleBufferWrite32(&audio->left, buffer[i])) { - CircleBufferRead32(&audio->left, &dummy); - CircleBufferWrite32(&audio->left, buffer[i]); + CircleBufferInit(&audio->left, samples * sizeof(int16_t)); + for (i = 0; i * sizeof(int16_t) < read; ++i) { + if (!CircleBufferWrite16(&audio->left, buffer[i])) { + CircleBufferRead16(&audio->left, &dummy); + CircleBufferWrite16(&audio->left, buffer[i]); } } read = CircleBufferDump(&audio->right, buffer, sizeof(buffer)); CircleBufferDeinit(&audio->right); - CircleBufferInit(&audio->right, samples * sizeof(int32_t)); - for (i = 0; i * sizeof(int32_t) < read; ++i) { - if (!CircleBufferWrite32(&audio->right, buffer[i])) { - CircleBufferRead32(&audio->right, &dummy); - CircleBufferWrite32(&audio->right, buffer[i]); + CircleBufferInit(&audio->right, samples * sizeof(int16_t)); + for (i = 0; i * sizeof(int16_t) < read; ++i) { + if (!CircleBufferWrite16(&audio->right, buffer[i])) { + CircleBufferRead16(&audio->right, &dummy); + CircleBufferWrite16(&audio->right, buffer[i]); } }@@ -476,16 +476,16 @@ unsigned GBAAudioCopy(struct GBAAudio* audio, void* left, void* right, unsigned nSamples) {
GBASyncLockAudio(audio->p->sync); unsigned read = 0; if (left) { - unsigned readL = CircleBufferRead(&audio->left, left, nSamples * sizeof(int32_t)) >> 2; + unsigned readL = CircleBufferRead(&audio->left, left, nSamples * sizeof(int16_t)) >> 1; if (readL < nSamples) { - memset((int32_t*) left + readL, 0, nSamples - readL); + memset((int16_t*) left + readL, 0, nSamples - readL); } read = readL; } if (right) { - unsigned readR = CircleBufferRead(&audio->right, right, nSamples * sizeof(int32_t)) >> 2; + unsigned readR = CircleBufferRead(&audio->right, right, nSamples * sizeof(int16_t)) >> 1; if (readR < nSamples) { - memset((int32_t*) right + readR, 0, nSamples - readR); + memset((int16_t*) right + readR, 0, nSamples - readR); } read = read >= readR ? read : readR; }@@ -494,8 +494,8 @@ return read;
} unsigned 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]; + int16_t left[GBA_AUDIO_SAMPLES]; + int16_t right[GBA_AUDIO_SAMPLES]; // toRead is in GBA samples // TODO: Do this with fixed-point math@@ -685,12 +685,12 @@ sample = 0x3FF;
} else if (sample < 0) { sample = 0; } - return (sample - GBARegisterSOUNDBIASGetBias(audio->soundbias)) << 6; + return (sample - GBARegisterSOUNDBIASGetBias(audio->soundbias)) << 5; } static void _sample(struct GBAAudio* audio) { - int32_t sampleLeft = 0; - int32_t sampleRight = 0; + int16_t sampleLeft = 0; + int16_t sampleRight = 0; int psgShift = 6 - audio->volume; if (audio->ch1Left) {@@ -748,8 +748,8 @@ sampleLeft = _applyBias(audio, sampleLeft);
sampleRight = _applyBias(audio, sampleRight); GBASyncLockAudio(audio->p->sync); - CircleBufferWrite32(&audio->left, sampleLeft); - CircleBufferWrite32(&audio->right, sampleRight); + CircleBufferWrite16(&audio->left, sampleLeft); + CircleBufferWrite16(&audio->right, sampleRight); unsigned produced = CircleBufferSize(&audio->left); struct GBAThread* thread = GBAThreadGetContext(); if (thread && thread->stream) {
M
src/util/circle-buffer.c
→
src/util/circle-buffer.c
@@ -97,6 +97,34 @@ #endif
return 4; } +int CircleBufferWrite16(struct CircleBuffer* buffer, int16_t value) { + int16_t* data = buffer->writePtr; + if (buffer->size + sizeof(int16_t) > buffer->capacity) { + return 0; + } + if ((intptr_t) data & 0x3) { + int written = 0; + written += CircleBufferWrite8(buffer, ((int8_t*) &value)[0]); + written += CircleBufferWrite8(buffer, ((int8_t*) &value)[1]); + return written; + } + *data = value; + ++data; + size_t size = (int8_t*) data - (int8_t*) buffer->data; + if (size < buffer->capacity) { + buffer->writePtr = data; + } else { + buffer->writePtr = buffer->data; + } + buffer->size += sizeof(int16_t); +#ifndef NDEBUG + if (!_checkIntegrity(buffer)) { + abort(); + } +#endif + return 2; +} + int CircleBufferRead8(struct CircleBuffer* buffer, int8_t* value) { int8_t* data = buffer->readPtr; if (buffer->size < sizeof(int8_t)) {@@ -117,6 +145,34 @@ abort();
} #endif return 1; +} + +int CircleBufferRead16(struct CircleBuffer* buffer, int16_t* value) { + int16_t* data = buffer->readPtr; + if (buffer->size < sizeof(int16_t)) { + return 0; + } + if ((intptr_t) data & 0x3) { + int read = 0; + read += CircleBufferRead8(buffer, &((int8_t*) value)[0]); + read += CircleBufferRead8(buffer, &((int8_t*) value)[1]); + return read; + } + *value = *data; + ++data; + size_t size = (int8_t*) data - (int8_t*) buffer->data; + if (size < buffer->capacity) { + buffer->readPtr = data; + } else { + buffer->readPtr = buffer->data; + } + buffer->size -= sizeof(int16_t); +#ifndef NDEBUG + if (!_checkIntegrity(buffer)) { + abort(); + } +#endif + return 2; } int CircleBufferRead32(struct CircleBuffer* buffer, int32_t* value) {
M
src/util/circle-buffer.h
→
src/util/circle-buffer.h
@@ -22,8 +22,10 @@ size_t CircleBufferSize(const struct CircleBuffer* buffer);
size_t CircleBufferCapacity(const struct CircleBuffer* buffer); void CircleBufferClear(struct CircleBuffer* buffer); int CircleBufferWrite8(struct CircleBuffer* buffer, int8_t value); +int CircleBufferWrite16(struct CircleBuffer* buffer, int16_t value); int CircleBufferWrite32(struct CircleBuffer* buffer, int32_t value); int CircleBufferRead8(struct CircleBuffer* buffer, int8_t* value); +int CircleBufferRead16(struct CircleBuffer* buffer, int16_t* value); int CircleBufferRead32(struct CircleBuffer* buffer, int32_t* value); size_t CircleBufferRead(struct CircleBuffer* buffer, void* output, size_t length); size_t CircleBufferDump(const struct CircleBuffer* buffer, void* output, size_t length);