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 typedef struct FAudioGMS_EffectChain
{ {
uint32_t id; uint32_t id;
uint32_t effectCount; FAudioEffectChain fAudioEffectChain;
FAudioSubmixVoice *effectVoice;
FAudioVoiceSends effectSends;
FAudioGMS_EffectType *effectTypes; /* length equal to effectCount */ FAudioGMS_EffectType *effectTypes; /* length equal to effectCount */
union FAudioGMS_EffectParameters *effectParameters; /* length equal to effectCount */ union FAudioGMS_EffectParameters *effectParameters; /* length equal to effectCount */
} FAudioGMS_EffectChain; } FAudioGMS_EffectChain;
@ -174,8 +176,6 @@ typedef struct FAudioGMS_Voice
uint8_t effectChainAttached; uint8_t effectChainAttached;
FAudioGMS_EffectChain *effectChain; FAudioGMS_EffectChain *effectChain;
FAudioSubmixVoice *effectVoice;
FAudioVoiceSends effectSends;
float effectGain; float effectGain;
} FAudioGMS_Voice; } FAudioGMS_Voice;
@ -375,13 +375,13 @@ static void FAudioGMS_INTERNAL_OnBufferEndCallback(
{ {
/* this is a callback so we don't want to immediately destroy and screw up data */ /* this is a callback so we don't want to immediately destroy and screw up data */
instance->destroyTimerActive = 1; instance->destroyTimerActive = 1;
instance->destroyTimer = 0; instance->destroyTimer = 0;
if (instance->voice.effectChainAttached) if (instance->voice.effectChainAttached)
{ {
/* If we have active reverb we don't want to clean up until the decay time is over /* 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) 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.effectChainAttached = 0;
device->fauxMasteringVoice.effectGain = 0; device->fauxMasteringVoice.effectGain = 0;
device->fauxMasteringVoice.effectVoice = NULL;
device->fauxMasteringVoice.effectSends.SendCount = 0;
device->fauxMasteringVoice.effectSends.pSends = NULL;
device->spatialDistanceScale = spatialDistanceScale; device->spatialDistanceScale = spatialDistanceScale;
@ -645,7 +642,7 @@ static void SetPanMatrixCoefficients(FAudioGMS_SoundInstance *instance)
} }
} }
static void FAudioGMS_INTERNAL_SoundInstance_ApplyPan(FAudioGMS_SoundInstance* instance) static void FAudioGMS_INTERNAL_SoundInstance_ApplyPan(FAudioGMS_SoundInstance* instance)
{ {
SetPanMatrixCoefficients(instance); SetPanMatrixCoefficients(instance);
@ -760,7 +757,6 @@ static FAudioGMS_SoundInstance *FAudioGMS_INTERNAL_SoundInstance_Init(
instance->voice.effectChainAttached = 0; instance->voice.effectChainAttached = 0;
instance->voice.effectChain = NULL; instance->voice.effectChain = NULL;
instance->voice.effectVoice = NULL;
instance->voice.effectGain = 0; instance->voice.effectGain = 0;
instance->lowPassFilter = 0.0f; instance->lowPassFilter = 0.0f;
@ -1580,12 +1576,6 @@ static void FAudioGMS_INTERNAL_SoundInstance_Destroy(FAudioGMS_SoundInstance *in
IdStack_Push(&device->soundInstanceIndexStack, instance->id); IdStack_Push(&device->soundInstanceIndexStack, instance->id);
FAudioGMS_INTERNAL_SoundInstance_Stop(instance); 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); SDL_free(instance->voice.sends.pSends);
FAudioVoice_DestroyVoice(instance->voice.handle); FAudioVoice_DestroyVoice(instance->voice.handle);
@ -1651,7 +1641,6 @@ 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->effectCount = 0;
effectChain->effectTypes = NULL; effectChain->effectTypes = NULL;
effectChain->effectParameters = NULL; effectChain->effectParameters = NULL;
@ -1671,6 +1660,25 @@ double FAudioGMS_EffectChain_Create()
device->effectChains[effectChain->id] = effectChain; 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; return effectChain->id;
} }
@ -1678,20 +1686,53 @@ static void FAudioGMS_INTERNAL_EffectChain_AddReverb(
FAudioGMS_EffectChain *effectChain, FAudioGMS_EffectChain *effectChain,
FAudioFXReverbParameters *reverbParameters) 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 = SDL_realloc(
effectChain->effectTypes, effectChain->effectTypes,
effectChain->effectCount * sizeof(FAudioGMS_EffectType)); effectChain->fAudioEffectChain.EffectCount * sizeof(FAudioGMS_EffectType));
effectChain->effectTypes[effectChain->effectCount - 1] = EffectType_Reverb;
effectChain->effectTypes[effectIndex] = EffectType_Reverb;
effectChain->effectParameters = SDL_realloc( effectChain->effectParameters = SDL_realloc(
effectChain->effectParameters, effectChain->effectParameters,
effectChain->effectCount * sizeof(FAudioGMS_EffectParameters)); effectChain->fAudioEffectChain.EffectCount * sizeof(FAudioGMS_EffectParameters));
SDL_memcpy( SDL_memcpy(
&effectChain->effectParameters[effectChain->effectCount - 1], &effectChain->effectParameters[effectIndex],
reverbParameters, reverbParameters,
sizeof(FAudioFXReverbParameters)); 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) void FAudioGMS_EffectChain_AddDefaultReverb(double effectChainID)
@ -1788,7 +1829,7 @@ static void FAudioGMS_INTERNAL_Voice_SetEffectGain(FAudioGMS_Voice *voice, float
{ {
if (voice->effectChainAttached) if (voice->effectChainAttached)
{ {
float *outputMatrix = SDL_stack_alloc(float, voice->effectSends.SendCount); float *outputMatrix = SDL_stack_alloc(float, voice->handle->outputChannels);
outputMatrix[0] = effectGain; outputMatrix[0] = effectGain;
if (voice->handle->outputChannels == 2) if (voice->handle->outputChannels == 2)
@ -1798,7 +1839,7 @@ static void FAudioGMS_INTERNAL_Voice_SetEffectGain(FAudioGMS_Voice *voice, float
FAudioVoice_SetOutputMatrix( FAudioVoice_SetOutputMatrix(
voice->handle, voice->handle,
voice->effectVoice, voice->effectChain->effectVoice,
voice->handle->outputChannels, voice->handle->outputChannels,
1, 1,
outputMatrix, 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( static void FAudioGMS_INTERNAL_SetEffectChain(
FAudioGMS_Voice *voice, FAudioGMS_Voice *voice,
FAudioGMS_EffectChain *effectChain, FAudioGMS_EffectChain *effectChain,
float effectGain) float effectGain)
{ {
uint32_t i; if (!voice->effectChainAttached)
if (voice->effectChainAttached)
{
/* This frees the effect chain on the voice */
FAudioVoice_SetEffectChain(voice->effectVoice, NULL);
SDL_free(voice->effectSends.pSends);
}
else
{ {
voice->sends.SendCount = 2; voice->sends.SendCount = 2;
voice->sends.pSends = SDL_realloc(voice->sends.pSends, 2 * sizeof(FAudioSendDescriptor)); 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 /* Set the instance voice to go through both faux mastering and effect voice
* for wet/dry */ * for wet/dry */
voice->sends.pSends[0].Flags = 0; 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[0].pOutputVoice = device->fauxMasteringVoice.handle;
} }
voice->sends.pSends[1].Flags = 0; 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; voice->effectChainAttached = 1;
FAudioVoice_SetOutputVoices(voice->handle, &voice->sends); FAudioVoice_SetOutputVoices(voice->handle, &voice->sends);
FAudioGMS_INTERNAL_Voice_SetEffectGain(voice, effectGain); 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( void FAudioGMS_SoundInstance_SetEffectChain(
@ -2000,6 +1942,7 @@ 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);
SDL_free(effectChain->fAudioEffectChain.pEffectDescriptors);
SDL_free(effectChain->effectParameters); SDL_free(effectChain->effectParameters);
SDL_free(effectChain->effectTypes); SDL_free(effectChain->effectTypes);
SDL_free(effectChain); SDL_free(effectChain);
@ -2021,7 +1964,7 @@ void FAudioGMS_EffectChain_Destroy(double effectChainID)
void FAudioGMS_Update() void FAudioGMS_Update()
{ {
RETURN_ON_NULL_DEVICE() RETURN_ON_NULL_DEVICE()
uint32_t i, j; uint32_t i;
for (i = 0; i < device->soundInstanceCount; i += 1) for (i = 0; i < device->soundInstanceCount; i += 1)
{ {