diff options
author | Chris Robinson <[email protected]> | 2017-05-03 03:29:21 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2017-05-03 03:29:21 -0700 |
commit | 444e9563b357b4e2af0d428afac9f87596aba9a6 (patch) | |
tree | 1fc1f56f2a748332ad21b482895ea1fff3f7f9f7 | |
parent | 4e5c4b8e01060bb34c58480895e70a0529d8a55e (diff) |
Add a mixing function to blend HRIRs
This is a bit more efficient than calling the normal HRTF mixing function
twice, and helps solve the problem of the values generated from convolution not
being consistent with the new HRIR.
-rw-r--r-- | Alc/mixer.c | 40 | ||||
-rw-r--r-- | Alc/mixer_c.c | 1 | ||||
-rw-r--r-- | Alc/mixer_defs.h | 15 | ||||
-rw-r--r-- | Alc/mixer_inc.c | 59 | ||||
-rw-r--r-- | Alc/mixer_neon.c | 1 | ||||
-rw-r--r-- | Alc/mixer_sse.c | 1 | ||||
-rw-r--r-- | OpenAL32/Include/alu.h | 5 |
7 files changed, 95 insertions, 27 deletions
diff --git a/Alc/mixer.c b/Alc/mixer.c index a7adf9b6..6eaf4caf 100644 --- a/Alc/mixer.c +++ b/Alc/mixer.c @@ -53,6 +53,7 @@ enum Resampler ResamplerDefault = LinearResampler; static MixerFunc MixSamples = Mix_C; static HrtfMixerFunc MixHrtfSamples = MixHrtf_C; +HrtfMixerBlendFunc MixHrtfBlendSamples = MixHrtfBlend_C; MixerFunc SelectMixer(void) { @@ -90,10 +91,22 @@ static inline HrtfMixerFunc SelectHrtfMixer(void) if((CPUCapFlags&CPU_CAP_SSE)) return MixHrtf_SSE; #endif - return MixHrtf_C; } +static inline HrtfMixerBlendFunc SelectHrtfBlendMixer(void) +{ +#ifdef HAVE_NEON + if((CPUCapFlags&CPU_CAP_NEON)) + return MixHrtfBlend_Neon; +#endif +#ifdef HAVE_SSE + if((CPUCapFlags&CPU_CAP_SSE)) + return MixHrtfBlend_SSE; +#endif + return MixHrtfBlend_C; +} + ResamplerFunc SelectResampler(enum Resampler resampler) { switch(resampler) @@ -174,6 +187,7 @@ void aluInitMixer(void) } } + MixHrtfBlendSamples = SelectHrtfBlendMixer(); MixHrtfSamples = SelectHrtfMixer(); MixSamples = SelectMixer(); } @@ -511,25 +525,10 @@ ALboolean MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALsizei } else if(firstpass) { - 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, - &backupstate, fademix - ); + fademix = mini(DstBufferSize, 64); /* The new coefficients need to fade in completely * since they're replacing the old ones. To keep the @@ -544,10 +543,11 @@ ALboolean MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALsizei hrtfparams.Delay[1] = parms->Hrtf.Target.Delay[1]; hrtfparams.Gain = 0.0f; hrtfparams.GainStep = gain / (ALfloat)fademix; - MixHrtfSamples( + + MixHrtfBlendSamples( voice->Direct.Buffer[lidx], voice->Direct.Buffer[ridx], - samples, voice->Offset, OutPos, IrSize, &hrtfparams, - &parms->Hrtf.State, fademix + samples, voice->Offset, OutPos, IrSize, &parms->Hrtf.Old, + &hrtfparams, &parms->Hrtf.State, fademix ); /* Update the old parameters with the result. */ parms->Hrtf.Old = parms->Hrtf.Target; diff --git a/Alc/mixer_c.c b/Alc/mixer_c.c index f0db2ebc..87f2fe90 100644 --- a/Alc/mixer_c.c +++ b/Alc/mixer_c.c @@ -146,6 +146,7 @@ static inline void ApplyCoeffs(ALsizei Offset, ALfloat (*restrict Values)[2], } #define MixHrtf MixHrtf_C +#define MixHrtfBlend MixHrtfBlend_C #define MixDirectHrtf MixDirectHrtf_C #include "mixer_inc.c" #undef MixHrtf diff --git a/Alc/mixer_defs.h b/Alc/mixer_defs.h index dce748c5..462d6179 100644 --- a/Alc/mixer_defs.h +++ b/Alc/mixer_defs.h @@ -24,6 +24,11 @@ void MixHrtf_C(ALfloat *restrict LeftOut, ALfloat *restrict RightOut, const ALfloat *data, ALsizei Offset, ALsizei OutPos, const ALsizei IrSize, struct MixHrtfParams *hrtfparams, struct HrtfState *hrtfstate, ALsizei BufferSize); +void MixHrtfBlend_C(ALfloat *restrict LeftOut, ALfloat *restrict RightOut, + const ALfloat *data, ALsizei Offset, ALsizei OutPos, + const ALsizei IrSize, const HrtfParams *oldparams, + MixHrtfParams *newparams, HrtfState *hrtfstate, + ALsizei BufferSize); void MixDirectHrtf_C(ALfloat *restrict LeftOut, ALfloat *restrict RightOut, const ALfloat *data, ALsizei Offset, const ALsizei IrSize, const ALfloat (*restrict Coeffs)[2], ALfloat (*restrict Values)[2], @@ -40,6 +45,11 @@ void MixHrtf_SSE(ALfloat *restrict LeftOut, ALfloat *restrict RightOut, const ALfloat *data, ALsizei Offset, ALsizei OutPos, const ALsizei IrSize, struct MixHrtfParams *hrtfparams, struct HrtfState *hrtfstate, ALsizei BufferSize); +void MixHrtfBlend_SSE(ALfloat *restrict LeftOut, ALfloat *restrict RightOut, + const ALfloat *data, ALsizei Offset, ALsizei OutPos, + const ALsizei IrSize, const HrtfParams *oldparams, + MixHrtfParams *newparams, HrtfState *hrtfstate, + ALsizei BufferSize); void MixDirectHrtf_SSE(ALfloat *restrict LeftOut, ALfloat *restrict RightOut, const ALfloat *data, ALsizei Offset, const ALsizei IrSize, const ALfloat (*restrict Coeffs)[2], ALfloat (*restrict Values)[2], @@ -89,6 +99,11 @@ void MixHrtf_Neon(ALfloat *restrict LeftOut, ALfloat *restrict RightOut, const ALfloat *data, ALsizei Offset, ALsizei OutPos, const ALsizei IrSize, struct MixHrtfParams *hrtfparams, struct HrtfState *hrtfstate, ALsizei BufferSize); +void MixHrtfBlend_Neon(ALfloat *restrict LeftOut, ALfloat *restrict RightOut, + const ALfloat *data, ALsizei Offset, ALsizei OutPos, + const ALsizei IrSize, const HrtfParams *oldparams, + MixHrtfParams *newparams, HrtfState *hrtfstate, + ALsizei BufferSize); void MixDirectHrtf_Neon(ALfloat *restrict LeftOut, ALfloat *restrict RightOut, const ALfloat *data, ALsizei Offset, const ALsizei IrSize, const ALfloat (*restrict Coeffs)[2], ALfloat (*restrict Values)[2], diff --git a/Alc/mixer_inc.c b/Alc/mixer_inc.c index 16c3a61e..3c9d4dc5 100644 --- a/Alc/mixer_inc.c +++ b/Alc/mixer_inc.c @@ -32,21 +32,66 @@ void MixHrtf(ALfloat *restrict LeftOut, ALfloat *restrict RightOut, for(i = 0;i < BufferSize;i++) { hrtfstate->History[Offset&HRTF_HISTORY_MASK] = *(data++); - left = hrtfstate->History[(Offset-Delay[0])&HRTF_HISTORY_MASK]; - right = hrtfstate->History[(Offset-Delay[1])&HRTF_HISTORY_MASK]; + left = hrtfstate->History[(Offset-Delay[0])&HRTF_HISTORY_MASK]*gain; + right = hrtfstate->History[(Offset-Delay[1])&HRTF_HISTORY_MASK]*gain; - hrtfstate->Values[(Offset+IrSize)&HRIR_MASK][0] = 0.0f; - hrtfstate->Values[(Offset+IrSize)&HRIR_MASK][1] = 0.0f; - Offset++; + hrtfstate->Values[(Offset+IrSize-1)&HRIR_MASK][0] = 0.0f; + hrtfstate->Values[(Offset+IrSize-1)&HRIR_MASK][1] = 0.0f; ApplyCoeffs(Offset, hrtfstate->Values, IrSize, Coeffs, left, right); - *(LeftOut++) += hrtfstate->Values[Offset&HRIR_MASK][0]*gain; - *(RightOut++) += hrtfstate->Values[Offset&HRIR_MASK][1]*gain; + *(LeftOut++) += hrtfstate->Values[Offset&HRIR_MASK][0]; + *(RightOut++) += hrtfstate->Values[Offset&HRIR_MASK][1]; + gain += gainstep; + Offset++; } hrtfparams->Gain = gain; } +void MixHrtfBlend(ALfloat *restrict LeftOut, ALfloat *restrict RightOut, + const ALfloat *data, ALsizei Offset, ALsizei OutPos, + const ALsizei IrSize, const HrtfParams *oldparams, + MixHrtfParams *newparams, HrtfState *hrtfstate, + ALsizei BufferSize) +{ + const ALfloat (*OldCoeffs)[2] = ASSUME_ALIGNED(oldparams->Coeffs, 16); + const ALsizei OldDelay[2] = { oldparams->Delay[0], oldparams->Delay[1] }; + ALfloat oldGain = oldparams->Gain; + ALfloat oldGainStep = -oldGain / (ALfloat)BufferSize; + const ALfloat (*NewCoeffs)[2] = ASSUME_ALIGNED(newparams->Coeffs, 16); + const ALsizei NewDelay[2] = { newparams->Delay[0], newparams->Delay[1] }; + ALfloat newGain = newparams->Gain; + ALfloat newGainStep = newparams->GainStep; + ALfloat left, right; + ALsizei i; + + LeftOut += OutPos; + RightOut += OutPos; + for(i = 0;i < BufferSize;i++) + { + hrtfstate->Values[(Offset+IrSize-1)&HRIR_MASK][0] = 0.0f; + hrtfstate->Values[(Offset+IrSize-1)&HRIR_MASK][1] = 0.0f; + + hrtfstate->History[Offset&HRTF_HISTORY_MASK] = *(data++); + + left = hrtfstate->History[(Offset-OldDelay[0])&HRTF_HISTORY_MASK]*oldGain; + right = hrtfstate->History[(Offset-OldDelay[1])&HRTF_HISTORY_MASK]*oldGain; + ApplyCoeffs(Offset, hrtfstate->Values, IrSize, OldCoeffs, left, right); + + left = hrtfstate->History[(Offset-NewDelay[0])&HRTF_HISTORY_MASK]*newGain; + right = hrtfstate->History[(Offset-NewDelay[1])&HRTF_HISTORY_MASK]*newGain; + ApplyCoeffs(Offset, hrtfstate->Values, IrSize, NewCoeffs, left, right); + + *(LeftOut++) += hrtfstate->Values[Offset&HRIR_MASK][0]; + *(RightOut++) += hrtfstate->Values[Offset&HRIR_MASK][1]; + + oldGain += oldGainStep; + newGain += newGainStep; + Offset++; + } + newparams->Gain = newGain; +} + void MixDirectHrtf(ALfloat *restrict LeftOut, ALfloat *restrict RightOut, const ALfloat *data, ALsizei Offset, const ALsizei IrSize, const ALfloat (*restrict Coeffs)[2], ALfloat (*restrict Values)[2], diff --git a/Alc/mixer_neon.c b/Alc/mixer_neon.c index 65dd608c..51191783 100644 --- a/Alc/mixer_neon.c +++ b/Alc/mixer_neon.c @@ -221,6 +221,7 @@ static inline void ApplyCoeffs(ALsizei Offset, ALfloat (*restrict Values)[2], } #define MixHrtf MixHrtf_Neon +#define MixHrtfBlend MixHrtfBlend_Neon #define MixDirectHrtf MixDirectHrtf_Neon #include "mixer_inc.c" #undef MixHrtf diff --git a/Alc/mixer_sse.c b/Alc/mixer_sse.c index d30ec982..68786573 100644 --- a/Alc/mixer_sse.c +++ b/Alc/mixer_sse.c @@ -124,6 +124,7 @@ static inline void ApplyCoeffs(ALsizei Offset, ALfloat (*restrict Values)[2], } #define MixHrtf MixHrtf_SSE +#define MixHrtfBlend MixHrtfBlend_SSE #define MixDirectHrtf MixDirectHrtf_SSE #include "mixer_inc.c" #undef MixHrtf diff --git a/OpenAL32/Include/alu.h b/OpenAL32/Include/alu.h index 3cb94270..168a754f 100644 --- a/OpenAL32/Include/alu.h +++ b/OpenAL32/Include/alu.h @@ -301,6 +301,11 @@ typedef void (*HrtfMixerFunc)(ALfloat *restrict LeftOut, ALfloat *restrict Right const ALfloat *data, ALsizei Offset, ALsizei OutPos, const ALsizei IrSize, MixHrtfParams *hrtfparams, HrtfState *hrtfstate, ALsizei BufferSize); +typedef void (*HrtfMixerBlendFunc)(ALfloat *restrict LeftOut, ALfloat *restrict RightOut, + const ALfloat *data, ALsizei Offset, ALsizei OutPos, + const ALsizei IrSize, const HrtfParams *oldparams, + MixHrtfParams *newparams, HrtfState *hrtfstate, + ALsizei BufferSize); typedef void (*HrtfDirectMixerFunc)(ALfloat *restrict LeftOut, ALfloat *restrict RightOut, const ALfloat *data, ALsizei Offset, const ALsizei IrSize, const ALfloat (*restrict Coeffs)[2], |