From 9069f34b7f443b109f4675a0bbbf0cf2427d0332 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Wed, 27 Oct 2021 21:18:59 -0700 Subject: [PATCH] change streaming to use OnBufferEnded callback --- src/FAudioGMS.c | 149 ++++++++++++------------------------------------ 1 file changed, 36 insertions(+), 113 deletions(-) diff --git a/src/FAudioGMS.c b/src/FAudioGMS.c index 107b957..f4c4efc 100644 --- a/src/FAudioGMS.c +++ b/src/FAudioGMS.c @@ -142,52 +142,6 @@ static inline uint32_t IdStack_Pop(IdStack* stack) return stack->array[stack->count]; } -typedef struct BufferQueue -{ - uint32_t head; - uint32_t tail; - uint32_t size; /* DO NOT MUTATE */ - uint32_t count; /* number of currently enqueued elements */ - uint8_t** buffers; -} BufferQueue; - -static inline void BufferQueue_Init(BufferQueue* queue, uint32_t size) -{ - queue->head = 0; - queue->tail = 0; - queue->size = size; - queue->count = 0; - queue->buffers = SDL_malloc(size * sizeof(uint8_t*)); -} - -static inline uint8_t* BufferQueue_Dequeue(BufferQueue *queue) -{ - if (queue->tail == queue->head) - { - return NULL; - } - - uint8_t* buffer = queue->buffers[queue->tail]; - queue->buffers[queue->tail] = NULL; - queue->tail = (queue->tail + 1) % queue->size; - - queue->count -= 1; - return buffer; -} - -static inline void BufferQueue_Enqueue(BufferQueue *queue, uint8_t* buffer) -{ - if (((queue->head + 1) % queue->size) == queue->tail) - { - return; - } - - queue->buffers[queue->head] = buffer; - queue->head = (queue->head + 1) % queue->size; - - queue->count += 1; -} - typedef enum FAudioGMS_SoundState { SoundState_Playing, @@ -210,7 +164,6 @@ typedef struct FAudioGMS_StreamingSound { stb_vorbis* fileHandle; stb_vorbis_info info; - BufferQueue bufferQueue; } FAudioGMS_StreamingSound; typedef struct FAudioGMS_SoundInstance @@ -272,10 +225,8 @@ typedef struct FAudioGMS_EffectChain static const float SPEED_OF_SOUND = 343.5f; static const float DOPPLER_SCALE = 1.0f; -static const uint32_t MINIMUM_BUFFER_CHECK = 3; -#define MAX_BUFFER_QUEUE_COUNT 16 -#define STREAMING_BUFFER_SIZE 1024 * 8 * sizeof(float) /* FIXME: what should this value be? */ +#define STREAMING_BUFFER_SIZE 1024 * 16 * sizeof(float) /* FIXME: what should this value be? */ typedef struct FAudioGMS_Device { @@ -288,6 +239,8 @@ typedef struct FAudioGMS_Device F3DAUDIO_LISTENER listener; float spatialDistanceScale; + FAudioVoiceCallback voiceCallbacks; + FAudioGMS_StaticSound **staticSounds; uint32_t staticSoundCount; IdStack staticSoundIndexStack; @@ -348,6 +301,17 @@ static inline FAudioGMS_EffectChain* FAudioGMS_INTERNAL_LookupEffectChain(uint32 } } +/* Forward declare this to avoid annoying BS */ +static void FAudioGMS_INTERNAL_SoundInstance_AddBuffer(FAudioGMS_SoundInstance* instance); + +static void FAudioGMS_INTERNAL_StreamingBufferEndCallback(FAudioVoiceCallback* callback, FAudioGMS_SoundInstance *instance) +{ + if (instance->soundState == SoundState_Playing) + { + FAudioGMS_INTERNAL_SoundInstance_AddBuffer(instance); + } +} + void FAudioGMS_Init(double spatialDistanceScale, double timestep) { device = SDL_malloc(sizeof(FAudioGMS_Device)); @@ -443,6 +407,14 @@ void FAudioGMS_Init(double spatialDistanceScale, double timestep) device->listener.Velocity.z = 0; device->listener.pCone = NULL; + device->voiceCallbacks.OnBufferEnd = FAudioGMS_INTERNAL_StreamingBufferEndCallback; + device->voiceCallbacks.OnBufferStart = NULL; + device->voiceCallbacks.OnLoopEnd = NULL; + device->voiceCallbacks.OnStreamEnd = NULL; + device->voiceCallbacks.OnVoiceError = NULL; + device->voiceCallbacks.OnVoiceProcessingPassEnd = NULL; + device->voiceCallbacks.OnVoiceProcessingPassStart = NULL; + device->staticSounds = NULL; device->staticSoundCount = 0; IdStack_Init(&device->staticSoundIndexStack); @@ -458,7 +430,7 @@ void FAudioGMS_Init(double spatialDistanceScale, double timestep) device->timestep = timestep; Log("FAudio initialized successfully!"); - printf("Device: %ls", device->deviceDetails.DisplayName); + printf("Device: %ls\n", device->deviceDetails.DisplayName); fflush(stdout); } @@ -716,12 +688,14 @@ static void FAudioGMS_INTERNAL_Apply3D(FAudioGMS_SoundInstance* instance) static FAudioGMS_SoundInstance* FAudioGMS_INTERNAL_SoundInstance_Init( uint32_t channelCount, - uint32_t samplesPerSecond + uint32_t samplesPerSecond, + uint8_t isStatic ) { FAudioGMS_SoundInstance* instance = SDL_malloc(sizeof(FAudioGMS_SoundInstance)); instance->handle = NULL; + instance->isStatic = isStatic; instance->loop = 0; instance->destroyOnFinish = 0; @@ -738,7 +712,7 @@ static FAudioGMS_SoundInstance* FAudioGMS_INTERNAL_SoundInstance_Init( &instance->format, FAUDIO_VOICE_USEFILTER, FAUDIO_DEFAULT_FREQ_RATIO, - NULL, + isStatic ? NULL : &device->voiceCallbacks, NULL, NULL); @@ -802,7 +776,8 @@ static FAudioGMS_SoundInstance* FAudioGMS_INTERNAL_SoundInstance_CreateFromStati ) { FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_SoundInstance_Init( staticSound->channels, - staticSound->samplesPerSecond + staticSound->samplesPerSecond, + 1 ); instance->isStatic = 1; @@ -827,8 +802,6 @@ static void FAudioGMS_INTERNAL_SoundInstance_AddBuffer(FAudioGMS_SoundInstance* uint8_t* nextBuffer = SDL_malloc(bufferLength); SDL_memcpy(nextBuffer, device->streamStagingBuffer, bufferLength); - BufferQueue_Enqueue(&instance->soundData.streamingSound.bufferQueue, nextBuffer); - FAudioBuffer buffer; buffer.AudioBytes = bufferLength; buffer.pAudioData = nextBuffer; @@ -842,7 +815,7 @@ static void FAudioGMS_INTERNAL_SoundInstance_AddBuffer(FAudioGMS_SoundInstance* buffer.LoopBegin = 0; buffer.LoopCount = 0; buffer.LoopLength = 0; - buffer.pContext = NULL; + buffer.pContext = instance; /* context for OnBufferEnd callback */ FAudioSourceVoice_SubmitSourceBuffer(instance->handle, &buffer, NULL); @@ -860,31 +833,6 @@ static void FAudioGMS_INTERNAL_SoundInstance_AddBuffer(FAudioGMS_SoundInstance* } } -static void FAudioGMS_INTERNAL_SoundInstance_StreamingUpdate(FAudioGMS_SoundInstance* instance) -{ - uint32_t i; - FAudioVoiceState voiceState; - - if (instance->isStatic) { return; } - - FAudioSourceVoice_GetState( - instance->handle, - &voiceState, - FAUDIO_VOICE_NOSAMPLESPLAYED - ); - - while (instance->soundData.streamingSound.bufferQueue.count > voiceState.BuffersQueued) - { - uint8_t* buffer = BufferQueue_Dequeue(&instance->soundData.streamingSound.bufferQueue); - SDL_free(buffer); - } - - for (i = MINIMUM_BUFFER_CHECK - instance->soundData.streamingSound.bufferQueue.count; i > 0; i -= 1) - { - FAudioGMS_INTERNAL_SoundInstance_AddBuffer(instance); - } -} - double FAudioGMS_StreamingSound_LoadOGG(char* filePath) { RETURN_ON_NULL_DEVICE(-1.0) @@ -902,15 +850,14 @@ double FAudioGMS_StreamingSound_LoadOGG(char* filePath) FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_SoundInstance_Init( info.channels, - info.sample_rate + info.sample_rate, + 0 ); - instance->isStatic = 0; instance->soundData.streamingSound.fileHandle = fileHandle; instance->soundData.streamingSound.info = info; - BufferQueue_Init(&instance->soundData.streamingSound.bufferQueue, MAX_BUFFER_QUEUE_COUNT); - FAudioGMS_INTERNAL_SoundInstance_StreamingUpdate(instance); + FAudioGMS_INTERNAL_SoundInstance_AddBuffer(instance); return instance->id; } @@ -956,18 +903,6 @@ static void FAudioGMS_INTERNAL_StaticSound_AddEmitter(FAudioGMS_SoundInstance* i FAudioGMS_INTERNAL_Apply3D(instance); } -static void FAudioGMS_INTERNAL_SoundInstance_ClearBuffers(FAudioGMS_SoundInstance* instance) -{ - uint32_t i; - uint32_t bufferCount = instance->soundData.streamingSound.bufferQueue.count; - - for (i = 0; i < bufferCount; i += 1) - { - uint8_t* buffer = BufferQueue_Dequeue(&instance->soundData.streamingSound.bufferQueue); - SDL_free(buffer); - } -} - static void FAudioGMS_INTERNAL_SoundInstance_Play(FAudioGMS_SoundInstance* instance) { if (instance->soundState == SoundState_Playing) @@ -992,10 +927,6 @@ static void FAudioGMS_INTERNAL_SoundInstance_Play(FAudioGMS_SoundInstance* insta FAudioSourceVoice_SubmitSourceBuffer(instance->handle, &instance->soundData.staticSound->buffer, NULL); } - else - { - FAudioGMS_INTERNAL_SoundInstance_StreamingUpdate(instance); - } FAudioSourceVoice_Start(instance->handle, 0, 0); instance->soundState = SoundState_Playing; @@ -1114,17 +1045,16 @@ static void FAudioGMS_INTERNAL_SoundInstance_Stop(FAudioGMS_SoundInstance* insta { if (instance != NULL) { + instance->soundState = SoundState_Stopped; /* set this before so flush buffers doesn't trigger buffer add callback */ + FAudioSourceVoice_Stop(instance->handle, 0, 0); FAudioSourceVoice_FlushSourceBuffers(instance->handle); if (!instance->isStatic) { - FAudioGMS_INTERNAL_SoundInstance_ClearBuffers(instance); stb_vorbis_seek_start(instance->soundData.streamingSound.fileHandle); /* back to the start */ - FAudioGMS_INTERNAL_SoundInstance_StreamingUpdate(instance); /* preload so we dont stutter on play */ + FAudioGMS_INTERNAL_SoundInstance_AddBuffer(instance); /* preload so we dont stutter on play */ } - - instance->soundState = SoundState_Stopped; } else { @@ -1317,7 +1247,6 @@ static void FAudioGMS_INTERNAL_SoundInstance_Destroy(FAudioGMS_SoundInstance* in FAudioVoice_DestroyVoice(instance->handle); if (!instance->isStatic) { - SDL_free(instance->soundData.streamingSound.bufferQueue.buffers); stb_vorbis_close(instance->soundData.streamingSound.fileHandle); } if (instance->is3D) @@ -1667,12 +1596,6 @@ void FAudioGMS_Update() FAudioGMS_INTERNAL_SoundInstance_SetVolume(instance, volume); } - /* Update streaming instance */ - if (!instance->isStatic && instance->soundState == SoundState_Playing) - { - FAudioGMS_INTERNAL_SoundInstance_StreamingUpdate(instance); - } - if (instance->destroyOnFinish) { FAudioVoiceState state;