Avoid a separate struct for the bandsplitter all-pass

This commit is contained in:
Chris Robinson 2019-06-04 17:50:36 -07:00
parent 4522a51ea2
commit 9d861406c0
5 changed files with 17 additions and 58 deletions

View File

@ -1499,7 +1499,6 @@ void ApplyStablizer(FrontStablizer *Stablizer, FloatBufferLine *Buffer, const in
}
}
const SplitterAllpass &APFilter = Stablizer->APFilter;
ALfloat (&lsplit)[2][BUFFERSIZE] = Stablizer->LSplit;
ALfloat (&rsplit)[2][BUFFERSIZE] = Stablizer->RSplit;
auto &tmpbuf = Stablizer->TempBuf;
@ -1507,7 +1506,7 @@ void ApplyStablizer(FrontStablizer *Stablizer, FloatBufferLine *Buffer, const in
/* This applies the band-splitter, preserving phase at the cost of some
* delay. The shorter the delay, the more error seeps into the result.
*/
auto apply_splitter = [&APFilter,&tmpbuf,SamplesToDo](const FloatBufferLine &Buffer,
auto apply_splitter = [&tmpbuf,SamplesToDo](const FloatBufferLine &Buffer,
ALfloat (&DelayBuf)[FrontStablizer::DelayLength], BandSplitter &Filter,
ALfloat (&splitbuf)[2][BUFFERSIZE]) -> void
{
@ -1522,13 +1521,9 @@ void ApplyStablizer(FrontStablizer *Stablizer, FloatBufferLine *Buffer, const in
std::copy_n(std::begin(tmpbuf), FrontStablizer::DelayLength, std::begin(DelayBuf));
/* Apply an all-pass on the reversed signal, then reverse the samples
* to get the forward signal with a reversed phase shift. Note that the
* all-pass filter is copied to a local for use, since each pass is
* indepedent because the signal's processed backwards (with a delay
* being used to hide discontinuities).
* to get the forward signal with a reversed phase shift.
*/
SplitterAllpass allpass{APFilter};
allpass.process(tmpbuf, SamplesToDo+FrontStablizer::DelayLength);
Filter.applyAllpass(tmpbuf, SamplesToDo+FrontStablizer::DelayLength);
std::reverse(std::begin(tmpbuf), tmpbuf_end+FrontStablizer::DelayLength);
/* Now apply the band-splitter, combining its phase shift with the

View File

@ -94,30 +94,13 @@ void BandSplitterR<Real>::applyHfScale(Real *samples, const Real hfscale, const
this->ap_z1 = ap_z1;
}
template class BandSplitterR<float>;
template class BandSplitterR<double>;
template<typename Real>
void SplitterAllpassR<Real>::init(Real f0norm)
{
const Real w{f0norm * al::MathDefs<Real>::Tau()};
const Real cw{std::cos(w)};
if(cw > std::numeric_limits<float>::epsilon())
coeff = (std::sin(w) - 1.0f) / cw;
else
coeff = cw * -0.5f;
z1 = 0.0f;
}
template<typename Real>
void SplitterAllpassR<Real>::process(Real *samples, int count)
void BandSplitterR<Real>::applyAllpass(Real *samples, const int count) const
{
ASSUME(count > 0);
const Real coeff{this->coeff};
Real z1{this->z1};
Real z1{0.0f};
auto proc_sample = [coeff,&z1](const Real in) noexcept -> Real
{
const Real out{in*coeff + z1};
@ -125,8 +108,8 @@ void SplitterAllpassR<Real>::process(Real *samples, int count)
return out;
};
std::transform(samples, samples+count, samples, proc_sample);
this->z1 = z1;
}
template class SplitterAllpassR<float>;
template class SplitterAllpassR<double>;
template class BandSplitterR<float>;
template class BandSplitterR<double>;

View File

@ -21,36 +21,23 @@ public:
void init(Real f0norm);
void clear() noexcept { lp_z1 = lp_z2 = ap_z1 = 0.0f; }
void process(Real *hpout, Real *lpout, const Real *input, const int count);
void applyHfScale(Real *samples, const Real hfscale, const int count);
/* The all-pass portion of the band splitter. Applies the same phase shift
* without splitting the signal. Note that each use of this method is
* indepedent, it does not track history between calls.
*/
void applyAllpass(Real *samples, const int count) const;
};
using BandSplitter = BandSplitterR<float>;
/* The all-pass portion of the band splitter. Applies the same phase shift
* without splitting the signal.
*/
template<typename Real>
class SplitterAllpassR {
Real coeff{0.0f};
Real z1{0.0f};
public:
SplitterAllpassR() = default;
SplitterAllpassR(const SplitterAllpassR&) = default;
SplitterAllpassR(Real f0norm) { init(f0norm); }
void init(Real f0norm);
void clear() noexcept { z1 = 0.0f; }
void process(Real *samples, int count);
};
using SplitterAllpass = SplitterAllpassR<float>;
struct FrontStablizer {
static constexpr size_t DelayLength{256u};
alignas(16) float DelayBuf[MAX_OUTPUT_CHANNELS][DelayLength];
SplitterAllpass APFilter;
BandSplitter LFilter, RFilter;
alignas(16) float LSplit[2][BUFFERSIZE];
alignas(16) float RSplit[2][BUFFERSIZE];

View File

@ -338,7 +338,6 @@ void BuildBFormatHrtf(const HrtfEntry *Hrtf, DirectHrtfState *state, const ALsiz
static constexpr ALsizei base_delay{DualBand ? 12 : 0};
const ALdouble xover_norm{400.0 / Hrtf->sampleRate};
BandSplitterR<double> splitter{xover_norm};
SplitterAllpassR<double> allpass{xover_norm};
auto tmpres = al::vector<HrirArray<ALdouble>>(NumChannels);
auto tmpfilt = al::vector<std::array<ALdouble,HRIR_LENGTH*4>>(3);
@ -381,8 +380,7 @@ void BuildBFormatHrtf(const HrtfEntry *Hrtf, DirectHrtfState *state, const ALsiz
* sample array. This produces the forward response with a backwards
* phase-shift (+n degrees becomes -n degrees).
*/
allpass.clear();
allpass.process(tmpfilt[2].data(), static_cast<int>(tmpfilt[2].size()));
splitter.applyAllpass(tmpfilt[2].data(), static_cast<int>(tmpfilt[2].size()));
std::reverse(tmpfilt[2].begin(), tmpfilt[2].end());
/* Now apply the band-splitter. This applies the normal phase-shift,
@ -408,8 +406,7 @@ void BuildBFormatHrtf(const HrtfEntry *Hrtf, DirectHrtfState *state, const ALsiz
std::transform(fir, fir+Hrtf->irSize, tmpfilt[2].rbegin() + HRIR_LENGTH*3,
[](const ALfloat (&ir)[2]) noexcept -> ALdouble { return ir[1]; });
allpass.clear();
allpass.process(tmpfilt[2].data(), static_cast<int>(tmpfilt[2].size()));
splitter.applyAllpass(tmpfilt[2].data(), static_cast<int>(tmpfilt[2].size()));
std::reverse(tmpfilt[2].begin(), tmpfilt[2].end());
splitter.clear();

View File

@ -841,9 +841,6 @@ void aluInitRenderer(ALCdevice *device, ALint hrtf_id, HrtfRequestMode hrtf_appr
stablizer->LFilter.init(scale);
stablizer->RFilter = stablizer->LFilter;
/* Initialize an all-pass filter for the phase corrector. */
stablizer->APFilter.init(scale);
device->Stablizer = std::move(stablizer);
/* NOTE: Don't know why this has to be "copied" into a local
* static constexpr variable to avoid a reference on