Audio: Now pass chunks in QueueChunk too

This commit is contained in:
UnknownShadow200 2024-06-14 07:17:57 +10:00
parent e7a0619e47
commit 6dcc9ec7e3
3 changed files with 61 additions and 61 deletions

View File

@ -183,8 +183,7 @@ static void Sounds_Play(cc_uint8 type, struct Soundboard* board) {
snd = Soundboard_PickRandom(board, type); snd = Soundboard_PickRandom(board, type);
if (!snd) return; if (!snd) return;
data.data = snd->chunk.data; data.chunk = snd->chunk;
data.size = snd->chunk.size;
data.channels = snd->channels; data.channels = snd->channels;
data.sampleRate = snd->sampleRate; data.sampleRate = snd->sampleRate;
data.rate = 100; data.rate = 100;
@ -331,10 +330,11 @@ static void* music_waitable;
static volatile cc_bool music_stopping, music_joining; static volatile cc_bool music_stopping, music_joining;
static int music_minDelay, music_maxDelay; 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; int samples = 0;
cc_int16* cur; cc_int16* cur;
cc_result res = 0, res2; cc_result res = 0, res2;
cc_int16* data = chunk->data;
while (samples < maxSamples) { while (samples < maxSamples) {
if ((res = Vorbis_DecodeFrame(ctx))) break; 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); 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; } if (res2) { music_stopping = true; return res2; }
return res; return res;
} }
@ -379,7 +380,7 @@ static cc_result Music_PlayOgg(struct Stream* source) {
/* fill up with some samples before playing */ /* fill up with some samples before playing */
for (i = 0; i < AUDIO_MAX_BUFFERS && !res; i++) 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; if (music_stopping) goto cleanup;
@ -411,7 +412,7 @@ static cc_result Music_PlayOgg(struct Stream* source) {
Thread_Sleep(10); continue; 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; cur = (cur + 1) % AUDIO_MAX_BUFFERS;
/* need to specially handle last bit of audio */ /* need to specially handle last bit of audio */

View File

@ -20,8 +20,15 @@ struct AudioContext;
#define DEFAULT_MUSIC_VOLUME 100 #define DEFAULT_MUSIC_VOLUME 100
#endif #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 { struct AudioData {
void* data; cc_uint32 size; /* the raw 16 bit integer samples */ struct AudioChunk chunk;
int channels; int channels;
int sampleRate; /* frequency / sample rate */ int sampleRate; /* frequency / sample rate */
int volume; /* volume data played at (100 = normal volume) */ int volume; /* volume data played at (100 = normal volume) */
@ -47,13 +54,6 @@ cc_bool AudioBackend_Init(void);
void AudioBackend_Tick(void); void AudioBackend_Tick(void);
void AudioBackend_Free(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. */ /* Initialises an audio context. */
cc_result Audio_Init(struct AudioContext* ctx, int buffers); cc_result Audio_Init(struct AudioContext* ctx, int buffers);
/* Stops any playing audio and then frees the audio context. */ /* 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); void Audio_SetVolume(struct AudioContext* ctx, int volume);
/* Queues the given audio chunk for playing. */ /* Queues the given audio chunk for playing. */
/* NOTE: You MUST ensure Audio_Poll indicates a buffer is free before calling this. */ /* 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 */ /* NOTE: Some backends directly read from the chunk data - therefore you MUST NOT modify it */
cc_result Audio_QueueChunk(struct AudioContext* ctx, void* chunk, cc_uint32 size); cc_result Audio_QueueChunk(struct AudioContext* ctx, struct AudioChunk* chunk);
/* Begins playing audio. Audio_QueueChunk must have been used before this. */ /* Begins playing audio. Audio_QueueChunk must have been used before this. */
cc_result Audio_Play(struct AudioContext* ctx); cc_result Audio_Play(struct AudioContext* ctx);
/* Polls the audio context and then potentially unqueues buffer */ /* Polls the audio context and then potentially unqueues buffer */

View File

@ -15,7 +15,7 @@ static cc_bool Audio_FastPlay(struct AudioContext* ctx, struct AudioData* data);
/* Common/Base methods */ /* Common/Base methods */
static void AudioBase_Clear(struct AudioContext* ctx); 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 cc_result AudioBase_AllocChunks(int size, struct AudioChunk* chunks, int numChunks);
static void AudioBase_FreeChunks(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 */ _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; ALuint buffer;
ALenum err; ALenum err;
@ -234,7 +234,7 @@ cc_result Audio_QueueChunk(struct AudioContext* ctx, void* chunk, cc_uint32 size
buffer = ctx->freeIDs[--ctx->free]; buffer = ctx->freeIDs[--ctx->free];
_alGetError(); /* Reset error state */ _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; if ((err = _alGetError())) return err;
_alSourceQueueBuffers(ctx->source, 1, &buffer); _alSourceQueueBuffers(ctx->source, 1, &buffer);
if ((err = _alGetError())) return err; 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; } 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; cc_result res;
WAVEHDR* hdr; WAVEHDR* hdr;
cc_bool ok; cc_bool ok;
int i; int i;
struct AudioChunk tmp = *chunk;
for (i = 0; i < ctx->count; i++) { for (i = 0; i < ctx->count; i++) {
hdr = &ctx->headers[i]; hdr = &ctx->headers[i];
if (!(hdr->dwFlags & WHDR_DONE)) continue; 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; if (!ok) return ERR_OUT_OF_MEMORY;
Mem_Set(hdr, 0, sizeof(WAVEHDR)); Mem_Set(hdr, 0, sizeof(WAVEHDR));
hdr->lpData = (LPSTR)chunk; hdr->lpData = (LPSTR)tmp.data;
hdr->dwBufferLength = dataSize; hdr->dwBufferLength = tmp.size;
hdr->dwLoops = 1; hdr->dwLoops = 1;
if ((res = waveOutPrepareHeader(ctx->handle, hdr, sizeof(WAVEHDR)))) return res; if ((res = waveOutPrepareHeader(ctx->handle, hdr, sizeof(WAVEHDR)))) return res;
@ -703,8 +704,8 @@ void Audio_SetVolume(struct AudioContext* ctx, int volume) {
UpdateVolume(ctx); UpdateVolume(ctx);
} }
cc_result Audio_QueueChunk(struct AudioContext* ctx, void* chunk, cc_uint32 size) { cc_result Audio_QueueChunk(struct AudioContext* ctx, struct AudioChunk* chunk) {
return (*ctx->playerQueue)->Enqueue(ctx->playerQueue, chunk, size); return (*ctx->playerQueue)->Enqueue(ctx->playerQueue, chunk->data, chunk->size);
} }
cc_result Audio_Pause(struct AudioContext* ctx) { cc_result Audio_Pause(struct AudioContext* ctx) {
@ -845,15 +846,15 @@ void Audio_SetVolume(struct AudioContext* ctx, int volume) {
ndspChnSetMix(ctx->chanID, mix); 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; ndspWaveBuf* buf;
// DSP audio buffers must be aligned to a multiple of 0x80, according to the example code I could find. // 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) { if (((uintptr_t)chunk->data & 0x7F) != 0) {
Platform_Log1("Audio_QueueData: tried to queue buffer with non-aligned audio buffer 0x%x\n", &chunk); Platform_Log1("Audio_QueueData: tried to queue buffer with non-aligned audio buffer 0x%x\n", &chunk>data);
} }
if ((dataSize & 0x7F) != 0) { if ((chunk->size & 0x7F) != 0) {
Platform_Log1("Audio_QueueData: unaligned audio data size 0x%x\n", &dataSize); Platform_Log1("Audio_QueueData: unaligned audio data size 0x%x\n", &chunk->size);
} }
for (int i = 0; i < ctx->count; i++) 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) if (buf->status == NDSP_WBUF_QUEUED || buf->status == NDSP_WBUF_PLAYING)
continue; continue;
buf->data_pcm16 = chunk; buf->data_pcm16 = chunk>data;
buf->nsamples = dataSize / (sizeof(cc_int16) * (ctx->stereo ? 2 : 1)); buf->nsamples = chunk->size / (sizeof(cc_int16) * (ctx->stereo ? 2 : 1));
DSP_FlushDataCache(buf->data_pcm16, dataSize); DSP_FlushDataCache(buf->data_pcm16, chunk->size);
ndspChnWaveBufAdd(ctx->chanID, buf); ndspChnWaveBufAdd(ctx->chanID, buf);
return 0; return 0;
} }
@ -1030,15 +1031,15 @@ void Audio_SetVolume(struct AudioContext* ctx, int volume) {
audrvVoiceSetVolume(&drv, ctx->chanID, volume / 100.0f); 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; AudioDriverWaveBuf* buf;
// Audio buffers must be aligned to a multiple of 0x1000, according to libnx example code // Audio buffers must be aligned to a multiple of 0x1000, according to libnx example code
if (((uintptr_t)chunk & 0xFFF) != 0) { if (((uintptr_t)chunk->data & 0xFFF) != 0) {
Platform_Log1("Audio_QueueData: tried to queue buffer with non-aligned audio buffer 0x%x\n", &chunk); Platform_Log1("Audio_QueueData: tried to queue buffer with non-aligned audio buffer 0x%x\n", &chunk->data);
} }
if ((dataSize & 0xFFF) != 0) { if ((chunk->size & 0xFFF) != 0) {
Platform_Log1("Audio_QueueData: unaligned audio data size 0x%x\n", &dataSize); Platform_Log1("Audio_QueueData: unaligned audio data size 0x%x\n", &chunk->size);
} }
@ -1046,14 +1047,13 @@ cc_result Audio_QueueChunk(struct AudioContext* ctx, void* chunk, cc_uint32 data
{ {
buf = &ctx->bufs[i]; buf = &ctx->bufs[i];
int state = buf->state; int state = buf->state;
cc_uint32 size = dataSize; cc_uint32 endOffset = chunk->size / (sizeof(cc_int16) * ((ctx->channels == 2) ? 2 : 1));
cc_uint32 endOffset = dataSize / (sizeof(cc_int16) * ((ctx->channels == 2) ? 2 : 1));
if (state == AudioDriverWaveBufState_Queued || state == AudioDriverWaveBufState_Playing || state == AudioDriverWaveBufState_Waiting) if (state == AudioDriverWaveBufState_Queued || state == AudioDriverWaveBufState_Playing || state == AudioDriverWaveBufState_Waiting)
continue; continue;
buf->data_pcm16 = chunk; buf->data_pcm16 = chunk->data;
buf->size = size; buf->size = chunk->size;
buf->start_sample_offset = 0; buf->start_sample_offset = 0;
buf->end_sample_offset = endOffset; buf->end_sample_offset = endOffset;
@ -1218,10 +1218,10 @@ void Audio_SetVolume(struct AudioContext* ctx, int volume) {
ctx->volume = (volume / 100.0f) * 255; 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 // Audio buffers must be aligned and padded to a multiple of 32 bytes
if (((uintptr_t)chunk & 0x1F) != 0) { if (((uintptr_t)chunk->data & 0x1F) != 0) {
Platform_Log1("Audio_QueueData: tried to queue buffer with non-aligned audio buffer 0x%x\n", &chunk); Platform_Log1("Audio_QueueData: tried to queue buffer with non-aligned audio buffer 0x%x\n", &chunk->data);
} }
struct AudioBuffer* buf; struct AudioBuffer* buf;
@ -1231,8 +1231,8 @@ cc_result Audio_QueueChunk(struct AudioContext* ctx, void* chunk, cc_uint32 data
buf = &ctx->bufs[i]; buf = &ctx->bufs[i];
if (!buf->available) continue; if (!buf->available) continue;
buf->samples = chunk; buf->samples = chunk->data;
buf->size = dataSize; buf->size = chunk->size;
buf->available = false; buf->available = false;
return 0; return 0;
@ -1385,7 +1385,7 @@ void Audio_SetVolume(struct AudioContext* ctx, int volume) {
snd_stream_volume(ctx->hnd, 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; struct AudioBuffer* buf;
for (int i = 0; i < ctx->count; i++) 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]; buf = &ctx->bufs[i];
if (!buf->available) continue; if (!buf->available) continue;
buf->samples = chunk; buf->samples = chunk->data;
buf->bytesLeft = dataSize; buf->bytesLeft = chunk->size;
buf->available = false; buf->available = false;
return 0; return 0;
} }
@ -1492,8 +1492,8 @@ void Audio_SetVolume(struct AudioContext* ctx, int volume) {
interop_AudioVolume(ctx->contextID, volume); interop_AudioVolume(ctx->contextID, volume);
} }
cc_result Audio_QueueChunk(struct AudioContext* ctx, void* chunk, cc_uint32 size) { cc_result Audio_QueueChunk(struct AudioContext* ctx, struct AudioChunk* chunk) {
ctx->data = chunk; return 0; ctx->data = chunk->data; return 0;
} }
cc_result Audio_Play(struct AudioContext* ctx) { 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) { } 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; 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; void* audio;
cc_uint32 src_size = *size; cc_uint32 src_size = chunk->size;
if (ctx->volume >= 100) return true; if (ctx->volume >= 100) return true;
/* copy to temp buffer to apply volume */ /* 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); audio = Mem_TryAlloc(src_size, 1);
} }
if (!data) return false; if (!audio) return false;
ctx->_tmpData[i] = audio; ctx->_tmpData[i] = audio;
ctx->_tmpSize[i] = src_size; ctx->_tmpSize[i] = src_size;
} }
audio = ctx->_tmpData[i]; 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); ApplyVolume((cc_int16*)audio, src_size / 2, ctx->volume);
*data = audio; chunk->data = audio;
*size = src_size;
return true; return true;
} }
#endif #endif
@ -1671,7 +1670,7 @@ static cc_result PlayAudio(struct AudioContext* ctx, struct AudioData* data) {
Audio_SetVolume(ctx, data->volume); Audio_SetVolume(ctx, data->volume);
if ((res = Audio_SetFormat(ctx, data->channels, data->sampleRate, data->rate))) return res; 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; if ((res = Audio_Play(ctx))) return res;
return 0; return 0;
} }