diff --git a/src/gba/gba-audio.c b/src/gba/gba-audio.c index 3fe333a60..27983ddbb 100644 --- a/src/gba/gba-audio.c +++ b/src/gba/gba-audio.c @@ -2,8 +2,9 @@ #include "gba.h" #include "gba-io.h" +#include "gba-thread.h" -const unsigned GBA_AUDIO_SAMPLES = 1024; +const unsigned GBA_AUDIO_SAMPLES = 512; const unsigned GBA_AUDIO_FIFO_SIZE = 8 * sizeof(int32_t); static void _sample(struct GBAAudio* audio); @@ -176,6 +177,9 @@ static void _sample(struct GBAAudio* audio) { } pthread_mutex_lock(&audio->bufferMutex); + while (CircleBufferSize(&audio->left) + (GBA_AUDIO_SAMPLES * 2 / 5) >= audio->left.capacity) { + GBASyncProduceAudio(audio->p->sync, &audio->bufferMutex); + } CircleBufferWrite32(&audio->left, sampleLeft); CircleBufferWrite32(&audio->right, sampleRight); pthread_mutex_unlock(&audio->bufferMutex); diff --git a/src/gba/gba-thread.c b/src/gba/gba-thread.c index c14d62a13..b2f1a10c4 100644 --- a/src/gba/gba-thread.c +++ b/src/gba/gba-thread.c @@ -92,6 +92,8 @@ int GBAThreadStart(struct GBAThread* threadContext) { pthread_mutex_init(&threadContext->sync.videoFrameMutex, 0); pthread_cond_init(&threadContext->sync.videoFrameAvailableCond, 0); pthread_cond_init(&threadContext->sync.videoFrameRequiredCond, 0); + pthread_cond_init(&threadContext->sync.audioAvailableCond, 0); + pthread_cond_init(&threadContext->sync.audioRequiredCond, 0); pthread_mutex_lock(&threadContext->startMutex); threadContext->activeKeys = 0; @@ -119,6 +121,11 @@ void GBAThreadJoin(struct GBAThread* threadContext) { pthread_cond_destroy(&threadContext->sync.videoFrameAvailableCond); pthread_cond_broadcast(&threadContext->sync.videoFrameRequiredCond); pthread_cond_destroy(&threadContext->sync.videoFrameRequiredCond); + + pthread_cond_broadcast(&threadContext->sync.audioAvailableCond); + pthread_cond_destroy(&threadContext->sync.audioAvailableCond); + pthread_cond_broadcast(&threadContext->sync.audioRequiredCond); + pthread_cond_destroy(&threadContext->sync.audioRequiredCond); } struct GBAThread* GBAThreadGetContext(void) { @@ -163,3 +170,14 @@ void GBASyncWaitFrameEnd(struct GBASync* sync) { int GBASyncDrawingFrame(struct GBASync* sync) { return sync->videoFrameSkip <= 0; } + +void GBASyncProduceAudio(struct GBASync* sync, pthread_mutex_t* mutex) { + pthread_cond_broadcast(&sync->audioAvailableCond); + if (&sync->audioWait) { + pthread_cond_wait(&sync->audioRequiredCond, mutex); + } +} + +void GBASyncConsumeAudio(struct GBASync* sync) { + pthread_cond_broadcast(&sync->audioRequiredCond); +} diff --git a/src/gba/gba-thread.h b/src/gba/gba-thread.h index 3611ca686..bcc38e046 100644 --- a/src/gba/gba-thread.h +++ b/src/gba/gba-thread.h @@ -30,6 +30,10 @@ struct GBAThread { pthread_mutex_t videoFrameMutex; pthread_cond_t videoFrameAvailableCond; pthread_cond_t videoFrameRequiredCond; + + int audioWait; + pthread_cond_t audioAvailableCond; + pthread_cond_t audioRequiredCond; } sync; }; @@ -42,4 +46,7 @@ void GBASyncWaitFrameStart(struct GBASync* sync, int frameskip); void GBASyncWaitFrameEnd(struct GBASync* sync); int GBASyncDrawingFrame(struct GBASync* sync); +void GBASyncProduceAudio(struct GBASync* sync, pthread_mutex_t* mutex); +void GBASyncConsumeAudio(struct GBASync* sync); + #endif diff --git a/src/gl-main.c b/src/gl-main.c index c7f7bb1c7..96277f610 100644 --- a/src/gl-main.c +++ b/src/gl-main.c @@ -72,6 +72,8 @@ int main(int argc, char** argv) { context.useDebugger = 1; context.renderer = &renderer.d.d; context.frameskip = 0; + context.sync.videoFrameWait = 0; + context.sync.audioWait = 1; GBAThreadStart(&context); renderer.audio.audio = &context.gba->audio; diff --git a/src/sdl/sdl-audio.c b/src/sdl/sdl-audio.c index 7e9cf83a2..1cabc8e18 100644 --- a/src/sdl/sdl-audio.c +++ b/src/sdl/sdl-audio.c @@ -1,6 +1,7 @@ #include "sdl-audio.h" #include "gba.h" +#include "gba-thread.h" static void _GBASDLAudioCallback(void* context, Uint8* data, int len); @@ -67,6 +68,7 @@ static void _GBASDLAudioCallback(void* context, Uint8* data, int len) { } ssamples[i] = audioContext->currentSample; } + GBASyncConsumeAudio(audioContext->audio->p->sync); pthread_mutex_unlock(&audioContext->audio->bufferMutex); } } diff --git a/src/sdl/sdl-events.c b/src/sdl/sdl-events.c index 2e0f8ced0..754b99a61 100644 --- a/src/sdl/sdl-events.c +++ b/src/sdl/sdl-events.c @@ -52,7 +52,7 @@ static void _GBASDLHandleKeypress(struct GBAThread* context, const struct SDL_Ke key = GBA_KEY_RIGHT; break; case SDLK_TAB: - context->sync.videoFrameWait = !context->sync.videoFrameWait; + context->sync.audioWait = !context->sync.audioWait; return; default: return;