SDL, Qt: Fix audio thread crashes

This commit is contained in:
Jeffrey Pfau 2015-10-18 11:22:32 -07:00
parent df47cb1f95
commit 7ce34411bb
2 changed files with 17 additions and 12 deletions

View File

@ -201,7 +201,6 @@ GameController::GameController(QObject* parent)
m_audioThread->start(QThread::TimeCriticalPriority); m_audioThread->start(QThread::TimeCriticalPriority);
m_audioProcessor->moveToThread(m_audioThread); m_audioProcessor->moveToThread(m_audioThread);
connect(this, SIGNAL(gameStarted(GBAThread*)), m_audioProcessor, SLOT(start())); 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(gamePaused(GBAThread*)), m_audioProcessor, SLOT(pause()));
connect(this, SIGNAL(gameUnpaused(GBAThread*)), m_audioProcessor, SLOT(start())); connect(this, SIGNAL(gameUnpaused(GBAThread*)), m_audioProcessor, SLOT(start()));
connect(this, SIGNAL(frameAvailable(const uint32_t*)), this, SLOT(pollEvents())); connect(this, SIGNAL(frameAvailable(const uint32_t*)), this, SLOT(pollEvents()));
@ -428,6 +427,7 @@ void GameController::closeGame() {
if (GBAThreadIsPaused(&m_threadContext)) { if (GBAThreadIsPaused(&m_threadContext)) {
GBAThreadUnpause(&m_threadContext); GBAThreadUnpause(&m_threadContext);
} }
m_audioProcessor->pause();
GBAThreadEnd(&m_threadContext); GBAThreadEnd(&m_threadContext);
GBAThreadJoin(&m_threadContext); GBAThreadJoin(&m_threadContext);
if (m_threadContext.fname) { if (m_threadContext.fname) {
@ -876,7 +876,6 @@ void GameController::reloadAudioDriver() {
} }
m_audioProcessor->moveToThread(m_audioThread); m_audioProcessor->moveToThread(m_audioThread);
connect(this, SIGNAL(gameStarted(GBAThread*)), m_audioProcessor, SLOT(start())); 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(gamePaused(GBAThread*)), m_audioProcessor, SLOT(pause()));
connect(this, SIGNAL(gameUnpaused(GBAThread*)), m_audioProcessor, SLOT(start())); connect(this, SIGNAL(gameUnpaused(GBAThread*)), m_audioProcessor, SLOT(start()));
if (isLoaded()) { if (isLoaded()) {

View File

@ -43,6 +43,7 @@ bool GBASDLInitAudio(struct GBASDLAudio* context, struct GBAThread* threadContex
} }
context->samples = context->obtainedSpec.samples; context->samples = context->obtainedSpec.samples;
context->gba = 0; context->gba = 0;
context->thread = 0;
if (threadContext) { if (threadContext) {
context->thread = threadContext; context->thread = threadContext;
@ -64,6 +65,8 @@ bool GBASDLInitAudio(struct GBASDLAudio* context, struct GBAThread* threadContex
void GBASDLDeinitAudio(struct GBASDLAudio* context) { void GBASDLDeinitAudio(struct GBASDLAudio* context) {
UNUSED(context); UNUSED(context);
context->thread = 0;
context->gba = 0;
#if SDL_VERSION_ATLEAST(2, 0, 0) #if SDL_VERSION_ATLEAST(2, 0, 0)
SDL_PauseAudioDevice(context->deviceId, 1); SDL_PauseAudioDevice(context->deviceId, 1);
SDL_CloseAudioDevice(context->deviceId); SDL_CloseAudioDevice(context->deviceId);
@ -94,15 +97,18 @@ void GBASDLResumeAudio(struct GBASDLAudio* context) {
static void _GBASDLAudioCallback(void* context, Uint8* data, int len) { static void _GBASDLAudioCallback(void* context, Uint8* data, int len) {
struct GBASDLAudio* audioContext = context; struct GBASDLAudio* audioContext = context;
if (!context || (!audioContext->gba && (!audioContext->thread || !audioContext->thread->gba))) { if (!context || (!audioContext->thread && !audioContext->gba)) {
memset(data, 0, len); memset(data, 0, len);
return; return;
} }
if (!audioContext->gba) { struct GBA* gba;
audioContext->gba = audioContext->thread->gba; if (audioContext->thread) {
gba = audioContext->thread->gba;
} else {
gba = audioContext->gba;
} }
#if RESAMPLE_LIBRARY == RESAMPLE_NN #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) { if (audioContext->ratio == INFINITY) {
memset(data, 0, len); memset(data, 0, len);
return; return;
@ -110,7 +116,7 @@ static void _GBASDLAudioCallback(void* context, Uint8* data, int len) {
struct GBAStereoSample* ssamples = (struct GBAStereoSample*) data; struct GBAStereoSample* ssamples = (struct GBAStereoSample*) data;
len /= 2 * audioContext->obtainedSpec.channels; len /= 2 * audioContext->obtainedSpec.channels;
if (audioContext->obtainedSpec.channels == 2) { 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 #elif RESAMPLE_LIBRARY == RESAMPLE_BLIP_BUF
double fauxClock = 1; double fauxClock = 1;
@ -118,16 +124,16 @@ static void _GBASDLAudioCallback(void* context, Uint8* data, int len) {
GBAAudioCalculateRatio(1, audioContext->thread->fpsTarget, 1); GBAAudioCalculateRatio(1, audioContext->thread->fpsTarget, 1);
GBASyncLockAudio(&audioContext->thread->sync); GBASyncLockAudio(&audioContext->thread->sync);
} }
blip_set_rates(audioContext->gba->audio.left, GBA_ARM7TDMI_FREQUENCY, audioContext->obtainedSpec.freq * fauxClock); blip_set_rates(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.right, GBA_ARM7TDMI_FREQUENCY, audioContext->obtainedSpec.freq * fauxClock);
len /= 2 * audioContext->obtainedSpec.channels; 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) { if (available > len) {
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) { 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) { if (audioContext->thread) {