SDL, Qt: Fix audio thread crashes
Jeffrey Pfau jeffrey@endrift.com
Sun, 18 Oct 2015 11:22:32 -0700
2 files changed,
17 insertions(+),
12 deletions(-)
M
src/platform/qt/GameController.cpp
→
src/platform/qt/GameController.cpp
@@ -201,7 +201,6 @@ m_audioThread->setObjectName("Audio Thread");
m_audioThread->start(QThread::TimeCriticalPriority); m_audioProcessor->moveToThread(m_audioThread); connect(this, SIGNAL(gameStarted(GBAThread*)), m_audioProcessor, SLOT(start())); - connect(this, SIGNAL(gameStopped(GBAThread*)), m_audioProcessor, SLOT(pause())); connect(this, SIGNAL(gamePaused(GBAThread*)), m_audioProcessor, SLOT(pause())); connect(this, SIGNAL(gameUnpaused(GBAThread*)), m_audioProcessor, SLOT(start())); connect(this, SIGNAL(frameAvailable(const uint32_t*)), this, SLOT(pollEvents()));@@ -428,6 +427,7 @@ m_rewindTimer.stop();
if (GBAThreadIsPaused(&m_threadContext)) { GBAThreadUnpause(&m_threadContext); } + m_audioProcessor->pause(); GBAThreadEnd(&m_threadContext); GBAThreadJoin(&m_threadContext); if (m_threadContext.fname) {@@ -876,7 +876,6 @@ m_audioProcessor->requestSampleRate(sampleRate);
} m_audioProcessor->moveToThread(m_audioThread); connect(this, SIGNAL(gameStarted(GBAThread*)), m_audioProcessor, SLOT(start())); - connect(this, SIGNAL(gameStopped(GBAThread*)), m_audioProcessor, SLOT(pause())); connect(this, SIGNAL(gamePaused(GBAThread*)), m_audioProcessor, SLOT(pause())); connect(this, SIGNAL(gameUnpaused(GBAThread*)), m_audioProcessor, SLOT(start())); if (isLoaded()) {
M
src/platform/sdl/sdl-audio.c
→
src/platform/sdl/sdl-audio.c
@@ -43,6 +43,7 @@ return false;
} context->samples = context->obtainedSpec.samples; context->gba = 0; + context->thread = 0; if (threadContext) { context->thread = threadContext;@@ -64,6 +65,8 @@ }
void GBASDLDeinitAudio(struct GBASDLAudio* context) { UNUSED(context); + context->thread = 0; + context->gba = 0; #if SDL_VERSION_ATLEAST(2, 0, 0) SDL_PauseAudioDevice(context->deviceId, 1); SDL_CloseAudioDevice(context->deviceId);@@ -94,15 +97,18 @@ }
static void _GBASDLAudioCallback(void* context, Uint8* data, int len) { struct GBASDLAudio* audioContext = context; - if (!context || (!audioContext->gba && (!audioContext->thread || !audioContext->thread->gba))) { + if (!context || (!audioContext->thread && !audioContext->gba)) { memset(data, 0, len); return; } - if (!audioContext->gba) { - audioContext->gba = audioContext->thread->gba; + struct GBA* gba; + if (audioContext->thread) { + gba = audioContext->thread->gba; + } else { + gba = audioContext->gba; } #if RESAMPLE_LIBRARY == RESAMPLE_NN - audioContext->ratio = GBAAudioCalculateRatio(audioContext->gba->audio.sampleRate, audioContext->fpsTarget, audioContext->obtainedSpec.freq); + audioContext->ratio = GBAAudioCalculateRatio(gba->audio.sampleRate, audioContext->fpsTarget, audioContext->obtainedSpec.freq); if (audioContext->ratio == INFINITY) { memset(data, 0, len); return;@@ -110,7 +116,7 @@ }
struct GBAStereoSample* ssamples = (struct GBAStereoSample*) data; len /= 2 * audioContext->obtainedSpec.channels; if (audioContext->obtainedSpec.channels == 2) { - GBAAudioResampleNN(&audioContext->gba->audio, audioContext->ratio, &audioContext->drift, ssamples, len); + GBAAudioResampleNN(&gba->audio, audioContext->ratio, &audioContext->drift, ssamples, len); } #elif RESAMPLE_LIBRARY == RESAMPLE_BLIP_BUF double fauxClock = 1;@@ -118,16 +124,16 @@ if (audioContext->thread) {
GBAAudioCalculateRatio(1, audioContext->thread->fpsTarget, 1); GBASyncLockAudio(&audioContext->thread->sync); } - blip_set_rates(audioContext->gba->audio.left, GBA_ARM7TDMI_FREQUENCY, audioContext->obtainedSpec.freq * fauxClock); - blip_set_rates(audioContext->gba->audio.right, GBA_ARM7TDMI_FREQUENCY, audioContext->obtainedSpec.freq * fauxClock); + blip_set_rates(gba->audio.left, GBA_ARM7TDMI_FREQUENCY, audioContext->obtainedSpec.freq * fauxClock); + blip_set_rates(gba->audio.right, GBA_ARM7TDMI_FREQUENCY, audioContext->obtainedSpec.freq * fauxClock); len /= 2 * audioContext->obtainedSpec.channels; - int available = blip_samples_avail(audioContext->gba->audio.left); + int available = blip_samples_avail(gba->audio.left); if (available > len) { available = len; } - blip_read_samples(audioContext->gba->audio.left, (short*) data, available, audioContext->obtainedSpec.channels == 2); + blip_read_samples(gba->audio.left, (short*) data, available, audioContext->obtainedSpec.channels == 2); if (audioContext->obtainedSpec.channels == 2) { - blip_read_samples(audioContext->gba->audio.right, ((short*) data) + 1, available, 1); + blip_read_samples(gba->audio.right, ((short*) data) + 1, available, 1); } if (audioContext->thread) {