aboutsummaryrefslogtreecommitdiffstats
path: root/Alc/mixer_inc.c
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2017-03-11 18:04:06 -0800
committerChris Robinson <[email protected]>2017-03-11 18:04:06 -0800
commit96aaab93662be289d3b2c5312ae50502afa8d221 (patch)
treec270633e689c7a64edaea8a6c15305197b435ced /Alc/mixer_inc.c
parentfeffe1e81a155ded0bcdb519a1a126fd8e908baa (diff)
Rework HRTF coefficient fading
This improves fading between HRIRs as sources pan around. In particular, it improves the issue with individual coefficients having various rounding errors in the stepping values, as well as issues with interpolating delay values. It does this by doing two mixing passes for each source. First using the last coefficients that fade to silence, and then again using the new coefficients that fade from silence. When added together, it creates a linear fade from one to the other. Additionally, the gain is applied separately so the individual coefficients don't step with rounding errors. Although this does increase CPU cost since it's doing two mixes per source, each mix is a bit cheaper now since the stepping is simplified to a single gain value, and the overall quality is improved.
Diffstat (limited to 'Alc/mixer_inc.c')
-rw-r--r--Alc/mixer_inc.c81
1 files changed, 13 insertions, 68 deletions
diff --git a/Alc/mixer_inc.c b/Alc/mixer_inc.c
index 8215743e..b42b0fd3 100644
--- a/Alc/mixer_inc.c
+++ b/Alc/mixer_inc.c
@@ -12,84 +12,27 @@
#define MAX_UPDATE_SAMPLES 128
-static inline void ApplyCoeffsStep(ALsizei Offset, ALfloat (*restrict Values)[2],
- const ALsizei irSize,
- ALfloat (*restrict Coeffs)[2],
- const ALfloat (*restrict CoeffStep)[2],
- ALfloat left, ALfloat right);
static inline void ApplyCoeffs(ALsizei Offset, ALfloat (*restrict Values)[2],
const ALsizei irSize,
- ALfloat (*restrict Coeffs)[2],
+ const ALfloat (*restrict Coeffs)[2],
ALfloat left, ALfloat right);
void MixHrtf(ALfloat *restrict LeftOut, ALfloat *restrict RightOut,
- const ALfloat *data, ALsizei Counter, ALsizei Offset, ALsizei OutPos,
- const ALsizei IrSize, const MixHrtfParams *hrtfparams, HrtfState *hrtfstate,
+ const ALfloat *data, ALsizei Offset, ALsizei OutPos,
+ const ALsizei IrSize, MixHrtfParams *hrtfparams, HrtfState *hrtfstate,
ALsizei BufferSize)
{
- ALfloat (*Coeffs)[2] = hrtfparams->Current->Coeffs;
+ const ALfloat (*Coeffs)[2] = hrtfparams->Current->Coeffs;
ALsizei Delay[2] = { hrtfparams->Current->Delay[0], hrtfparams->Current->Delay[1] };
- ALfloat out[MAX_UPDATE_SAMPLES][2];
+ ALfloat gainstep = hrtfparams->GainStep;
+ ALfloat gain = hrtfparams->Gain;
ALfloat left, right;
- ALsizei minsize;
ALsizei pos, i;
- pos = 0;
- if(Counter == 0)
- goto skip_stepping;
-
- minsize = minu(BufferSize, Counter);
- while(pos < minsize)
- {
- ALsizei todo = mini(minsize-pos, MAX_UPDATE_SAMPLES);
-
- for(i = 0;i < todo;i++)
- {
- hrtfstate->History[Offset&HRTF_HISTORY_MASK] = data[pos++];
- left = lerp(hrtfstate->History[(Offset-(Delay[0]>>HRTFDELAY_BITS))&HRTF_HISTORY_MASK],
- hrtfstate->History[(Offset-(Delay[0]>>HRTFDELAY_BITS)-1)&HRTF_HISTORY_MASK],
- (Delay[0]&HRTFDELAY_MASK)*(1.0f/HRTFDELAY_FRACONE));
- right = lerp(hrtfstate->History[(Offset-(Delay[1]>>HRTFDELAY_BITS))&HRTF_HISTORY_MASK],
- hrtfstate->History[(Offset-(Delay[1]>>HRTFDELAY_BITS)-1)&HRTF_HISTORY_MASK],
- (Delay[1]&HRTFDELAY_MASK)*(1.0f/HRTFDELAY_FRACONE));
-
- Delay[0] += hrtfparams->Steps.Delay[0];
- Delay[1] += hrtfparams->Steps.Delay[1];
-
- hrtfstate->Values[(Offset+IrSize)&HRIR_MASK][0] = 0.0f;
- hrtfstate->Values[(Offset+IrSize)&HRIR_MASK][1] = 0.0f;
- Offset++;
-
- ApplyCoeffsStep(Offset, hrtfstate->Values, IrSize, Coeffs, hrtfparams->Steps.Coeffs, left, right);
- out[i][0] = hrtfstate->Values[Offset&HRIR_MASK][0];
- out[i][1] = hrtfstate->Values[Offset&HRIR_MASK][1];
- }
-
- for(i = 0;i < todo;i++)
- LeftOut[OutPos+i] += out[i][0];
- for(i = 0;i < todo;i++)
- RightOut[OutPos+i] += out[i][1];
- OutPos += todo;
- }
-
- if(pos == Counter)
- {
- *hrtfparams->Current = *hrtfparams->Target;
- Delay[0] = hrtfparams->Target->Delay[0];
- Delay[1] = hrtfparams->Target->Delay[1];
- }
- else
- {
- hrtfparams->Current->Delay[0] = Delay[0];
- hrtfparams->Current->Delay[1] = Delay[1];
- }
-
-skip_stepping:
- Delay[0] >>= HRTFDELAY_BITS;
- Delay[1] >>= HRTFDELAY_BITS;
- while(pos < BufferSize)
+ for(pos = 0;pos < BufferSize;)
{
+ ALfloat out[MAX_UPDATE_SAMPLES][2];
ALsizei todo = mini(BufferSize-pos, MAX_UPDATE_SAMPLES);
for(i = 0;i < todo;i++)
@@ -103,8 +46,9 @@ skip_stepping:
Offset++;
ApplyCoeffs(Offset, hrtfstate->Values, IrSize, Coeffs, left, right);
- out[i][0] = hrtfstate->Values[Offset&HRIR_MASK][0];
- out[i][1] = hrtfstate->Values[Offset&HRIR_MASK][1];
+ out[i][0] = hrtfstate->Values[Offset&HRIR_MASK][0]*gain;
+ out[i][1] = hrtfstate->Values[Offset&HRIR_MASK][1]*gain;
+ gain += gainstep;
}
for(i = 0;i < todo;i++)
@@ -113,11 +57,12 @@ skip_stepping:
RightOut[OutPos+i] += out[i][1];
OutPos += todo;
}
+ hrtfparams->Gain = gain;
}
void MixDirectHrtf(ALfloat *restrict LeftOut, ALfloat *restrict RightOut,
const ALfloat *data, ALsizei Offset, const ALsizei IrSize,
- ALfloat (*restrict Coeffs)[2], ALfloat (*restrict Values)[2],
+ const ALfloat (*restrict Coeffs)[2], ALfloat (*restrict Values)[2],
ALsizei BufferSize)
{
ALfloat out[MAX_UPDATE_SAMPLES][2];