mirror of https://github.com/mgba-emu/mgba.git
Wii: Improve audio buffering (fixes #1617)
This commit is contained in:
parent
2f68ea1b48
commit
d4e30b74ff
1
CHANGES
1
CHANGES
|
@ -113,6 +113,7 @@ Other fixes:
|
||||||
- Qt: Release held actions if they get rebound
|
- Qt: Release held actions if they get rebound
|
||||||
- Vita: Fix analog controls (fixes mgba.io/i/1554)
|
- Vita: Fix analog controls (fixes mgba.io/i/1554)
|
||||||
- Wii: Fix game fast-forwarding after slowing down
|
- Wii: Fix game fast-forwarding after slowing down
|
||||||
|
- Wii: Improve audio buffering (fixes mgba.io/i/1617)
|
||||||
Misc:
|
Misc:
|
||||||
- GB Memory: Support manual SRAM editing (fixes mgba.io/i/1580)
|
- GB Memory: Support manual SRAM editing (fixes mgba.io/i/1580)
|
||||||
- GBA Audio: Redo channel 4 batching for GBA only
|
- GBA Audio: Redo channel 4 batching for GBA only
|
||||||
|
|
|
@ -64,7 +64,8 @@ static enum VideoMode {
|
||||||
VM_MAX
|
VM_MAX
|
||||||
} videoMode = VM_AUTODETECT;
|
} videoMode = VM_AUTODETECT;
|
||||||
|
|
||||||
#define SAMPLES 1024
|
#define SAMPLES 512
|
||||||
|
#define BUFFERS 8
|
||||||
#define GUI_SCALE 1.35f
|
#define GUI_SCALE 1.35f
|
||||||
#define GUI_SCALE_240p 2.0f
|
#define GUI_SCALE_240p 2.0f
|
||||||
|
|
||||||
|
@ -131,9 +132,12 @@ size_t romBufferSize;
|
||||||
static void* framebuffer[2] = { 0, 0 };
|
static void* framebuffer[2] = { 0, 0 };
|
||||||
static int whichFb = 0;
|
static int whichFb = 0;
|
||||||
|
|
||||||
static struct GBAStereoSample audioBuffer[3][SAMPLES] __attribute__((__aligned__(32)));
|
static struct AudioBuffer {
|
||||||
static volatile size_t audioBufferSize = 0;
|
struct GBAStereoSample samples[SAMPLES] __attribute__((__aligned__(32)));
|
||||||
|
volatile size_t size;
|
||||||
|
} audioBuffer[BUFFERS] = {0};
|
||||||
static volatile int currentAudioBuffer = 0;
|
static volatile int currentAudioBuffer = 0;
|
||||||
|
static volatile int nextAudioBuffer = 0;
|
||||||
static double audioSampleRate = 60.0 / 1.001;
|
static double audioSampleRate = 60.0 / 1.001;
|
||||||
|
|
||||||
static struct GUIFont* font;
|
static struct GUIFont* font;
|
||||||
|
@ -610,32 +614,43 @@ int main(int argc, char* argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _audioDMA(void) {
|
static void _audioDMA(void) {
|
||||||
if (!audioBufferSize) {
|
struct AudioBuffer* buffer = &audioBuffer[currentAudioBuffer];
|
||||||
|
if (buffer->size != SAMPLES) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
DCFlushRange(audioBuffer[currentAudioBuffer], audioBufferSize * sizeof(struct GBAStereoSample));
|
DCFlushRange(buffer->samples, SAMPLES * sizeof(struct GBAStereoSample));
|
||||||
AUDIO_InitDMA((u32) audioBuffer[currentAudioBuffer], audioBufferSize * sizeof(struct GBAStereoSample));
|
AUDIO_InitDMA((u32) buffer->samples, SAMPLES * sizeof(struct GBAStereoSample));
|
||||||
currentAudioBuffer = (currentAudioBuffer + 1) % 3;
|
buffer->size = 0;
|
||||||
audioBufferSize = 0;
|
currentAudioBuffer = (currentAudioBuffer + 1) % BUFFERS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _postAudioBuffer(struct mAVStream* stream, blip_t* left, blip_t* right) {
|
static void _postAudioBuffer(struct mAVStream* stream, blip_t* left, blip_t* right) {
|
||||||
UNUSED(stream);
|
UNUSED(stream);
|
||||||
|
|
||||||
|
u32 level = 0;
|
||||||
|
_CPU_ISR_Disable(level);
|
||||||
|
struct AudioBuffer* buffer = &audioBuffer[nextAudioBuffer];
|
||||||
int available = blip_samples_avail(left);
|
int available = blip_samples_avail(left);
|
||||||
if (available + audioBufferSize > SAMPLES) {
|
if (available + buffer->size > SAMPLES) {
|
||||||
available = SAMPLES - audioBufferSize;
|
available = SAMPLES - buffer->size;
|
||||||
}
|
}
|
||||||
available &= ~((32 / sizeof(struct GBAStereoSample)) - 1); // Force align to 32 bytes
|
|
||||||
if (available > 0) {
|
if (available > 0) {
|
||||||
// These appear to be reversed for AUDIO_InitDMA
|
// These appear to be reversed for AUDIO_InitDMA
|
||||||
blip_read_samples(left, &audioBuffer[currentAudioBuffer][audioBufferSize].right, available, true);
|
blip_read_samples(left, &buffer->samples[buffer->size].right, available, true);
|
||||||
blip_read_samples(right, &audioBuffer[currentAudioBuffer][audioBufferSize].left, available, true);
|
blip_read_samples(right, &buffer->samples[buffer->size].left, available, true);
|
||||||
audioBufferSize += available;
|
buffer->size += available;
|
||||||
}
|
}
|
||||||
if (audioBufferSize == SAMPLES && !AUDIO_GetDMAEnableFlag()) {
|
if (buffer->size == SAMPLES) {
|
||||||
_audioDMA();
|
int next = (nextAudioBuffer + 1) % BUFFERS;
|
||||||
AUDIO_StartDMA();
|
if ((currentAudioBuffer + BUFFERS - next) % BUFFERS != 1) {
|
||||||
|
nextAudioBuffer = next;
|
||||||
|
}
|
||||||
|
if (!AUDIO_GetDMAEnableFlag()) {
|
||||||
|
_audioDMA();
|
||||||
|
AUDIO_StartDMA();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
_CPU_ISR_Restore(level);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _drawStart(void) {
|
static void _drawStart(void) {
|
||||||
|
@ -798,6 +813,12 @@ void _setup(struct mGUIRunner* runner) {
|
||||||
outputBuffer = memalign(32, TEX_W * TEX_H * BYTES_PER_PIXEL);
|
outputBuffer = memalign(32, TEX_W * TEX_H * BYTES_PER_PIXEL);
|
||||||
runner->core->setVideoBuffer(runner->core, outputBuffer, TEX_W);
|
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);
|
runner->core->setAudioBufferSize(runner->core, SAMPLES);
|
||||||
|
|
||||||
double ratio = GBAAudioCalculateRatio(1, audioSampleRate, 1);
|
double ratio = GBAAudioCalculateRatio(1, audioSampleRate, 1);
|
||||||
|
|
Loading…
Reference in New Issue