Remove the reversed all-pass trick in MixDirectHrtfBase

Given the minimum phase HRTF, it's not going to stay linear phase anyway.
This commit is contained in:
Chris Robinson 2022-03-30 04:06:00 -07:00
parent a033f8c274
commit f15106e77f
6 changed files with 11 additions and 50 deletions

View File

@ -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())

View File

@ -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;

View File

@ -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};

View File

@ -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.
* 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());
/* 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.
*/
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());
/* 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{});
}

View File

@ -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{};

View File

@ -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(),