all repos — mgba @ e5272203987c17d9de06662a840ff5fb7b383689

mGBA Game Boy Advance Emulator

Ability to resize internal sound buffers
Jeffrey Pfau jeffrey@endrift.com
Mon, 21 Jul 2014 00:14:48 -0700
commit

e5272203987c17d9de06662a840ff5fb7b383689

parent

10fc916425cbd4650bf8c8a56f8c9428bed052d7

5 files changed, 53 insertions(+), 6 deletions(-)

jump to
M src/gba/gba-audio.csrc/gba/gba-audio.c

@@ -20,9 +20,9 @@ static int32_t _updateChannel4(struct GBAAudioChannel4* ch);

static int _applyBias(struct GBAAudio* audio, int sample); static void _sample(struct GBAAudio* audio); -void GBAAudioInit(struct GBAAudio* audio) { - CircleBufferInit(&audio->left, GBA_AUDIO_SAMPLES * sizeof(int32_t)); - CircleBufferInit(&audio->right, GBA_AUDIO_SAMPLES * sizeof(int32_t)); +void GBAAudioInit(struct GBAAudio* audio, size_t samples) { + CircleBufferInit(&audio->left, samples * sizeof(int32_t)); + CircleBufferInit(&audio->right, samples * sizeof(int32_t)); CircleBufferInit(&audio->chA.fifo, GBA_AUDIO_FIFO_SIZE); CircleBufferInit(&audio->chB.fifo, GBA_AUDIO_FIFO_SIZE); }

@@ -68,6 +68,40 @@ CircleBufferDeinit(&audio->left);

CircleBufferDeinit(&audio->right); CircleBufferDeinit(&audio->chA.fifo); CircleBufferDeinit(&audio->chB.fifo); +} + +void GBAAudioResizeBuffer(struct GBAAudio* audio, size_t samples) { + if (samples >= GBA_AUDIO_SAMPLES) { + return; + } + + GBASyncLockAudio(audio->p->sync); + int32_t buffer[GBA_AUDIO_SAMPLES]; + int32_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]); + } + } + + 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]); + } + } + + GBASyncUnlockAudio(audio->p->sync); } int32_t GBAAudioProcessEvents(struct GBAAudio* audio, int32_t cycles) {

@@ -670,7 +704,7 @@ GBASyncLockAudio(audio->p->sync);

CircleBufferWrite32(&audio->left, sampleLeft); CircleBufferWrite32(&audio->right, sampleRight); unsigned produced = CircleBufferSize(&audio->left); - GBASyncProduceAudio(audio->p->sync, produced >= GBA_AUDIO_SAMPLES * 3); + GBASyncProduceAudio(audio->p->sync, produced >= CircleBufferCapacity(&audio->left) / sizeof(int32_t) * 3); } void GBAAudioSerialize(const struct GBAAudio* audio, struct GBASerializedState* state) {
M src/gba/gba-audio.hsrc/gba/gba-audio.h

@@ -218,9 +218,11 @@ int16_t left;

int16_t right; }; -void GBAAudioInit(struct GBAAudio* audio); +void GBAAudioInit(struct GBAAudio* audio, size_t samples); void GBAAudioReset(struct GBAAudio* audio); void GBAAudioDeinit(struct GBAAudio* audio); + +void GBAAudioResizeBuffer(struct GBAAudio* audio, size_t samples); int32_t GBAAudioProcessEvents(struct GBAAudio* audio, int32_t cycles); void GBAAudioScheduleFifoDma(struct GBAAudio* audio, int number, struct GBADMA* info);
M src/gba/gba-thread.csrc/gba/gba-thread.c

@@ -86,6 +86,11 @@ pthread_setspecific(_contextKey, threadContext);

#else TlsSetValue(_contextKey, threadContext); #endif + + if (threadContext->audioBuffers) { + GBAAudioResizeBuffer(&gba.audio, threadContext->audioBuffers); + } + if (threadContext->renderer) { GBAVideoAssociateRenderer(&gba.video, threadContext->renderer); }

@@ -549,6 +554,10 @@ }

void GBASyncLockAudio(struct GBASync* sync) { MutexLock(&sync->audioBufferMutex); +} + +void GBASyncUnlockAudio(struct GBASync* sync) { + MutexUnlock(&sync->audioBufferMutex); } void GBASyncConsumeAudio(struct GBASync* sync) {
M src/gba/gba-thread.hsrc/gba/gba-thread.h

@@ -57,6 +57,7 @@ const char* fname;

int activeKeys; int frameskip; float fpsTarget; + size_t audioBuffers; // Threading state Thread thread;

@@ -106,6 +107,7 @@ bool GBASyncDrawingFrame(struct GBASync* sync);

void GBASyncProduceAudio(struct GBASync* sync, int wait); void GBASyncLockAudio(struct GBASync* sync); +void GBASyncUnlockAudio(struct GBASync* sync); void GBASyncConsumeAudio(struct GBASync* sync); #endif
M src/gba/gba.csrc/gba/gba.c

@@ -121,7 +121,7 @@ gba->video.p = gba;

GBAVideoInit(&gba->video); gba->audio.p = gba; - GBAAudioInit(&gba->audio); + GBAAudioInit(&gba->audio, GBA_AUDIO_SAMPLES); GBAIOInit(gba);