From 6dcc9ec7e3b018b5c4c0dce53b522b153c988c92 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Fri, 14 Jun 2024 07:17:57 +1000 Subject: [PATCH] Audio: Now pass chunks in QueueChunk too --- src/Audio.c | 13 +++---- src/Audio.h | 20 +++++------ src/AudioBackend.c | 89 +++++++++++++++++++++++----------------------- 3 files changed, 61 insertions(+), 61 deletions(-) diff --git a/src/Audio.c b/src/Audio.c index fbdd4ad2c..f9bd8a2e9 100644 --- a/src/Audio.c +++ b/src/Audio.c @@ -183,8 +183,7 @@ static void Sounds_Play(cc_uint8 type, struct Soundboard* board) { snd = Soundboard_PickRandom(board, type); if (!snd) return; - data.data = snd->chunk.data; - data.size = snd->chunk.size; + data.chunk = snd->chunk; data.channels = snd->channels; data.sampleRate = snd->sampleRate; data.rate = 100; @@ -331,10 +330,11 @@ static void* music_waitable; static volatile cc_bool music_stopping, music_joining; static int music_minDelay, music_maxDelay; -static cc_result Music_Buffer(cc_int16* data, int maxSamples, struct VorbisState* ctx) { +static cc_result Music_Buffer(struct AudioChunk* chunk, int maxSamples, struct VorbisState* ctx) { int samples = 0; cc_int16* cur; cc_result res = 0, res2; + cc_int16* data = chunk->data; while (samples < maxSamples) { if ((res = Vorbis_DecodeFrame(ctx))) break; @@ -343,7 +343,8 @@ static cc_result Music_Buffer(cc_int16* data, int maxSamples, struct VorbisState samples += Vorbis_OutputFrame(ctx, cur); } - res2 = Audio_QueueChunk(&music_ctx, data, samples * 2); + chunk->size = samples * 2; + res2 = Audio_QueueChunk(&music_ctx, chunk); if (res2) { music_stopping = true; return res2; } return res; } @@ -379,7 +380,7 @@ static cc_result Music_PlayOgg(struct Stream* source) { /* fill up with some samples before playing */ for (i = 0; i < AUDIO_MAX_BUFFERS && !res; i++) { - res = Music_Buffer((cc_int16*)chunks[i].data, samplesPerSecond, &vorbis); + res = Music_Buffer(&chunks[i], samplesPerSecond, &vorbis); } if (music_stopping) goto cleanup; @@ -411,7 +412,7 @@ static cc_result Music_PlayOgg(struct Stream* source) { Thread_Sleep(10); continue; } - res = Music_Buffer((cc_int16*)chunks[cur].data, samplesPerSecond, &vorbis); + res = Music_Buffer(&chunks[cur], samplesPerSecond, &vorbis); cur = (cur + 1) % AUDIO_MAX_BUFFERS; /* need to specially handle last bit of audio */ diff --git a/src/Audio.h b/src/Audio.h index d1f1f96eb..77d09a269 100644 --- a/src/Audio.h +++ b/src/Audio.h @@ -20,8 +20,15 @@ struct AudioContext; #define DEFAULT_MUSIC_VOLUME 100 #endif +union AudioChunkMeta { void* ptr; cc_uintptr val; }; +struct AudioChunk { + void* data; /* the raw 16 bit integer samples */ + cc_uint32 size; + union AudioChunkMeta meta; +}; + struct AudioData { - void* data; cc_uint32 size; /* the raw 16 bit integer samples */ + struct AudioChunk chunk; int channels; int sampleRate; /* frequency / sample rate */ int volume; /* volume data played at (100 = normal volume) */ @@ -47,13 +54,6 @@ cc_bool AudioBackend_Init(void); void AudioBackend_Tick(void); void AudioBackend_Free(void); -union AudioChunkMeta { void* ptr; cc_uintptr val; }; -struct AudioChunk { - void* data; - cc_uint32 size; - union AudioChunkMeta meta; -}; - /* Initialises an audio context. */ cc_result Audio_Init(struct AudioContext* ctx, int buffers); /* Stops any playing audio and then frees the audio context. */ @@ -65,8 +65,8 @@ cc_result Audio_SetFormat(struct AudioContext* ctx, int channels, int sampleRate void Audio_SetVolume(struct AudioContext* ctx, int volume); /* Queues the given audio chunk for playing. */ /* NOTE: You MUST ensure Audio_Poll indicates a buffer is free before calling this. */ -/* NOTE: Some backends directly read from the data - therefore you MUST NOT modify it */ -cc_result Audio_QueueChunk(struct AudioContext* ctx, void* chunk, cc_uint32 size); +/* NOTE: Some backends directly read from the chunk data - therefore you MUST NOT modify it */ +cc_result Audio_QueueChunk(struct AudioContext* ctx, struct AudioChunk* chunk); /* Begins playing audio. Audio_QueueChunk must have been used before this. */ cc_result Audio_Play(struct AudioContext* ctx); /* Polls the audio context and then potentially unqueues buffer */ diff --git a/src/AudioBackend.c b/src/AudioBackend.c index 2c9240b92..1c6d68644 100644 --- a/src/AudioBackend.c +++ b/src/AudioBackend.c @@ -15,7 +15,7 @@ static cc_bool Audio_FastPlay(struct AudioContext* ctx, struct AudioData* data); /* Common/Base methods */ static void AudioBase_Clear(struct AudioContext* ctx); -static cc_bool AudioBase_AdjustSound(struct AudioContext* ctx, int i, void** data, cc_uint32* size); +static cc_bool AudioBase_AdjustSound(struct AudioContext* ctx, int i, struct AudioChunk* chunk); static cc_result AudioBase_AllocChunks(int size, struct AudioChunk* chunks, int numChunks); static void AudioBase_FreeChunks(struct AudioChunk* chunks, int numChunks); @@ -226,7 +226,7 @@ void Audio_SetVolume(struct AudioContext* ctx, int volume) { _alGetError(); /* Reset error state */ } -cc_result Audio_QueueChunk(struct AudioContext* ctx, void* chunk, cc_uint32 size) { +cc_result Audio_QueueChunk(struct AudioContext* ctx, struct AudioChunk* chunk) { ALuint buffer; ALenum err; @@ -234,7 +234,7 @@ cc_result Audio_QueueChunk(struct AudioContext* ctx, void* chunk, cc_uint32 size buffer = ctx->freeIDs[--ctx->free]; _alGetError(); /* Reset error state */ - _alBufferData(buffer, ctx->format, chunk, size, ctx->sampleRate); + _alBufferData(buffer, ctx->format, chunk->data, chunk->size, ctx->sampleRate); if ((err = _alGetError())) return err; _alSourceQueueBuffers(ctx->source, 1, &buffer); if ((err = _alGetError())) return err; @@ -433,22 +433,23 @@ cc_result Audio_SetFormat(struct AudioContext* ctx, int channels, int sampleRate void Audio_SetVolume(struct AudioContext* ctx, int volume) { ctx->volume = volume; } -cc_result Audio_QueueChunk(struct AudioContext* ctx, void* chunk, cc_uint32 dataSize) { +cc_result Audio_QueueChunk(struct AudioContext* ctx, struct AudioChunk* chunk) { cc_result res; WAVEHDR* hdr; cc_bool ok; int i; + struct AudioChunk tmp = *chunk; for (i = 0; i < ctx->count; i++) { hdr = &ctx->headers[i]; if (!(hdr->dwFlags & WHDR_DONE)) continue; - ok = AudioBase_AdjustSound(ctx, i, &chunk, &dataSize); + ok = AudioBase_AdjustSound(ctx, i, &tmp); if (!ok) return ERR_OUT_OF_MEMORY; Mem_Set(hdr, 0, sizeof(WAVEHDR)); - hdr->lpData = (LPSTR)chunk; - hdr->dwBufferLength = dataSize; + hdr->lpData = (LPSTR)tmp.data; + hdr->dwBufferLength = tmp.size; hdr->dwLoops = 1; if ((res = waveOutPrepareHeader(ctx->handle, hdr, sizeof(WAVEHDR)))) return res; @@ -703,8 +704,8 @@ void Audio_SetVolume(struct AudioContext* ctx, int volume) { UpdateVolume(ctx); } -cc_result Audio_QueueChunk(struct AudioContext* ctx, void* chunk, cc_uint32 size) { - return (*ctx->playerQueue)->Enqueue(ctx->playerQueue, chunk, size); +cc_result Audio_QueueChunk(struct AudioContext* ctx, struct AudioChunk* chunk) { + return (*ctx->playerQueue)->Enqueue(ctx->playerQueue, chunk->data, chunk->size); } cc_result Audio_Pause(struct AudioContext* ctx) { @@ -845,15 +846,15 @@ void Audio_SetVolume(struct AudioContext* ctx, int volume) { ndspChnSetMix(ctx->chanID, mix); } -cc_result Audio_QueueChunk(struct AudioContext* ctx, void* chunk, cc_uint32 dataSize) { +cc_result Audio_QueueChunk(struct AudioContext* ctx, struct AudioChunk* chunk) { ndspWaveBuf* buf; // DSP audio buffers must be aligned to a multiple of 0x80, according to the example code I could find. - if (((uintptr_t)chunk & 0x7F) != 0) { - Platform_Log1("Audio_QueueData: tried to queue buffer with non-aligned audio buffer 0x%x\n", &chunk); + if (((uintptr_t)chunk->data & 0x7F) != 0) { + Platform_Log1("Audio_QueueData: tried to queue buffer with non-aligned audio buffer 0x%x\n", &chunk>data); } - if ((dataSize & 0x7F) != 0) { - Platform_Log1("Audio_QueueData: unaligned audio data size 0x%x\n", &dataSize); + if ((chunk->size & 0x7F) != 0) { + Platform_Log1("Audio_QueueData: unaligned audio data size 0x%x\n", &chunk->size); } for (int i = 0; i < ctx->count; i++) @@ -862,9 +863,9 @@ cc_result Audio_QueueChunk(struct AudioContext* ctx, void* chunk, cc_uint32 data if (buf->status == NDSP_WBUF_QUEUED || buf->status == NDSP_WBUF_PLAYING) continue; - buf->data_pcm16 = chunk; - buf->nsamples = dataSize / (sizeof(cc_int16) * (ctx->stereo ? 2 : 1)); - DSP_FlushDataCache(buf->data_pcm16, dataSize); + buf->data_pcm16 = chunk>data; + buf->nsamples = chunk->size / (sizeof(cc_int16) * (ctx->stereo ? 2 : 1)); + DSP_FlushDataCache(buf->data_pcm16, chunk->size); ndspChnWaveBufAdd(ctx->chanID, buf); return 0; } @@ -1030,15 +1031,15 @@ void Audio_SetVolume(struct AudioContext* ctx, int volume) { audrvVoiceSetVolume(&drv, ctx->chanID, volume / 100.0f); } -cc_result Audio_QueueChunk(struct AudioContext* ctx, void* chunk, cc_uint32 dataSize) { +cc_result Audio_QueueChunk(struct AudioContext* ctx, struct AudioChunk* chunk) { AudioDriverWaveBuf* buf; // Audio buffers must be aligned to a multiple of 0x1000, according to libnx example code - if (((uintptr_t)chunk & 0xFFF) != 0) { - Platform_Log1("Audio_QueueData: tried to queue buffer with non-aligned audio buffer 0x%x\n", &chunk); + if (((uintptr_t)chunk->data & 0xFFF) != 0) { + Platform_Log1("Audio_QueueData: tried to queue buffer with non-aligned audio buffer 0x%x\n", &chunk->data); } - if ((dataSize & 0xFFF) != 0) { - Platform_Log1("Audio_QueueData: unaligned audio data size 0x%x\n", &dataSize); + if ((chunk->size & 0xFFF) != 0) { + Platform_Log1("Audio_QueueData: unaligned audio data size 0x%x\n", &chunk->size); } @@ -1046,16 +1047,15 @@ cc_result Audio_QueueChunk(struct AudioContext* ctx, void* chunk, cc_uint32 data { buf = &ctx->bufs[i]; int state = buf->state; - cc_uint32 size = dataSize; - cc_uint32 endOffset = dataSize / (sizeof(cc_int16) * ((ctx->channels == 2) ? 2 : 1)); + cc_uint32 endOffset = chunk->size / (sizeof(cc_int16) * ((ctx->channels == 2) ? 2 : 1)); if (state == AudioDriverWaveBufState_Queued || state == AudioDriverWaveBufState_Playing || state == AudioDriverWaveBufState_Waiting) continue; - buf->data_pcm16 = chunk; - buf->size = size; + buf->data_pcm16 = chunk->data; + buf->size = chunk->size; buf->start_sample_offset = 0; - buf->end_sample_offset = endOffset; + buf->end_sample_offset = endOffset; Mutex_Lock(audrv_mutex); audrvVoiceAddWaveBuf(&drv, ctx->chanID, buf); @@ -1218,10 +1218,10 @@ void Audio_SetVolume(struct AudioContext* ctx, int volume) { ctx->volume = (volume / 100.0f) * 255; } -cc_result Audio_QueueChunk(struct AudioContext* ctx, void* chunk, cc_uint32 dataSize) { +cc_result Audio_QueueChunk(struct AudioContext* ctx, struct AudioChunk* chunk) { // Audio buffers must be aligned and padded to a multiple of 32 bytes - if (((uintptr_t)chunk & 0x1F) != 0) { - Platform_Log1("Audio_QueueData: tried to queue buffer with non-aligned audio buffer 0x%x\n", &chunk); + if (((uintptr_t)chunk->data & 0x1F) != 0) { + Platform_Log1("Audio_QueueData: tried to queue buffer with non-aligned audio buffer 0x%x\n", &chunk->data); } struct AudioBuffer* buf; @@ -1231,8 +1231,8 @@ cc_result Audio_QueueChunk(struct AudioContext* ctx, void* chunk, cc_uint32 data buf = &ctx->bufs[i]; if (!buf->available) continue; - buf->samples = chunk; - buf->size = dataSize; + buf->samples = chunk->data; + buf->size = chunk->size; buf->available = false; return 0; @@ -1385,7 +1385,7 @@ void Audio_SetVolume(struct AudioContext* ctx, int volume) { snd_stream_volume(ctx->hnd, volume); } -cc_result Audio_QueueChunk(struct AudioContext* ctx, void* chunk, cc_uint32 dataSize) { +cc_result Audio_QueueChunk(struct AudioContext* ctx, struct AudioChunk* chunk) { struct AudioBuffer* buf; for (int i = 0; i < ctx->count; i++) @@ -1393,8 +1393,8 @@ cc_result Audio_QueueChunk(struct AudioContext* ctx, void* chunk, cc_uint32 data buf = &ctx->bufs[i]; if (!buf->available) continue; - buf->samples = chunk; - buf->bytesLeft = dataSize; + buf->samples = chunk->data; + buf->bytesLeft = chunk->size; buf->available = false; return 0; } @@ -1492,8 +1492,8 @@ void Audio_SetVolume(struct AudioContext* ctx, int volume) { interop_AudioVolume(ctx->contextID, volume); } -cc_result Audio_QueueChunk(struct AudioContext* ctx, void* chunk, cc_uint32 size) { - ctx->data = chunk; return 0; +cc_result Audio_QueueChunk(struct AudioContext* ctx, struct AudioChunk* chunk) { + ctx->data = chunk->data; return 0; } cc_result Audio_Play(struct AudioContext* ctx) { @@ -1546,7 +1546,7 @@ cc_result Audio_SetFormat(struct AudioContext* ctx, int channels, int sampleRate void Audio_SetVolume(struct AudioContext* ctx, int volume) { } -cc_result Audio_QueueChunk(struct AudioContext* ctx, void* chunk, cc_uint32 size) { +cc_result Audio_QueueChunk(struct AudioContext* ctx, struct AudioChunk* chunk) { return ERR_NOT_SUPPORTED; } @@ -1609,9 +1609,9 @@ static void AudioBase_Clear(struct AudioContext* ctx) { } } -static cc_bool AudioBase_AdjustSound(struct AudioContext* ctx, int i, void** data, cc_uint32* size) { +static cc_bool AudioBase_AdjustSound(struct AudioContext* ctx, int i, struct AudioChunk* chunk) { void* audio; - cc_uint32 src_size = *size; + cc_uint32 src_size = chunk->size; if (ctx->volume >= 100) return true; /* copy to temp buffer to apply volume */ @@ -1623,17 +1623,16 @@ static cc_bool AudioBase_AdjustSound(struct AudioContext* ctx, int i, void** dat audio = Mem_TryAlloc(src_size, 1); } - if (!data) return false; + if (!audio) return false; ctx->_tmpData[i] = audio; ctx->_tmpSize[i] = src_size; } audio = ctx->_tmpData[i]; - Mem_Copy(audio, *data, src_size); + Mem_Copy(audio, chunk->data, src_size); ApplyVolume((cc_int16*)audio, src_size / 2, ctx->volume); - *data = audio; - *size = src_size; + chunk->data = audio; return true; } #endif @@ -1671,7 +1670,7 @@ static cc_result PlayAudio(struct AudioContext* ctx, struct AudioData* data) { Audio_SetVolume(ctx, data->volume); 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_QueueChunk(ctx, &data->chunk))) return res; if ((res = Audio_Play(ctx))) return res; return 0; }