mirror of https://github.com/mgba-emu/mgba.git
Core: Fix audio sync breaking when interrupted
This commit is contained in:
parent
2aa8716cc9
commit
2ee648a2bb
1
CHANGES
1
CHANGES
|
@ -34,6 +34,7 @@ Bugfixes:
|
|||
- GBA Savedata: Fix savedata modified time updating when read-only
|
||||
- GB Video: Fix enabling window when LY > WY (fixes mgba.io/i/409)
|
||||
- GBA Video: Start timing mid-scanline when skipping BIOS
|
||||
- Core: Fix audio sync breaking when interrupted
|
||||
Misc:
|
||||
- GBA Timer: Use global cycles for timers
|
||||
- GBA: Extend oddly-sized ROMs to full address space (fixes mgba.io/i/722)
|
||||
|
|
|
@ -33,7 +33,8 @@ bool mCoreSyncWaitFrameStart(struct mCoreSync* sync);
|
|||
void mCoreSyncWaitFrameEnd(struct mCoreSync* sync);
|
||||
void mCoreSyncSetVideoSync(struct mCoreSync* sync, bool wait);
|
||||
|
||||
void mCoreSyncProduceAudio(struct mCoreSync* sync, bool wait);
|
||||
struct blip_t;
|
||||
bool mCoreSyncProduceAudio(struct mCoreSync* sync, const struct blip_t*, size_t samples);
|
||||
void mCoreSyncLockAudio(struct mCoreSync* sync);
|
||||
void mCoreSyncUnlockAudio(struct mCoreSync* sync);
|
||||
void mCoreSyncConsumeAudio(struct mCoreSync* sync);
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include <mgba/core/sync.h>
|
||||
|
||||
#include <mgba/core/blip_buf.h>
|
||||
|
||||
static void _changeVideoSync(struct mCoreSync* sync, bool frameOn) {
|
||||
// Make sure the video thread can process events while the GBA thread is paused
|
||||
MutexLock(&sync->videoFrameMutex);
|
||||
|
@ -76,16 +78,20 @@ void mCoreSyncSetVideoSync(struct mCoreSync* sync, bool wait) {
|
|||
_changeVideoSync(sync, wait);
|
||||
}
|
||||
|
||||
void mCoreSyncProduceAudio(struct mCoreSync* sync, bool wait) {
|
||||
bool mCoreSyncProduceAudio(struct mCoreSync* sync, const struct blip_t* buf, size_t samples) {
|
||||
if (!sync) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (sync->audioWait && wait) {
|
||||
// TODO loop properly in event of spurious wakeups
|
||||
size_t produced = blip_samples_avail(buf);
|
||||
size_t producedNew = produced;
|
||||
while (sync->audioWait && producedNew >= samples) {
|
||||
ConditionWait(&sync->audioRequiredCond, &sync->audioBufferMutex);
|
||||
produced = producedNew;
|
||||
producedNew = blip_samples_avail(buf);
|
||||
}
|
||||
MutexUnlock(&sync->audioBufferMutex);
|
||||
return producedNew != produced;
|
||||
}
|
||||
|
||||
void mCoreSyncLockAudio(struct mCoreSync* sync) {
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include <mgba/core/thread.h>
|
||||
|
||||
#include <mgba/core/blip_buf.h>
|
||||
#include <mgba/core/core.h>
|
||||
#include <mgba/core/serialize.h>
|
||||
#include <mgba-util/patch.h>
|
||||
|
@ -219,6 +220,11 @@ static THREAD_ENTRY _mCoreThreadRun(void* context) {
|
|||
deferred = impl->state;
|
||||
while (impl->state >= THREAD_WAITING && impl->state <= THREAD_MAX_WAITING) {
|
||||
ConditionWait(&impl->stateCond, &impl->stateMutex);
|
||||
|
||||
if (impl->sync.audioWait) {
|
||||
mCoreSyncLockAudio(&impl->sync);
|
||||
mCoreSyncProduceAudio(&impl->sync, core->getAudioChannel(core, 0), core->getAudioBufferSize(core));
|
||||
}
|
||||
}
|
||||
}
|
||||
MutexUnlock(&impl->stateMutex);
|
||||
|
|
|
@ -667,7 +667,10 @@ static void _sample(struct mTiming* timing, void* user, uint32_t cyclesLate) {
|
|||
audio->p->stream->postAudioFrame(audio->p->stream, sampleLeft, sampleRight);
|
||||
}
|
||||
bool wait = produced >= audio->samples;
|
||||
mCoreSyncProduceAudio(audio->p->sync, wait);
|
||||
if (!mCoreSyncProduceAudio(audio->p->sync, audio->left, audio->samples)) {
|
||||
// Interrupted
|
||||
audio->p->earlyExit = true;
|
||||
}
|
||||
|
||||
if (wait && audio->p->stream && audio->p->stream->postAudioBuffer) {
|
||||
audio->p->stream->postAudioBuffer(audio->p->stream, audio->left, audio->right);
|
||||
|
|
|
@ -307,7 +307,10 @@ static void _sample(struct mTiming* timing, void* user, uint32_t cyclesLate) {
|
|||
audio->p->stream->postAudioFrame(audio->p->stream, sampleLeft, sampleRight);
|
||||
}
|
||||
bool wait = produced >= audio->samples;
|
||||
mCoreSyncProduceAudio(audio->p->sync, wait);
|
||||
if (!mCoreSyncProduceAudio(audio->p->sync, audio->psg.left, audio->samples)) {
|
||||
// Interrupted
|
||||
audio->p->earlyExit = true;
|
||||
}
|
||||
|
||||
if (wait && audio->p->stream && audio->p->stream->postAudioBuffer) {
|
||||
audio->p->stream->postAudioBuffer(audio->p->stream, audio->psg.left, audio->psg.right);
|
||||
|
|
Loading…
Reference in New Issue