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]; |     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 | typedef enum FAudioGMS_SoundState | ||||||
| { | { | ||||||
|     SoundState_Playing, |     SoundState_Playing, | ||||||
|  | @ -210,7 +164,6 @@ typedef struct FAudioGMS_StreamingSound | ||||||
| { | { | ||||||
|     stb_vorbis* fileHandle; |     stb_vorbis* fileHandle; | ||||||
|     stb_vorbis_info info; |     stb_vorbis_info info; | ||||||
|     BufferQueue bufferQueue; |  | ||||||
| } FAudioGMS_StreamingSound; | } FAudioGMS_StreamingSound; | ||||||
| 
 | 
 | ||||||
| typedef struct FAudioGMS_SoundInstance | typedef struct FAudioGMS_SoundInstance | ||||||
|  | @ -272,10 +225,8 @@ typedef struct FAudioGMS_EffectChain | ||||||
| 
 | 
 | ||||||
| static const float SPEED_OF_SOUND = 343.5f; | static const float SPEED_OF_SOUND = 343.5f; | ||||||
| static const float DOPPLER_SCALE = 1.0f; | 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 * 16 * sizeof(float) /* FIXME: what should this value be? */ | ||||||
| #define STREAMING_BUFFER_SIZE 1024 * 8 * sizeof(float) /* FIXME: what should this value be? */ |  | ||||||
| 
 | 
 | ||||||
| typedef struct FAudioGMS_Device | typedef struct FAudioGMS_Device | ||||||
| { | { | ||||||
|  | @ -288,6 +239,8 @@ typedef struct FAudioGMS_Device | ||||||
|     F3DAUDIO_LISTENER listener; |     F3DAUDIO_LISTENER listener; | ||||||
|     float spatialDistanceScale; |     float spatialDistanceScale; | ||||||
| 
 | 
 | ||||||
|  |     FAudioVoiceCallback voiceCallbacks; | ||||||
|  | 
 | ||||||
|     FAudioGMS_StaticSound **staticSounds; |     FAudioGMS_StaticSound **staticSounds; | ||||||
|     uint32_t staticSoundCount; |     uint32_t staticSoundCount; | ||||||
|     IdStack staticSoundIndexStack; |     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) | void FAudioGMS_Init(double spatialDistanceScale, double timestep) | ||||||
| { | { | ||||||
|     device = SDL_malloc(sizeof(FAudioGMS_Device)); |     device = SDL_malloc(sizeof(FAudioGMS_Device)); | ||||||
|  | @ -443,6 +407,14 @@ void FAudioGMS_Init(double spatialDistanceScale, double timestep) | ||||||
|     device->listener.Velocity.z = 0; |     device->listener.Velocity.z = 0; | ||||||
|     device->listener.pCone = NULL; |     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->staticSounds = NULL; | ||||||
|     device->staticSoundCount = 0; |     device->staticSoundCount = 0; | ||||||
|     IdStack_Init(&device->staticSoundIndexStack); |     IdStack_Init(&device->staticSoundIndexStack); | ||||||
|  | @ -458,7 +430,7 @@ void FAudioGMS_Init(double spatialDistanceScale, double timestep) | ||||||
|     device->timestep = timestep; |     device->timestep = timestep; | ||||||
| 
 | 
 | ||||||
|     Log("FAudio initialized successfully!"); |     Log("FAudio initialized successfully!"); | ||||||
|     printf("Device: %ls", device->deviceDetails.DisplayName); |     printf("Device: %ls\n", device->deviceDetails.DisplayName); | ||||||
|     fflush(stdout); |     fflush(stdout); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -716,12 +688,14 @@ static void FAudioGMS_INTERNAL_Apply3D(FAudioGMS_SoundInstance* instance) | ||||||
| 
 | 
 | ||||||
| static FAudioGMS_SoundInstance* FAudioGMS_INTERNAL_SoundInstance_Init( | static FAudioGMS_SoundInstance* FAudioGMS_INTERNAL_SoundInstance_Init( | ||||||
|     uint32_t channelCount, |     uint32_t channelCount, | ||||||
|     uint32_t samplesPerSecond |     uint32_t samplesPerSecond, | ||||||
|  |     uint8_t isStatic | ||||||
| ) { | ) { | ||||||
|     FAudioGMS_SoundInstance* instance = SDL_malloc(sizeof(FAudioGMS_SoundInstance)); |     FAudioGMS_SoundInstance* instance = SDL_malloc(sizeof(FAudioGMS_SoundInstance)); | ||||||
| 
 | 
 | ||||||
|     instance->handle = NULL; |     instance->handle = NULL; | ||||||
| 
 | 
 | ||||||
|  |     instance->isStatic = isStatic; | ||||||
|     instance->loop = 0; |     instance->loop = 0; | ||||||
|     instance->destroyOnFinish = 0; |     instance->destroyOnFinish = 0; | ||||||
| 
 | 
 | ||||||
|  | @ -738,7 +712,7 @@ static FAudioGMS_SoundInstance* FAudioGMS_INTERNAL_SoundInstance_Init( | ||||||
|         &instance->format, |         &instance->format, | ||||||
|         FAUDIO_VOICE_USEFILTER, |         FAUDIO_VOICE_USEFILTER, | ||||||
|         FAUDIO_DEFAULT_FREQ_RATIO, |         FAUDIO_DEFAULT_FREQ_RATIO, | ||||||
|         NULL, |         isStatic ? NULL : &device->voiceCallbacks, | ||||||
|         NULL, |         NULL, | ||||||
|         NULL); |         NULL); | ||||||
| 
 | 
 | ||||||
|  | @ -802,7 +776,8 @@ static FAudioGMS_SoundInstance* FAudioGMS_INTERNAL_SoundInstance_CreateFromStati | ||||||
| ) { | ) { | ||||||
|     FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_SoundInstance_Init( |     FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_SoundInstance_Init( | ||||||
|         staticSound->channels, |         staticSound->channels, | ||||||
|         staticSound->samplesPerSecond |         staticSound->samplesPerSecond, | ||||||
|  |         1 | ||||||
|     ); |     ); | ||||||
| 
 | 
 | ||||||
|     instance->isStatic = 1; |     instance->isStatic = 1; | ||||||
|  | @ -827,8 +802,6 @@ static void FAudioGMS_INTERNAL_SoundInstance_AddBuffer(FAudioGMS_SoundInstance* | ||||||
|     uint8_t* nextBuffer = SDL_malloc(bufferLength); |     uint8_t* nextBuffer = SDL_malloc(bufferLength); | ||||||
|     SDL_memcpy(nextBuffer, device->streamStagingBuffer, bufferLength); |     SDL_memcpy(nextBuffer, device->streamStagingBuffer, bufferLength); | ||||||
| 
 | 
 | ||||||
|     BufferQueue_Enqueue(&instance->soundData.streamingSound.bufferQueue, nextBuffer); |  | ||||||
| 
 |  | ||||||
|     FAudioBuffer buffer; |     FAudioBuffer buffer; | ||||||
|     buffer.AudioBytes = bufferLength; |     buffer.AudioBytes = bufferLength; | ||||||
|     buffer.pAudioData = nextBuffer; |     buffer.pAudioData = nextBuffer; | ||||||
|  | @ -842,7 +815,7 @@ static void FAudioGMS_INTERNAL_SoundInstance_AddBuffer(FAudioGMS_SoundInstance* | ||||||
|     buffer.LoopBegin = 0; |     buffer.LoopBegin = 0; | ||||||
|     buffer.LoopCount = 0; |     buffer.LoopCount = 0; | ||||||
|     buffer.LoopLength = 0; |     buffer.LoopLength = 0; | ||||||
|     buffer.pContext = NULL; |     buffer.pContext = instance; /* context for OnBufferEnd callback */ | ||||||
| 
 | 
 | ||||||
|     FAudioSourceVoice_SubmitSourceBuffer(instance->handle, &buffer, NULL); |     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) | double FAudioGMS_StreamingSound_LoadOGG(char* filePath) | ||||||
| { | { | ||||||
|     RETURN_ON_NULL_DEVICE(-1.0) |     RETURN_ON_NULL_DEVICE(-1.0) | ||||||
|  | @ -902,15 +850,14 @@ double FAudioGMS_StreamingSound_LoadOGG(char* filePath) | ||||||
| 
 | 
 | ||||||
|     FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_SoundInstance_Init( |     FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_SoundInstance_Init( | ||||||
|         info.channels, |         info.channels, | ||||||
|         info.sample_rate |         info.sample_rate, | ||||||
|  |         0 | ||||||
|     ); |     ); | ||||||
| 
 | 
 | ||||||
|     instance->isStatic = 0; |  | ||||||
|     instance->soundData.streamingSound.fileHandle = fileHandle; |     instance->soundData.streamingSound.fileHandle = fileHandle; | ||||||
|     instance->soundData.streamingSound.info = info; |     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; |     return instance->id; | ||||||
| } | } | ||||||
|  | @ -956,18 +903,6 @@ static void FAudioGMS_INTERNAL_StaticSound_AddEmitter(FAudioGMS_SoundInstance* i | ||||||
|     FAudioGMS_INTERNAL_Apply3D(instance); |     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) | static void FAudioGMS_INTERNAL_SoundInstance_Play(FAudioGMS_SoundInstance* instance) | ||||||
| { | { | ||||||
|     if (instance->soundState == SoundState_Playing) |     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); |         FAudioSourceVoice_SubmitSourceBuffer(instance->handle, &instance->soundData.staticSound->buffer, NULL); | ||||||
|     } |     } | ||||||
|     else |  | ||||||
|     { |  | ||||||
|         FAudioGMS_INTERNAL_SoundInstance_StreamingUpdate(instance); |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     FAudioSourceVoice_Start(instance->handle, 0, 0); |     FAudioSourceVoice_Start(instance->handle, 0, 0); | ||||||
|     instance->soundState = SoundState_Playing; |     instance->soundState = SoundState_Playing; | ||||||
|  | @ -1114,17 +1045,16 @@ static void FAudioGMS_INTERNAL_SoundInstance_Stop(FAudioGMS_SoundInstance* insta | ||||||
| { | { | ||||||
|     if (instance != NULL) |     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_Stop(instance->handle, 0, 0); | ||||||
|         FAudioSourceVoice_FlushSourceBuffers(instance->handle); |         FAudioSourceVoice_FlushSourceBuffers(instance->handle); | ||||||
| 
 | 
 | ||||||
|         if (!instance->isStatic) |         if (!instance->isStatic) | ||||||
|         { |         { | ||||||
|             FAudioGMS_INTERNAL_SoundInstance_ClearBuffers(instance); |  | ||||||
|             stb_vorbis_seek_start(instance->soundData.streamingSound.fileHandle); /* back to the start */ |             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 |     else | ||||||
|     { |     { | ||||||
|  | @ -1317,7 +1247,6 @@ static void FAudioGMS_INTERNAL_SoundInstance_Destroy(FAudioGMS_SoundInstance* in | ||||||
|         FAudioVoice_DestroyVoice(instance->handle); |         FAudioVoice_DestroyVoice(instance->handle); | ||||||
|         if (!instance->isStatic) |         if (!instance->isStatic) | ||||||
|         { |         { | ||||||
|             SDL_free(instance->soundData.streamingSound.bufferQueue.buffers); |  | ||||||
|             stb_vorbis_close(instance->soundData.streamingSound.fileHandle); |             stb_vorbis_close(instance->soundData.streamingSound.fileHandle); | ||||||
|         } |         } | ||||||
|         if (instance->is3D) |         if (instance->is3D) | ||||||
|  | @ -1667,12 +1596,6 @@ void FAudioGMS_Update() | ||||||
|                 FAudioGMS_INTERNAL_SoundInstance_SetVolume(instance, volume); |                 FAudioGMS_INTERNAL_SoundInstance_SetVolume(instance, volume); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             /* Update streaming instance */ |  | ||||||
|             if (!instance->isStatic && instance->soundState == SoundState_Playing) |  | ||||||
|             { |  | ||||||
|                 FAudioGMS_INTERNAL_SoundInstance_StreamingUpdate(instance); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             if (instance->destroyOnFinish) |             if (instance->destroyOnFinish) | ||||||
|             { |             { | ||||||
|                 FAudioVoiceState state; |                 FAudioVoiceState state; | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue