mirror of https://github.com/mgba-emu/mgba.git
GBA Audio: Change internal audio sample buffer from 32-bit to 16-bit samples
This commit is contained in:
parent
2fb098cb01
commit
660ac6a6be
1
CHANGES
1
CHANGES
|
@ -18,6 +18,7 @@ Misc:
|
||||||
- Qt: Disable sync to video by default
|
- Qt: Disable sync to video by default
|
||||||
- GBA: Exit cleanly on FATAL if the port supports it
|
- GBA: Exit cleanly on FATAL if the port supports it
|
||||||
- Qt: Handle a game crash without crashing
|
- Qt: Handle a game crash without crashing
|
||||||
|
- GBA Audio: Change internal audio sample buffer from 32-bit to 16-bit samples
|
||||||
|
|
||||||
0.1.0: (2014-12-13)
|
0.1.0: (2014-12-13)
|
||||||
- Initial release
|
- Initial release
|
||||||
|
|
|
@ -27,8 +27,8 @@ static int _applyBias(struct GBAAudio* audio, int sample);
|
||||||
static void _sample(struct GBAAudio* audio);
|
static void _sample(struct GBAAudio* audio);
|
||||||
|
|
||||||
void GBAAudioInit(struct GBAAudio* audio, size_t samples) {
|
void GBAAudioInit(struct GBAAudio* audio, size_t samples) {
|
||||||
CircleBufferInit(&audio->left, samples * sizeof(int32_t));
|
CircleBufferInit(&audio->left, samples * sizeof(int16_t));
|
||||||
CircleBufferInit(&audio->right, samples * sizeof(int32_t));
|
CircleBufferInit(&audio->right, samples * sizeof(int16_t));
|
||||||
CircleBufferInit(&audio->chA.fifo, GBA_AUDIO_FIFO_SIZE);
|
CircleBufferInit(&audio->chA.fifo, GBA_AUDIO_FIFO_SIZE);
|
||||||
CircleBufferInit(&audio->chB.fifo, GBA_AUDIO_FIFO_SIZE);
|
CircleBufferInit(&audio->chB.fifo, GBA_AUDIO_FIFO_SIZE);
|
||||||
}
|
}
|
||||||
|
@ -96,28 +96,28 @@ void GBAAudioResizeBuffer(struct GBAAudio* audio, size_t samples) {
|
||||||
}
|
}
|
||||||
|
|
||||||
GBASyncLockAudio(audio->p->sync);
|
GBASyncLockAudio(audio->p->sync);
|
||||||
int32_t buffer[GBA_AUDIO_SAMPLES];
|
int16_t buffer[GBA_AUDIO_SAMPLES];
|
||||||
int32_t dummy;
|
int16_t dummy;
|
||||||
size_t read;
|
size_t read;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
read = CircleBufferDump(&audio->left, buffer, sizeof(buffer));
|
read = CircleBufferDump(&audio->left, buffer, sizeof(buffer));
|
||||||
CircleBufferDeinit(&audio->left);
|
CircleBufferDeinit(&audio->left);
|
||||||
CircleBufferInit(&audio->left, samples * sizeof(int32_t));
|
CircleBufferInit(&audio->left, samples * sizeof(int16_t));
|
||||||
for (i = 0; i * sizeof(int32_t) < read; ++i) {
|
for (i = 0; i * sizeof(int16_t) < read; ++i) {
|
||||||
if (!CircleBufferWrite32(&audio->left, buffer[i])) {
|
if (!CircleBufferWrite16(&audio->left, buffer[i])) {
|
||||||
CircleBufferRead32(&audio->left, &dummy);
|
CircleBufferRead16(&audio->left, &dummy);
|
||||||
CircleBufferWrite32(&audio->left, buffer[i]);
|
CircleBufferWrite16(&audio->left, buffer[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
read = CircleBufferDump(&audio->right, buffer, sizeof(buffer));
|
read = CircleBufferDump(&audio->right, buffer, sizeof(buffer));
|
||||||
CircleBufferDeinit(&audio->right);
|
CircleBufferDeinit(&audio->right);
|
||||||
CircleBufferInit(&audio->right, samples * sizeof(int32_t));
|
CircleBufferInit(&audio->right, samples * sizeof(int16_t));
|
||||||
for (i = 0; i * sizeof(int32_t) < read; ++i) {
|
for (i = 0; i * sizeof(int16_t) < read; ++i) {
|
||||||
if (!CircleBufferWrite32(&audio->right, buffer[i])) {
|
if (!CircleBufferWrite16(&audio->right, buffer[i])) {
|
||||||
CircleBufferRead32(&audio->right, &dummy);
|
CircleBufferRead16(&audio->right, &dummy);
|
||||||
CircleBufferWrite32(&audio->right, buffer[i]);
|
CircleBufferWrite16(&audio->right, buffer[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -476,16 +476,16 @@ unsigned GBAAudioCopy(struct GBAAudio* audio, void* left, void* right, unsigned
|
||||||
GBASyncLockAudio(audio->p->sync);
|
GBASyncLockAudio(audio->p->sync);
|
||||||
unsigned read = 0;
|
unsigned read = 0;
|
||||||
if (left) {
|
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) {
|
if (readL < nSamples) {
|
||||||
memset((int32_t*) left + readL, 0, nSamples - readL);
|
memset((int16_t*) left + readL, 0, nSamples - readL);
|
||||||
}
|
}
|
||||||
read = readL;
|
read = readL;
|
||||||
}
|
}
|
||||||
if (right) {
|
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) {
|
if (readR < nSamples) {
|
||||||
memset((int32_t*) right + readR, 0, nSamples - readR);
|
memset((int16_t*) right + readR, 0, nSamples - readR);
|
||||||
}
|
}
|
||||||
read = read >= readR ? read : readR;
|
read = read >= readR ? read : readR;
|
||||||
}
|
}
|
||||||
|
@ -494,8 +494,8 @@ unsigned GBAAudioCopy(struct GBAAudio* audio, void* left, void* right, unsigned
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned GBAAudioResampleNN(struct GBAAudio* audio, float ratio, float* drift, struct GBAStereoSample* output, unsigned nSamples) {
|
unsigned GBAAudioResampleNN(struct GBAAudio* audio, float ratio, float* drift, struct GBAStereoSample* output, unsigned nSamples) {
|
||||||
int32_t left[GBA_AUDIO_SAMPLES];
|
int16_t left[GBA_AUDIO_SAMPLES];
|
||||||
int32_t right[GBA_AUDIO_SAMPLES];
|
int16_t right[GBA_AUDIO_SAMPLES];
|
||||||
|
|
||||||
// toRead is in GBA samples
|
// toRead is in GBA samples
|
||||||
// TODO: Do this with fixed-point math
|
// TODO: Do this with fixed-point math
|
||||||
|
@ -685,12 +685,12 @@ static int _applyBias(struct GBAAudio* audio, int sample) {
|
||||||
} else if (sample < 0) {
|
} else if (sample < 0) {
|
||||||
sample = 0;
|
sample = 0;
|
||||||
}
|
}
|
||||||
return (sample - GBARegisterSOUNDBIASGetBias(audio->soundbias)) << 6;
|
return (sample - GBARegisterSOUNDBIASGetBias(audio->soundbias)) << 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _sample(struct GBAAudio* audio) {
|
static void _sample(struct GBAAudio* audio) {
|
||||||
int32_t sampleLeft = 0;
|
int16_t sampleLeft = 0;
|
||||||
int32_t sampleRight = 0;
|
int16_t sampleRight = 0;
|
||||||
int psgShift = 6 - audio->volume;
|
int psgShift = 6 - audio->volume;
|
||||||
|
|
||||||
if (audio->ch1Left) {
|
if (audio->ch1Left) {
|
||||||
|
@ -748,8 +748,8 @@ static void _sample(struct GBAAudio* audio) {
|
||||||
sampleRight = _applyBias(audio, sampleRight);
|
sampleRight = _applyBias(audio, sampleRight);
|
||||||
|
|
||||||
GBASyncLockAudio(audio->p->sync);
|
GBASyncLockAudio(audio->p->sync);
|
||||||
CircleBufferWrite32(&audio->left, sampleLeft);
|
CircleBufferWrite16(&audio->left, sampleLeft);
|
||||||
CircleBufferWrite32(&audio->right, sampleRight);
|
CircleBufferWrite16(&audio->right, sampleRight);
|
||||||
unsigned produced = CircleBufferSize(&audio->left);
|
unsigned produced = CircleBufferSize(&audio->left);
|
||||||
struct GBAThread* thread = GBAThreadGetContext();
|
struct GBAThread* thread = GBAThreadGetContext();
|
||||||
if (thread && thread->stream) {
|
if (thread && thread->stream) {
|
||||||
|
|
|
@ -97,6 +97,34 @@ int CircleBufferWrite32(struct CircleBuffer* buffer, int32_t value) {
|
||||||
return 4;
|
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) {
|
int CircleBufferRead8(struct CircleBuffer* buffer, int8_t* value) {
|
||||||
int8_t* data = buffer->readPtr;
|
int8_t* data = buffer->readPtr;
|
||||||
if (buffer->size < sizeof(int8_t)) {
|
if (buffer->size < sizeof(int8_t)) {
|
||||||
|
@ -119,6 +147,34 @@ int CircleBufferRead8(struct CircleBuffer* buffer, int8_t* value) {
|
||||||
return 1;
|
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) {
|
int CircleBufferRead32(struct CircleBuffer* buffer, int32_t* value) {
|
||||||
int32_t* data = buffer->readPtr;
|
int32_t* data = buffer->readPtr;
|
||||||
if (buffer->size < sizeof(int32_t)) {
|
if (buffer->size < sizeof(int32_t)) {
|
||||||
|
|
|
@ -22,8 +22,10 @@ size_t CircleBufferSize(const struct CircleBuffer* buffer);
|
||||||
size_t CircleBufferCapacity(const struct CircleBuffer* buffer);
|
size_t CircleBufferCapacity(const struct CircleBuffer* buffer);
|
||||||
void CircleBufferClear(struct CircleBuffer* buffer);
|
void CircleBufferClear(struct CircleBuffer* buffer);
|
||||||
int CircleBufferWrite8(struct CircleBuffer* buffer, int8_t value);
|
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 CircleBufferWrite32(struct CircleBuffer* buffer, int32_t value);
|
||||||
int CircleBufferRead8(struct CircleBuffer* buffer, int8_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);
|
int CircleBufferRead32(struct CircleBuffer* buffer, int32_t* value);
|
||||||
size_t CircleBufferRead(struct CircleBuffer* buffer, void* output, size_t length);
|
size_t CircleBufferRead(struct CircleBuffer* buffer, void* output, size_t length);
|
||||||
size_t CircleBufferDump(const struct CircleBuffer* buffer, void* output, size_t length);
|
size_t CircleBufferDump(const struct CircleBuffer* buffer, void* output, size_t length);
|
||||||
|
|
Loading…
Reference in New Issue