aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Robinson <chris.kcat@gmail.com>2022-03-30 04:06:00 -0700
committerChris Robinson <chris.kcat@gmail.com>2022-03-30 04:06:00 -0700
commitf15106e77f0baa793320aa23aaf876f39b615500 (patch)
treeb90a46eeaef5b8017a868ca2adc2cfde54da973a
parenta033f8c2749cb9af14297fea7c2115f798892494 (diff)
Remove the reversed all-pass trick in MixDirectHrtfBase
Given the minimum phase HRTF, it's not going to stay linear phase anyway.
-rw-r--r--alc/alc.cpp2
-rw-r--r--core/device.h2
-rw-r--r--core/hrtf.h2
-rw-r--r--core/mixer/hrtfbase.h47
-rw-r--r--core/mixer/hrtfdefs.h3
-rw-r--r--core/voice.cpp5
6 files changed, 11 insertions, 50 deletions
diff --git a/alc/alc.cpp b/alc/alc.cpp
index c71d84ae..4579232b 100644
--- a/alc/alc.cpp
+++ b/alc/alc.cpp
@@ -2093,8 +2093,6 @@ ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList)
nanoseconds::rep sample_delay{0};
if(device->mUhjEncoder)
sample_delay += UhjEncoder::sFilterDelay;
- if(device->mHrtfState)
- sample_delay += HrtfDirectDelay;
if(auto *ambidec = device->AmbiDecoder.get())
{
if(ambidec->hasStablizer())
diff --git a/core/device.h b/core/device.h
index 48d04f77..58a30f1b 100644
--- a/core/device.h
+++ b/core/device.h
@@ -197,7 +197,7 @@ struct DeviceBase {
};
/* Persistent storage for HRTF mixing. */
- alignas(16) float2 HrtfAccumData[BufferLineSize + HrirLength + HrtfDirectDelay];
+ alignas(16) float2 HrtfAccumData[BufferLineSize + HrirLength];
/* Mixing buffer used by the Dry mix and Real output. */
al::vector<FloatBufferLine, 16> MixBuffer;
diff --git a/core/hrtf.h b/core/hrtf.h
index 61e5bada..9cf11efb 100644
--- a/core/hrtf.h
+++ b/core/hrtf.h
@@ -58,7 +58,7 @@ struct AngularPoint {
struct DirectHrtfState {
- std::array<float,HrtfDirectDelay+BufferLineSize> mTemp;
+ std::array<float,BufferLineSize> mTemp;
/* HRTF filter state for dry buffer content */
uint mIrSize{0};
diff --git a/core/mixer/hrtfbase.h b/core/mixer/hrtfbase.h
index 79b09a3d..ade6f693 100644
--- a/core/mixer/hrtfbase.h
+++ b/core/mixer/hrtfbase.h
@@ -90,46 +90,15 @@ inline void MixDirectHrtfBase(const FloatBufferSpan LeftOut, const FloatBufferSp
{
ASSUME(BufferSize > 0);
- /* 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[HrtfDirectDelay+i][0] += LeftOut[i];
- AccumSamples[HrtfDirectDelay+i][1] += RightOut[i];
- }
-
for(const FloatBufferLine &input : InSamples)
{
/* For dual-band processing, the signal needs extra scaling applied to
- * the high frequency response. The band-splitter alone creates a
- * frequency-dependent phase shift, which is not ideal. To counteract
- * it, combine it with a backwards phase shift.
- */
-
- /* Load the input signal backwards, into a temp buffer with delay
- * padding. The delay serves to reduce the error caused by the IIR
- * filter's phase shift on a partial input.
+ * 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), HrtfDirectDelay+BufferSize};
- auto tmpiter = std::reverse_copy(input.begin(), input.begin()+BufferSize, tempbuf.begin());
- std::copy(ChanState->mDelay.cbegin(), ChanState->mDelay.cend(), tmpiter);
-
- /* Save the unfiltered newest input samples for next time. */
- std::copy_n(tempbuf.begin(), ChanState->mDelay.size(), ChanState->mDelay.begin());
+ al::span<float> tempbuf{al::assume_aligned<16>(TempBuf), BufferSize};
+ std::copy(input.begin(), input.begin()+BufferSize, tempbuf.begin());
- /* Apply the all-pass on the reversed signal and reverse the resulting
- * sample array. This produces the forward response with a backwards
- * phase shift (+n degrees becomes -n degrees).
- */
- ChanState->mSplitter.applyAllpass(tempbuf);
- tempbuf = tempbuf.subspan<HrtfDirectDelay>();
- std::reverse(tempbuf.begin(), tempbuf.end());
-
- /* Now apply the HF scale with the band-splitter. This applies the
- * forward phase shift, which cancels out with the backwards phase
- * shift to get the original phase on the scaled signal.
- */
ChanState->mSplitter.processHfScale(tempbuf, ChanState->mHfScale);
/* Now apply the HRIR coefficients to this channel. */
@@ -143,16 +112,16 @@ inline void MixDirectHrtfBase(const FloatBufferSpan LeftOut, const FloatBufferSp
++ChanState;
}
+ /* Add the HRTF signal to the existing "direct" signal. */
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, HrirLength+HrtfDirectDelay,
- AccumSamples);
+ auto accum_iter = std::copy_n(AccumSamples+BufferSize, HrirLength, AccumSamples);
std::fill_n(accum_iter, BufferSize, float2{});
}
diff --git a/core/mixer/hrtfdefs.h b/core/mixer/hrtfdefs.h
index 7046a31e..3c903ed8 100644
--- a/core/mixer/hrtfdefs.h
+++ b/core/mixer/hrtfdefs.h
@@ -26,8 +26,6 @@ constexpr uint HrirMask{HrirLength - 1};
constexpr uint MinIrLength{8};
-constexpr uint HrtfDirectDelay{256};
-
using HrirArray = std::array<float2,HrirLength>;
using HrirSpan = al::span<float2,HrirLength>;
using ConstHrirSpan = al::span<const float2,HrirLength>;
@@ -47,7 +45,6 @@ struct HrtfFilter {
struct HrtfChannelState {
- std::array<float,HrtfDirectDelay> mDelay{};
BandSplitter mSplitter;
float mHfScale{};
alignas(16) HrirArray mCoeffs{};
diff --git a/core/voice.cpp b/core/voice.cpp
index 07400b07..0060737f 100644
--- a/core/voice.cpp
+++ b/core/voice.cpp
@@ -355,10 +355,7 @@ void DoHrtfMix(const float *samples, const uint DstBufferSize, DirectParams &par
{
const uint IrSize{Device->mIrSize};
auto &HrtfSamples = Device->HrtfSourceData;
- /* Source HRTF mixing needs to include the direct delay so it remains
- * aligned with the direct mix's HRTF filtering.
- */
- float2 *AccumSamples{Device->HrtfAccumData + HrtfDirectDelay};
+ auto &AccumSamples = Device->HrtfAccumData;
/* 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(),