26#ifndef SBL_DSP_PRIMITIVES_THIRAN_ALLPASS_HPP_
27#define SBL_DSP_PRIMITIVES_THIRAN_ALLPASS_HPP_
38inline constexpr float binomial(uint8_t n, uint8_t k) {
40 for (uint8_t i = 0; i < k; ++i) {
41 result *=
static_cast<float>(n - i) /
static_cast<float>(i + 1);
55template<u
int8_t N = 1>
57 static_assert(N >= 1,
"Thiran allpass needs at least first order");
58 static_assert(N <= 4,
"high orders cost accuracy in float; use a longer delay line");
70 constexpr float lo =
static_cast<float>(N) - 0.5f;
71 constexpr float hi =
static_cast<float>(N) + 0.5f;
76 for (uint8_t k = 1; k <= N; ++k) {
78 for (uint8_t n = 0; n <= N; ++n) {
79 coeff *= (d -
static_cast<float>(N) +
static_cast<float>(n)) /
80 (d -
static_cast<float>(N) +
static_cast<float>(k + n));
82 a_[k - 1] = (k & 1) ? -coeff : coeff;
93 float y = a_[N - 1] * x;
94 for (uint8_t k = 1; k < N; ++k) {
95 y += a_[N - 1 - k] * x_hist_[k - 1];
98 for (uint8_t k = 1; k <= N; ++k) {
99 y -= a_[k - 1] * y_hist_[k - 1];
102 for (uint8_t i = N - 1; i > 0; --i) {
103 x_hist_[i] = x_hist_[i - 1];
104 y_hist_[i] = y_hist_[i - 1];
115 for (uint8_t i = 0; i < N; ++i) {
121 static constexpr uint8_t
order() {
return N; }
124 static constexpr float min_delay() {
return static_cast<float>(N) - 0.5f; }
125 static constexpr float max_delay() {
return static_cast<float>(N) + 0.5f; }
131 float delay_ =
static_cast<float>(N);
Clamping (Cross-cutting — Math)
Order-N Thiran allpass: fractional delay by phase, not interpolation.
static constexpr float min_delay()
Smallest and largest delay this order can express.
float process(float x)
Process one sample.
void set_delay(float delay_samples)
Set the total phase delay in samples.
float group_delay_samples() const
Phase delay the filter is tuned to, in samples (flat at DC by design).
static constexpr uint8_t order()
static constexpr float max_delay()
constexpr float clamp(float x, float lo, float hi)
x held to [lo, hi]; NaN → lo.
constexpr float binomial(uint8_t n, uint8_t k)
Binomial coefficient C(n, k) for the small orders this filter allows.
Stateful, single-concern building blocks.