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:
parent
a033f8c274
commit
f15106e77f
@ -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())
|
||||
|
@ -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;
|
||||
|
@ -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};
|
||||
|
@ -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{});
|
||||
}
|
||||
|
||||
|
@ -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{};
|
||||
|
@ -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(),
|
||||
|
Loading…
x
Reference in New Issue
Block a user