aboutsummaryrefslogtreecommitdiffstats
path: root/alc/filters
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2020-04-23 22:13:52 -0700
committerChris Robinson <[email protected]>2020-04-23 22:13:52 -0700
commit873983377052594b418bfa6cd505df7c604792ea (patch)
tree8b500bb483a079107dfd9feb368e8751f14ce44e /alc/filters
parente89978195f3910693958b8faebbd88b4643f8d57 (diff)
Add a method to process two biquads at once
Diffstat (limited to 'alc/filters')
-rw-r--r--alc/filters/biquad.cpp39
-rw-r--r--alc/filters/biquad.h12
2 files changed, 50 insertions, 1 deletions
diff --git a/alc/filters/biquad.cpp b/alc/filters/biquad.cpp
index 271ca696..fefdc8e1 100644
--- a/alc/filters/biquad.cpp
+++ b/alc/filters/biquad.cpp
@@ -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>;
diff --git a/alc/filters/biquad.h b/alc/filters/biquad.h
index 30eed57d..3ce70cb3 100644
--- a/alc/filters/biquad.h
+++ b/alc/filters/biquad.h
@@ -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 */