forked from MoonsideGames/FAudioGMS
				
			playing sound effects
							parent
							
								
									15edf9bf8a
								
							
						
					
					
						commit
						761457831c
					
				|  | @ -1,3 +1,6 @@ | |||
| [submodule "FAudio"] | ||||
| 	path = lib/FAudio | ||||
| 	url = https://github.com/FNA-XNA/FAudio | ||||
| [submodule "lib/SDL"] | ||||
| 	path = lib/SDL | ||||
| 	url = https://github.com/libsdl-org/SDL.git | ||||
|  |  | |||
|  | @ -0,0 +1 @@ | |||
| Subproject commit 25f9ed87ff6947d9576fc9d79dee0784e638ac58 | ||||
							
								
								
									
										540
									
								
								src/FAudioGMS.c
								
								
								
								
							
							
						
						
									
										540
									
								
								src/FAudioGMS.c
								
								
								
								
							|  | @ -24,6 +24,8 @@ | |||
|  * | ||||
|  */ | ||||
| 
 | ||||
| #include "../lib/SDL/include/SDL.h" | ||||
| 
 | ||||
| #include "FAudioGMS.h" | ||||
| #include "../lib/FAudio/include/FAPOBase.h" | ||||
| #include "../lib/FAudio/include/FAudioFX.h" | ||||
|  | @ -33,12 +35,11 @@ | |||
| #define DR_WAV_IMPLEMENTATION | ||||
| #include "../lib/dr_wav.h" | ||||
| 
 | ||||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| 
 | ||||
| static inline void Log(char *string) | ||||
| { | ||||
|     printf("%s", string); | ||||
|     printf("%s\n", string); | ||||
|     fflush(stdout); | ||||
| } | ||||
| 
 | ||||
|  | @ -75,6 +76,19 @@ typedef struct FAudioGMS_SoundInstance | |||
|     float lowPassFilter; | ||||
|     float highPassFilter; | ||||
|     float bandPassFilter; | ||||
| 
 | ||||
|     uint8_t reverbAttached; | ||||
|     FAudioSubmixVoice* reverbVoice; | ||||
|     FAudioVoiceSends reverbSends; | ||||
| 
 | ||||
|     uint8_t isStatic; | ||||
|     uint8_t destroyOnFinish; | ||||
| 
 | ||||
|     union | ||||
|     { | ||||
|         FAudioGMS_StaticSound *staticSound; | ||||
|         /* TODO: streaming */ | ||||
|     } parent; | ||||
| } FAudioGMS_SoundInstance; | ||||
| 
 | ||||
| typedef struct FAudioGMS_Device | ||||
|  | @ -82,28 +96,26 @@ typedef struct FAudioGMS_Device | |||
|     FAudio* handle; | ||||
|     FAudioDeviceDetails deviceDetails; | ||||
|     FAudioMasteringVoice *masteringVoice; | ||||
|     FAudioSubmixVoice *reverbVoice; | ||||
|     FAudioVoiceSends reverbSends; | ||||
| 
 | ||||
|     FAudioGMS_StaticSound **staticSounds; | ||||
|     uint32_t staticSoundCount; | ||||
| 
 | ||||
|     FAudioGMS_SoundInstance **staticSoundInstances; | ||||
|     uint32_t staticSoundInstanceCount; | ||||
|     FAudioGMS_SoundInstance **soundInstances; | ||||
|     uint32_t soundInstanceCount; | ||||
| } FAudioGMS_Device; | ||||
| 
 | ||||
| static FAudioGMS_Device *device = NULL; | ||||
| 
 | ||||
