fix effect chain memory issues

main
cosmonaut 2021-10-28 14:58:48 -07:00
parent 8c26f79d28
commit 6cd6147961
2 changed files with 117 additions and 68 deletions

View File

@ -220,9 +220,9 @@ typedef union FAudioGMS_EffectParameters
typedef struct FAudioGMS_EffectChain typedef struct FAudioGMS_EffectChain
{ {
uint32_t id; uint32_t id;
FAudioEffectChain fAudioEffectChain; uint32_t effectCount;
FAudioGMS_EffectType *effectTypes; /* size equal to effect chain size */ FAudioGMS_EffectType *effectTypes; /* length equal to effectCount */
union FAudioGMS_EffectParameters *effectParameters; /* size equal to effect chain size */ union FAudioGMS_EffectParameters *effectParameters; /* length equal to effectCount */
} FAudioGMS_EffectChain; } FAudioGMS_EffectChain;
static const float SPEED_OF_SOUND = 343.5f; 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; device->soundInstances[instance->id] = NULL;
IdStack_Push(&device->soundInstanceIndexStack, instance->id); IdStack_Push(&device->soundInstanceIndexStack, instance->id);
FAudioGMS_INTERNAL_SoundInstance_Stop(instance); FAudioGMS_INTERNAL_SoundInstance_Stop(instance);
if (instance->effectChainAttached)
{
FAudioVoice_DestroyVoice(instance->effectVoice);
SDL_free(instance->effectSends.pSends);
}
FAudioVoice_DestroyVoice(instance->handle); FAudioVoice_DestroyVoice(instance->handle);
if (!instance->isStatic) if (!instance->isStatic)
{ {
SDL_free(instance->soundData.streamingSound.streamBuffer); SDL_free(instance->soundData.streamingSound.streamBuffer);
@ -1329,8 +1337,7 @@ double FAudioGMS_EffectChain_Create()
RETURN_ON_NULL_DEVICE(-1.0) RETURN_ON_NULL_DEVICE(-1.0)
FAudioGMS_EffectChain* effectChain = SDL_malloc(sizeof(FAudioGMS_EffectChain)); FAudioGMS_EffectChain* effectChain = SDL_malloc(sizeof(FAudioGMS_EffectChain));
effectChain->fAudioEffectChain.EffectCount = 0; effectChain->effectCount = 0;
effectChain->fAudioEffectChain.pEffectDescriptors = NULL;
effectChain->effectTypes = NULL; effectChain->effectTypes = NULL;
effectChain->effectParameters = NULL; effectChain->effectParameters = NULL;
@ -1353,23 +1360,13 @@ double FAudioGMS_EffectChain_Create()
static void FAudioGMS_INTERNAL_EffectChain_AddReverb(FAudioGMS_EffectChain* effectChain, FAudioFXReverbParameters *reverbParameters) static void FAudioGMS_INTERNAL_EffectChain_AddReverb(FAudioGMS_EffectChain* effectChain, FAudioFXReverbParameters *reverbParameters)
{ {
FAPO* reverb; effectChain->effectCount += 1;
FAudioCreateReverb(&reverb, 0);
effectChain->fAudioEffectChain.EffectCount += 1; effectChain->effectTypes = SDL_realloc(effectChain->effectTypes, effectChain->effectCount * sizeof(FAudioGMS_EffectType));
effectChain->fAudioEffectChain.pEffectDescriptors = SDL_realloc(effectChain->fAudioEffectChain.pEffectDescriptors, effectChain->fAudioEffectChain.EffectCount * sizeof(FAudioEffectDescriptor)); effectChain->effectTypes[effectChain->effectCount - 1] = EffectType_Reverb;
FAudioEffectDescriptor* reverbDescriptor = &effectChain->fAudioEffectChain.pEffectDescriptors[effectChain->fAudioEffectChain.EffectCount - 1]; effectChain->effectParameters = SDL_realloc(effectChain->effectParameters, effectChain->effectCount * sizeof(FAudioGMS_EffectParameters));
SDL_memcpy(&effectChain->effectParameters[effectChain->effectCount - 1], reverbParameters, sizeof(FAudioFXReverbParameters));
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) 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) void FAudioGMS_SoundInstance_SetEffectChain(double soundInstanceID, double effectChainID, double effectGain)
{ {
RETURN_ON_NULL_DEVICE() RETURN_ON_NULL_DEVICE()
@ -1469,36 +1530,34 @@ void FAudioGMS_SoundInstance_SetEffectChain(double soundInstanceID, double effec
if (instance != NULL && effectChain != NULL) if (instance != NULL && effectChain != NULL)
{ {
if (!instance->effectChainAttached) if (instance->effectChainAttached)
{ {
FAudio_CreateSubmixVoice( /* This frees the effect chain on the voice */
device->handle, FAudioVoice_SetEffectChain(instance->handle, NULL);
&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) 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; uint32_t parametersSize;
void *parameters; void *parameters;
@ -1526,24 +1585,15 @@ void FAudioGMS_SoundInstance_SetEffectChain(double soundInstanceID, double effec
instance->handle, instance->handle,
&instance->effectSends); &instance->effectSends);
/* TODO: move this to a different API call */ FAudioGMS_INTERNAL_SoundInstance_SetEffectGain(instance, effectGain);
float *outputMatrix = instance->dspSettings.pMatrixCoefficients;
outputMatrix[0] = effectGain; /* all the effect parameters are copied to the voice so we free here */
if (instance->dspSettings.SrcChannelCount == 2) for (i = 0; i < effectChain->effectCount; i += 1)
{ {
outputMatrix[1] = effectGain; FAPOBase_Release((FAPOBase*)fAudioEffectChain->pEffectDescriptors[i].pEffect);
} }
SDL_free(fAudioEffectChain->pEffectDescriptors);
FAudioVoice_SetOutputMatrix( SDL_free(fAudioEffectChain);
instance->handle,
instance->effectVoice,
instance->dspSettings.SrcChannelCount,
1,
outputMatrix,
0);
instance->effectGain = effectGain;
} }
} }
@ -1555,14 +1605,8 @@ static void FAudioGMS_INTERNAL_EffectChain_Destroy(FAudioGMS_EffectChain *effect
device->effectChains[effectChain->id] = NULL; device->effectChains[effectChain->id] = NULL;
IdStack_Push(&device->effectChainIndexStack, effectChain->id); 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->effectParameters);
SDL_free(effectChain->effectTypes); SDL_free(effectChain->effectTypes);
SDL_free(effectChain->fAudioEffectChain.pEffectDescriptors);
SDL_free(effectChain); SDL_free(effectChain);
} }
} }

View File

@ -93,7 +93,12 @@ FAUDIOGMSAPI void FAudioGMS_EffectChain_AddReverb(
); );
FAUDIOGMSAPI void FAudioGMS_EffectChain_Destroy(double effectChainID); 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_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); FAUDIOGMSAPI void FAudioGMS_SetListenerPosition(double x, double y, double z);