Permalink
Browse files

Core: Fix audio sync breaking when interrupted

  • Loading branch information...
endrift committed May 29, 2018
1 parent 2aa8716 commit 2ee648a2bb4a0953d489e0bf225bba7d9d9752dc
Showing with 27 additions and 7 deletions.
  1. +1 −0 CHANGES
  2. +2 −1 include/mgba/core/sync.h
  3. +10 −4 src/core/sync.c
  4. +6 −0 src/core/thread.c
  5. +4 −1 src/gb/audio.c
  6. +4 −1 src/gba/audio.c
View
@@ -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)
View
@@ -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);
View
@@ -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) {
View
@@ -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);
View
@@ -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);
View
@@ -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);

0 comments on commit 2ee648a

Please sign in to comment.