Add a method to process two biquads at once
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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
@@ -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
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user