27 using Series = std::vector<long double>;
28 std::array<DcBlockState, 16> states_{};
30 int stride_ = 1, write_ = 0, latency_ = 0;
32 static Series multiply(
const Series &a,
const Series &b)
34 Series result(a.size());
35 for (std::size_t i = 0; i < a.size(); ++i)
36 for (std::size_t j = 0; i + j < a.size(); ++j)
37 result[i + j] += a[i] * b[j];
40 static Series halfAngle(
const Series &h)
42 auto square = multiply(h, h);
43 Series root(h.size()), product(h.size()), result(h.size());
45 for (std::size_t i = 1; i < h.size(); ++i)
46 product[i] = 4 * square[i - 1] - (i >= 2 ? 4 * square[i - 2] : 0);
48 for (std::size_t i = 1; i < h.size(); ++i)
51 for (std::size_t j = 1; j < i; ++j)
52 sum += root[j] * root[i - j];
53 root[i] = (product[i] - sum) / 2;
56 for (std::size_t i = 0; i < h.size(); ++i)
58 long double value = h[i];
59 for (std::size_t j = 1; j <= i; ++j)
60 value -= root[j] * result[i - j];
61 result[i] = value / root[0];
65 static std::vector<double> ratioTaps(
const Series &h,
double pole)
67 const int order =
static_cast<int>(h.size()) - 1, center = order + 1;
68 Series basis(
static_cast<std::size_t
>(2 * center + 1)), symmetric(basis.size());
70 for (
int k = 0; k <= order; ++k)
72 for (std::size_t i = 0; i < basis.size(); ++i)
73 symmetric[i] += h[k] * basis[i];
76 Series next(basis.size());
77 for (
int j = center - k; j <= center + k; ++j)
79 next[j - 1] -= .25L * basis[j];
80 next[j] += .5L * basis[j];
81 next[j + 1] -= .25L * basis[j];
83 basis = std::move(next);
85 std::vector<double> taps(basis.size());
86 taps[center] = (1 + pole) / 2;
87 const long double b = (1 - pole) / 2;
88 for (std::size_t i = 1; i + 1 < taps.size(); ++i)
90 taps[i - 1] +=
static_cast<double>(b * symmetric[i] / 2);
91 taps[i + 1] -=
static_cast<double>(b * symmetric[i] / 2);
97 [[nodiscard]]
static int filterLength(
int factor,
int sourceFactor)
noexcept
99 if (factor >= sourceFactor)
102 for (
int ratio = sourceFactor / factor; ratio > 1; ratio /= 2)
104 return 1 + 2 * stages * (factor <= 2 ? 25 : 13);
108 [[nodiscard]]
static std::size_t
allocationBound(
int factor,
int sourceFactor)
noexcept
113 const std::size_t order = factor <= 2 ? 24 : 12, n = order + 1, taps = 2 * n + 1;
114 const auto stages =
static_cast<std::size_t
>((length - 1) / (2 * n));
116 (stages + 1 + 4 * (stages - 1)) * n *
sizeof(
long double) + stages *
sizeof(Series);
118 stages * (order + 2) * taps *
sizeof(
long double) +
119 (stages * taps + 1 + stages + n * stages * (stages + 1)) *
sizeof(double);
121 static_cast<std::size_t
>(length) * (
sizeof(std::atomic<double>) + 4 *
sizeof(double)) +
123 return series + kernels + fir + (stages * order + 9 * stages + 4) * 64;
127 if (factor >= sourceFactor)
129 const int ratio = sourceFactor / factor, order = factor <= 2 ? 24 : 12;
131 while ((1 << stages) < ratio)
133 std::vector<Series> series(
static_cast<std::size_t
>(stages),
134 Series(
static_cast<std::size_t
>(order + 1)));
135 for (
int k = 0; k <= order; ++k)
137 for (
int i = 1; i < stages; ++i)
138 series[i] = halfAngle(series[i - 1]);
139 std::vector<double> result{1.};
140 for (
int i = stages - 1; i >= 0; --i)
142 const double pole = std::pow(.9995, ratio / (1 << (i + 1)));
143 auto taps = ratioTaps(series[i], pole);
144 std::vector<double> combined(result.size() + taps.size() - 1);
145 for (std::size_t j = 0; j < result.size(); ++j)
146 for (std::size_t k = 0; k < taps.size(); ++k)
147 combined[j + k] += result[j] * taps[k];
148 result = std::move(combined);
154 assert(factor >= 1 && factor <= 16 && (factor & (factor - 1)) == 0);
155 assert(sourceFactor >= 1 && sourceFactor <= 16 && (sourceFactor & (sourceFactor - 1)) == 0);
156 if (factor >= sourceFactor)
158 stride_ = factor / sourceFactor;
161 pole_ = std::pow(.9995, sourceFactor / factor);
163 latency_ =
static_cast<int>(taps.size() / 2);
164 filter_.
prepare(
static_cast<int>(taps.size()), 1);
179 const double y =
dcBlockStep(pole_, states_[write_], x);
180 write_ = (write_ + 1) % stride_;
double dcBlockStep(double pole, DcBlockState &state, double input) noexcept
Applies (1 - z^-1) / (1 - pole * z^-1), with a pole in [0, 1).