73 static_assert(std::is_floating_point_v<T>,
"MinBlepTable requires float or double");
77 static constexpr int kTaps = 64;
108 const auto idx =
static_cast<int>(pos);
111 const T frac = pos -
static_cast<T
>(idx);
112 const T a = residual_[
static_cast<size_t>(idx)];
113 const T b = residual_[
static_cast<size_t>(idx) + 1];
114 return a + frac * (b - a);
128 [[nodiscard]] T
dcDelay() const noexcept {
return dcDelay_; }
133 void build() noexcept
136 constexpr size_t fftSize = 65536;
137 constexpr double pi = std::numbers::pi_v<double>;
143 std::vector<double> x(fftSize, 0.0);
144 std::vector<double> win(n);
146 const double center = 0.5 * (n - 1);
148 for (
int i = 0; i < n; ++i)
150 const double t = (
static_cast<double>(i) - center) /
kOversample;
151 const double s = (std::abs(t) < 1e-9) ? 1.0 : std::sin(
pi * t) / (
pi * t);
152 x[
static_cast<size_t>(i)] = s * win[
static_cast<size_t>(i)];
153 dc += s * win[
static_cast<size_t>(i)];
155 for (
int i = 0; i < n; ++i)
156 x[
static_cast<size_t>(i)] /= dc;
161 FFTReal<double> fft(fftSize);
162 std::vector<double> spec(fftSize + 2);
163 std::vector<double> cep(fftSize);
164 fft.forward(x.data(), spec.data());
166 const size_t bins = fftSize / 2 + 1;
167 for (
size_t k = 0; k < bins; ++k)
169 const double re = spec[2 * k];
170 const double im = spec[2 * k + 1];
176 constexpr double floorMag = 1e-5;
177 const double mag = std::sqrt(re * re + im * im + floorMag * floorMag);
178 spec[2 * k] = std::log(mag);
179 spec[2 * k + 1] = 0.0;
181 fft.inverse(spec.data(), cep.data());
186 for (
size_t q = 1; q < fftSize / 2; ++q)
189 cep[fftSize - q] = 0.0;
194 fft.forward(cep.data(), spec.data());
195 for (
size_t k = 0; k < bins; ++k)
197 const double m = std::exp(spec[2 * k]);
198 const double ph = spec[2 * k + 1];
199 spec[2 * k] = m * std::cos(ph);
200 spec[2 * k + 1] = m * std::sin(ph);
202 fft.inverse(spec.data(), x.data());
208 std::vector<double> step(n);
209 for (
int i = 0; i < n; ++i)
211 acc += x[
static_cast<size_t>(i)];
212 step[
static_cast<size_t>(i)] = acc;
214 const double settle = step[
static_cast<size_t>(n - 1)];
216 for (
int i = 0; i < n; ++i)
218 const double r = step[
static_cast<size_t>(i)] / settle - 1.0;
219 residual_[
static_cast<size_t>(i)] =
static_cast<T
>(r);
222 area += (i == 0 || i == n - 1) ? 0.5 * r : r;
227 std::array<T, kTableSize> residual_{};