aboutsummaryrefslogtreecommitdiffstats
path: root/alc
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2020-05-20 11:13:06 -0700
committerChris Robinson <[email protected]>2020-05-20 11:13:06 -0700
commit200c164d786a2fd33962b2fcc5ded176e47a0f3d (patch)
tree488548dedfd2f90ab87feb72246915c191816baf /alc
parentf38b813ba8703c6cb868f76e6603e863affa665c (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.h2
-rw-r--r--alc/hrtf.h2
-rw-r--r--alc/mixer/hrtfbase.h42
-rw-r--r--alc/voice.cpp5
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;
diff --git a/alc/hrtf.h b/alc/hrtf.h
index 7876265b..29a0864c 100644
--- a/alc/hrtf.h
+++ b/alc/hrtf.h
@@ -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(),