| void FAudioGMS_Init() | ||||
| { | ||||
|     device = malloc(sizeof(FAudioGMS_Device)); | ||||
|     device = SDL_malloc(sizeof(FAudioGMS_Device)); | ||||
| 
 | ||||
|     uint32_t result = FAudioCreate(&device->handle, 0, FAUDIO_DEFAULT_PROCESSOR); | ||||
| 
 | ||||
|     if (result != 0) | ||||
|     { | ||||
|         Log("Failed to create device! Bailing!"); | ||||
|         free(device); | ||||
|         SDL_free(device); | ||||
|         device = NULL; | ||||
|         return; | ||||
|     } | ||||
|  | @ -117,7 +129,7 @@ void FAudioGMS_Init() | |||
|     { | ||||
|         Log("No audio devices found! Bailing!"); | ||||
|         FAudio_Release(device->handle); | ||||
|         free(device); | ||||
|         SDL_free(device); | ||||
|         device = NULL; | ||||
|         return; | ||||
|     } | ||||
|  | @ -162,96 +174,88 @@ void FAudioGMS_Init() | |||
|     { | ||||
|         Log("No mastering voice found! Bailing!"); | ||||
|         FAudio_Release(device->handle); | ||||
|         free(device); | ||||
|         SDL_free(device); | ||||
|         device = NULL; | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     /* Init reverb */ | ||||
| 
 | ||||
|     FAPO *reverb = malloc(sizeof(FAPO)); | ||||
| 
 | ||||
|     FAudioCreateReverb(&reverb, 0); | ||||
| 
 | ||||
|     FAudioEffectChain *reverbChain = malloc(sizeof(FAudioEffectChain)); | ||||
| 
 | ||||
|     reverbChain->EffectCount = 1; | ||||
|     reverbChain->pEffectDescriptors = malloc(sizeof(FAudioEffectDescriptor)); | ||||
| 
 | ||||
|     FAudioEffectDescriptor *reverbDescriptor = reverbChain->pEffectDescriptors; | ||||
| 
 | ||||
|     reverbDescriptor->InitialState = 1; | ||||
|     reverbDescriptor->OutputChannels = device->deviceDetails.OutputFormat.Format.nChannels == 6 ? 6 : 1; | ||||
|     reverbDescriptor->pEffect = reverb; | ||||
| 
 | ||||
|     FAudio_CreateSubmixVoice( | ||||
|         device->handle, | ||||
|         &device->reverbVoice, | ||||
|         1, /* omnidirectional reverb */ | ||||
|         device->deviceDetails.OutputFormat.Format.nSamplesPerSec, | ||||
|         0, | ||||
|         0, | ||||
|         NULL, | ||||
|         reverbChain); | ||||
| 
 | ||||
|     FAPOBase_Release((FAPOBase*)reverb); | ||||
|     free(reverb); | ||||
|     free(reverbChain->pEffectDescriptors); | ||||
|     free(reverbChain); | ||||
| 
 | ||||
|     FAudioFXReverbParameters *reverbParams = malloc(sizeof(FAudioFXReverbParameters)); | ||||
| 
 | ||||
|     reverbParams->WetDryMix = 100.0f; | ||||
|     reverbParams->ReflectionsDelay = 7; | ||||
|     reverbParams->ReverbDelay = 11; | ||||
|     reverbParams->RearDelay = FAUDIOFX_REVERB_DEFAULT_REAR_DELAY; | ||||
|     reverbParams->PositionLeft = FAUDIOFX_REVERB_DEFAULT_POSITION; | ||||
|     reverbParams->PositionRight = FAUDIOFX_REVERB_DEFAULT_POSITION; | ||||
|     reverbParams->PositionMatrixLeft = FAUDIOFX_REVERB_DEFAULT_POSITION_MATRIX; | ||||
|     reverbParams->PositionMatrixRight = FAUDIOFX_REVERB_DEFAULT_POSITION_MATRIX; | ||||
|     reverbParams->EarlyDiffusion = 15; | ||||
|     reverbParams->LateDiffusion = 15; | ||||
|     reverbParams->LowEQGain = 8; | ||||
|     reverbParams->LowEQCutoff = 4; | ||||
|     reverbParams->HighEQGain = 8; | ||||
|     reverbParams->HighEQCutoff = 6; | ||||
|     reverbParams->RoomFilterFreq = 5000.0f; | ||||
|     reverbParams->RoomFilterMain = -10.0f; | ||||
|     reverbParams->RoomFilterHF = -1.0f; | ||||
|     reverbParams->ReflectionsGain = -26.0200005f; | ||||
|     reverbParams->ReverbGain = 10.0f; | ||||
|     reverbParams->DecayTime = 1.49000001f; | ||||
|     reverbParams->Density = 100.0f; | ||||
|     reverbParams->RoomSize = FAUDIOFX_REVERB_DEFAULT_ROOM_SIZE; | ||||
| 
 | ||||
|     FAudioVoice_SetEffectParameters( | ||||
|         device->reverbVoice, | ||||
|         0, | ||||
|         reverbParams, | ||||
|         sizeof(FAudioFXReverbParameters), | ||||
|         0); | ||||
| 
 | ||||
|     free(reverbParams); | ||||
| 
 | ||||
|     /* Init reverb sends */ | ||||
| 
 | ||||
|     device->reverbSends.SendCount = 2; | ||||
|     device->reverbSends.pSends = malloc(2 * sizeof(FAudioSendDescriptor)); | ||||
| 
 | ||||
|     device->reverbSends.pSends[0].Flags = 0; | ||||
|     device->reverbSends.pSends[0].pOutputVoice = device->masteringVoice; | ||||
|     device->reverbSends.pSends[1].Flags = 0; | ||||
|     device->reverbSends.pSends[1].pOutputVoice = device->reverbVoice; | ||||
| 
 | ||||
|     device->staticSounds = NULL; | ||||
|     device->staticSoundCount = 0; | ||||
| 
 | ||||
|     device->soundInstances = NULL; | ||||
|     device->soundInstanceCount = 0; | ||||
| 
 | ||||
|     Log("FAudio initialized successfully!"); | ||||
|     printf("Device: %ls", device->deviceDetails.DisplayName); | ||||
|     fflush(stdout); | ||||
| } | ||||
| 
 | ||||
| static void FAudioGMS_INTERNAL_SoundInstance_Destroy(FAudioGMS_SoundInstance* instance) | ||||
| { | ||||
|     if (instance != NULL) | ||||
|     { | ||||
|         device->soundInstances[instance->id] = NULL; | ||||
|         FAudioSourceVoice_Stop(instance->handle, 0, 0); | ||||
|         FAudioSourceVoice_FlushSourceBuffers(instance->handle); | ||||
|         FAudioVoice_DestroyVoice(instance->handle); | ||||
|         SDL_free(instance->dspSettings.pMatrixCoefficients); | ||||
|         SDL_free(instance); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void FAudioGMS_SoundInstance_Destroy(double id) | ||||
| { | ||||
|     FAudioGMS_INTERNAL_SoundInstance_Destroy(device->soundInstances[(uint32_t)id]); | ||||
| } | ||||
| 
 | ||||
| void FAudioGMS_SoundInstance_DestroyWhenFinished(double id) | ||||
| { | ||||
|     FAudioGMS_SoundInstance *instance = device->soundInstances[(uint32_t)id]; | ||||
| 
 | ||||
|     if (instance != NULL) | ||||
|     { | ||||
|         instance->destroyOnFinish = 1; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /* FIXME: this will die horribly if a sound is playing */ | ||||
| static void FAudioGMS_INTERNAL_StaticSound_Destroy(FAudioGMS_StaticSound* sound) | ||||
| { | ||||
|     if (sound != NULL) | ||||
|     { | ||||
|         device->staticSounds[sound->id] = NULL; | ||||
|         SDL_free((void*)sound->buffer.pAudioData); | ||||
|         SDL_free(sound); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void FAudioGMS_StaticSound_Destroy(double id) | ||||
| { | ||||
|     FAudioGMS_INTERNAL_StaticSound_Destroy(device->staticSounds[(uint32_t)id]); | ||||
| } | ||||
| 
 | ||||
| void FAudioGMS_Update() | ||||
| { | ||||
|     uint32_t i; | ||||
| 
 | ||||
|     for (i = 0; i < device->soundInstanceCount; i += 1) | ||||
|     { | ||||
|         FAudioGMS_SoundInstance* instance = device->soundInstances[i]; | ||||
| 
 | ||||
|         if (instance != NULL) | ||||
|         { | ||||
|             if (instance->destroyOnFinish) | ||||
|             { | ||||
|                 FAudioVoiceState state; | ||||
|                 FAudioSourceVoice_GetState(instance->handle, &state, FAUDIO_VOICE_NOSAMPLESPLAYED); | ||||
| 
 | ||||
|                 if (state.BuffersQueued == 0) | ||||
|                 { | ||||
|                     FAudioGMS_INTERNAL_SoundInstance_Destroy(instance); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /* Taken from https://github.com/FNA-XNA/FNA/blob/master/src/Audio/SoundEffectInstance.cs */ | ||||
|  | @ -313,7 +317,7 @@ double FAudioGMS_StaticSound_LoadWAV(char *filePath) | |||
| { | ||||
|     drwav_uint64 frameCount; | ||||
| 
 | ||||
|     FAudioGMS_StaticSound *sound = malloc(sizeof(FAudioGMS_StaticSound)); | ||||
|     FAudioGMS_StaticSound *sound = SDL_malloc(sizeof(FAudioGMS_StaticSound)); | ||||
|     float *pSampleData = drwav_open_file_and_read_pcm_frames_f32(filePath, &sound->channels, &sound->samplesPerSecond, &frameCount, NULL); | ||||
|     if (pSampleData == NULL) | ||||
|     { | ||||
|  | @ -337,19 +341,210 @@ double FAudioGMS_StaticSound_LoadWAV(char *filePath) | |||
|     /* FIXME: id re-use system */ | ||||
|     sound->id = device->staticSoundCount; | ||||
| 
 | ||||
|     device->staticSounds = realloc(device->staticSounds, (device->staticSoundCount + 1) * sizeof(FAudioGMS_StaticSound*)); | ||||
|     device->staticSounds = SDL_realloc(device->staticSounds, (device->staticSoundCount + 1) * sizeof(FAudioGMS_StaticSound*)); | ||||
|     device->staticSounds[device->staticSoundCount] = sound; | ||||
|     device->staticSoundCount += 1; | ||||
| 
 | ||||
|     return (double)sound->id; | ||||
| } | ||||
| 
 | ||||
| double FAudioGMS_SoundInstance_CreateFromStaticSound(double id) | ||||
| static void FAudioGMS_INTERNAL_SoundInstance_AttachReverb(FAudioGMS_SoundInstance* instance) | ||||
| { | ||||
|     FAudioGMS_StaticSound *staticSound = device->staticSounds[(uint32_t)id]; | ||||
|     FAudioGMS_SoundInstance *instance = malloc(sizeof(FAudioGMS_SoundInstance)); | ||||
|     if (!instance->reverbAttached) | ||||
|     { | ||||
|         /* Init reverb */ | ||||
| 
 | ||||
|         FAPO* reverb; | ||||
|         FAudioCreateReverb(&reverb, 0); | ||||
| 
 | ||||
|         FAudioEffectChain* reverbChain = SDL_malloc(sizeof(FAudioEffectChain)); | ||||
| 
 | ||||
|         reverbChain->EffectCount = 1; | ||||
|         reverbChain->pEffectDescriptors = SDL_malloc(sizeof(FAudioEffectDescriptor)); | ||||
| 
 | ||||
|         FAudioEffectDescriptor* reverbDescriptor = reverbChain->pEffectDescriptors; | ||||
| 
 | ||||
|         reverbDescriptor->InitialState = 1; | ||||
|         reverbDescriptor->OutputChannels = device->deviceDetails.OutputFormat.Format.nChannels == 6 ? 6 : 1; | ||||
|         reverbDescriptor->pEffect = reverb; | ||||
| 
 | ||||
|         FAudio_CreateSubmixVoice( | ||||
|             device->handle, | ||||
|             &instance->reverbVoice, | ||||
|             1, /* omnidirectional reverb */ | ||||
|             device->deviceDetails.OutputFormat.Format.nSamplesPerSec, | ||||
|             0, | ||||
|             0, | ||||
|             NULL, | ||||
|             reverbChain); | ||||
| 
 | ||||
|         FAPOBase_Release((FAPOBase*)reverb); | ||||
|         SDL_free(reverbChain->pEffectDescriptors); | ||||
|         SDL_free(reverbChain); | ||||
| 
 | ||||
|         FAudioFXReverbParameters* reverbParams = SDL_malloc(sizeof(FAudioFXReverbParameters)); | ||||
| 
 | ||||
|         reverbParams->WetDryMix = 100.0f; | ||||
|         reverbParams->ReflectionsDelay = 7; | ||||
|         reverbParams->ReverbDelay = 11; | ||||
|         reverbParams->RearDelay = FAUDIOFX_REVERB_DEFAULT_REAR_DELAY; | ||||
|         reverbParams->PositionLeft = FAUDIOFX_REVERB_DEFAULT_POSITION; | ||||
|         reverbParams->PositionRight = FAUDIOFX_REVERB_DEFAULT_POSITION; | ||||
|         reverbParams->PositionMatrixLeft = FAUDIOFX_REVERB_DEFAULT_POSITION_MATRIX; | ||||
|         reverbParams->PositionMatrixRight = FAUDIOFX_REVERB_DEFAULT_POSITION_MATRIX; | ||||
|         reverbParams->EarlyDiffusion = 15; | ||||
|         reverbParams->LateDiffusion = 15; | ||||
|         reverbParams->LowEQGain = 8; | ||||
|         reverbParams->LowEQCutoff = 4; | ||||
|         reverbParams->HighEQGain = 8; | ||||
|         reverbParams->HighEQCutoff = 6; | ||||
|         reverbParams->RoomFilterFreq = 5000.0f; | ||||
|         reverbParams->RoomFilterMain = -10.0f; | ||||
|         reverbParams->RoomFilterHF = -1.0f; | ||||
|         reverbParams->ReflectionsGain = -26.0200005f; | ||||
|         reverbParams->ReverbGain = 10.0f; | ||||
|         reverbParams->DecayTime = 1.49000001f; | ||||
|         reverbParams->Density = 100.0f; | ||||
|         reverbParams->RoomSize = FAUDIOFX_REVERB_DEFAULT_ROOM_SIZE; | ||||
| 
 | ||||
|         FAudioVoice_SetEffectParameters( | ||||
|             instance->reverbVoice, | ||||
|             0, | ||||
|             reverbParams, | ||||
|             sizeof(FAudioFXReverbParameters), | ||||
|             0); | ||||
| 
 | ||||
|         SDL_free(reverbParams); | ||||
| 
 | ||||
|         /* Init reverb sends */ | ||||
| 
 | ||||
|         instance->reverbSends.SendCount = 2; | ||||
|         instance->reverbSends.pSends = SDL_malloc(2 * sizeof(FAudioSendDescriptor)); | ||||
| 
 | ||||
|         instance->reverbSends.pSends[0].Flags = 0; | ||||
|         instance->reverbSends.pSends[0].pOutputVoice = device->masteringVoice; | ||||
|         instance->reverbSends.pSends[1].Flags = 0; | ||||
|         instance->reverbSends.pSends[1].pOutputVoice = instance->reverbVoice; | ||||
| 
 | ||||
|         instance->reverbAttached = 1; | ||||
|     } | ||||
| 
 | ||||
|     FAudioVoice_SetOutputVoices( | ||||
|         instance->handle, | ||||
|         &instance->reverbSends); | ||||
| } | ||||
| 
 | ||||
| static void FAudioGMS_INTERNAL_SoundInstance_SetReverb(FAudioGMS_SoundInstance *instance, float reverb) | ||||
| { | ||||
|     if (!instance->reverbAttached) | ||||
|     { | ||||
|         FAudioGMS_INTERNAL_SoundInstance_AttachReverb(instance); | ||||
|     } | ||||
| 
 | ||||
|     float* outputMatrix = instance->dspSettings.pMatrixCoefficients; | ||||
| 
 | ||||
|     outputMatrix[0] = reverb; | ||||
|     if (instance->dspSettings.SrcChannelCount == 2) | ||||
|     { | ||||
|         outputMatrix[1] = reverb; | ||||
|     } | ||||
| 
 | ||||
|     FAudioVoice_SetOutputMatrix( | ||||
|         instance->handle,  | ||||
|         instance->reverbVoice,  | ||||
|         instance->dspSettings.SrcChannelCount,  | ||||
|         1,  | ||||
|         outputMatrix, | ||||
|         0); | ||||
| 
 | ||||
|     instance->reverb = reverb; | ||||
| } | ||||
| 
 | ||||
| static void FAudioGMS_INTERNAL_SoundInstance_SetLowPassFilter(FAudioGMS_SoundInstance* instance, float lowPassFilter) | ||||
| { | ||||
|     FAudioFilterParameters p; | ||||
|     p.Type = FAudioLowPassFilter; | ||||
|     p.Frequency = lowPassFilter; | ||||
|     p.OneOverQ = 1.0f; | ||||
| 
 | ||||
|     FAudioVoice_SetFilterParameters(instance->handle, &p, 0); | ||||
| 
 | ||||
|     instance->lowPassFilter = lowPassFilter; | ||||
| } | ||||
| 
 | ||||
| static void FAudioGMS_INTERNAL_SoundInstance_SetHighPassFilter(FAudioGMS_SoundInstance* instance, float highPassFilter) | ||||
| { | ||||
|     FAudioFilterParameters p; | ||||
|     p.Type = FAudioHighPassFilter; | ||||
|     p.Frequency = highPassFilter; | ||||
|     p.OneOverQ = 1.0f; | ||||
| 
 | ||||
|     FAudioVoice_SetFilterParameters(instance->handle, &p, 0); | ||||
| 
 | ||||
|     instance->highPassFilter = highPassFilter; | ||||
| } | ||||
| 
 | ||||
| static void FAudioGMS_INTERNAL_SoundInstance_SetBandPassFilter(FAudioGMS_SoundInstance* instance, float bandPassFilter) | ||||
| { | ||||
|     FAudioFilterParameters p; | ||||
|     p.Type = FAudioBandPassFilter; | ||||
|     p.Frequency = bandPassFilter; | ||||
|     p.OneOverQ = 1.0f; | ||||
| 
 | ||||
|     FAudioVoice_SetFilterParameters(instance->handle, &p, 0); | ||||
| 
 | ||||
|     instance->bandPassFilter = bandPassFilter; | ||||
| } | ||||
| 
 | ||||
| static void FAudioGMS_INTERNAL_SoundInstance_SetPan(FAudioGMS_SoundInstance* instance, float pan) | ||||
| { | ||||
|     instance->pan = pan; | ||||
|     SetPanMatrixCoefficients(instance); | ||||
| 
 | ||||
|     FAudioVoice_SetOutputMatrix( | ||||
|         instance->handle, | ||||
|         device->masteringVoice, | ||||
|         instance->dspSettings.SrcChannelCount, | ||||
|         instance->dspSettings.DstChannelCount, | ||||
|         instance->dspSettings.pMatrixCoefficients, | ||||
|         0 | ||||
|     ); | ||||
| } | ||||
| 
 | ||||
| static void FAudioGMS_INTERNAL_SoundInstance_SetPitch(FAudioGMS_SoundInstance* instance, float pitch) | ||||
| { | ||||
|     instance->pitch = pitch; | ||||
| 
 | ||||
|     pitch -= 1.0; /* default pitch is 1.0 as per GM standard */ | ||||
|     pitch = SDL_max(-1.0, SDL_min(1.0, pitch)); | ||||
| 
 | ||||
|     FAudioSourceVoice_SetFrequencyRatio( | ||||
|         instance->handle, | ||||
|         SDL_powf(2.0f, pitch), | ||||
|         0 | ||||
|     ); | ||||
| } | ||||
| 
 | ||||
| static void FAudioGMS_INTERNAL_SoundInstance_SetVolume(FAudioGMS_SoundInstance* instance, float volume) | ||||
| { | ||||
|     FAudioVoice_SetVolume(instance->handle, volume, 0); | ||||
| } | ||||
| 
 | ||||
| static FAudioGMS_SoundInstance* FAudioGMS_INTERNAL_SoundInstance_CreateFromStaticSound( | ||||
|     FAudioGMS_StaticSound *staticSound, | ||||
|     double pan, | ||||
|     double pitch, | ||||
|     double volume, | ||||
|     double reverb | ||||
| ) { | ||||
|     FAudioGMS_SoundInstance *instance = SDL_malloc(sizeof(FAudioGMS_SoundInstance)); | ||||
| 
 | ||||
|     instance->handle = NULL; | ||||
|     instance->parent.staticSound = staticSound; | ||||
|     instance->isStatic = 1; | ||||
|     instance->loop = 0; | ||||
|     instance->destroyOnFinish = 0; | ||||
| 
 | ||||
|     instance->format.wFormatTag = 3; | ||||
|     instance->format.wBitsPerSample = 32; | ||||
|     instance->format.nChannels = staticSound->channels; | ||||
|  | @ -370,8 +565,8 @@ double FAudioGMS_SoundInstance_CreateFromStaticSound(double id) | |||
|     if (instance->handle == NULL) | ||||
|     { | ||||
|         Log("SoundInstance failed to initialize!"); | ||||
|         free(instance); | ||||
|         return -1; | ||||
|         SDL_free(instance); | ||||
|         return NULL; | ||||
|     } | ||||
| 
 | ||||
|     instance->dspSettings.DopplerFactor = 1.0f; | ||||
|  | @ -379,55 +574,162 @@ double FAudioGMS_SoundInstance_CreateFromStaticSound(double id) | |||
|     instance->dspSettings.DstChannelCount = device->deviceDetails.OutputFormat.Format.nChannels; | ||||
| 
 | ||||
|     uint32_t memsize = 4 * instance->dspSettings.SrcChannelCount * instance->dspSettings.DstChannelCount; | ||||
|     instance->dspSettings.pMatrixCoefficients = malloc(memsize); | ||||
|     memset(instance->dspSettings.pMatrixCoefficients, 0, memsize); | ||||
|     instance->dspSettings.pMatrixCoefficients = SDL_malloc(memsize); | ||||
|     SDL_memset(instance->dspSettings.pMatrixCoefficients, 0, memsize); | ||||
| 
 | ||||
|     SetPanMatrixCoefficients(instance); | ||||
|     FAudioGMS_INTERNAL_SoundInstance_SetPan(instance, pan); | ||||
|     FAudioGMS_INTERNAL_SoundInstance_SetPitch(instance, pitch); | ||||
|     FAudioGMS_INTERNAL_SoundInstance_SetVolume(instance, volume); | ||||
| 
 | ||||
|     FAudioVoice_SetOutputVoices( | ||||
|         instance->handle, | ||||
|         &device->reverbSends); | ||||
|     instance->reverbAttached = 0; | ||||
|     instance->reverb = 0.0f; | ||||
|     instance->lowPassFilter = 0.0f; | ||||
|     instance->highPassFilter = 0.0f; | ||||
|     instance->bandPassFilter = 0.0f; | ||||
| 
 | ||||
|     if (reverb > 0.0f) | ||||
|     { | ||||
|         FAudioGMS_INTERNAL_SoundInstance_SetReverb(instance, reverb); | ||||
|     } | ||||
| 
 | ||||
|     instance->soundState = SoundState_Stopped; | ||||
| 
 | ||||
|     /* FIXME: id re-use system */ | ||||
|     instance->id = device->staticSoundInstanceCount; | ||||
|     instance->id = device->soundInstanceCount; | ||||
| 
 | ||||
|     device->staticSoundInstances = realloc(device->staticSoundInstances, (device->staticSoundCount + 1) * sizeof(FAudioGMS_SoundInstance*)); | ||||
|     device->staticSoundInstances[device->staticSoundInstanceCount] = instance; | ||||
|     device->staticSoundInstanceCount += 1; | ||||
|     device->soundInstances = SDL_realloc(device->soundInstances, (device->soundInstanceCount + 1) * sizeof(FAudioGMS_SoundInstance*)); | ||||
|     device->soundInstances[device->soundInstanceCount] = instance; | ||||
|     device->soundInstanceCount += 1; | ||||
| 
 | ||||
|     return (double)instance->id; | ||||
|     return instance; | ||||
| } | ||||
| 
 | ||||
| void FAudioGMS_SoundInstance_Destroy(double id) | ||||
| static void FAudioGMS_INTERNAL_SoundInstance_Play(FAudioGMS_SoundInstance* instance) | ||||
| { | ||||
|     FAudioGMS_SoundInstance *instance = device->staticSoundInstances[(uint32_t)id]; | ||||
|     if (instance->isStatic) | ||||
|     { | ||||
|         if (instance->soundState == SoundState_Playing) | ||||
|         { | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         if (instance->loop) | ||||
|         { | ||||
|             instance->parent.staticSound->buffer.LoopCount = FAUDIO_LOOP_INFINITE; | ||||
|             instance->parent.staticSound->buffer.LoopBegin = instance->parent.staticSound->loopStart; | ||||
|             instance->parent.staticSound->buffer.LoopLength = instance->parent.staticSound->loopLength; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             instance->parent.staticSound->buffer.LoopCount = 0; | ||||
|             instance->parent.staticSound->buffer.LoopBegin = 0; | ||||
|             instance->parent.staticSound->buffer.LoopLength = 0; | ||||
|         } | ||||
| 
 | ||||
|         FAudioSourceVoice_SubmitSourceBuffer(instance->handle, &instance->parent.staticSound->buffer, NULL); | ||||
|         FAudioSourceVoice_Start(instance->handle, 0, 0); | ||||
|         instance->soundState = SoundState_Playing; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void FAudioGMS_StaticSound_PlayOneOff(double staticSoundID, double pan, double pitch, double volume, double reverb) | ||||
| { | ||||
|     FAudioGMS_StaticSound* staticSound = device->staticSounds[(uint32_t)staticSoundID]; | ||||
| 
 | ||||
|     if (staticSound != NULL) | ||||
|     { | ||||
|         FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_SoundInstance_CreateFromStaticSound(staticSound, pan, pitch, volume, reverb); | ||||
|         instance->destroyOnFinish = 1; | ||||
|         FAudioGMS_INTERNAL_SoundInstance_Play(instance); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         Log("StaticSound_PlayOneOff: Invalid static sound ID! Did you destroy this sound?"); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| double FAudioGMS_StaticSound_Play(double staticSoundID, double pan, double pitch, double volume, double reverb, double loop) | ||||
| { | ||||
|     FAudioGMS_StaticSound* staticSound = device->staticSounds[(uint32_t)staticSoundID]; | ||||
| 
 | ||||
|     if (staticSound != NULL) | ||||
|     { | ||||
|         FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_SoundInstance_CreateFromStaticSound(staticSound, pan, pitch, volume, reverb); | ||||
|         instance->loop = (uint8_t)loop; | ||||
|         FAudioGMS_INTERNAL_SoundInstance_Play(instance); | ||||
|         return (double)instance->id; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         Log("StaticSound_Play: Invalid static sound ID! Did you destroy this sound?"); | ||||
|         return -1; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void FAudioGMS_SoundInstance_Play(double id) | ||||
| { | ||||
|     FAudioGMS_SoundInstance *instance = device->soundInstances[(uint32_t)id]; | ||||
| 
 | ||||
|     if (instance != NULL) | ||||
|     { | ||||
|         FAudioVoice_DestroyVoice(instance->handle); | ||||
|         free(instance->dspSettings.pMatrixCoefficients); | ||||
|         free(instance); | ||||
|         device->staticSoundInstances[(uint32_t)id] = NULL; | ||||
|         FAudioGMS_INTERNAL_SoundInstance_Play(instance); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void FAudioGMS_StaticSound_Destroy(double id) | ||||
| void FAudioGMS_SoundInstance_Pause(double id) | ||||
| { | ||||
|     FAudioGMS_StaticSound *sound = device->staticSounds[(uint32_t)id]; | ||||
|     FAudioGMS_SoundInstance* instance = device->soundInstances[(uint32_t)id]; | ||||
| 
 | ||||
|     if (sound != NULL) | ||||
|     if (instance != NULL) | ||||
|     { | ||||
|         free((void*)sound->buffer.pAudioData); | ||||
|         free(sound); | ||||
|         device->staticSounds[(uint32_t)id] = NULL; | ||||
|         if (instance->isStatic) | ||||
|         { | ||||
|             if (instance->soundState == SoundState_Playing) | ||||
|             { | ||||
|                 FAudioSourceVoice_Stop(instance->handle, 0, 0); | ||||
|                 instance->soundState = SoundState_Paused; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         Log("SoundInstance_Pause: Invalid sound instance ID! Did you destroy this instance?"); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void FAudioGMS_SoundInstance_Stop(double id) | ||||
| { | ||||
|     FAudioGMS_SoundInstance* instance = device->soundInstances[(uint32_t)id]; | ||||
| 
 | ||||
|     if (instance != NULL) | ||||
|     { | ||||
|         if (instance->isStatic) | ||||
|         { | ||||
|             FAudioSourceVoice_ExitLoop(instance->handle, 0); | ||||
|         } | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         Log("SoundInstance_Stop: Invalid sound instance ID! Did you destroy this instance?"); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void FAudioGMS_Destroy() | ||||
| { | ||||
|     FAudio_Release(device->handle); | ||||
|     free(device); | ||||
|     device = NULL; | ||||
|     uint32_t i = 0; | ||||
|     for (i = 0; i < device->staticSoundCount; i += 1) | ||||
|     { | ||||
|         FAudioGMS_INTERNAL_StaticSound_Destroy(device->staticSounds[i]); | ||||
|     } | ||||
| 
 | ||||
|     for (i = 0; i < device->soundInstanceCount; i += 1) | ||||
|     { | ||||
|         FAudioGMS_INTERNAL_SoundInstance_Destroy(device->soundInstances[i]); | ||||
|     } | ||||
| 
 | ||||
|     FAudio_Release(device->handle); | ||||
|     SDL_free(device); | ||||
|     device = NULL; | ||||
| 
 | ||||
|     Log("FAudio cleaned up successfully!"); | ||||
| } | ||||
|  |  | |||
|  | @ -27,10 +27,6 @@ | |||
| #ifndef FAUDIOGMS_H | ||||
| #define FAUDIOGMS_H | ||||
| 
 | ||||
| #include <math.h> | ||||
| #include <stdbool.h> | ||||
| #include <stdint.h> | ||||
| 
 | ||||
| #ifdef _WIN32 | ||||
| #define FAUDIOGMSAPI __declspec(dllexport) | ||||
| #define FAUDIOGMSCALL __cdecl | ||||
|  | @ -46,11 +42,16 @@ extern "C" { | |||
| FAUDIOGMSAPI void FAudioGMS_Init(); | ||||
| FAUDIOGMSAPI void FAudioGMS_Update(); | ||||
| 
 | ||||
| FAUDIOGMSAPI double FAudioGMS_StaticSound_LoadWAV(char *filePath); | ||||
| FAUDIOGMSAPI double FAudioGMS_StaticSound_LoadWAV(char *filePath); /* returns a static sound ID */ | ||||
| FAUDIOGMSAPI void FAudioGMS_StaticSound_PlayOneOff(double staticSoundID, double pan, double pitch, double volume, double reverb); /* automatically frees itself when done! */ | ||||
| FAUDIOGMSAPI double FAudioGMS_StaticSound_Play(double staticSoundID, double pan, double pitch, double volume, double reverb, double loop); /* returns a sound instance ID. must be freed! */ | ||||
| 
 | ||||
| FAUDIOGMSAPI double FAudioGMS_SoundInstance_CreateFromStaticSound(double id); | ||||
| FAUDIOGMSAPI void FAudioGMS_SoundInstance_Play(double id); | ||||
| FAUDIOGMSAPI void FAudioGMS_SoundInstance_Pause(double id); | ||||
| FAUDIOGMSAPI void FAudioGMS_SoundInstance_Stop(double id); | ||||
| 
 | ||||
| FAUDIOGMSAPI void FAudioGMS_SoundInstance_Destroy(double id); | ||||
| FAUDIOGMSAPI void FAudioGMS_SoundInstance_DestroyWhenFinished(double id); | ||||
| FAUDIOGMSAPI void FAudioGMS_StaticSound_Destroy(double id); | ||||
| FAUDIOGMSAPI void FAudioGMS_Destroy(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -9,6 +9,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FAudioGMS", "FAudioGMS.vcxp | |||
| EndProject | ||||
| Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FAudio", "..\lib\FAudio\visualc\FAudio.vcxproj", "{90A103EF-E403-47D4-BBBB-0F206B9FA7F2}" | ||||
| EndProject | ||||
| Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SDL2", "..\lib\SDL\VisualC\SDL\SDL.vcxproj", "{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}" | ||||
| EndProject | ||||
| Global | ||||
| 	GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||||
| 		Debug|x64 = Debug|x64 | ||||
|  | @ -53,6 +55,22 @@ Global | |||
| 		{90A103EF-E403-47D4-BBBB-0F206B9FA7F2}.RelWithDebInfo|x64.Build.0 = Release|x64 | ||||
| 		{90A103EF-E403-47D4-BBBB-0F206B9FA7F2}.RelWithDebInfo|x86.ActiveCfg = Release|Win32 | ||||
| 		{90A103EF-E403-47D4-BBBB-0F206B9FA7F2}.RelWithDebInfo|x86.Build.0 = Release|Win32 | ||||
| 		{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Debug|x64.ActiveCfg = Debug|x64 | ||||
| 		{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Debug|x64.Build.0 = Debug|x64 | ||||
| 		{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Debug|x86.ActiveCfg = Debug|Win32 | ||||
| 		{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Debug|x86.Build.0 = Debug|Win32 | ||||
| 		{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.MinSizeRel|x64.ActiveCfg = Debug|x64 | ||||
| 		{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.MinSizeRel|x64.Build.0 = Debug|x64 | ||||
| 		{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.MinSizeRel|x86.ActiveCfg = Debug|Win32 | ||||
| 		{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.MinSizeRel|x86.Build.0 = Debug|Win32 | ||||
| 		{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Release|x64.ActiveCfg = Release|x64 | ||||
| 		{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Release|x64.Build.0 = Release|x64 | ||||
| 		{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Release|x86.ActiveCfg = Release|Win32 | ||||
| 		{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Release|x86.Build.0 = Release|Win32 | ||||
| 		{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.RelWithDebInfo|x64.ActiveCfg = Release|x64 | ||||
| 		{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.RelWithDebInfo|x64.Build.0 = Release|x64 | ||||
| 		{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.RelWithDebInfo|x86.ActiveCfg = Release|Win32 | ||||
| 		{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.RelWithDebInfo|x86.Build.0 = Release|Win32 | ||||
| 	EndGlobalSection | ||||
| 	GlobalSection(SolutionProperties) = preSolution | ||||
| 		HideSolutionNode = FALSE | ||||
|  |  | |||
|  | @ -68,10 +68,18 @@ | |||
|       <WarningLevel>Level3</WarningLevel> | ||||
|       <Optimization>Disabled</Optimization> | ||||
|       <LanguageStandard_C Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Default</LanguageStandard_C> | ||||
|       <RuntimeLibrary Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">MultiThreadedDebugDLL</RuntimeLibrary> | ||||
|       <FunctionLevelLinking Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</FunctionLevelLinking> | ||||
|       <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(OutDir)</AdditionalIncludeDirectories> | ||||
|     </ClCompile> | ||||
|     <Link> | ||||
|       <GenerateDebugInformation>DebugFull</GenerateDebugInformation> | ||||
|       <SubSystem Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotSet</SubSystem> | ||||
|       <AdditionalDependencies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">SetupAPI.lib;Version.lib;Winmm.lib;Imm32.lib;libucrt.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies> | ||||
|     </Link> | ||||
|     <ProjectReference> | ||||
|       <UseLibraryDependencyInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</UseLibraryDependencyInputs> | ||||
|     </ProjectReference> | ||||
|   </ItemDefinitionGroup> | ||||
|   <ItemDefinitionGroup Condition="'$(Configuration)'=='Release'"> | ||||
|     <ClCompile> | ||||
|  | @ -83,6 +91,7 @@ | |||
|     <Link> | ||||
|       <GenerateDebugInformation>true</GenerateDebugInformation> | ||||
|       <OptimizeReferences>true</OptimizeReferences> | ||||
|       <AdditionalDependencies Condition="'$(Configuration)|$(Platform)'=='Release|x64'">SetupAPI.lib;Version.lib;Winmm.lib;Imm32.lib;libucrt.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies> | ||||
|     </Link> | ||||
|   </ItemDefinitionGroup> | ||||
|   <ItemGroup> | ||||
|  | @ -95,6 +104,9 @@ | |||
|     <ProjectReference Include="..\lib\FAudio\visualc\FAudio.vcxproj"> | ||||
|       <Project>{90a103ef-e403-47d4-bbbb-0f206b9fa7f2}</Project> | ||||
|     </ProjectReference> | ||||
|     <ProjectReference Include="..\lib\SDL\VisualC\SDL\SDL.vcxproj"> | ||||
|       <Project>{81ce8daf-ebb2-4761-8e45-b71abcca8c68}</Project> | ||||
|     </ProjectReference> | ||||
|   </ItemGroup> | ||||
|   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> | ||||
|   <ImportGroup Label="ExtensionTargets"> | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue