mirror of https://github.com/mgba-emu/mgba.git
SDL, Qt: Fix audio thread crashes
This commit is contained in:
parent
df47cb1f95
commit
7ce34411bb
|
@ -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()) {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Reference in New Issue