fix audio buffer stutter + add pass filter API
							parent
							
								
									e5b743d06b
								
							
						
					
					
						commit
						2ee6e8b5b5
					
				
							
								
								
									
										186
									
								
								src/FAudioGMS.c
								
								
								
								
							
							
						
						
									
										186
									
								
								src/FAudioGMS.c
								
								
								
								
							|  | @ -257,7 +257,7 @@ 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 * 128 * 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 | ||||
| { | ||||
|  | @ -645,6 +645,16 @@ static void FAudioGMS_INTERNAL_SoundInstance_SetLowPassFilter(FAudioGMS_SoundIns | |||
|     instance->lowPassFilter = lowPassFilter; | ||||
| } | ||||
| 
 | ||||
| void FAudioGMS_SoundInstance_SetLowPassFilter(double soundInstanceID, float lowPassFilter) | ||||
| { | ||||
|     FAudioGMS_SoundInstance *instance = FAudioGMS_INTERNAL_LookupSoundInstance((uint32_t)soundInstanceID); | ||||
| 
 | ||||
|     if (instance != NULL) | ||||
|     { | ||||
|         FAudioGMS_INTERNAL_SoundInstance_SetLowPassFilter(instance, lowPassFilter); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void FAudioGMS_INTERNAL_SoundInstance_SetHighPassFilter(FAudioGMS_SoundInstance* instance, float highPassFilter) | ||||
| { | ||||
|     FAudioFilterParameters p; | ||||
|  | @ -657,6 +667,16 @@ static void FAudioGMS_INTERNAL_SoundInstance_SetHighPassFilter(FAudioGMS_SoundIn | |||
|     instance->highPassFilter = highPassFilter; | ||||
| } | ||||
| 
 | ||||
| void FAudioGMS_SoundInstance_SetHighPassFilter(double soundInstanceID, float highPassFilter) | ||||
| { | ||||
|     FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_LookupSoundInstance((uint32_t)soundInstanceID); | ||||
| 
 | ||||
|     if (instance != NULL) | ||||
|     { | ||||
|         FAudioGMS_INTERNAL_SoundInstance_SetHighPassFilter(instance, highPassFilter); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void FAudioGMS_INTERNAL_SoundInstance_SetBandPassFilter(FAudioGMS_SoundInstance* instance, float bandPassFilter) | ||||
| { | ||||
|     FAudioFilterParameters p; | ||||
|  | @ -669,6 +689,16 @@ static void FAudioGMS_INTERNAL_SoundInstance_SetBandPassFilter(FAudioGMS_SoundIn | |||
|     instance->bandPassFilter = bandPassFilter; | ||||
| } | ||||
| 
 | ||||
| void FAudioGMS_SoundInstance_SetBandPassFilter(double soundInstanceID, float bandPassFilter) | ||||
| { | ||||
|     FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_LookupSoundInstance((uint32_t)soundInstanceID); | ||||
| 
 | ||||
|     if (instance != NULL) | ||||
|     { | ||||
|         FAudioGMS_INTERNAL_SoundInstance_SetBandPassFilter(instance, bandPassFilter); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void FAudioGMS_INTERNAL_SoundInstance_SetPan(FAudioGMS_SoundInstance* instance, float pan) | ||||
| { | ||||
|     instance->pan = pan; | ||||
|  | @ -713,6 +743,7 @@ static void FAudioGMS_INTERNAL_SoundInstance_SetPitch(FAudioGMS_SoundInstance* i | |||
| 
 | ||||
| static void FAudioGMS_INTERNAL_SoundInstance_SetVolume(FAudioGMS_SoundInstance* instance, float volume) | ||||
| { | ||||
|     instance->volume = volume; | ||||
|     FAudioVoice_SetVolume(instance->handle, volume, 0); | ||||
| } | ||||
| 
 | ||||
|  | @ -852,6 +883,80 @@ static FAudioGMS_SoundInstance* FAudioGMS_INTERNAL_SoundInstance_CreateFromStati | |||
|     return instance; | ||||
| } | ||||
| 
 | ||||
| static void FAudioGMS_INTERNAL_SoundInstance_AddBuffer(FAudioGMS_SoundInstance* instance) | ||||
| { | ||||
|     /* NOTE: this function returns samples per channel, not total samples */ | ||||
|     uint32_t samples = stb_vorbis_get_samples_float_interleaved( | ||||
|         instance->soundData.streamingSound.fileHandle, | ||||
|         instance->format.nChannels, | ||||
|         device->streamStagingBuffer, | ||||
|         STREAMING_BUFFER_SIZE | ||||
|     ); | ||||
| 
 | ||||
|     uint32_t sampleCount = samples * instance->format.nChannels; | ||||
|     uint32_t bufferLength = sampleCount * sizeof(float); | ||||
| 
 | ||||
|     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; | ||||
|     buffer.PlayLength = | ||||
|         bufferLength / | ||||
|         instance->format.nChannels / | ||||
|         (instance->format.wBitsPerSample / 8); | ||||
|     buffer.PlayBegin = 0; | ||||
| 
 | ||||
|     buffer.Flags = 0; | ||||
|     buffer.LoopBegin = 0; | ||||
|     buffer.LoopCount = 0; | ||||
|     buffer.LoopLength = 0; | ||||
|     buffer.pContext = NULL; | ||||
| 
 | ||||
|     FAudioSourceVoice_SubmitSourceBuffer(instance->handle, &buffer, NULL); | ||||
|      | ||||
|     /* We have reached the end of the file! */ | ||||
|     if (sampleCount < STREAMING_BUFFER_SIZE) | ||||
|     { | ||||
|         if (instance->loop) | ||||
|         { | ||||
|             stb_vorbis_seek_start(instance->soundData.streamingSound.fileHandle); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             instance->soundState = SoundState_Stopped; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 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) | ||||
| { | ||||
|     int error = 0; | ||||
|  | @ -876,6 +981,8 @@ double FAudioGMS_StreamingSound_LoadOGG(char* filePath) | |||
|     instance->soundData.streamingSound.info = info; | ||||
|     BufferQueue_Init(&instance->soundData.streamingSound.bufferQueue, MAX_BUFFER_QUEUE_COUNT); | ||||
| 
 | ||||
|     FAudioGMS_INTERNAL_SoundInstance_StreamingUpdate(instance); | ||||
| 
 | ||||
|     return instance->id; | ||||
| } | ||||
| 
 | ||||
|  | @ -920,83 +1027,6 @@ static void FAudioGMS_INTERNAL_StaticSound_AddEmitter(FAudioGMS_SoundInstance* i | |||
|     FAudioGMS_INTERNAL_Apply3D(instance); | ||||
| } | ||||
| 
 | ||||
| static void FAudioGMS_INTERNAL_SoundInstance_AddBuffer(FAudioGMS_SoundInstance* instance) | ||||
| { | ||||
|     /* NOTE: this function returns samples per channel, not total samples */ | ||||
|     uint32_t samples = stb_vorbis_get_samples_float_interleaved( | ||||
|         instance->soundData.streamingSound.fileHandle, | ||||
|         instance->format.nChannels, | ||||
|         device->streamStagingBuffer, | ||||
|         STREAMING_BUFFER_SIZE | ||||
|     ); | ||||
| 
 | ||||
|     uint32_t sampleCount = samples * instance->format.nChannels; | ||||
|     uint32_t bufferLength = sampleCount * sizeof(float); | ||||
| 
 | ||||
|     uint8_t* nextBuffer = SDL_malloc(bufferLength); | ||||
|     SDL_memcpy(nextBuffer, device->streamStagingBuffer, bufferLength); | ||||
| 
 | ||||
|     BufferQueue_Enqueue(&instance->soundData.streamingSound.bufferQueue, nextBuffer); | ||||
| 
 | ||||
|     if (instance->soundState != SoundState_Stopped) | ||||
|     { | ||||
|         FAudioBuffer buffer; | ||||
|         buffer.AudioBytes = bufferLength; | ||||
|         buffer.pAudioData = nextBuffer; | ||||
|         buffer.PlayLength = | ||||
|             bufferLength / | ||||
|             instance->format.nChannels / | ||||
|             (instance->format.wBitsPerSample / 8); | ||||
|         buffer.PlayBegin = 0; | ||||
| 
 | ||||
|         buffer.Flags = 0; | ||||
|         buffer.LoopBegin = 0; | ||||
|         buffer.LoopCount = 0; | ||||
|         buffer.LoopLength = 0; | ||||
|         buffer.pContext = NULL; | ||||
| 
 | ||||
|         FAudioSourceVoice_SubmitSourceBuffer(instance->handle, &buffer, NULL); | ||||
|     } | ||||
| 
 | ||||
|     /* We have reached the end of the file! */ | ||||
|     if (sampleCount < STREAMING_BUFFER_SIZE) | ||||
|     { | ||||
|         if (instance->loop) | ||||
|         { | ||||
|             stb_vorbis_seek_start(instance->soundData.streamingSound.fileHandle); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             instance->soundState = SoundState_Stopped; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 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); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void FAudioGMS_INTERNAL_SoundInstance_ClearBuffers(FAudioGMS_SoundInstance* instance) | ||||
| { | ||||
|     uint32_t i; | ||||
|  |  | |||
|  | @ -62,6 +62,9 @@ FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetReverb(double soundInstanceID, doub | |||
| FAUDIOGMSAPI void FAudioGMS_SoundInstance_Set3DPosition(double soundInstanceID, double x, double y, double z); | ||||
| FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetTrackPosition(double soundInstanceID, double trackPositionInSeconds); | ||||
| FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetVolumeOverTime(double soundInstanceID, double volume, double milliseconds); | ||||
| FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetLowPassFilter(double soundInstanceID, float lowPassFilter); | ||||
| FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetHighPassFilter(double soundInstanceID, float highPassFilter); | ||||
| FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetBandPassFilter(double soundInstanceID, float bandPassFilter); | ||||
| 
 | ||||
| FAUDIOGMSAPI double FAudioGMS_SoundInstance_GetPitch(double soundInstanceID); | ||||
| FAUDIOGMSAPI double FAudioGMS_SoundInstance_GetVolume(double soundInstanceID); | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue