40 std::uint64_t target_max_bytes,
41 std::uint64_t& bytes)
noexcept {
42 std::uint64_t elements = 0;
44 static_cast<std::uint64_t
>(2 * std::max(1,
half_width)),
45 UINT64_MAX, elements))
48 if (!charge.
add<SampleType>(elements))
return false;
49 bytes = charge.
total();
70 phases_ = std::max(1, phases);
71 cutoff_ = std::isfinite(
cutoff) ? std::clamp(
cutoff, 1.0e-6, 1.0) : 1.0;
72 const int taps = 2 * half_;
75 table_.assign(
static_cast<size_t>(phases_ + 1) *
taps, SampleType{0.0f});
77 build_i0_beta_ = bessel_i0(beta);
78 next_build_phase_ = 0;
82 if (next_build_phase_ > phases_)
84 const int ph = next_build_phase_;
85 const int taps = 2 * half_;
86 const double frac =
static_cast<double>(ph) / phases_;
88 for (
int t = 0; t <
taps; ++t) {
89 const double x =
static_cast<double>(t - half_ + 1) - frac;
90 const double s = cutoff_ * sinc(cutoff_ * x);
91 const double wn = x / half_;
93 (wn > -1.0 && wn < 1.0)
94 ? bessel_i0(build_beta_ * std::sqrt(1.0 - wn * wn)) / build_i0_beta_
96 table_[
static_cast<size_t>(ph) *
taps + t] =
static_cast<SampleType
>(s * w);
99 if (std::abs(sum) > 1.0e-12)
100 for (
int t = 0; t <
taps; ++t)
101 table_[
static_cast<size_t>(ph) *
taps + t] /=
static_cast<SampleType
>(sum);
103 return next_build_phase_ > phases_;
113 return !table_.empty() && next_build_phase_ > phases_;
119 return table_.capacity() *
sizeof(SampleType);
127 SampleType
apply(
const SampleType* samples,
double frac)
const {
128 const int taps = 2 * half_;
129 const double ph = frac * phases_;
130 const int p0 =
static_cast<int>(ph);
131 const SampleType
a =
static_cast<SampleType
>(ph - p0);
132 const SampleType* row0 = table_.data() +
static_cast<size_t>(p0) *
taps;
133 const SampleType* row1 = table_.data() +
static_cast<size_t>(p0 + 1) *
taps;
134 SampleType acc = SampleType{0.0f};
135 for (
int t = 0; t <
taps; ++t)
136 acc += (row0[t] +
a * (row1[t] - row0[t])) * samples[t];
144 SampleType
read(
const SampleType* src,
int len,
double pos)
const {
145 if (src ==
nullptr || len <= 0 || !
ready() || !std::isfinite(pos))
146 return SampleType{0};
147 pos = std::clamp(pos, 0.0,
static_cast<double>(len - 1));
148 const int taps = 2 * half_;
149 const long i0 =
static_cast<long>(std::floor(pos));
150 const double frac = pos -
static_cast<double>(i0);
152 const double ph = frac * phases_;
153 const int p0 =
static_cast<int>(ph);
154 const SampleType
a =
static_cast<SampleType
>(ph - p0);
155 const SampleType* row0 = table_.data() +
static_cast<size_t>(p0) *
taps;
156 const SampleType* row1 = table_.data() +
static_cast<size_t>(p0 + 1) *
taps;
157 SampleType acc = SampleType{0.0f};
158 for (
int t = 0; t <
taps; ++t) {
159 long idx = i0 + t - half_ + 1;
164 const SampleType k = row0[t] +
a * (row1[t] - row0[t]);
171 static double sinc(
double x) {
172 if (std::abs(x) < 1
e-9)
174 const double px = 3.14159265358979323846 * x;
175 return std::sin(px) / px;
178 static double bessel_i0(
double x) {
179 double sum = 1.0, term = 1.0;
180 const double half_x = x * 0.5;
181 for (
int k = 1; k < 40; ++k) {
182 term *= (half_x / k) * (half_x / k);
184 if (term < 1
e-12 * sum)
192 double cutoff_ = 1.0;
193 std::vector<SampleType> table_;
194 double build_beta_ = 9.0;
195 double build_i0_beta_ = 1.0;
196 int next_build_phase_ = 1;
Definition checked_allocation.hpp:57
bool add(std::uint64_t elements) noexcept
Definition checked_allocation.hpp:63
std::uint64_t total() const noexcept
Definition checked_allocation.hpp:83
Definition sinc_resampler.hpp:37
std::size_t prepared_bytes() const noexcept
Definition sinc_resampler.hpp:118
bool build_step()
Definition sinc_resampler.hpp:81
void build(int half_width=16, int phases=512, double beta=9.0, double cutoff=1.0)
Build the kernel.
Definition sinc_resampler.hpp:59
bool ready() const
Definition sinc_resampler.hpp:112
SampleType apply(const SampleType *samples, double frac) const
Apply the kernel at fractional phase frac (in [0,1)) to exactly taps() contiguous samples,...
Definition sinc_resampler.hpp:127
double cutoff() const
Definition sinc_resampler.hpp:115
SampleType read(const SampleType *src, int len, double pos) const
Read src at fractional position pos (in samples).
Definition sinc_resampler.hpp:144
static bool checked_retained_bytes(int half_width, int phases, std::uint64_t target_max_bytes, std::uint64_t &bytes) noexcept
Definition sinc_resampler.hpp:39
void begin_build(int half_width=16, int phases=512, double beta=9.0, double cutoff=1.0)
Starts a resumable kernel-table build.
Definition sinc_resampler.hpp:67
int taps() const
Definition sinc_resampler.hpp:109
int half_width() const
Definition sinc_resampler.hpp:106
Definition additive_bank.hpp:218
float sinc(float x)
Sinc function: sin(pi*x) / (pi*x), with sinc(0) = 1.
Definition special_functions.hpp:17
bool checked_capacity_product(std::uint64_t lhs, std::uint64_t rhs, std::uint64_t maximum, std::uint64_t &product) noexcept
Definition checked_allocation.hpp:12
SincResamplerT< float > SincResampler
Definition sinc_resampler.hpp:199
@ a
Definition formant_filter_bank.hpp:20
@ e
Definition formant_filter_bank.hpp:20
SincResamplerT< double > SincResampler64
Definition sinc_resampler.hpp:200