Avoid a separate struct for the bandsplitter all-pass
This commit is contained in:
parent
4522a51ea2
commit
9d861406c0
11
Alc/alu.cpp
11
Alc/alu.cpp
@ -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
|
||||
|
@ -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>;
|
||||
|
@ -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];
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user