From 1668a1ba2b84f6ca94cd0e35b95258b19e635a3b Mon Sep 17 00:00:00 2001 From: headshot2017 <> Date: Tue, 26 Mar 2024 13:54:16 -0400 Subject: [PATCH] Wii: some more fixes to audio backend/music --- src/AudioBackend.c | 89 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 72 insertions(+), 17 deletions(-) diff --git a/src/AudioBackend.c b/src/AudioBackend.c index 113554f2e..29c6ccd62 100644 --- a/src/AudioBackend.c +++ b/src/AudioBackend.c @@ -1134,8 +1134,15 @@ void Audio_FreeChunks(void** chunks, int numChunks) { #include #include +struct AudioBuffer { + int available; + int size; + void* samples; +}; + struct AudioContext { - int chanID, count; + int chanID, count, bufHead; + struct AudioBuffer bufs[AUDIO_MAX_BUFFERS]; int channels, sampleRate, volume; }; @@ -1152,10 +1159,29 @@ void AudioBackend_Free(void) { ASND_End(); } +void MusicCallback(s32 voice) { + struct AudioContext* ctx = &music_ctx; + struct AudioBuffer* buf = &ctx->bufs[ctx->bufHead]; + struct AudioBuffer* nextBuf = &ctx->bufs[(ctx->bufHead + 1) % ctx->count]; + + if (ASND_AddVoice(voice, buf->samples, buf->size) == SND_OK) { + ctx->bufHead = (ctx->bufHead + 1) % ctx->count; + buf->samples = NULL; + buf->available = true; + } +} + cc_result Audio_Init(struct AudioContext* ctx, int buffers) { - ctx->chanID = -1; - ctx->count = buffers; - ctx->volume = 255; + ctx->chanID = ASND_GetFirstUnusedVoice();; + ctx->count = buffers; + ctx->volume = 255; + ctx->bufHead = 0; + + Mem_Set(ctx->bufs, 0, sizeof(ctx->bufs)); + for (int i = 0; i < buffers; i++) { + ctx->bufs[i].available = true; + } + return 0; } @@ -1169,7 +1195,7 @@ cc_result Audio_SetFormat(struct AudioContext* ctx, int channels, int sampleRate sampleRate = Audio_AdjustSampleRate(sampleRate, playbackRate); ctx->channels = channels; ctx->sampleRate = sampleRate; - ctx->chanID = ASND_GetFirstUnusedVoice(); + return 0; } @@ -1182,41 +1208,70 @@ cc_result Audio_QueueChunk(struct AudioContext* ctx, void* chunk, cc_uint32 data if (((uintptr_t)chunk & 0x20) != 0) { Platform_Log1("Audio_QueueData: tried to queue buffer with non-aligned audio buffer 0x%x\n", &chunk); } - if ((dataSize & 0x20) != 0) { - Platform_Log1("Audio_QueueData: unaligned audio data size 0x%x\n", &dataSize); + + struct AudioBuffer* buf; + + for (int i = 0; i < ctx->count; i++) + { + buf = &ctx->bufs[i]; + if (!buf->available) continue; + + buf->samples = chunk; + buf->size = dataSize; + buf->available = false; + + return 0; } - int format = (ctx->channels == 2) ? VOICE_STEREO_16BIT : VOICE_MONO_16BIT; - ASND_SetVoice(ctx->chanID, format, ctx->sampleRate, 0, chunk, dataSize, ctx->volume, ctx->volume, NULL); - - return 0; - // tried to queue data without polling for free buffers first return ERR_INVALID_ARGUMENT; } cc_result Audio_Play(struct AudioContext* ctx) { + int format = (ctx->channels == 2) ? VOICE_STEREO_16BIT : VOICE_MONO_16BIT; + ASND_SetVoice(ctx->chanID, format, ctx->sampleRate, 0, ctx->bufs[0].samples, ctx->bufs[0].size, ctx->volume, ctx->volume, (ctx->count > 1) ? MusicCallback : NULL); + return 0; } cc_result Audio_Poll(struct AudioContext* ctx, int* inUse) { - int status = ASND_StatusVoice(ctx->chanID); - *inUse = (status <= 0) ? 0 : ctx->count; + struct AudioBuffer* buf; + int count = 0; + for (int i = 0; i < ctx->count; i++) { + buf = &ctx->bufs[i]; + if (!buf->available) count++; + } + + *inUse = count; return 0; } -static cc_bool Audio_FastPlay(struct AudioContext* ctx, struct AudioData* data) { + +cc_bool Audio_FastPlay(struct AudioContext* ctx, struct AudioData* data) { return true; } +cc_result Audio_PlayData(struct AudioContext* ctx, struct AudioData* data) { + cc_result res; + + ctx->volume = data->volume/100.f*255; + + if ((res = Audio_SetFormat(ctx, data->channels, data->sampleRate, data->rate))) return res; + if ((res = Audio_QueueChunk(ctx, data->data, data->size))) return res; + if ((res = Audio_Play(ctx))) return res; + + return 0; +} + cc_bool Audio_DescribeError(cc_result res, cc_string* dst) { return false; } cc_result Audio_AllocChunks(cc_uint32 size, void** chunks, int numChunks) { - size = (size + 0x1F) & ~0x1F; // round up to nearest multiple of 0x20 - void* dst = aligned_alloc(0x20, size * numChunks); + size = (size + 0x1F) & ~0x1F; // round up to nearest multiple of 0x20 + cc_uint32 alignedSize = ((size*numChunks) + 0x1F) & ~0x1F; // round up to nearest multiple of 0x20 + void* dst = aligned_alloc(0x20, alignedSize); if (!dst) return ERR_OUT_OF_MEMORY; for (int i = 0; i < numChunks; i++) {