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);
120 void build() noexcept
123 constexpr size_t fftSize = 65536;
124 constexpr double pi = std::numbers::pi_v<double>;
130 std::vector<double> x(fftSize, 0.0);
131 std::vector<double> win(n);
133 const double center = 0.5 * (n - 1);
135 for (
int i = 0; i < n; ++i)
137 const double t = (
static_cast<double>(i) - center) /
kOversample;
138 const double s = (std::abs(t) < 1e-9) ? 1.0 : std::sin(
pi * t) / (
pi * t);
139 x[
static_cast<size_t>(i)] = s * win[
static_cast<size_t>(i)];
140 dc += s * win[
static_cast<size_t>(i)];
142 for (
int i = 0; i < n; ++i)
143 x[
static_cast<size_t>(i)] /= dc;
148 FFTReal<double> fft(fftSize);
149 std::vector<double> spec(fftSize + 2);
150 std::vector<double> cep(fftSize);
151 fft.forward(x.data(), spec.data());
153 const size_t bins = fftSize / 2 + 1;
154 for (
size_t k = 0; k < bins; ++k)
156 const double re = spec[2 * k];
157 const double im = spec[2 * k + 1];
163 constexpr double floorMag = 1e-5;
164 const double mag = std::sqrt(re * re + im * im + floorMag * floorMag);
165 spec[2 * k] = std::log(mag);
166 spec[2 * k + 1] = 0.0;
168 fft.inverse(spec.data(), cep.data());
173 for (
size_t q = 1; q < fftSize / 2; ++q)
176 cep[fftSize - q] = 0.0;
181 fft.forward(cep.data(), spec.data());
182 for (
size_t k = 0; k < bins; ++k)
184 const double m = std::exp(spec[2 * k]);
185 const double ph = spec[2 * k + 1];
186 spec[2 * k] = m * std::cos(ph);
187 spec[2 * k + 1] = m * std::sin(ph);
189 fft.inverse(spec.data(), x.data());
195 std::vector<double> step(n);
196 for (
int i = 0; i < n; ++i)
198 acc += x[
static_cast<size_t>(i)];
199 step[
static_cast<size_t>(i)] = acc;
201 const double settle = step[
static_cast<size_t>(n - 1)];
202 for (
int i = 0; i < n; ++i)
203 residual_[
static_cast<size_t>(i)] =
204 static_cast<T
>(step[
static_cast<size_t>(i)] / settle - 1.0);
207 std::array<T, kTableSize> residual_{};