fix audio buffer stutter + add pass filter API
							parent
							
								
									cd30405820
								
							
						
					
					
						commit
						92fdc4753b
					
				
							
								
								
									
										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; | static const uint32_t MINIMUM_BUFFER_CHECK = 3; | ||||||
| 
 | 
 | ||||||
| #define MAX_BUFFER_QUEUE_COUNT 16 | #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 | typedef struct FAudioGMS_Device | ||||||
| { | { | ||||||
|  | @ -645,6 +645,16 @@ static void FAudioGMS_INTERNAL_SoundInstance_SetLowPassFilter(FAudioGMS_SoundIns | ||||||
|     instance->lowPassFilter = lowPassFilter; |     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) | static void FAudioGMS_INTERNAL_SoundInstance_SetHighPassFilter(FAudioGMS_SoundInstance* instance, float highPassFilter) | ||||||
| { | { | ||||||
|     FAudioFilterParameters p; |     FAudioFilterParameters p; | ||||||
|  | @ -657,6 +667,16 @@ static void FAudioGMS_INTERNAL_SoundInstance_SetHighPassFilter(FAudioGMS_SoundIn | ||||||
|     instance->highPassFilter = highPassFilter; |     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) | static void FAudioGMS_INTERNAL_SoundInstance_SetBandPassFilter(FAudioGMS_SoundInstance* instance, float bandPassFilter) | ||||||
| { | { | ||||||
|     FAudioFilterParameters p; |     FAudioFilterParameters p; | ||||||
|  | @ -669,6 +689,16 @@ static void FAudioGMS_INTERNAL_SoundInstance_SetBandPassFilter(FAudioGMS_SoundIn | ||||||
|     instance->bandPassFilter = bandPassFilter; |     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) | static void FAudioGMS_INTERNAL_SoundInstance_SetPan(FAudioGMS_SoundInstance* instance, float pan) | ||||||
| { | { | ||||||
|     instance->pan = 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) | static void FAudioGMS_INTERNAL_SoundInstance_SetVolume(FAudioGMS_SoundInstance* instance, float volume) | ||||||
| { | { | ||||||
|  |     instance->volume = volume; | ||||||
|     FAudioVoice_SetVolume(instance->handle, volume, 0); |     FAudioVoice_SetVolume(instance->handle, volume, 0); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -852,6 +883,80 @@ static FAudioGMS_SoundInstance* FAudioGMS_INTERNAL_SoundInstance_CreateFromStati | ||||||
|     return instance; |     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) | double FAudioGMS_StreamingSound_LoadOGG(char* filePath) | ||||||
| { | { | ||||||
|     int error = 0; |     int error = 0; | ||||||
|  | @ -876,6 +981,8 @@ double FAudioGMS_StreamingSound_LoadOGG(char* filePath) | ||||||
|     instance->soundData.streamingSound.info = info; |     instance->soundData.streamingSound.info = info; | ||||||
|     BufferQueue_Init(&instance->soundData.streamingSound.bufferQueue, MAX_BUFFER_QUEUE_COUNT); |     BufferQueue_Init(&instance->soundData.streamingSound.bufferQueue, MAX_BUFFER_QUEUE_COUNT); | ||||||
| 
 | 
 | ||||||
|  |     FAudioGMS_INTERNAL_SoundInstance_StreamingUpdate(instance); | ||||||
|  | 
 | ||||||
|     return instance->id; |     return instance->id; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -920,83 +1027,6 @@ static void FAudioGMS_INTERNAL_StaticSound_AddEmitter(FAudioGMS_SoundInstance* i | ||||||
|     FAudioGMS_INTERNAL_Apply3D(instance); |     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) | static void FAudioGMS_INTERNAL_SoundInstance_ClearBuffers(FAudioGMS_SoundInstance* instance) | ||||||
| { | { | ||||||
|     uint32_t i; |     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_Set3DPosition(double soundInstanceID, double x, double y, double z); | ||||||
| FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetTrackPosition(double soundInstanceID, double trackPositionInSeconds); | FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetTrackPosition(double soundInstanceID, double trackPositionInSeconds); | ||||||
| FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetVolumeOverTime(double soundInstanceID, double volume, double milliseconds); | 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_GetPitch(double soundInstanceID); | ||||||
| FAUDIOGMSAPI double FAudioGMS_SoundInstance_GetVolume(double soundInstanceID); | FAUDIOGMSAPI double FAudioGMS_SoundInstance_GetVolume(double soundInstanceID); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue