forked from MoonsideGames/FAudioGMS
refactor effect chains to use a single voice
parent
4e1f53ce03
commit
6d8c80064c
BIN
gamemaker/extensions/FAudioGMS/FAudioGMS.dll (Stored with Git LFS)
BIN
gamemaker/extensions/FAudioGMS/FAudioGMS.dll (Stored with Git LFS)
Binary file not shown.
197
src/FAudioGMS.c
197
src/FAudioGMS.c
|
@ -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;
|
||||
|
||||
|
@ -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 */
|
||||
instance->destroyTimerActive = 1;
|
||||
instance->destroyTimer = 0;
|
||||
instance->destroyTimer = 0;
|
||||
|
||||
if (instance->voice.effectChainAttached)
|
||||
{
|
||||
/* 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;
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue