32template <
typename SampleType =
float>
53template <
typename SampleType =
float>
67 bands_.reserve(bands.size());
68 for (
auto& b : bands) {
69 if (!b.samples.empty()) bands_.push_back(std::move(b));
71 std::sort(bands_.begin(), bands_.end(),
74 return a.max_frequency_hz < b.max_frequency_hz;
76 target_band_ = select_band_for(frequency_);
77 crossfade_source_ = target_band_;
81 if (sr > SampleType{0.0f}) sample_rate_ = sr;
84 if (hz <= SampleType{0.0f})
return;
86 const int new_band = select_band_for(frequency_);
87 if (new_band != target_band_) {
94 if (crossfade_samples_remaining_ > 0) {
95 in_flight_source_ = crossfade_source_;
96 in_flight_target_ = target_band_;
97 in_flight_remaining_ = crossfade_samples_remaining_;
98 has_in_flight_ =
true;
100 has_in_flight_ =
false;
102 crossfade_source_ = target_band_;
103 target_band_ = new_band;
117 if (hz <= SampleType{0.0f})
return;
119 target_band_ = select_band_for(frequency_);
120 crossfade_source_ = target_band_;
121 crossfade_samples_remaining_ = 0;
122 has_in_flight_ =
false;
123 in_flight_remaining_ = 0;
128 crossfade_samples_remaining_ = 0;
129 crossfade_source_ = target_band_;
130 has_in_flight_ =
false;
131 in_flight_remaining_ = 0;
137 if (bands_.empty())
return SampleType{0.0f};
139 const SampleType new_sample = sample_band(target_band_, phase_);
140 SampleType out = new_sample;
141 if (crossfade_samples_remaining_ > 0) {
142 const SampleType t = SampleType{1.0f} -
143 (
static_cast<SampleType
>(crossfade_samples_remaining_) /
149 SampleType source_sample;
150 if (has_in_flight_ && in_flight_remaining_ > 0) {
151 const SampleType old_t = SampleType{1.0f}
152 - (
static_cast<SampleType
>(in_flight_remaining_)
154 const SampleType old_src = sample_band(in_flight_source_, phase_);
155 const SampleType old_tgt = sample_band(in_flight_target_, phase_);
156 source_sample = old_src * (SampleType{1.0f} - old_t) + old_tgt * old_t;
157 --in_flight_remaining_;
158 if (in_flight_remaining_ == 0) has_in_flight_ =
false;
160 source_sample = sample_band(crossfade_source_, phase_);
161 has_in_flight_ =
false;
163 out = source_sample * (SampleType{1.0f} - t) + new_sample * t;
164 --crossfade_samples_remaining_;
167 const SampleType dt = frequency_ / sample_rate_;
169 while (phase_ >= SampleType{1.0f}) phase_ -= SampleType{1.0f};
170 while (phase_ < SampleType{0.0f}) phase_ += SampleType{1.0f};
184 return i < bands_.size() ? bands_[
i].max_frequency_hz : SampleType{0.0f};
193 std::size_t table_length = 2048,
194 SampleType reference_sample_rate = SampleType{48000.0f});
196 std::size_t bands = 10,
197 std::size_t table_length = 2048,
198 SampleType reference_sample_rate = SampleType{48000.0f});
200 std::size_t bands = 10,
201 std::size_t table_length = 2048,
202 SampleType reference_sample_rate = SampleType{48000.0f});
204 std::size_t bands = 10,
205 std::size_t table_length = 2048,
206 SampleType reference_sample_rate = SampleType{48000.0f});
209 int select_band_for(SampleType hz)
const {
210 if (bands_.empty())
return 0;
211 for (std::size_t
i = 0;
i < bands_.size(); ++
i) {
212 if (hz <= bands_[
i].max_frequency_hz)
return static_cast<int>(
i);
214 return static_cast<int>(bands_.size() - 1);
216 SampleType sample_band(
int band, SampleType phase)
const {
217 if (band < 0 ||
static_cast<std::size_t
>(band) >= bands_.size())
218 return SampleType{0.0f};
219 const auto& table = bands_[band].samples;
220 if (table.empty())
return SampleType{0.0f};
221 const SampleType
n =
static_cast<SampleType
>(table.size());
222 const SampleType pos = phase *
n;
223 const std::size_t i0 =
static_cast<std::size_t
>(std::floor(pos)) % table.size();
224 const std::size_t i1 = (i0 + 1) % table.size();
225 const SampleType frac = pos - std::floor(pos);
226 return table[i0] * (SampleType{1.0f} - frac) + table[i1] * frac;
229 std::vector<WavetableEntryT<SampleType>> bands_;
230 SampleType sample_rate_ = SampleType{48000.0f};
231 SampleType frequency_ = SampleType{440.0f};
232 SampleType phase_ = SampleType{0.0f};
233 int target_band_ = 0;
234 int crossfade_source_ = 0;
235 std::size_t crossfade_samples_remaining_ = 0;
238 bool has_in_flight_ =
false;
239 int in_flight_source_ = 0;
240 int in_flight_target_ = 0;
241 std::size_t in_flight_remaining_ = 0;
250template <
typename SampleType =
float>
255 : tables_(
std::move(waveforms)) {}
258 for (
auto& t : tables_) t.set_sample_rate(sr);
261 for (
auto& t : tables_) t.set_frequency(hz);
267 for (
auto& t : tables_) t.set_frequency_immediate(hz);
270 position_ = std::clamp(pos, SampleType{0.0f}, SampleType{1.0f});
274 if (tables_.empty())
return SampleType{0.0f};
275 if (tables_.size() == 1)
return tables_.front().next();
277 const SampleType scaled =
278 position_ *
static_cast<SampleType
>(tables_.size() - 1);
279 const std::size_t lo =
static_cast<std::size_t
>(std::floor(scaled));
280 const std::size_t hi = std::min(lo + 1, tables_.size() - 1);
281 const SampleType frac = scaled -
static_cast<SampleType
>(lo);
285 SampleType lo_sample = SampleType{0.0f};
286 SampleType hi_sample = SampleType{0.0f};
287 for (std::size_t
i = 0;
i < tables_.size(); ++
i) {
288 const SampleType s = tables_[
i].next();
289 if (
i == lo) lo_sample = s;
290 if (
i == hi) hi_sample = s;
292 return lo_sample * (SampleType{1.0f} - frac) + hi_sample * frac;
296 for (
auto& t : tables_) t.reset();
299 std::size_t
size()
const {
return tables_.size(); }
302 std::vector<WavetableT<SampleType>> tables_;
303 SampleType position_ = SampleType{0.0f};
315template <
typename SampleType>
317 static_cast<SampleType
>(6.283185307179586476925286766559L);
322template <
typename SampleType>
324 std::size_t num_bands, SampleType reference_sample_rate) {
325 if (num_bands == 0 || !(reference_sample_rate > SampleType{0.0f}))
return {};
326 const SampleType nyquist = reference_sample_rate * SampleType{0.5f};
327 constexpr SampleType kBaseFreq = SampleType{20.0f};
328 std::vector<SampleType> ceilings;
329 ceilings.reserve(num_bands);
330 const SampleType
ratio =
331 std::pow(nyquist / kBaseFreq,
332 SampleType{1.0f} /
static_cast<SampleType
>(num_bands));
333 SampleType ceiling = kBaseFreq;
334 for (std::size_t b = 0; b < num_bands; ++b) {
336 ceilings.push_back(std::min(ceiling, nyquist));
341template <
typename SampleType,
typename HarmonicAmp>
343 std::size_t max_harmonic,
344 HarmonicAmp&& harmonic_amp) {
345 std::vector<SampleType> samples(length, SampleType{0.0f});
346 if (length == 0 || max_harmonic == 0)
return samples;
347 for (std::size_t
i = 0;
i < length; ++
i) {
348 const SampleType phase =
349 static_cast<SampleType
>(
i) /
static_cast<SampleType
>(length);
350 SampleType s = SampleType{0.0f};
351 for (std::size_t k = 1; k <= max_harmonic; ++k) {
352 const SampleType amp = harmonic_amp(k);
353 if (amp == SampleType{0.0f})
continue;
355 static_cast<SampleType
>(k) * phase);
359 SampleType
peak = SampleType{0.0f};
360 for (SampleType s : samples)
peak = std::max(
peak, std::fabs(s));
361 if (
peak > SampleType{0.0f}) {
362 const SampleType inv = SampleType{1.0f} /
peak;
363 for (SampleType& s : samples) s *= inv;
368template <
typename SampleType,
typename HarmonicAmp>
370 std::size_t num_bands,
371 std::size_t table_length,
372 SampleType reference_sample_rate,
373 HarmonicAmp&& harmonic_amp) {
374 if (num_bands == 0)
return {};
378 if (!(reference_sample_rate > SampleType{0.0f}))
return {};
379 const SampleType nyquist = reference_sample_rate * SampleType{0.5f};
380 std::vector<WavetableEntryT<SampleType>> bands;
381 bands.reserve(num_bands);
382 const auto ceilings =
384 for (
const SampleType clamped_ceiling : ceilings) {
385 std::size_t max_harmonic =
static_cast<std::size_t
>(
386 std::floor(nyquist / clamped_ceiling));
387 if (max_harmonic < 1) max_harmonic = 1;
399template <
typename SampleType>
401 std::size_t table_length,
402 SampleType reference_sample_rate) {
405 if (!(reference_sample_rate > SampleType{0.0f}))
return WavetableT();
406 std::vector<WavetableEntryT<SampleType>> bands;
411 return k == 1 ? SampleType{1.0f} : SampleType{0.0f};
413 reference_sample_rate * SampleType{0.5f},
418template <
typename SampleType>
421 std::size_t table_length,
422 SampleType reference_sample_rate) {
424 bands, table_length, reference_sample_rate,
426 return SampleType{1.0f} /
static_cast<SampleType
>(k);
430template <
typename SampleType>
433 std::size_t table_length,
434 SampleType reference_sample_rate) {
436 bands, table_length, reference_sample_rate,
439 ? SampleType{1.0f} /
static_cast<SampleType
>(k)
444template <
typename SampleType>
447 std::size_t table_length,
448 SampleType reference_sample_rate) {
450 bands, table_length, reference_sample_rate,
452 if (k % 2 == 0)
return SampleType{0.0f};
453 const SampleType kk =
static_cast<SampleType
>(k);
454 const SampleType sign = ((k - 1) / 2) % 2 == 0
457 return sign / (kk * kk);
Linear-interpolated morph across N Wavetables.
Definition wavetable.hpp:251
void set_sample_rate(SampleType sr)
Definition wavetable.hpp:257
WavetableBankT(std::vector< WavetableT< SampleType > > waveforms)
Definition wavetable.hpp:254
void set_position(SampleType pos)
Definition wavetable.hpp:269
SampleType next()
Definition wavetable.hpp:273
void set_frequency(SampleType hz)
Definition wavetable.hpp:260
std::size_t size() const
Definition wavetable.hpp:299
void reset()
Definition wavetable.hpp:295
void set_frequency_immediate(SampleType hz)
Snap every table to the band for hz with no crossfade — the first frequency after construction/reset,...
Definition wavetable.hpp:266
Wavetable oscillator with band-switching.
Definition wavetable.hpp:54
std::size_t band_count() const
Definition wavetable.hpp:174
void set_sample_rate(SampleType sr)
Definition wavetable.hpp:80
void set_frequency_immediate(SampleType hz)
Select the band for hz with NO crossfade — snap straight to it.
Definition wavetable.hpp:116
bool is_crossfading() const
Definition wavetable.hpp:176
static WavetableT make_saw(std::size_t bands=10, std::size_t table_length=2048, SampleType reference_sample_rate=SampleType{48000.0f})
Definition wavetable.hpp:419
void set_frequency(SampleType hz)
Definition wavetable.hpp:83
static WavetableT make_triangle(std::size_t bands=10, std::size_t table_length=2048, SampleType reference_sample_rate=SampleType{48000.0f})
Definition wavetable.hpp:445
int current_band() const
Definition wavetable.hpp:175
SampleType next()
Generate the next sample.
Definition wavetable.hpp:136
WavetableT(std::vector< WavetableEntryT< SampleType > > bands)
Construct from a list of bands.
Definition wavetable.hpp:66
static WavetableT make_square(std::size_t bands=10, std::size_t table_length=2048, SampleType reference_sample_rate=SampleType{48000.0f})
Definition wavetable.hpp:431
void reset()
Definition wavetable.hpp:126
SampleType band_max_frequency_hz(std::size_t i) const
Upper alias-free playback frequency of band i — its max_frequency_hz, the ceiling select_band_for com...
Definition wavetable.hpp:183
static WavetableT make_sine(std::size_t table_length=2048, SampleType reference_sample_rate=SampleType{48000.0f})
Compose a stack of harmonic-based bands for one of the four classical shapes (sine,...
Definition wavetable.hpp:400
static constexpr std::size_t kCrossfadeSamples
Definition wavetable.hpp:59
Round-2 effect-wave vocabulary.
Definition analysis_frontends.hpp:50
std::vector< SampleType > generate_wavetable(std::size_t length, std::size_t max_harmonic, HarmonicAmp &&harmonic_amp)
Definition wavetable.hpp:342
std::vector< SampleType > build_wavetable_band_ceilings(std::size_t num_bands, SampleType reference_sample_rate)
Shared ceiling plan for synthesized and authored wavetable stacks.
Definition wavetable.hpp:323
constexpr SampleType kWavetableTwoPi
Definition wavetable.hpp:316
std::vector< WavetableEntryT< SampleType > > build_wavetable_band_stack(std::size_t num_bands, std::size_t table_length, SampleType reference_sample_rate, HarmonicAmp &&harmonic_amp)
Definition wavetable.hpp:369
Definition additive_bank.hpp:218
@ peak
Sample peak. Literal, fastest-responding.
Definition feedforward_compressor.hpp:119
WavetableBankT< float > WavetableBank
Definition wavetable.hpp:308
WavetableBankT< double > WavetableBank64
Definition wavetable.hpp:309
@ ratio
base_frequency_hz * ratio.
Definition fm_operator_engine.hpp:20
WavetableEntryT< float > WavetableEntry
Definition wavetable.hpp:38
@ a
Definition formant_filter_bank.hpp:20
@ i
Definition formant_filter_bank.hpp:20
WavetableEntryT< double > WavetableEntry64
Definition wavetable.hpp:39
WavetableT< double > Wavetable64
Definition wavetable.hpp:307
WavetableT< float > Wavetable
Definition wavetable.hpp:306
@ n
Definition input_events.hpp:40
One single-cycle wavetable plus the maximum playback frequency it remains bandlimited at.
Definition wavetable.hpp:33
std::vector< float > samples
Definition wavetable.hpp:34
float max_frequency_hz
Definition wavetable.hpp:35