all repos — mgba @ d4e30b74ff3d34352ca86094bb1a4f97ccf12a8f

mGBA Game Boy Advance Emulator

Wii: Improve audio buffering (fixes #1617)
Vicki Pfau vi@endrift.com
Mon, 13 Jan 2020 19:24:57 -0800
commit

d4e30b74ff3d34352ca86094bb1a4f97ccf12a8f

parent

2f68ea1b48da14a1a0be06e84fd9a898d93bcdfd

2 files changed, 39 insertions(+), 17 deletions(-)

jump to
M CHANGESCHANGES

@@ -113,6 +113,7 @@ - Qt: Fix inability to clear default keybindings

- Qt: Release held actions if they get rebound - Vita: Fix analog controls (fixes mgba.io/i/1554) - Wii: Fix game fast-forwarding after slowing down + - Wii: Improve audio buffering (fixes mgba.io/i/1617) Misc: - GB Memory: Support manual SRAM editing (fixes mgba.io/i/1580) - GBA Audio: Redo channel 4 batching for GBA only
M src/platform/wii/main.csrc/platform/wii/main.c

@@ -64,7 +64,8 @@ // TODO: PAL support

VM_MAX } videoMode = VM_AUTODETECT; -#define SAMPLES 1024 +#define SAMPLES 512 +#define BUFFERS 8 #define GUI_SCALE 1.35f #define GUI_SCALE_240p 2.0f

@@ -131,9 +132,12 @@

static void* framebuffer[2] = { 0, 0 }; static int whichFb = 0; -static struct GBAStereoSample audioBuffer[3][SAMPLES] __attribute__((__aligned__(32))); -static volatile size_t audioBufferSize = 0; +static struct AudioBuffer { + struct GBAStereoSample samples[SAMPLES] __attribute__((__aligned__(32))); + volatile size_t size; +} audioBuffer[BUFFERS] = {0}; static volatile int currentAudioBuffer = 0; +static volatile int nextAudioBuffer = 0; static double audioSampleRate = 60.0 / 1.001; static struct GUIFont* font;

@@ -610,32 +614,43 @@ return 0;

} static void _audioDMA(void) { - if (!audioBufferSize) { + struct AudioBuffer* buffer = &audioBuffer[currentAudioBuffer]; + if (buffer->size != SAMPLES) { return; } - DCFlushRange(audioBuffer[currentAudioBuffer], audioBufferSize * sizeof(struct GBAStereoSample)); - AUDIO_InitDMA((u32) audioBuffer[currentAudioBuffer], audioBufferSize * sizeof(struct GBAStereoSample)); - currentAudioBuffer = (currentAudioBuffer + 1) % 3; - audioBufferSize = 0; + DCFlushRange(buffer->samples, SAMPLES * sizeof(struct GBAStereoSample)); + AUDIO_InitDMA((u32) buffer->samples, SAMPLES * sizeof(struct GBAStereoSample)); + buffer->size = 0; + currentAudioBuffer = (currentAudioBuffer + 1) % BUFFERS; } static void _postAudioBuffer(struct mAVStream* stream, blip_t* left, blip_t* right) { UNUSED(stream); + + u32 level = 0; + _CPU_ISR_Disable(level); + struct AudioBuffer* buffer = &audioBuffer[nextAudioBuffer]; int available = blip_samples_avail(left); - if (available + audioBufferSize > SAMPLES) { - available = SAMPLES - audioBufferSize; + if (available + buffer->size > SAMPLES) { + available = SAMPLES - buffer->size; } - available &= ~((32 / sizeof(struct GBAStereoSample)) - 1); // Force align to 32 bytes if (available > 0) { // These appear to be reversed for AUDIO_InitDMA - blip_read_samples(left, &audioBuffer[currentAudioBuffer][audioBufferSize].right, available, true); - blip_read_samples(right, &audioBuffer[currentAudioBuffer][audioBufferSize].left, available, true); - audioBufferSize += available; + blip_read_samples(left, &buffer->samples[buffer->size].right, available, true); + blip_read_samples(right, &buffer->samples[buffer->size].left, available, true); + buffer->size += available; } - if (audioBufferSize == SAMPLES && !AUDIO_GetDMAEnableFlag()) { - _audioDMA(); - AUDIO_StartDMA(); + if (buffer->size == SAMPLES) { + int next = (nextAudioBuffer + 1) % BUFFERS; + if ((currentAudioBuffer + BUFFERS - next) % BUFFERS != 1) { + nextAudioBuffer = next; + } + if (!AUDIO_GetDMAEnableFlag()) { + _audioDMA(); + AUDIO_StartDMA(); + } } + _CPU_ISR_Restore(level); } static void _drawStart(void) {

@@ -798,6 +813,12 @@

outputBuffer = memalign(32, TEX_W * TEX_H * BYTES_PER_PIXEL); runner->core->setVideoBuffer(runner->core, outputBuffer, TEX_W); + nextAudioBuffer = 0; + currentAudioBuffer = 0; + int i; + for (i = 0; i < BUFFERS; ++i) { + audioBuffer[i].size = 0; + } runner->core->setAudioBufferSize(runner->core, SAMPLES); double ratio = GBAAudioCalculateRatio(1, audioSampleRate, 1);