change streaming to use OnBufferEnded callback
							parent
							
								
									d1a7ddcb9f
								
							
						
					
					
						commit
						9069f34b7f
					
				
							
								
								
									
										149
									
								
								src/FAudioGMS.c
								
								
								
								
							
							
						
						
									
										149
									
								
								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; | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue