Fade HRTF coefficients over 64 samples at most

This greatly improves HRTF performance since the dual-mix only applies to the
64-sample coefficient transition. So rather than doubling the full mix, it only
doubles 64 samples out of the full mix.
This commit is contained in:
Chris Robinson 2017-04-28 10:05:57 -07:00
parent bf138fb4ea
commit dc25370063

View File

@ -277,6 +277,7 @@ ALboolean MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALsizei
ALsizei OutPos;
ALsizei IrSize;
bool isplaying;
bool firstpass;
ALsizei chan;
ALsizei send;
@ -296,7 +297,9 @@ ALboolean MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALsizei
Resample_copy32_C : voice->Resampler);
Counter = (voice->Flags&VOICE_IS_MOVING) ? SamplesToDo : 0;
firstpass = true;
OutPos = 0;
do {
ALsizei SrcBufferSize, DstBufferSize;
@ -485,6 +488,7 @@ ALboolean MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALsizei
else
{
MixHrtfParams hrtfparams;
ALsizei fademix = 0;
int lidx, ridx;
lidx = GetChannelIdxByName(Device->RealOut, FrontLeft);
@ -493,70 +497,94 @@ ALboolean MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALsizei
if(!Counter)
{
/* No fading, just overwrite the old HRTF params. */
parms->Hrtf.Old = parms->Hrtf.Target;
hrtfparams.Coeffs = SAFE_CONST(ALfloat2*,parms->Hrtf.Target.Coeffs);
hrtfparams.Delay[0] = parms->Hrtf.Target.Delay[0];
hrtfparams.Delay[1] = parms->Hrtf.Target.Delay[1];
hrtfparams.Gain = parms->Hrtf.Target.Gain;
hrtfparams.GainStep = 0.0f;
}
else if(!(parms->Hrtf.Old.Gain > GAIN_SILENCE_THRESHOLD))
{
/* The old HRTF params are silent, so overwrite the old
* coefficients with the new, and reset the old gain to
* 0. The future mix will then fade from silence.
*/
parms->Hrtf.Old = parms->Hrtf.Target;
parms->Hrtf.Old.Gain = 0.0f;
}
else if(firstpass && parms->Hrtf.Old.Gain > GAIN_SILENCE_THRESHOLD)
{
HrtfState backupstate = parms->Hrtf.State;
ALfloat gain;
/* Fade between the coefficients over 64 samples. */
fademix = mini(DstBufferSize, 64);
/* The old coefficients need to fade to silence
* completely since they'll be replaced after this mix.
*/
hrtfparams.Coeffs = SAFE_CONST(ALfloat2*,parms->Hrtf.Old.Coeffs);
hrtfparams.Delay[0] = parms->Hrtf.Old.Delay[0];
hrtfparams.Delay[1] = parms->Hrtf.Old.Delay[1];
hrtfparams.Gain = parms->Hrtf.Old.Gain;
hrtfparams.GainStep = -hrtfparams.Gain / (ALfloat)fademix;
MixHrtfSamples(
voice->Direct.Buffer[lidx], voice->Direct.Buffer[ridx],
samples, voice->Offset, OutPos, IrSize, &hrtfparams,
&parms->Hrtf.State, DstBufferSize
&backupstate, fademix
);
}
else
{
ALfloat gain;
/* The old coefficients need to fade to silence
* completely since they'll be replaced after the mix.
* So it needs to fade out over DstBufferSize instead
* of Counter.
*
* Don't bother with the fade out when starting from
* silence.
*/
if(parms->Hrtf.Old.Gain > GAIN_SILENCE_THRESHOLD)
{
HrtfState backupstate = parms->Hrtf.State;
hrtfparams.Coeffs = SAFE_CONST(ALfloat2*,parms->Hrtf.Old.Coeffs);
hrtfparams.Delay[0] = parms->Hrtf.Old.Delay[0];
hrtfparams.Delay[1] = parms->Hrtf.Old.Delay[1];
hrtfparams.Gain = parms->Hrtf.Old.Gain;
hrtfparams.GainStep = -hrtfparams.Gain /
(ALfloat)DstBufferSize;
MixHrtfSamples(
voice->Direct.Buffer[lidx], voice->Direct.Buffer[ridx],
samples, voice->Offset, OutPos, IrSize, &hrtfparams,
&backupstate, DstBufferSize
);
}
/* The new coefficients need to fade in completely
* since they're replacing the old ones. To keep the
* source gain fading consistent, interpolate between
* the old and new target gain given how much of the
* fade time this mix handles.
* gain fading consistent, interpolate between the old
* and new target gains given how much of the fade time
* this mix handles.
*/
gain = lerp(parms->Hrtf.Old.Gain, parms->Hrtf.Target.Gain,
(ALfloat)DstBufferSize/Counter);
minf(1.0f, (ALfloat)fademix/Counter));
hrtfparams.Coeffs = SAFE_CONST(ALfloat2*,parms->Hrtf.Target.Coeffs);
hrtfparams.Delay[0] = parms->Hrtf.Target.Delay[0];
hrtfparams.Delay[1] = parms->Hrtf.Target.Delay[1];
hrtfparams.Gain = 0.0f;
hrtfparams.GainStep = gain / (ALfloat)DstBufferSize;
hrtfparams.GainStep = gain / (ALfloat)fademix;
MixHrtfSamples(
voice->Direct.Buffer[lidx], voice->Direct.Buffer[ridx],
samples, voice->Offset, OutPos, IrSize, &hrtfparams,
&parms->Hrtf.State, DstBufferSize
&parms->Hrtf.State, fademix
);
/* Update the old parameters with the result. */
parms->Hrtf.Old = parms->Hrtf.Target;
if(DstBufferSize < Counter)
if(fademix < Counter)
parms->Hrtf.Old.Gain = hrtfparams.Gain;
}
if(fademix < DstBufferSize)
{
ALsizei todo = DstBufferSize - fademix;
ALfloat gain = parms->Hrtf.Target.Gain;
/* Interpolate the target gain if the gain fading lasts
* longer than this mix.
*/
if(Counter > DstBufferSize)
gain = lerp(parms->Hrtf.Old.Gain, gain,
(ALfloat)todo/(Counter-fademix));
hrtfparams.Coeffs = SAFE_CONST(ALfloat2*,parms->Hrtf.Target.Coeffs);
hrtfparams.Delay[0] = parms->Hrtf.Target.Delay[0];
hrtfparams.Delay[1] = parms->Hrtf.Target.Delay[1];
hrtfparams.Gain = parms->Hrtf.Old.Gain;
hrtfparams.GainStep = (gain - parms->Hrtf.Old.Gain) / (ALfloat)todo;
MixHrtfSamples(
voice->Direct.Buffer[lidx], voice->Direct.Buffer[ridx],
samples+fademix, voice->Offset+fademix, OutPos+fademix, IrSize,
&hrtfparams, &parms->Hrtf.State, todo
);
/* Store the interpolated gain or the final target gain
* depending if the fade is done.
*/
if(DstBufferSize < Counter)
parms->Hrtf.Old.Gain = gain;
else
parms->Hrtf.Old.Gain = parms->Hrtf.Target.Gain;
}
}
}
@ -589,6 +617,7 @@ ALboolean MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALsizei
OutPos += DstBufferSize;
voice->Offset += DstBufferSize;
Counter = maxi(DstBufferSize, Counter) - DstBufferSize;
firstpass = false;
/* Handle looping sources */
while(1)