diff options
author | Chris Robinson <[email protected]> | 2020-05-20 11:13:06 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2020-05-20 11:13:06 -0700 |
commit | 200c164d786a2fd33962b2fcc5ded176e47a0f3d (patch) | |
tree | 488548dedfd2f90ab87feb72246915c191816baf /alc | |
parent | f38b813ba8703c6cb868f76e6603e863affa665c (diff) |
Improve HRTF delay handling
Ensures source-level HRTF, the dry mix, and direct output all align properly,
and simplifies adding the delay in the direct mix output.
Diffstat (limited to 'alc')
-rw-r--r-- | alc/alcmain.h | 2 | ||||
-rw-r--r-- | alc/hrtf.h | 2 | ||||
-rw-r--r-- | alc/mixer/hrtfbase.h | 42 | ||||
-rw-r--r-- | alc/voice.cpp | 5 |
4 files changed, 19 insertions, 32 deletions
diff --git a/alc/alcmain.h b/alc/alcmain.h index 3a14e68f..c577551b 100644 --- a/alc/alcmain.h +++ b/alc/alcmain.h @@ -269,7 +269,7 @@ struct ALCdevice : public al::intrusive_ref<ALCdevice> { }; /* Persistent storage for HRTF mixing. */ - alignas(16) float2 HrtfAccumData[BUFFERSIZE + HRIR_LENGTH]; + alignas(16) float2 HrtfAccumData[BUFFERSIZE + HRIR_LENGTH + HRTF_DIRECT_DELAY]; /* Mixing buffer used by the Dry mix and Real output. */ al::vector<FloatBufferLine, 16> MixBuffer; @@ -88,8 +88,6 @@ struct DirectHrtfState { alignas(16) HrirArray mCoeffs{}; }; - std::array<float,HRTF_DIRECT_DELAY> mLeftDelay{}; - std::array<float,HRTF_DIRECT_DELAY> mRightDelay{}; std::array<float,HRTF_DIRECT_DELAY+BUFFERSIZE> mTemp; /* HRTF filter state for dry buffer content */ diff --git a/alc/mixer/hrtfbase.h b/alc/mixer/hrtfbase.h index 59ff7633..8db26d70 100644 --- a/alc/mixer/hrtfbase.h +++ b/alc/mixer/hrtfbase.h @@ -85,8 +85,16 @@ inline void MixDirectHrtfBase(FloatBufferLine &LeftOut, FloatBufferLine &RightOu { ASSUME(BufferSize > 0); - const uint_fast32_t IrSize{State->mIrSize}; + /* Add the existing signal directly to the accumulation buffer, unfiltered, + * and with a delay to align with the input delay. + */ + for(size_t i{0};i < BufferSize;++i) + { + AccumSamples[HRTF_DIRECT_DELAY+i][0] += LeftOut[i]; + AccumSamples[HRTF_DIRECT_DELAY+i][1] += RightOut[i]; + } + const uint_fast32_t IrSize{State->mIrSize}; auto chan_iter = State->mChannels.begin(); for(const FloatBufferLine &input : InSamples) { @@ -123,47 +131,25 @@ inline void MixDirectHrtfBase(FloatBufferLine &LeftOut, FloatBufferLine &RightOu /* Now apply the HRIR coefficients to this channel. */ const auto &Coeffs = chan_iter->mCoeffs; - ++chan_iter; - for(size_t i{0u};i < BufferSize;++i) { const float insample{tempbuf[i]}; ApplyCoeffs(AccumSamples+i, IrSize, Coeffs, insample, insample); } - } - - /* Apply a delay to the existing signal to align with the input delay. */ - auto &ldelay = State->mLeftDelay; - auto &rdelay = State->mRightDelay; - if LIKELY(BufferSize >= HRTF_DIRECT_DELAY) - { - auto buffer_end = LeftOut.begin() + BufferSize; - auto delay_end = std::rotate(LeftOut.begin(), buffer_end - HRTF_DIRECT_DELAY, buffer_end); - std::swap_ranges(LeftOut.begin(), delay_end, ldelay.begin()); - buffer_end = RightOut.begin() + BufferSize; - delay_end = std::rotate(RightOut.begin(), buffer_end - HRTF_DIRECT_DELAY, buffer_end); - std::swap_ranges(RightOut.begin(), delay_end, rdelay.begin()); + ++chan_iter; } - else - { - auto buffer_end = LeftOut.begin() + BufferSize; - auto delay_start = std::swap_ranges(LeftOut.begin(), buffer_end, ldelay.begin()); - std::rotate(ldelay.begin(), delay_start, ldelay.end()); - buffer_end = RightOut.begin() + BufferSize; - delay_start = std::swap_ranges(RightOut.begin(), buffer_end, rdelay.begin()); - std::rotate(rdelay.begin(), delay_start, rdelay.end()); - } for(size_t i{0u};i < BufferSize;++i) - LeftOut[i] += AccumSamples[i][0]; + LeftOut[i] = AccumSamples[i][0]; for(size_t i{0u};i < BufferSize;++i) - RightOut[i] += AccumSamples[i][1]; + RightOut[i] = AccumSamples[i][1]; /* 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); + auto accum_iter = std::copy_n(AccumSamples+BufferSize, HRIR_LENGTH+HRTF_DIRECT_DELAY, + AccumSamples); std::fill_n(accum_iter, BufferSize, float2{}); } diff --git a/alc/voice.cpp b/alc/voice.cpp index 0e92e423..7d4f638c 100644 --- a/alc/voice.cpp +++ b/alc/voice.cpp @@ -468,7 +468,10 @@ void DoHrtfMix(const float *samples, const ALuint DstBufferSize, DirectParams &p ALCdevice *Device) { auto &HrtfSamples = Device->HrtfSourceData; - auto &AccumSamples = Device->HrtfAccumData; + /* Source HRTF mixing needs to include the direct delay so it remains + * aligned with the direct mix's HRTF filtering. + */ + float2 *AccumSamples{Device->HrtfAccumData + HRTF_DIRECT_DELAY}; /* Copy the HRTF history and new input samples into a temp buffer. */ auto src_iter = std::copy(parms.Hrtf.History.begin(), parms.Hrtf.History.end(), |