fix effect chain memory issues

mastering_effects
cosmonaut 2021-10-28 14:58:48 -07:00
parent b896704dc2
commit 97924093ee
2 changed files with 117 additions and 68 deletions

View File

@ -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);
}
}

View File

@ -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);