diff options
author | Chris Robinson <[email protected]> | 2019-11-03 00:30:33 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2019-11-03 00:30:33 -0700 |
commit | d2608e4bde41b3005a06346bea99bbe06404ef22 (patch) | |
tree | b57b085c64bff88056b07437c41ddf6e09d7d9de | |
parent | 2741a94e58ed2f9a17d05fd2499e1a3ea4ac43e8 (diff) |
Avoid holding HRTF accumulation samples per-source
It notably simplifies things to mix HRTF sources into an accumulation buffer
together, which the Dry buffer's Ambisonic-to-HRTF decode is then added to,
before being mixed to the Real output.
-rw-r--r-- | alc/alc.cpp | 2 | ||||
-rw-r--r-- | alc/alcmain.h | 2 | ||||
-rw-r--r-- | alc/hrtf.h | 2 | ||||
-rw-r--r-- | alc/mixer/defs.h | 10 | ||||
-rw-r--r-- | alc/mixer/hrtfbase.h | 27 | ||||
-rw-r--r-- | alc/mixer/mixer_c.cpp | 15 | ||||
-rw-r--r-- | alc/mixer/mixer_neon.cpp | 15 | ||||
-rw-r--r-- | alc/mixer/mixer_sse.cpp | 15 | ||||
-rw-r--r-- | alc/voice.cpp | 39 |
9 files changed, 44 insertions, 83 deletions
diff --git a/alc/alc.cpp b/alc/alc.cpp index cd2911f5..bee42fc5 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -1853,6 +1853,8 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) device->Limiter = nullptr; device->ChannelDelay.clear(); + std::fill(std::begin(device->HrtfAccumData), std::end(device->HrtfAccumData), float2{}); + device->Dry.AmbiMap.fill(BFChannelConfig{}); device->Dry.Buffer = {}; std::fill(std::begin(device->NumChannelsPerOrder), std::end(device->NumChannelsPerOrder), 0u); diff --git a/alc/alcmain.h b/alc/alcmain.h index c26b3a28..30c5b835 100644 --- a/alc/alcmain.h +++ b/alc/alcmain.h @@ -277,6 +277,8 @@ struct ALCdevice : public al::intrusive_ref<ALCdevice> { alignas(16) ALfloat HrtfSourceData[BUFFERSIZE + HRTF_HISTORY_LENGTH]; alignas(16) ALfloat NfcSampleData[BUFFERSIZE]; }; + + /* Persistent storage for HRTF mixing. */ alignas(16) float2 HrtfAccumData[BUFFERSIZE + HRIR_LENGTH]; /* Mixing buffer used by the Dry mix and Real output. */ @@ -68,7 +68,6 @@ using HrirArray = std::array<float2,HRIR_LENGTH>; struct HrtfState { alignas(16) std::array<ALfloat,HRTF_HISTORY_LENGTH> History; - alignas(16) HrirArray Values; }; struct HrtfFilter { @@ -80,7 +79,6 @@ struct HrtfFilter { struct DirectHrtfState { /* HRTF filter state for dry buffer content */ ALuint IrSize{0}; - alignas(16) HrirArray Values{}; al::FlexArray<HrirArray,16> Coeffs; DirectHrtfState(size_t numchans) : Coeffs{numchans} { } diff --git a/alc/mixer/defs.h b/alc/mixer/defs.h index b2535265..1e5b40d8 100644 --- a/alc/mixer/defs.h +++ b/alc/mixer/defs.h @@ -41,13 +41,11 @@ void MixRow_(const al::span<float> OutBuffer, const al::span<const float> Gains, const float *InSamples, const size_t InStride); template<InstSetType InstTag> -void MixHrtf_(FloatBufferLine &LeftOut, FloatBufferLine &RightOut, const float *InSamples, - float2 *AccumSamples, const size_t OutPos, const ALuint IrSize, MixHrtfFilter *hrtfparams, - const size_t BufferSize); +void MixHrtf_(const float *InSamples, float2 *AccumSamples, const ALuint IrSize, + MixHrtfFilter *hrtfparams, const size_t BufferSize); template<InstSetType InstTag> -void MixHrtfBlend_(FloatBufferLine &LeftOut, FloatBufferLine &RightOut, const float *InSamples, - float2 *AccumSamples, const size_t OutPos, const ALuint IrSize, const HrtfFilter *oldparams, - MixHrtfFilter *newparams, const size_t BufferSize); +void MixHrtfBlend_(const float *InSamples, float2 *AccumSamples, const ALuint IrSize, + const HrtfFilter *oldparams, MixHrtfFilter *newparams, const size_t BufferSize); template<InstSetType InstTag> void MixDirectHrtf_(FloatBufferLine &LeftOut, FloatBufferLine &RightOut, const al::span<const FloatBufferLine> InSamples, float2 *AccumSamples, DirectHrtfState *State, diff --git a/alc/mixer/hrtfbase.h b/alc/mixer/hrtfbase.h index cbc885c5..4a6eab50 100644 --- a/alc/mixer/hrtfbase.h +++ b/alc/mixer/hrtfbase.h @@ -13,9 +13,8 @@ using ApplyCoeffsT = void(&)(float2 *RESTRICT Values, const ALuint irSize, const const float left, const float right); template<ApplyCoeffsT ApplyCoeffs> -inline void MixHrtfBase(FloatBufferLine &LeftOut, FloatBufferLine &RightOut, - const float *InSamples, float2 *RESTRICT AccumSamples, const size_t OutPos, - const ALuint IrSize, MixHrtfFilter *hrtfparams, const size_t BufferSize) +inline void MixHrtfBase(const float *InSamples, float2 *RESTRICT AccumSamples, const ALuint IrSize, + MixHrtfFilter *hrtfparams, const size_t BufferSize) { ASSUME(BufferSize > 0); @@ -38,17 +37,11 @@ inline void MixHrtfBase(FloatBufferLine &LeftOut, FloatBufferLine &RightOut, stepcount += 1.0f; } - for(size_t i{0u};i < BufferSize;++i) - LeftOut[OutPos+i] += AccumSamples[i][0]; - for(size_t i{0u};i < BufferSize;++i) - RightOut[OutPos+i] += AccumSamples[i][1]; - hrtfparams->Gain = gain + gainstep*stepcount; } template<ApplyCoeffsT ApplyCoeffs> -inline void MixHrtfBlendBase(FloatBufferLine &LeftOut, FloatBufferLine &RightOut, - const float *InSamples, float2 *RESTRICT AccumSamples, const size_t OutPos, +inline void MixHrtfBlendBase(const float *InSamples, float2 *RESTRICT AccumSamples, const ALuint IrSize, const HrtfFilter *oldparams, MixHrtfFilter *newparams, const size_t BufferSize) { @@ -89,11 +82,6 @@ inline void MixHrtfBlendBase(FloatBufferLine &LeftOut, FloatBufferLine &RightOut stepcount += 1.0f; } - for(size_t i{0u};i < BufferSize;++i) - LeftOut[OutPos+i] += AccumSamples[i][0]; - for(size_t i{0u};i < BufferSize;++i) - RightOut[OutPos+i] += AccumSamples[i][1]; - newparams->Gain = newGainStep*stepcount; } @@ -106,9 +94,6 @@ inline void MixDirectHrtfBase(FloatBufferLine &LeftOut, FloatBufferLine &RightOu const ALuint IrSize{State->IrSize}; - auto accum_iter = std::copy_n(State->Values.begin(), State->Values.size(), AccumSamples); - std::fill_n(accum_iter, BufferSize, float2{}); - auto coeff_iter = State->Coeffs.begin(); for(const FloatBufferLine &input : InSamples) { @@ -124,7 +109,11 @@ inline void MixDirectHrtfBase(FloatBufferLine &LeftOut, FloatBufferLine &RightOu for(size_t i{0u};i < BufferSize;++i) RightOut[i] += AccumSamples[i][1]; - std::copy_n(AccumSamples + BufferSize, State->Values.size(), State->Values.begin()); + /* Copy the new in-progress accumulation values to the front and clear the + * following samples for the next mix. + */ + auto accum_iter = std::copy_n(AccumSamples+BufferSize, HRIR_LENGTH, AccumSamples); + std::fill_n(accum_iter, BufferSize, float2{}); } #endif /* MIXER_HRTFBASE_H */ diff --git a/alc/mixer/mixer_c.cpp b/alc/mixer/mixer_c.cpp index 8d375de7..fad33746 100644 --- a/alc/mixer/mixer_c.cpp +++ b/alc/mixer/mixer_c.cpp @@ -136,21 +136,16 @@ const ALfloat *Resample_<FastBSincTag,CTag>(const InterpState *state, const ALfl template<> -void MixHrtf_<CTag>(FloatBufferLine &LeftOut, FloatBufferLine &RightOut, - const float *InSamples, float2 *AccumSamples, const size_t OutPos, const ALuint IrSize, +void MixHrtf_<CTag>(const float *InSamples, float2 *AccumSamples, const ALuint IrSize, MixHrtfFilter *hrtfparams, const size_t BufferSize) -{ - MixHrtfBase<ApplyCoeffs>(LeftOut, RightOut, InSamples, AccumSamples, OutPos, IrSize, - hrtfparams, BufferSize); -} +{ MixHrtfBase<ApplyCoeffs>(InSamples, AccumSamples, IrSize, hrtfparams, BufferSize); } template<> -void MixHrtfBlend_<CTag>(FloatBufferLine &LeftOut, FloatBufferLine &RightOut, - const float *InSamples, float2 *AccumSamples, const size_t OutPos, const ALuint IrSize, +void MixHrtfBlend_<CTag>(const float *InSamples, float2 *AccumSamples, const ALuint IrSize, const HrtfFilter *oldparams, MixHrtfFilter *newparams, const size_t BufferSize) { - MixHrtfBlendBase<ApplyCoeffs>(LeftOut, RightOut, InSamples, AccumSamples, OutPos, IrSize, - oldparams, newparams, BufferSize); + MixHrtfBlendBase<ApplyCoeffs>(InSamples, AccumSamples, IrSize, oldparams, newparams, + BufferSize); } template<> diff --git a/alc/mixer/mixer_neon.cpp b/alc/mixer/mixer_neon.cpp index ae782897..67bf9c71 100644 --- a/alc/mixer/mixer_neon.cpp +++ b/alc/mixer/mixer_neon.cpp @@ -190,21 +190,16 @@ const ALfloat *Resample_<FastBSincTag,NEONTag>(const InterpState *state, template<> -void MixHrtf_<NEONTag>(FloatBufferLine &LeftOut, FloatBufferLine &RightOut, - const float *InSamples, float2 *AccumSamples, const size_t OutPos, const ALuint IrSize, +void MixHrtf_<NEONTag>(const float *InSamples, float2 *AccumSamples, const ALuint IrSize, MixHrtfFilter *hrtfparams, const size_t BufferSize) -{ - MixHrtfBase<ApplyCoeffs>(LeftOut, RightOut, InSamples, AccumSamples, OutPos, IrSize, - hrtfparams, BufferSize); -} +{ MixHrtfBase<ApplyCoeffs>(InSamples, AccumSamples, IrSize, hrtfparams, BufferSize); } template<> -void MixHrtfBlend_<NEONTag>(FloatBufferLine &LeftOut, FloatBufferLine &RightOut, - const float *InSamples, float2 *AccumSamples, const size_t OutPos, const ALuint IrSize, +void MixHrtfBlend_<NEONTag>(const float *InSamples, float2 *AccumSamples, const ALuint IrSize, const HrtfFilter *oldparams, MixHrtfFilter *newparams, const size_t BufferSize) { - MixHrtfBlendBase<ApplyCoeffs>(LeftOut, RightOut, InSamples, AccumSamples, OutPos, IrSize, - oldparams, newparams, BufferSize); + MixHrtfBlendBase<ApplyCoeffs>(InSamples, AccumSamples, IrSize, oldparams, newparams, + BufferSize); } template<> diff --git a/alc/mixer/mixer_sse.cpp b/alc/mixer/mixer_sse.cpp index 62ce5eab..aaf37df6 100644 --- a/alc/mixer/mixer_sse.cpp +++ b/alc/mixer/mixer_sse.cpp @@ -165,21 +165,16 @@ const ALfloat *Resample_<FastBSincTag,SSETag>(const InterpState *state, template<> -void MixHrtf_<SSETag>(FloatBufferLine &LeftOut, FloatBufferLine &RightOut, - const float *InSamples, float2 *AccumSamples, const size_t OutPos, const ALuint IrSize, +void MixHrtf_<SSETag>(const float *InSamples, float2 *AccumSamples, const ALuint IrSize, MixHrtfFilter *hrtfparams, const size_t BufferSize) -{ - MixHrtfBase<ApplyCoeffs>(LeftOut, RightOut, InSamples, AccumSamples, OutPos, IrSize, - hrtfparams, BufferSize); -} +{ MixHrtfBase<ApplyCoeffs>(InSamples, AccumSamples, IrSize, hrtfparams, BufferSize); } template<> -void MixHrtfBlend_<SSETag>(FloatBufferLine &LeftOut, FloatBufferLine &RightOut, - const float *InSamples, float2 *AccumSamples, const size_t OutPos, const ALuint IrSize, +void MixHrtfBlend_<SSETag>(const float *InSamples, float2 *AccumSamples, const ALuint IrSize, const HrtfFilter *oldparams, MixHrtfFilter *newparams, const size_t BufferSize) { - MixHrtfBlendBase<ApplyCoeffs>(LeftOut, RightOut, InSamples, AccumSamples, OutPos, IrSize, - oldparams, newparams, BufferSize); + MixHrtfBlendBase<ApplyCoeffs>(InSamples, AccumSamples, IrSize, oldparams, newparams, + BufferSize); } template<> diff --git a/alc/voice.cpp b/alc/voice.cpp index 0aac0258..1c38f36f 100644 --- a/alc/voice.cpp +++ b/alc/voice.cpp @@ -72,12 +72,11 @@ Resampler ResamplerDefault{Resampler::Linear}; namespace { -using HrtfMixerFunc = void(*)(FloatBufferLine &LeftOut, FloatBufferLine &RightOut, - const ALfloat *InSamples, float2 *AccumSamples, const size_t OutPos, const ALuint IrSize, +using HrtfMixerFunc = void(*)(const ALfloat *InSamples, float2 *AccumSamples, const ALuint IrSize, MixHrtfFilter *hrtfparams, const size_t BufferSize); -using HrtfMixerBlendFunc = void(*)(FloatBufferLine &LeftOut, FloatBufferLine &RightOut, - const ALfloat *InSamples, float2 *AccumSamples, const size_t OutPos, const ALuint IrSize, - const HrtfFilter *oldparams, MixHrtfFilter *newparams, const size_t BufferSize); +using HrtfMixerBlendFunc = void(*)(const ALfloat *InSamples, float2 *AccumSamples, + const ALuint IrSize, const HrtfFilter *oldparams, MixHrtfFilter *newparams, + const size_t BufferSize); HrtfMixerFunc MixHrtfSamples = MixHrtf_<CTag>; HrtfMixerBlendFunc MixHrtfBlendSamples = MixHrtfBlend_<CTag>; @@ -423,12 +422,10 @@ ALfloat *LoadBufferQueue(ALbufferlistitem *BufferListItem, ALbufferlistitem *Buf } -void DoHrtfMix(ALvoice::TargetData &Direct, const float TargetGain, DirectParams &parms, - const float *samples, const ALuint DstBufferSize, const ALuint Counter, const ALuint OutPos, - const ALuint IrSize, ALCdevice *Device) +void DoHrtfMix(const float TargetGain, DirectParams &parms, const float *samples, + const ALuint DstBufferSize, const ALuint Counter, ALuint OutPos, const ALuint IrSize, + ALCdevice *Device) { - const ALuint OutLIdx{GetChannelIdxByName(Device->RealOut, FrontLeft)}; - const ALuint OutRIdx{GetChannelIdxByName(Device->RealOut, FrontRight)}; auto &HrtfSamples = Device->HrtfSourceData; auto &AccumSamples = Device->HrtfAccumData; @@ -440,12 +437,6 @@ void DoHrtfMix(ALvoice::TargetData &Direct, const float TargetGain, DirectParams std::copy_n(std::begin(HrtfSamples) + DstBufferSize, parms.Hrtf.State.History.size(), parms.Hrtf.State.History.begin()); - /* Copy the current filtered values being accumulated into the temp buffer. */ - auto accum_iter = std::copy_n(parms.Hrtf.State.Values.begin(), parms.Hrtf.State.Values.size(), - std::begin(AccumSamples)); - /* Clear the accumulation buffer that will start getting filled in. */ - std::fill_n(accum_iter, DstBufferSize, float2{}); - /* If fading, the old gain is not silence, and this is the first mixing * pass, fade between the IRs. */ @@ -473,14 +464,15 @@ void DoHrtfMix(ALvoice::TargetData &Direct, const float TargetGain, DirectParams hrtfparams.Gain = 0.0f; hrtfparams.GainStep = gain / static_cast<float>(fademix); - MixHrtfBlendSamples(Direct.Buffer[OutLIdx], Direct.Buffer[OutRIdx], HrtfSamples, - AccumSamples, OutPos, IrSize, &parms.Hrtf.Old, &hrtfparams, fademix); + MixHrtfBlendSamples(HrtfSamples, AccumSamples+OutPos, IrSize, &parms.Hrtf.Old, &hrtfparams, + fademix); /* Update the old parameters with the result. */ parms.Hrtf.Old = parms.Hrtf.Target; if(fademix < Counter) parms.Hrtf.Old.Gain = hrtfparams.Gain; else parms.Hrtf.Old.Gain = TargetGain; + OutPos += fademix; } if LIKELY(fademix < DstBufferSize) @@ -503,8 +495,7 @@ void DoHrtfMix(ALvoice::TargetData &Direct, const float TargetGain, DirectParams hrtfparams.Delay[1] = parms.Hrtf.Target.Delay[1]; hrtfparams.Gain = parms.Hrtf.Old.Gain; hrtfparams.GainStep = (gain - parms.Hrtf.Old.Gain) / static_cast<float>(todo); - MixHrtfSamples(Direct.Buffer[OutLIdx], Direct.Buffer[OutRIdx], HrtfSamples+fademix, - AccumSamples+fademix, OutPos+fademix, IrSize, &hrtfparams, todo); + MixHrtfSamples(HrtfSamples+fademix, AccumSamples+OutPos, IrSize, &hrtfparams, todo); /* Store the interpolated gain or the final target gain depending if * the fade is done. */ @@ -513,10 +504,6 @@ void DoHrtfMix(ALvoice::TargetData &Direct, const float TargetGain, DirectParams else parms.Hrtf.Old.Gain = TargetGain; } - - /* Copy the new in-progress accumulation values back for the next mix. */ - std::copy_n(std::begin(AccumSamples) + DstBufferSize, parms.Hrtf.State.Values.size(), - parms.Hrtf.State.Values.begin()); } void DoNfcMix(ALvoice::TargetData &Direct, const float *TargetGains, DirectParams &parms, @@ -713,8 +700,8 @@ void ALvoice::mix(const State vstate, ALCcontext *Context, const ALuint SamplesT { const ALfloat TargetGain{UNLIKELY(vstate == ALvoice::Stopping) ? 0.0f : parms.Hrtf.Target.Gain}; - DoHrtfMix(mDirect, TargetGain, parms, samples, DstBufferSize, Counter, OutPos, - IrSize, Device); + DoHrtfMix(TargetGain, parms, samples, DstBufferSize, Counter, OutPos, IrSize, + Device); } else if((mFlags&VOICE_HAS_NFC)) { |