Add a method to process two biquads at once

This commit is contained in:
Chris Robinson
2020-04-23 22:13:52 -07:00
parent e89978195f
commit 8739833770
4 changed files with 61 additions and 16 deletions
+1 -4
View File
@@ -301,10 +301,7 @@ struct T60Filter {
/* Applies the two T60 damping filter sections. */
void process(const al::span<float> samples)
{
HFFilter.process(samples, samples.begin());
LFFilter.process(samples, samples.begin());
}
{ DualBiquad{HFFilter, LFFilter}.process(samples, samples.data()); }
};
struct EarlyReflections {
+39
View File
@@ -120,5 +120,44 @@ void BiquadFilterR<Real>::process(const al::span<const Real> src, Real *dst)
mZ2 = z2;
}
template<typename Real>
void BiquadFilterR<Real>::dualProcess(BiquadFilterR &other, const al::span<const Real> src,
Real *dst)
{
const Real b00{mB0};
const Real b01{mB1};
const Real b02{mB2};
const Real a01{mA1};
const Real a02{mA2};
const Real b10{other.mB0};
const Real b11{other.mB1};
const Real b12{other.mB2};
const Real a11{other.mA1};
const Real a12{other.mA2};
Real z01{mZ1};
Real z02{mZ2};
Real z11{other.mZ1};
Real z12{other.mZ2};
auto proc_sample = [b00,b01,b02,a01,a02,b10,b11,b12,a11,a12,&z01,&z02,&z11,&z12](Real input) noexcept -> Real
{
const Real tmpout{input*b00 + z01};
z01 = input*b01 - tmpout*a01 + z02;
z02 = input*b02 - tmpout*a02;
input = tmpout;
const Real output{input*b10 + z11};
z11 = input*b11 - output*a11 + z12;
z12 = input*b12 - output*a12;
return output;
};
std::transform(src.cbegin(), src.cend(), dst, proc_sample);
mZ1 = z01;
mZ2 = z02;
other.mZ1 = z11;
other.mZ2 = z12;
}
template class BiquadFilterR<float>;
template class BiquadFilterR<double>;
+11 -1
View File
@@ -114,8 +114,9 @@ public:
mA2 = other.mA2;
}
void process(const al::span<const Real> src, Real *dst);
/** Processes this filter and the other at the same time. */
void dualProcess(BiquadFilterR &other, const al::span<const Real> src, Real *dst);
/* Rather hacky. It's just here to support "manual" processing. */
std::pair<Real,Real> getComponents() const noexcept { return {mZ1, mZ2}; }
@@ -129,6 +130,15 @@ public:
}
};
template<typename Real>
struct DualBiquadR {
BiquadFilterR<Real> &f0, &f1;
void process(const al::span<const Real> src, Real *dst)
{ f0.dualProcess(f1, src, dst); }
};
using BiquadFilter = BiquadFilterR<float>;
using DualBiquad = DualBiquadR<float>;
#endif /* FILTERS_BIQUAD_H */
+10 -11
View File
@@ -309,28 +309,27 @@ void SendSourceStoppedEvent(ALCcontext *context, ALuint id)
}
const float *DoFilters(BiquadFilter *lpfilter, BiquadFilter *hpfilter, float *dst,
const float *DoFilters(BiquadFilter &lpfilter, BiquadFilter &hpfilter, float *dst,
const al::span<const float> src, int type)
{
switch(type)
{
case AF_None:
lpfilter->clear();
hpfilter->clear();
lpfilter.clear();
hpfilter.clear();
break;
case AF_LowPass:
lpfilter->process(src, dst);
hpfilter->clear();
lpfilter.process(src, dst);
hpfilter.clear();
return dst;
case AF_HighPass:
lpfilter->clear();
hpfilter->process(src, dst);
lpfilter.clear();
hpfilter.process(src, dst);
return dst;
case AF_BandPass:
lpfilter->process(src, dst);
hpfilter->process({dst, src.size()}, dst);
DualBiquad{lpfilter, hpfilter}.process(src, dst);
return dst;
}
return src.data();
@@ -765,7 +764,7 @@ void Voice::mix(const State vstate, ALCcontext *Context, const ALuint SamplesToD
float (&FilterBuf)[BUFFERSIZE] = Device->FilteredData;
{
DirectParams &parms = chandata.mDryParams;
const float *samples{DoFilters(&parms.LowPass, &parms.HighPass, FilterBuf,
const float *samples{DoFilters(parms.LowPass, parms.HighPass, FilterBuf,
{ResampledData, DstBufferSize}, mDirect.FilterType)};
if((mFlags&VOICE_HAS_HRTF))
@@ -797,7 +796,7 @@ void Voice::mix(const State vstate, ALCcontext *Context, const ALuint SamplesToD
continue;
SendParams &parms = chandata.mWetParams[send];
const float *samples{DoFilters(&parms.LowPass, &parms.HighPass, FilterBuf,
const float *samples{DoFilters(parms.LowPass, parms.HighPass, FilterBuf,
{ResampledData, DstBufferSize}, mSend[send].FilterType)};
const float *TargetGains{UNLIKELY(vstate == Stopping) ? SilentTarget.data()