diff options
-rw-r--r-- | core/filters/splitter.cpp | 35 | ||||
-rw-r--r-- | core/filters/splitter.h | 2 | ||||
-rw-r--r-- | core/mixer/hrtfbase.h | 13 |
3 files changed, 44 insertions, 6 deletions
diff --git a/core/filters/splitter.cpp b/core/filters/splitter.cpp index 5ffe51e1..19f7646a 100644 --- a/core/filters/splitter.cpp +++ b/core/filters/splitter.cpp @@ -61,6 +61,41 @@ void BandSplitterR<Real>::process(const al::span<const Real> input, Real *hpout, } template<typename Real> +void BandSplitterR<Real>::processHfScale(const al::span<const Real> input, Real *RESTRICT output, + const Real hfscale) +{ + const Real ap_coeff{mCoeff}; + const Real lp_coeff{mCoeff*0.5f + 0.5f}; + Real lp_z1{mLpZ1}; + Real lp_z2{mLpZ2}; + Real ap_z1{mApZ1}; + auto proc_sample = [hfscale,ap_coeff,lp_coeff,&lp_z1,&lp_z2,&ap_z1](const Real in) noexcept -> Real + { + /* Low-pass sample processing. */ + Real d{(in - lp_z1) * lp_coeff}; + Real lp_y{lp_z1 + d}; + lp_z1 = lp_y + d; + + d = (lp_y - lp_z2) * lp_coeff; + lp_y = lp_z2 + d; + lp_z2 = lp_y + d; + + /* All-pass sample processing. */ + Real ap_y{in*ap_coeff + ap_z1}; + ap_z1 = in - ap_y*ap_coeff; + + /* High-pass generated by removing the low-passed signal, which is then + * scaled and added back to the low-passed signal. + */ + return (ap_y-lp_y)*hfscale + lp_y; + }; + std::transform(input.begin(), input.end(), output, proc_sample); + mLpZ1 = lp_z1; + mLpZ2 = lp_z2; + mApZ1 = ap_z1; +} + +template<typename Real> void BandSplitterR<Real>::processHfScale(const al::span<Real> samples, const Real hfscale) { const Real ap_coeff{mCoeff}; diff --git a/core/filters/splitter.h b/core/filters/splitter.h index e428418f..41805c70 100644 --- a/core/filters/splitter.h +++ b/core/filters/splitter.h @@ -24,6 +24,8 @@ public: void clear() noexcept { mLpZ1 = mLpZ2 = mApZ1 = 0.0f; } void process(const al::span<const Real> input, Real *hpout, Real *lpout); + void processHfScale(const al::span<const Real> input, Real *output, const Real hfscale); + void processHfScale(const al::span<Real> samples, const Real hfscale); void processScale(const al::span<Real> samples, const Real hfscale, const Real lfscale); diff --git a/core/mixer/hrtfbase.h b/core/mixer/hrtfbase.h index ade6f693..606f9d4e 100644 --- a/core/mixer/hrtfbase.h +++ b/core/mixer/hrtfbase.h @@ -96,12 +96,11 @@ inline void MixDirectHrtfBase(const FloatBufferSpan LeftOut, const FloatBufferSp * the high frequency response. The band-splitter applies this scaling * with a consistent phase shift regardless of the scale amount. */ - al::span<float> tempbuf{al::assume_aligned<16>(TempBuf), BufferSize}; - std::copy(input.begin(), input.begin()+BufferSize, tempbuf.begin()); - - ChanState->mSplitter.processHfScale(tempbuf, ChanState->mHfScale); + ChanState->mSplitter.processHfScale({input.data(), BufferSize}, TempBuf, + ChanState->mHfScale); /* Now apply the HRIR coefficients to this channel. */ + const float *RESTRICT tempbuf{al::assume_aligned<16>(TempBuf)}; const ConstHrirSpan Coeffs{ChanState->mCoeffs}; for(size_t i{0u};i < BufferSize;++i) { @@ -113,10 +112,12 @@ inline void MixDirectHrtfBase(const FloatBufferSpan LeftOut, const FloatBufferSp } /* Add the HRTF signal to the existing "direct" signal. */ + float *RESTRICT left{al::assume_aligned<16>(LeftOut.data())}; + float *RESTRICT right{al::assume_aligned<16>(RightOut.data())}; for(size_t i{0u};i < BufferSize;++i) - LeftOut[i] += AccumSamples[i][0]; + left[i] += AccumSamples[i][0]; for(size_t i{0u};i < BufferSize;++i) - RightOut[i] += AccumSamples[i][1]; + right[i] += AccumSamples[i][1]; /* Copy the new in-progress accumulation values to the front and clear the * following samples for the next mix. |