diff --git a/src/FAudioGMS.c b/src/FAudioGMS.c index 14925cb..e1c060d 100644 --- a/src/FAudioGMS.c +++ b/src/FAudioGMS.c @@ -142,7 +142,7 @@ static inline uint32_t IdStack_Pop(IdStack* stack) return stack->array[stack->count]; } -typedef struct BufferQueue +typedef struct BufferQueue { uint32_t head; uint32_t tail; @@ -160,9 +160,9 @@ static inline void BufferQueue_Init(BufferQueue* queue, uint32_t size) queue->buffers = SDL_malloc(size * sizeof(uint8_t*)); } -static inline uint8_t* BufferQueue_Dequeue(BufferQueue *queue) +static inline uint8_t* BufferQueue_Dequeue(BufferQueue *queue) { - if (queue->tail == queue->head) + if (queue->tail == queue->head) { return NULL; } @@ -175,9 +175,9 @@ static inline uint8_t* BufferQueue_Dequeue(BufferQueue *queue) return buffer; } -static inline void BufferQueue_Enqueue(BufferQueue *queue, uint8_t* buffer) +static inline void BufferQueue_Enqueue(BufferQueue *queue, uint8_t* buffer) { - if (((queue->head + 1) % queue->size) == queue->tail) + if (((queue->head + 1) % queue->size) == queue->tail) { return; } @@ -225,14 +225,14 @@ typedef struct FAudioGMS_SoundInstance float pan; float pitch; float volume; - float reverb; float lowPassFilter; float highPassFilter; float bandPassFilter; - uint8_t reverbAttached; - FAudioSubmixVoice* reverbVoice; - FAudioVoiceSends reverbSends; + uint8_t effectChainAttached; + FAudioSubmixVoice* effectVoice; + FAudioVoiceSends effectSends; + float effectGain; uint8_t adjustingVolumeOverTime; float targetVolume; @@ -252,6 +252,24 @@ typedef struct FAudioGMS_SoundInstance } soundData; } FAudioGMS_SoundInstance; +typedef enum FAudioGMS_EffectType +{ + EffectType_Reverb +} FAudioGMS_EffectType; + +typedef union FAudioGMS_EffectParameters +{ + FAudioFXReverbParameters reverbParameters; +} FAudioGMS_EffectParameters; + +typedef struct FAudioGMS_EffectChain +{ + uint32_t id; + FAudioEffectChain fAudioEffectChain; + FAudioGMS_EffectType *effectTypes; /* size equal to effect chain size */ + union FAudioGMS_EffectParameters *effectParameters; /* size equal to effect chain size */ +} 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; @@ -278,6 +296,10 @@ typedef struct FAudioGMS_Device uint32_t soundInstanceCount; IdStack soundInstanceIndexStack; + FAudioGMS_EffectChain** effectChains; + uint32_t effectChainCount; + IdStack effectChainIndexStack; + float streamStagingBuffer[STREAMING_BUFFER_SIZE]; double timestep; } FAudioGMS_Device; @@ -310,6 +332,19 @@ static inline FAudioGMS_SoundInstance* FAudioGMS_INTERNAL_LookupSoundInstance(ui } } +static inline FAudioGMS_EffectChain* FAudioGMS_INTERNAL_LookupEffectChain(uint32_t id) +{ + if (id >= 0 && id < device->effectChainCount) + { + return device->effectChains[id]; + } + else + { + Log("Invalid EffectChain ID!"); + return NULL; + } +} + void FAudioGMS_Init(double spatialDistanceScale, double timestep) { device = SDL_malloc(sizeof(FAudioGMS_Device)); @@ -413,6 +448,10 @@ void FAudioGMS_Init(double spatialDistanceScale, double timestep) device->soundInstanceCount = 0; IdStack_Init(&device->soundInstanceIndexStack); + device->effectChains = NULL; + device->effectChainCount = 0; + IdStack_Init(&device->effectChainIndexStack); + device->timestep = timestep; Log("FAudio initialized successfully!"); @@ -521,118 +560,6 @@ double FAudioGMS_StaticSound_LoadWAV(char *filePath) return (double)sound->id; } -static void FAudioGMS_INTERNAL_SoundInstance_AttachReverb(FAudioGMS_SoundInstance* instance) -{ - 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; @@ -747,16 +674,11 @@ static void FAudioGMS_INTERNAL_SoundInstance_SetVolume(FAudioGMS_SoundInstance* FAudioVoice_SetVolume(instance->handle, volume, 0); } -static void FAudioGMS_INTERNAL_SoundInstance_SetProperties(FAudioGMS_SoundInstance* instance, double pan, double pitch, double volume, double reverb) +static void FAudioGMS_INTERNAL_SoundInstance_SetProperties(FAudioGMS_SoundInstance* instance, double pan, double pitch, double volume) { FAudioGMS_INTERNAL_SoundInstance_SetPan(instance, pan); FAudioGMS_INTERNAL_SoundInstance_SetPitch(instance, pitch); FAudioGMS_INTERNAL_SoundInstance_SetVolume(instance, volume); - - if (reverb > 0.0f) - { - FAudioGMS_INTERNAL_SoundInstance_SetReverb(instance, reverb); - } } static void FAudioGMS_INTERNAL_Apply3D(FAudioGMS_SoundInstance* instance) @@ -831,8 +753,10 @@ static FAudioGMS_SoundInstance* FAudioGMS_INTERNAL_SoundInstance_Init( instance->dspSettings.pMatrixCoefficients = SDL_malloc(memsize); SDL_memset(instance->dspSettings.pMatrixCoefficients, 0, memsize); - instance->reverbAttached = 0; - instance->reverb = 0.0f; + instance->effectChainAttached = 0; + instance->effectVoice = NULL; + instance->effectGain = 0; + instance->lowPassFilter = 0.0f; instance->highPassFilter = 0.0f; instance->bandPassFilter = 0.0f; @@ -917,7 +841,7 @@ static void FAudioGMS_INTERNAL_SoundInstance_AddBuffer(FAudioGMS_SoundInstance* buffer.pContext = NULL; FAudioSourceVoice_SubmitSourceBuffer(instance->handle, &buffer, NULL); - + /* We have reached the end of the file! */ if (sampleCount < STREAMING_BUFFER_SIZE) { @@ -1072,7 +996,7 @@ static void FAudioGMS_INTERNAL_SoundInstance_Play(FAudioGMS_SoundInstance* insta instance->soundState = SoundState_Playing; } -void FAudioGMS_StaticSound_PlayOneOff(double staticSoundID, double pan, double pitch, double volume, double reverb) +void FAudioGMS_StaticSound_PlayOneOff(double staticSoundID, double pan, double pitch, double volume) { FAudioGMS_StaticSound* staticSound = FAudioGMS_INTERNAL_LookupStaticSound((uint32_t)staticSoundID); @@ -1080,7 +1004,7 @@ void FAudioGMS_StaticSound_PlayOneOff(double staticSoundID, double pan, double p { FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_SoundInstance_CreateFromStaticSound(staticSound); instance->destroyOnFinish = 1; - FAudioGMS_INTERNAL_SoundInstance_SetProperties(instance, pan, pitch, volume, reverb); + FAudioGMS_INTERNAL_SoundInstance_SetProperties(instance, pan, pitch, volume); FAudioGMS_INTERNAL_SoundInstance_Play(instance); } else @@ -1089,7 +1013,7 @@ void FAudioGMS_StaticSound_PlayOneOff(double staticSoundID, double pan, double p } } -void FAudioGMS_StaticSound_PlayOneOffSpatial(double staticSoundID, double x, double y, double z, double pitch, double volume, double reverb) +void FAudioGMS_StaticSound_PlayOneOffSpatial(double staticSoundID, double x, double y, double z, double pitch, double volume) { FAudioGMS_StaticSound* staticSound = FAudioGMS_INTERNAL_LookupStaticSound((uint32_t)staticSoundID); @@ -1097,7 +1021,7 @@ void FAudioGMS_StaticSound_PlayOneOffSpatial(double staticSoundID, double x, dou { FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_SoundInstance_CreateFromStaticSound(staticSound); instance->destroyOnFinish = 1; - FAudioGMS_INTERNAL_SoundInstance_SetProperties(instance, 0, pitch, volume, reverb); + FAudioGMS_INTERNAL_SoundInstance_SetProperties(instance, 0, pitch, volume); FAudioGMS_INTERNAL_StaticSound_AddEmitter(instance, x, y, z); FAudioGMS_INTERNAL_SoundInstance_Play(instance); } @@ -1107,7 +1031,7 @@ void FAudioGMS_StaticSound_PlayOneOffSpatial(double staticSoundID, double x, dou } } -double FAudioGMS_StaticSound_Play(double staticSoundID, double pan, double pitch, double volume, double reverb, double loop) +double FAudioGMS_StaticSound_Play(double staticSoundID, double pan, double pitch, double volume, double loop) { FAudioGMS_StaticSound* staticSound = FAudioGMS_INTERNAL_LookupStaticSound((uint32_t)staticSoundID); @@ -1115,7 +1039,7 @@ double FAudioGMS_StaticSound_Play(double staticSoundID, double pan, double pitch { FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_SoundInstance_CreateFromStaticSound(staticSound); instance->loop = (uint8_t)loop; - FAudioGMS_INTERNAL_SoundInstance_SetProperties(instance, pan, pitch, volume, reverb); + FAudioGMS_INTERNAL_SoundInstance_SetProperties(instance, pan, pitch, volume); FAudioGMS_INTERNAL_SoundInstance_Play(instance); return (double)instance->id; } @@ -1126,7 +1050,7 @@ double FAudioGMS_StaticSound_Play(double staticSoundID, double pan, double pitch } } -double FAudioGMS_StaticSound_PlaySpatial(double staticSoundID, double x, double y, double z, double pitch, double volume, double reverb, double loop) +double FAudioGMS_StaticSound_PlaySpatial(double staticSoundID, double x, double y, double z, double pitch, double volume, double loop) { FAudioGMS_StaticSound* staticSound = FAudioGMS_INTERNAL_LookupStaticSound((uint32_t)staticSoundID); @@ -1134,7 +1058,7 @@ double FAudioGMS_StaticSound_PlaySpatial(double staticSoundID, double x, double { FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_SoundInstance_CreateFromStaticSound(staticSound); instance->loop = (uint8_t)loop; - FAudioGMS_INTERNAL_SoundInstance_SetProperties(instance, 0, pitch, volume, reverb); + FAudioGMS_INTERNAL_SoundInstance_SetProperties(instance, 0, pitch, volume); FAudioGMS_INTERNAL_StaticSound_AddEmitter(instance, x, y, z); FAudioGMS_INTERNAL_SoundInstance_Play(instance); return (double)instance->id; @@ -1254,16 +1178,6 @@ void FAudioGMS_SoundInstance_SetVolume(double soundInstanceID, double volume) } } -void FAudioGMS_SoundInstance_SetReverb(double soundInstanceID, double reverb) -{ - FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_LookupSoundInstance((uint32_t)soundInstanceID); - - if (instance != NULL) - { - FAudioGMS_INTERNAL_SoundInstance_SetReverb(instance, reverb); - } -} - void FAudioGMS_SoundInstance_Set3DPosition(double soundInstanceID, double x, double y, double z) { FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_LookupSoundInstance((uint32_t)soundInstanceID); @@ -1451,6 +1365,255 @@ void FAudioGMS_StaticSound_Destroy(double staticSoundID) FAudioGMS_INTERNAL_StaticSound_Destroy(sound); } +double FAudioGMS_EffectChain_Create() +{ + FAudioGMS_EffectChain* effectChain = SDL_malloc(sizeof(FAudioGMS_EffectChain)); + + effectChain->fAudioEffectChain.EffectCount = 0; + effectChain->fAudioEffectChain.pEffectDescriptors = NULL; + effectChain->effectTypes = NULL; + effectChain->effectParameters = NULL; + + if (device->effectChainIndexStack.count > 0) + { + effectChain->id = IdStack_Pop(&device->effectChainIndexStack); + } + else + { + effectChain->id = device->effectChainCount; + + device->effectChains = SDL_realloc(device->effectChains, (device->effectChainCount + 1) * sizeof(FAudioGMS_EffectChain*)); + device->effectChainCount += 1; + } + + device->effectChains[effectChain->id] = effectChain; + + return effectChain->id; +} + +static void FAudioGMS_INTERNAL_EffectChain_AddReverb(FAudioGMS_EffectChain* effectChain, FAudioFXReverbParameters *reverbParameters) +{ + FAPO* reverb; + FAudioCreateReverb(&reverb, 0); + + effectChain->fAudioEffectChain.EffectCount += 1; + effectChain->fAudioEffectChain.pEffectDescriptors = SDL_realloc(effectChain->fAudioEffectChain.pEffectDescriptors, effectChain->fAudioEffectChain.EffectCount * sizeof(FAudioEffectDescriptor)); + + FAudioEffectDescriptor* reverbDescriptor = &effectChain->fAudioEffectChain.pEffectDescriptors[effectChain->fAudioEffectChain.EffectCount - 1]; + + reverbDescriptor->InitialState = 1; + reverbDescriptor->OutputChannels = device->deviceDetails.OutputFormat.Format.nChannels == 6 ? 6 : 1; + reverbDescriptor->pEffect = reverb; + + effectChain->effectTypes = SDL_realloc(effectChain->effectTypes, effectChain->fAudioEffectChain.EffectCount * sizeof(FAudioGMS_EffectType)); + effectChain->effectTypes[effectChain->fAudioEffectChain.EffectCount - 1] = EffectType_Reverb; + + effectChain->effectParameters = SDL_realloc(effectChain->effectParameters, effectChain->fAudioEffectChain.EffectCount * sizeof(FAudioGMS_EffectParameters)); + SDL_memcpy(&effectChain->effectParameters[effectChain->fAudioEffectChain.EffectCount - 1], reverbParameters, sizeof(FAudioFXReverbParameters)); +} + +void FAudioGMS_EffectChain_AddDefaultReverb(double effectChainID) +{ + FAudioGMS_EffectChain *effectChain = FAudioGMS_INTERNAL_LookupEffectChain((uint32_t)effectChainID); + + if (effectChain != NULL) + { + FAudioFXReverbParameters reverbParams; + + 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; + + FAudioGMS_INTERNAL_EffectChain_AddReverb(effectChain, &reverbParams); + } +} + +/* no room filter params because game maker only supports 16 arguments lmao */ +void FAudioGMS_EffectChain_AddReverb( + double effectChainID, + double wetDryMix, + double reflectionsDelay, + double reverbDelay, + double earlyDiffusion, + double lateDiffusion, + double lowEQGain, + double lowEQCutoff, + double highEQGain, + double highEQCutoff, + double reflectionsGain, + double reverbGain, + double decayTime, + double density, + double roomSize +) { + FAudioGMS_EffectChain* effectChain = FAudioGMS_INTERNAL_LookupEffectChain((uint32_t)effectChainID); + + if (effectChain != NULL) + { + FAudioFXReverbParameters reverbParams; + + reverbParams.WetDryMix = wetDryMix; + reverbParams.ReflectionsDelay = reflectionsDelay; + reverbParams.ReverbDelay = reverbDelay; + 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 = earlyDiffusion; + reverbParams.LateDiffusion = lateDiffusion; + reverbParams.LowEQGain = lowEQGain; + reverbParams.LowEQCutoff = lowEQCutoff; + reverbParams.HighEQGain = highEQGain; + reverbParams.HighEQCutoff = highEQCutoff; + reverbParams.RoomFilterFreq = 5000.0f; + reverbParams.RoomFilterMain = -10.0f; + reverbParams.RoomFilterHF = -1.0f; + reverbParams.ReflectionsGain = reflectionsGain; + reverbParams.ReverbGain = reverbGain; + reverbParams.DecayTime = decayTime; + reverbParams.Density = density; + reverbParams.RoomSize = roomSize; + + FAudioGMS_INTERNAL_EffectChain_AddReverb(effectChain, &reverbParams); + } +} + +void FAudioGMS_SoundInstance_SetEffectChain(double soundInstanceID, double effectChainID, double effectGain) +{ + FAudioGMS_SoundInstance *instance = FAudioGMS_INTERNAL_LookupSoundInstance((uint32_t)soundInstanceID); + FAudioGMS_EffectChain *effectChain = FAudioGMS_INTERNAL_LookupEffectChain((uint32_t)effectChainID); + uint32_t i; + + if (instance != NULL && effectChain != NULL) + { + if (!instance->effectChainAttached) + { + FAudio_CreateSubmixVoice( + device->handle, + &instance->effectVoice, + 1, /* FIXME: is this correct? */ + device->deviceDetails.OutputFormat.Format.nSamplesPerSec, + 0, + 0, + NULL, + &effectChain->fAudioEffectChain); + + instance->effectSends.SendCount = 2; + instance->effectSends.pSends = SDL_malloc(2 * sizeof(FAudioSendDescriptor)); + + instance->effectSends.pSends[0].Flags = 0; + instance->effectSends.pSends[0].pOutputVoice = device->masteringVoice; + instance->effectSends.pSends[1].Flags = 0; + instance->effectSends.pSends[1].pOutputVoice = instance->effectVoice; + + instance->effectChainAttached = 1; + } + else + { + FAudioVoice_SetEffectChain( + instance->effectVoice, + &effectChain->fAudioEffectChain); + } + + for (i = 0; i < effectChain->fAudioEffectChain.EffectCount; i += 1) + { + uint32_t parametersSize; + void *parameters; + + switch (effectChain->effectTypes[i]) + { + case EffectType_Reverb: + parametersSize = sizeof(FAudioFXReverbParameters); + parameters = &effectChain->effectParameters[i].reverbParameters; + break; + + default: + Log("Unknown effect type! Something is very wrong!"); + } + + FAudioVoice_SetEffectParameters( + instance->effectVoice, + i, + parameters, + parametersSize, + 0); + } + + FAudioVoice_SetOutputVoices( + instance->handle, + &instance->effectSends); + + /* TODO: move this to a different API call */ + float *outputMatrix = instance->dspSettings.pMatrixCoefficients; + + outputMatrix[0] = effectGain; + if (instance->dspSettings.SrcChannelCount == 2) + { + outputMatrix[1] = effectGain; + } + + FAudioVoice_SetOutputMatrix( + instance->handle, + instance->effectVoice, + instance->dspSettings.SrcChannelCount, + 1, + outputMatrix, + 0); + + instance->effectGain = effectGain; + } +} + +static void FAudioGMS_INTERNAL_EffectChain_Destroy(FAudioGMS_EffectChain *effectChain) +{ + uint32_t i; + if (effectChain != NULL) + { + device->effectChains[effectChain->id] = NULL; + IdStack_Push(&device->effectChainIndexStack, effectChain->id); + + for (i = 0; i < effectChain->fAudioEffectChain.EffectCount; i += 1) + { + FAPOBase_Release((FAPOBase*)effectChain->fAudioEffectChain.pEffectDescriptors[i].pEffect); + } + + SDL_free(effectChain->effectParameters); + SDL_free(effectChain->effectTypes); + SDL_free(effectChain->fAudioEffectChain.pEffectDescriptors); + SDL_free(effectChain); + } +} + +void FAudioGMS_EffectChain_Destroy(double effectChainID) +{ + FAudioGMS_EffectChain *effectChain = FAudioGMS_INTERNAL_LookupEffectChain((uint32_t)effectChainID); + + if (effectChain != NULL) + { + FAudioGMS_INTERNAL_EffectChain_Destroy(effectChain); + } +} + void FAudioGMS_Update() { uint32_t i; @@ -1532,6 +1695,11 @@ void FAudioGMS_Destroy() FAudioGMS_INTERNAL_SoundInstance_Destroy(device->soundInstances[i]); } + for (i = 0; i < device->effectChainCount; i += 1) + { + FAudioGMS_INTERNAL_EffectChain_Destroy(device->effectChains[i]); + } + for (i = 0; i < device->staticSoundCount; i += 1) { FAudioGMS_INTERNAL_StaticSound_Destroy(device->staticSounds[i]); diff --git a/src/FAudioGMS.h b/src/FAudioGMS.h index 9157935..23dadf6 100644 --- a/src/FAudioGMS.h +++ b/src/FAudioGMS.h @@ -42,10 +42,10 @@ extern "C" { FAUDIOGMSAPI void FAudioGMS_Init(double spatialDistanceScale, double timestep); 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 void FAudioGMS_StaticSound_PlayOneOffSpatial(double staticSoundID, double x, double y, double z, 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_StaticSound_PlaySpatial(double staticSoundID, double x, double y, double z, double pitch, double volume, double reverb, double loop); /* returns a sound instance ID. must be freed! */ +FAUDIOGMSAPI void FAudioGMS_StaticSound_PlayOneOff(double staticSoundID, double pan, double pitch, double volume); /* automatically frees itself when done! */ +FAUDIOGMSAPI void FAudioGMS_StaticSound_PlayOneOffSpatial(double staticSoundID, double x, double y, double z, double pitch, double volume); /* automatically frees itself when done! */ +FAUDIOGMSAPI double FAudioGMS_StaticSound_Play(double staticSoundID, double pan, double pitch, double volume, double loop); /* returns a sound instance ID. must be freed! */ +FAUDIOGMSAPI double FAudioGMS_StaticSound_PlaySpatial(double staticSoundID, double x, double y, double z, double pitch, double volume, double loop); /* returns a sound instance ID. must be freed! */ FAUDIOGMSAPI void FAudioGMS_StaticSound_Destroy(double staticSoundID); FAUDIOGMSAPI double FAudioGMS_StreamingSound_LoadOGG(char* filepath); /* returns a sound instance */ @@ -58,7 +58,6 @@ FAUDIOGMSAPI void FAudioGMS_SoundInstance_StopImmediate(double soundInstanceID); FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetPan(double soundInstanceID, double pan); FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetPitch(double soundInstanceID, double pitch); FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetVolume(double soundInstanceID, double volume); -FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetReverb(double soundInstanceID, double reverb); 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); @@ -73,6 +72,29 @@ FAUDIOGMSAPI double FAudioGMS_SoundInstance_GetTrackLengthInSeconds(double sound FAUDIOGMSAPI void FAudioGMS_SoundInstance_Destroy(double soundInstanceID); FAUDIOGMSAPI void FAudioGMS_SoundInstance_DestroyWhenFinished(double soundInstanceID); +FAUDIOGMSAPI double FAudioGMS_EffectChain_Create(); +FAUDIOGMSAPI void FAudioGMS_EffectChain_AddDefaultReverb(double effectChainID); +FAUDIOGMSAPI void FAudioGMS_EffectChain_AddReverb( + double effectChainID, + double wetDryMix, + double reflectionsDelay, + double reverbDelay, + double earlyDiffusion, + double lateDiffusion, + double lowEQGain, + double lowEQCutoff, + double highEQGain, + double highEQCutoff, + double reflectionsGain, + double reverbGain, + double decayTime, + double density, + double roomSize +); +FAUDIOGMSAPI void FAudioGMS_EffectChain_Destroy(double effectChainID); + +FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetEffectChain(double soundInstanceID, double effectChainID, double effectGain); + FAUDIOGMSAPI void FAudioGMS_SetListenerPosition(double x, double y, double z); FAUDIOGMSAPI void FAudioGMS_StopAll();