From 6cd6147961c6dd7496711170b79375a76086b163 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Thu, 28 Oct 2021 14:58:48 -0700 Subject: [PATCH] fix effect chain memory issues --- src/FAudioGMS.c | 180 ++++++++++++++++++++++++++++++------------------ src/FAudioGMS.h | 5 ++ 2 files changed, 117 insertions(+), 68 deletions(-) diff --git a/src/FAudioGMS.c b/src/FAudioGMS.c index b27e564..af50922 100644 --- a/src/FAudioGMS.c +++ b/src/FAudioGMS.c @@ -220,9 +220,9 @@ typedef union 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 */ + uint32_t effectCount; + FAudioGMS_EffectType *effectTypes; /* length equal to effectCount */ + union FAudioGMS_EffectParameters *effectParameters; /* length equal to effectCount */ } FAudioGMS_EffectChain; static const float SPEED_OF_SOUND = 343.5f; @@ -1268,7 +1268,15 @@ static void FAudioGMS_INTERNAL_SoundInstance_Destroy(FAudioGMS_SoundInstance* in device->soundInstances[instance->id] = NULL; IdStack_Push(&device->soundInstanceIndexStack, instance->id); FAudioGMS_INTERNAL_SoundInstance_Stop(instance); + + if (instance->effectChainAttached) + { + FAudioVoice_DestroyVoice(instance->effectVoice); + SDL_free(instance->effectSends.pSends); + } + FAudioVoice_DestroyVoice(instance->handle); + if (!instance->isStatic) { SDL_free(instance->soundData.streamingSound.streamBuffer); @@ -1329,8 +1337,7 @@ double FAudioGMS_EffectChain_Create() RETURN_ON_NULL_DEVICE(-1.0) FAudioGMS_EffectChain* effectChain = SDL_malloc(sizeof(FAudioGMS_EffectChain)); - effectChain->fAudioEffectChain.EffectCount = 0; - effectChain->fAudioEffectChain.pEffectDescriptors = NULL; + effectChain->effectCount = 0; effectChain->effectTypes = NULL; effectChain->effectParameters = NULL; @@ -1353,23 +1360,13 @@ double FAudioGMS_EffectChain_Create() static void FAudioGMS_INTERNAL_EffectChain_AddReverb(FAudioGMS_EffectChain* effectChain, FAudioFXReverbParameters *reverbParameters) { - FAPO* reverb; - FAudioCreateReverb(&reverb, 0); + effectChain->effectCount += 1; - effectChain->fAudioEffectChain.EffectCount += 1; - effectChain->fAudioEffectChain.pEffectDescriptors = SDL_realloc(effectChain->fAudioEffectChain.pEffectDescriptors, effectChain->fAudioEffectChain.EffectCount * sizeof(FAudioEffectDescriptor)); + effectChain->effectTypes = SDL_realloc(effectChain->effectTypes, effectChain->effectCount * sizeof(FAudioGMS_EffectType)); + effectChain->effectTypes[effectChain->effectCount - 1] = EffectType_Reverb; - 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)); + effectChain->effectParameters = SDL_realloc(effectChain->effectParameters, effectChain->effectCount * sizeof(FAudioGMS_EffectParameters)); + SDL_memcpy(&effectChain->effectParameters[effectChain->effectCount - 1], reverbParameters, sizeof(FAudioFXReverbParameters)); } void FAudioGMS_EffectChain_AddDefaultReverb(double effectChainID) @@ -1460,6 +1457,70 @@ void FAudioGMS_EffectChain_AddReverb( } } +static void FAudioGMS_INTERNAL_SoundInstance_SetEffectGain(FAudioGMS_SoundInstance *instance, float effectGain) +{ + 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; +} + +void FAudioGMS_SoundInstance_SetEffectGain(double soundInstanceID, double effectGain) +{ + RETURN_ON_NULL_DEVICE() + FAudioGMS_SoundInstance *instance = FAudioGMS_INTERNAL_LookupSoundInstance((uint32_t)soundInstanceID); + + if (instance != NULL) + { + FAudioGMS_INTERNAL_SoundInstance_SetEffectGain(instance, effectGain); + } +} + +static FAudioEffectChain* FAudioGMS_INTERNAL_CreateFAudioEffectChain(FAudioGMS_EffectChain* effectChain) +{ + FAudioEffectChain* fAudioEffectChain = SDL_malloc(sizeof(FAudioEffectChain)); + uint32_t i; + + fAudioEffectChain->EffectCount = effectChain->effectCount; + fAudioEffectChain->pEffectDescriptors = SDL_malloc(fAudioEffectChain->EffectCount * sizeof(FAudioEffectDescriptor)); + + FAPO* reverb; + + for (i = 0; i < effectChain->effectCount; i += 1) + { + switch (effectChain->effectTypes[i]) + { + case EffectType_Reverb: + FAudioCreateReverb(&reverb, 0); + + FAudioEffectDescriptor* reverbDescriptor = &fAudioEffectChain->pEffectDescriptors[i]; + reverbDescriptor->InitialState = 1; + reverbDescriptor->OutputChannels = device->deviceDetails.OutputFormat.Format.nChannels == 6 ? 6 : 1; + reverbDescriptor->pEffect = reverb; + break; + + default: + Log("Unknown effect type! Something is very wrong!"); + return; + } + } + + return fAudioEffectChain; +} + void FAudioGMS_SoundInstance_SetEffectChain(double soundInstanceID, double effectChainID, double effectGain) { RETURN_ON_NULL_DEVICE() @@ -1469,36 +1530,34 @@ void FAudioGMS_SoundInstance_SetEffectChain(double soundInstanceID, double effec if (instance != NULL && effectChain != NULL) { - if (!instance->effectChainAttached) + 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); + /* This frees the effect chain on the voice */ + FAudioVoice_SetEffectChain(instance->handle, NULL); } - for (i = 0; i < effectChain->fAudioEffectChain.EffectCount; i += 1) + FAudioEffectChain* fAudioEffectChain = FAudioGMS_INTERNAL_CreateFAudioEffectChain(effectChain); + FAudio_CreateSubmixVoice( + device->handle, + &instance->effectVoice, + 1, /* FIXME: is this correct? */ + device->deviceDetails.OutputFormat.Format.nSamplesPerSec, + 0, + 0, + NULL, + 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; + + for (i = 0; i < effectChain->effectCount; i += 1) { uint32_t parametersSize; void *parameters; @@ -1526,24 +1585,15 @@ void FAudioGMS_SoundInstance_SetEffectChain(double soundInstanceID, double effec instance->handle, &instance->effectSends); - /* TODO: move this to a different API call */ - float *outputMatrix = instance->dspSettings.pMatrixCoefficients; + FAudioGMS_INTERNAL_SoundInstance_SetEffectGain(instance, effectGain); - outputMatrix[0] = effectGain; - if (instance->dspSettings.SrcChannelCount == 2) + /* all the effect parameters are copied to the voice so we free here */ + for (i = 0; i < effectChain->effectCount; i += 1) { - outputMatrix[1] = effectGain; + FAPOBase_Release((FAPOBase*)fAudioEffectChain->pEffectDescriptors[i].pEffect); } - - FAudioVoice_SetOutputMatrix( - instance->handle, - instance->effectVoice, - instance->dspSettings.SrcChannelCount, - 1, - outputMatrix, - 0); - - instance->effectGain = effectGain; + SDL_free(fAudioEffectChain->pEffectDescriptors); + SDL_free(fAudioEffectChain); } } @@ -1555,14 +1605,8 @@ static void FAudioGMS_INTERNAL_EffectChain_Destroy(FAudioGMS_EffectChain *effect 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); } } diff --git a/src/FAudioGMS.h b/src/FAudioGMS.h index c865df3..56d0dd9 100644 --- a/src/FAudioGMS.h +++ b/src/FAudioGMS.h @@ -93,7 +93,12 @@ FAUDIOGMSAPI void FAudioGMS_EffectChain_AddReverb( ); FAUDIOGMSAPI void FAudioGMS_EffectChain_Destroy(double effectChainID); +/* + * NOTE: Any changes to the effect chain will NOT apply after this is set! + * You MUST call SetEffectChain again if you make changes to the effect chain parameters! + */ FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetEffectChain(double soundInstanceID, double effectChainID, double effectGain); +FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetEffectGain(double soundInstanceID, double effectGain); FAUDIOGMSAPI void FAudioGMS_SetListenerPosition(double x, double y, double z);