Wii: some more fixes to audio backend/music

This commit is contained in:
headshot2017 2024-03-26 13:54:16 -04:00
parent 8bfe004d71
commit 1668a1ba2b

View File

@ -1134,8 +1134,15 @@ void Audio_FreeChunks(void** chunks, int numChunks) {
#include <stdio.h>
#include <stdlib.h>
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++) {