refactor effect chains to use a single voice

main
cosmonaut 2021-11-16 23:06:44 -08:00
parent 4e1f53ce03
commit 6d8c80064c
2 changed files with 72 additions and 129 deletions

Binary file not shown.

View File

@ -155,7 +155,9 @@ typedef union FAudioGMS_EffectParameters
typedef struct FAudioGMS_EffectChain
{
uint32_t id;
uint32_t effectCount;
FAudioEffectChain fAudioEffectChain;
FAudioSubmixVoice *effectVoice;
FAudioVoiceSends effectSends;
FAudioGMS_EffectType *effectTypes; /* length equal to effectCount */
union FAudioGMS_EffectParameters *effectParameters; /* length equal to effectCount */
} FAudioGMS_EffectChain;
@ -174,8 +176,6 @@ typedef struct FAudioGMS_Voice
uint8_t effectChainAttached;
FAudioGMS_EffectChain *effectChain;
FAudioSubmixVoice *effectVoice;
FAudioVoiceSends effectSends;
float effectGain;
} FAudioGMS_Voice;
@ -381,7 +381,7 @@ static void FAudioGMS_INTERNAL_OnBufferEndCallback(
{
/* If we have active reverb we don't want to clean up until the decay time is over
*/
for (i = 0; i < instance->voice.effectChain->effectCount; i += 1)
for (i = 0; i < instance->voice.effectChain->fAudioEffectChain.EffectCount; i += 1)
{
if (instance->voice.effectChain->effectTypes[i] == EffectType_Reverb)
{
@ -485,9 +485,6 @@ void FAudioGMS_Init(double spatialDistanceScale, double timestep)
device->fauxMasteringVoice.effectChainAttached = 0;
device->fauxMasteringVoice.effectGain = 0;
device->fauxMasteringVoice.effectVoice = NULL;
device->fauxMasteringVoice.effectSends.SendCount = 0;
device->fauxMasteringVoice.effectSends.pSends = NULL;
device->spatialDistanceScale = spatialDistanceScale;
@ -760,7 +757,6 @@ static FAudioGMS_SoundInstance *FAudioGMS_INTERNAL_SoundInstance_Init(
instance->voice.effectChainAttached = 0;
instance->voice.effectChain = NULL;
instance->voice.effectVoice = NULL;
instance->voice.effectGain = 0;
instance->lowPassFilter = 0.0f;
@ -1580,12 +1576,6 @@ static void FAudioGMS_INTERNAL_SoundInstance_Destroy(FAudioGMS_SoundInstance *in
IdStack_Push(&device->soundInstanceIndexStack, instance->id);
FAudioGMS_INTERNAL_SoundInstance_Stop(instance);
if (instance->voice.effectChainAttached)
{
FAudioVoice_DestroyVoice(instance->voice.effectVoice);
SDL_free(instance->voice.effectSends.pSends);
}
SDL_free(instance->voice.sends.pSends);
FAudioVoice_DestroyVoice(instance->voice.handle);
@ -1651,7 +1641,6 @@ double FAudioGMS_EffectChain_Create()
RETURN_ON_NULL_DEVICE(-1.0)
FAudioGMS_EffectChain *effectChain = SDL_malloc(sizeof(FAudioGMS_EffectChain));
effectChain->effectCount = 0;
effectChain->effectTypes = NULL;
effectChain->effectParameters = NULL;
@ -1671,6 +1660,25 @@ double FAudioGMS_EffectChain_Create()
device->effectChains[effectChain->id] = effectChain;
effectChain->fAudioEffectChain.EffectCount = 0;
effectChain->fAudioEffectChain.pEffectDescriptors = NULL;
effectChain->effectSends.SendCount = 1;
effectChain->effectSends.pSends = SDL_malloc(sizeof(FAudioSendDescriptor));
effectChain->effectSends.pSends[0].Flags = 0;
effectChain->effectSends.pSends[0].pOutputVoice = device->masteringVoice;
FAudio_CreateSubmixVoice(
device->handle,
&effectChain->effectVoice,
1, /* FIXME: is this correct? */
device->deviceDetails.OutputFormat.Format.nSamplesPerSec,
0,
0,
&effectChain->effectSends,
&effectChain->fAudioEffectChain);
return effectChain->id;
}
@ -1678,20 +1686,53 @@ static void FAudioGMS_INTERNAL_EffectChain_AddReverb(
FAudioGMS_EffectChain *effectChain,
FAudioFXReverbParameters *reverbParameters)
{
effectChain->effectCount += 1;
uint32_t effectIndex;
effectChain->fAudioEffectChain.EffectCount += 1;
effectChain->fAudioEffectChain.pEffectDescriptors = SDL_realloc(
effectChain->fAudioEffectChain.pEffectDescriptors,
effectChain->fAudioEffectChain.EffectCount * sizeof(FAudioEffectDescriptor));
effectIndex = effectChain->fAudioEffectChain.EffectCount - 1;
effectChain->effectTypes = SDL_realloc(
effectChain->effectTypes,
effectChain->effectCount * sizeof(FAudioGMS_EffectType));
effectChain->effectTypes[effectChain->effectCount - 1] = EffectType_Reverb;
effectChain->fAudioEffectChain.EffectCount * sizeof(FAudioGMS_EffectType));
effectChain->effectTypes[effectIndex] = EffectType_Reverb;
effectChain->effectParameters = SDL_realloc(
effectChain->effectParameters,
effectChain->effectCount * sizeof(FAudioGMS_EffectParameters));
effectChain->fAudioEffectChain.EffectCount * sizeof(FAudioGMS_EffectParameters));
SDL_memcpy(
&effectChain->effectParameters[effectChain->effectCount - 1],
&effectChain->effectParameters[effectIndex],
reverbParameters,
sizeof(FAudioFXReverbParameters));
FAPO *reverb;
FAudioCreateReverb(&reverb, 0);
FAudioEffectDescriptor *reverbDescriptor =
&effectChain->fAudioEffectChain.pEffectDescriptors[effectIndex];
reverbDescriptor->InitialState = 1;
reverbDescriptor->OutputChannels =
device->deviceDetails.OutputFormat.Format.nChannels == 6 ? 6 : 1;
reverbDescriptor->pEffect = reverb;
FAudioVoice_SetEffectChain(effectChain->effectVoice, &effectChain->fAudioEffectChain);
FAudioVoice_SetEffectParameters(
effectChain->effectVoice,
effectIndex,
&effectChain->effectParameters[effectIndex].reverbParameters,
sizeof(FAudioFXReverbParameters),
0);
/* All the effect parameters are copied to the voice so we free here */
FAPOBase_Release((FAPOBase*)reverb);
}
void FAudioGMS_EffectChain_AddDefaultReverb(double effectChainID)
@ -1788,7 +1829,7 @@ static void FAudioGMS_INTERNAL_Voice_SetEffectGain(FAudioGMS_Voice *voice, float
{
if (voice->effectChainAttached)
{
float *outputMatrix = SDL_stack_alloc(float, voice->effectSends.SendCount);
float *outputMatrix = SDL_stack_alloc(float, voice->handle->outputChannels);
outputMatrix[0] = effectGain;
if (voice->handle->outputChannels == 2)
@ -1798,7 +1839,7 @@ static void FAudioGMS_INTERNAL_Voice_SetEffectGain(FAudioGMS_Voice *voice, float
FAudioVoice_SetOutputMatrix(
voice->handle,
voice->effectVoice,
voice->effectChain->effectVoice,
voice->handle->outputChannels,
1,
outputMatrix,
@ -1822,108 +1863,17 @@ void FAudioGMS_SoundInstance_SetEffectGain(double soundInstanceID, double effect
}
}
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 NULL;
}
}
return fAudioEffectChain;
}
static void FAudioGMS_INTERNAL_SetEffectChain(
FAudioGMS_Voice *voice,
FAudioGMS_EffectChain *effectChain,
float effectGain)
{
uint32_t i;
if (voice->effectChainAttached)
{
/* This frees the effect chain on the voice */
FAudioVoice_SetEffectChain(voice->effectVoice, NULL);
SDL_free(voice->effectSends.pSends);
}
else
if (!voice->effectChainAttached)
{
voice->sends.SendCount = 2;
voice->sends.pSends = SDL_realloc(voice->sends.pSends, 2 * sizeof(FAudioSendDescriptor));
}
voice->effectChain = effectChain;
FAudioEffectChain *fAudioEffectChain = FAudioGMS_INTERNAL_CreateFAudioEffectChain(effectChain);
voice->effectSends.SendCount = 1;
voice->effectSends.pSends = SDL_malloc(sizeof(FAudioSendDescriptor));
voice->effectSends.pSends[0].Flags = 0;
if (voice == &device->fauxMasteringVoice)
{
voice->effectSends.pSends[0].pOutputVoice = device->masteringVoice;
}
else
{
voice->effectSends.pSends[0].pOutputVoice = device->fauxMasteringVoice.handle;
}
FAudio_CreateSubmixVoice(
device->handle,
&voice->effectVoice,
1, /* FIXME: is this correct? */
device->deviceDetails.OutputFormat.Format.nSamplesPerSec,
0,
0,
&voice->effectSends,
fAudioEffectChain);
/* Copy the effect params */
for (i = 0; i < effectChain->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(voice->effectVoice, i, parameters, parametersSize, 0);
}
/* Set the instance voice to go through both faux mastering and effect voice
* for wet/dry */
voice->sends.pSends[0].Flags = 0;
@ -1936,21 +1886,13 @@ static void FAudioGMS_INTERNAL_SetEffectChain(
voice->sends.pSends[0].pOutputVoice = device->fauxMasteringVoice.handle;
}
voice->sends.pSends[1].Flags = 0;
voice->sends.pSends[1].pOutputVoice = voice->effectVoice;
voice->sends.pSends[1].pOutputVoice = effectChain->effectVoice;
voice->effectChain = effectChain;
voice->effectChainAttached = 1;
FAudioVoice_SetOutputVoices(voice->handle, &voice->sends);
FAudioGMS_INTERNAL_Voice_SetEffectGain(voice, effectGain);
/* All the effect parameters are copied to the voice so we free here */
for (i = 0; i < effectChain->effectCount; i += 1)
{
FAPOBase_Release((FAPOBase *)fAudioEffectChain->pEffectDescriptors[i].pEffect);
}
SDL_free(fAudioEffectChain->pEffectDescriptors);
SDL_free(fAudioEffectChain);
}
void FAudioGMS_SoundInstance_SetEffectChain(
@ -2000,6 +1942,7 @@ static void FAudioGMS_INTERNAL_EffectChain_Destroy(FAudioGMS_EffectChain *effect
device->effectChains[effectChain->id] = NULL;
IdStack_Push(&device->effectChainIndexStack, effectChain->id);
SDL_free(effectChain->fAudioEffectChain.pEffectDescriptors);
SDL_free(effectChain->effectParameters);
SDL_free(effectChain->effectTypes);
SDL_free(effectChain);
@ -2021,7 +1964,7 @@ void FAudioGMS_EffectChain_Destroy(double effectChainID)
void FAudioGMS_Update()
{
RETURN_ON_NULL_DEVICE()
uint32_t i, j;
uint32_t i;
for (i = 0; i < device->soundInstanceCount; i += 1)
{