74template <
typename SampleType, LfoConvention Convention>
79 enum class Wave : std::uint8_t {
126 sample_rate_ = sample_rate > 0.0 ? sample_rate : 1.0;
128 update_stage_lengths_();
139 restart_lifecycle_();
152 restart_lifecycle_();
163 requested_rate_hz_ = hz;
172 increment_ = 1.0 / std::max(samples, min_period);
173 rate_hz_ = increment_ * sample_rate_;
174 requested_rate_hz_ = rate_hz_;
178 double period_samples()
const {
return increment_ > 0.0 ? 1.0 / increment_ : 0.0; }
187 morph_enabled_ =
false;
218 shape_morph_ = std::clamp(m, 0.0f, 3.0f);
219 morph_enabled_ =
true;
259 phase_offset_ = wrap01(cycles01);
261 stereo_offset_ = wrap01(cycles01);
269 delay_ms_ = std::clamp(ms, 0.0, 120000.0);
270 update_stage_lengths_();
276 fade_in_ms_ = std::clamp(ms, 0.0, 120000.0);
277 update_stage_lengths_();
283 fade_out_ms_ = std::clamp(ms, 0.0, 120000.0);
284 fade_out_enabled_ = enabled;
285 update_stage_lengths_();
315 return band_limited_;
334 const double p = wrap01(phase_ +
static_cast<double>(phase_offset_));
335 update_chain_(chains_[0], p);
336 return static_cast<SampleType
>(envelope_() * shape_(p, chains_[0]));
338 const double span =
static_cast<double>(samples) * increment_;
339 const bool deterministic =
341 const int limit = effective_repeat_();
342 const bool ends_this_block =
343 limit > 0 && cycles_ +
static_cast<long long>(std::floor(phase_ + span)) >= limit;
344 if (stage_ !=
Stage::sustain || !deterministic || ends_this_block) {
346 for (
int i = 0;
i < samples; ++
i)
347 acc +=
static_cast<double>(
next());
348 return static_cast<SampleType
>(acc /
static_cast<double>(samples));
353 const double p = wrap01(phase_ +
static_cast<double>(phase_offset_)) - 0.5 * increment_;
354 const float env = envelope_();
356 morph_enabled_ ? morph_mean_(p, p + span) : wave_mean_(wave_, p, p + span);
359 const double whole = std::floor(phase_);
361 cycles_ +=
static_cast<long long>(whole);
362 on_cycles_completed_();
364 return static_cast<SampleType
>(
static_cast<double>(env) * mean);
372 return wrap01(phase_ +
static_cast<double>(phase_offset_));
381 const float env = envelope_();
382 const double p = wrap01(phase_ +
static_cast<double>(phase_offset_));
383 update_chain_(chains_[0], p);
385 return static_cast<SampleType
>(
static_cast<double>(env)
386 * legacy_effect_shape_(p, chains_[0]));
387 const float value = shape_(p, chains_[0]);
389 return static_cast<SampleType
>(env * value);
408 const float env = envelope_();
409 const double pl = wrap01(phase_ +
static_cast<double>(phase_offset_));
410 update_chain_(chains_[0], pl);
411 const float l = shape_(pl, chains_[0]);
413 if (stereo_offset_ != 0.0f) {
414 const double pr = wrap01(pl +
static_cast<double>(stereo_offset_));
415 update_chain_(chains_[1], pr);
416 r = shape_(pr, chains_[1]);
418 left =
static_cast<SampleType
>(env * l);
419 right =
static_cast<SampleType
>(env * r);
429 const float env = envelope_();
430 const double p = wrap01(phase_ +
static_cast<double>(phase_offset_));
431 update_chain_(chains_[0], p);
432 const double angle = 6.283185307179586477 * p;
434 sine_out =
static_cast<SampleType
>(
static_cast<double>(env) * std::sin(angle));
435 cosine_out =
static_cast<SampleType
>(
static_cast<double>(env) * std::cos(angle));
438 sine_out =
static_cast<SampleType
>(env *
static_cast<float>(std::sin(angle)));
439 cosine_out =
static_cast<SampleType
>(env *
static_cast<float>(std::cos(angle)));
447 float glide_prev = 0.0f;
448 float glide_next = 0.0f;
449 float seg_frac = 0.0f;
451 float prev_phase = 2.0f;
454 float smooth()
const {
455 const float w = 0.5f - 0.5f * std::cos(3.14159265358979324f * seg_frac);
456 return glide_prev + (glide_next - glide_prev) * w;
460 static double wrap01(
double x) {
return x - std::floor(x); }
461 static float wrap01(
float x) {
return x - std::floor(x); }
463 void update_increment_() {
468 rate_hz_ = std::clamp(requested_rate_hz_, min_rate,
469 std::max(min_rate, max_rate));
470 increment_ = rate_hz_ / sample_rate_;
473 void update_stage_lengths_() {
474 delay_samples_ =
static_cast<long long>(std::lround(delay_ms_ * 0.001 * sample_rate_));
475 fade_in_samples_ =
static_cast<long long>(std::lround(fade_in_ms_ * 0.001 * sample_rate_));
476 fade_out_samples_ =
static_cast<long long>(std::lround(fade_out_ms_ * 0.001 * sample_rate_));
479 void seed_chains_() {
480 chains_[0] = RandomChain{};
481 chains_[1] = RandomChain{};
482 chains_[0].rng.seed(
static_cast<std::uint32_t
>(
mix64(seed_) & 0xFFFFFFFFu));
483 chains_[1].rng.seed(
static_cast<std::uint32_t
>(
mix64(seed_ ^ 0x5DEECE66Du) >> 32));
486 void restart_lifecycle_() {
488 fade_out_start_ = 1.0f;
497 void restart_if_idle_() {
498 if (stage_pos_ == 0 && cycles_ == 0 && phase_ == 0.0) restart_lifecycle_();
501 int effective_repeat_()
const {
503 return repeat_count_;
506 float fade_shape_(
float t)
const {
507 const float c = std::clamp(t, 0.0f, 1.0f);
511 float envelope_()
const {
516 if (fade_in_samples_ <= 0)
return 1.0f;
517 return fade_shape_(
static_cast<float>(stage_pos_)
518 /
static_cast<float>(fade_in_samples_));
522 if (fade_out_samples_ <= 0)
return 0.0f;
523 return fade_out_start_
524 * (1.0f - fade_shape_(
static_cast<float>(stage_pos_)
525 /
static_cast<float>(fade_out_samples_)));
533 const Stage before = stage_;
534 advance_lifecycle_();
539 void advance_lifecycle_() {
542 if (++stage_pos_ >= delay_samples_) {
548 if (++stage_pos_ >= fade_in_samples_) {
554 if (++stage_pos_ >= fade_out_samples_) {
566 void advance_phase_() {
567 phase_ += increment_;
569 const double whole = std::floor(phase_);
571 cycles_ +=
static_cast<long long>(
whole);
572 on_cycles_completed_();
576 void on_cycles_completed_() {
577 const int limit = effective_repeat_();
578 if (limit <= 0 || cycles_ < limit)
return;
580 if (fade_out_enabled_ && fade_out_samples_ > 0) {
581 fade_out_start_ = envelope_();
590 void update_chain_(RandomChain&
c,
double phase) {
591 const auto p =
static_cast<float>(
phase);
592 if (!
c.primed || p <
c.prev_phase) {
593 c.sh =
c.rng.next_bipolar();
597 const float scaled =
p *
static_cast<float>(segments_);
598 int seg =
static_cast<int>(scaled);
599 seg = std::clamp(seg, 0, segments_ - 1);
600 if (seg !=
c.seg_index) {
601 c.glide_prev =
c.seg_index < 0 ?
c.rng.next_bipolar() :
c.glide_next;
602 c.glide_next =
c.rng.next_bipolar();
605 c.seg_frac = std::clamp(scaled -
static_cast<float>(seg), 0.0f, 1.0f);
608 static constexpr LfoWave sampling_wave_(
Wave w)
noexcept {
628 LfoShapeParams shape_params_() const noexcept {
629 LfoShapeParams params;
630 params.pulse_width =
static_cast<double>(pulse_width_);
631 params.triangle_peak =
632 static_cast<double>(std::clamp(0.5f + 0.5f * tri_bias_, 1.0e-4f, 1.0f - 1.0e-4f));
636 double wave_mean_(
Wave w,
double from,
double to)
const noexcept {
637 return lfo_wave_mean(sampling_wave_(w), from, to, shape_params_());
640 double morph_mean_(
double from,
double to)
const noexcept {
643 int index =
static_cast<int>(shape_morph_);
644 index = std::clamp(index, 0, 2);
645 const double w =
static_cast<double>(shape_morph_ -
static_cast<float>(
index));
646 const double a = wave_mean_(kMorphOrder[index], from, to);
649 const double b = wave_mean_(kMorphOrder[index + 1], from, to);
650 return a +
w * (
b -
a);
653 float pure_wave_(
Wave w,
double phase,
const RandomChain&
c)
const {
657 return static_cast<float>(
660 const auto p =
static_cast<float>(
phase);
663 return static_cast<float>(std::sin(6.283185307179586477 *
phase));
666 if (p < 0.25f)
return 4.0f *
p;
667 if (p < 0.75f)
return 2.0f - 4.0f *
p;
668 return 4.0f *
p - 4.0f;
670 const float peak = std::clamp(0.5f + 0.5f * tri_bias_, 1.0e-4f, 1.0f - 1.0e-4f);
671 if (p <
peak)
return -1.0f + 2.0f * (
p /
peak);
672 return 1.0f - 2.0f * ((
p -
peak) / (1.0f -
peak));
675 return 2.0f *
p - 1.0f;
677 return 1.0f - 2.0f *
p;
679 return p < pulse_width_ ? 1.0f : -1.0f;
693 double legacy_effect_shape_(
double p,
const RandomChain&
c)
const {
695 case Wave::sine:
return std::sin(6.283185307179586477 * p);
697 if (p < 0.25)
return 4.0 *
p;
698 if (p < 0.75)
return 2.0 - 4.0 *
p;
699 return 4.0 *
p - 4.0;
702 case Wave::square:
return p < static_cast<double>(pulse_width_) ? 1.0 : -1.0;
705 default:
return static_cast<double>(shape_(p,
c));
709 float morph_shape_(
double phase,
const RandomChain&
c)
const {
710 static constexpr Wave kMorphOrder[4] = {
712 int index =
static_cast<int>(shape_morph_);
713 index = std::clamp(index, 0, 2);
714 const float w = shape_morph_ -
static_cast<float>(
index);
718 if (w == 0.0f)
return pure_wave_(kMorphOrder[index],
phase,
c);
719 if (w == 1.0f)
return pure_wave_(kMorphOrder[index + 1],
phase,
c);
720 const float a = pure_wave_(kMorphOrder[index],
phase,
c);
721 const float b = pure_wave_(kMorphOrder[index + 1],
phase,
c);
722 return a +
w * (
b -
a);
725 float shape_(
double phase,
const RandomChain&
c)
const {
726 const float base = morph_enabled_ ? morph_shape_(
phase,
c)
727 : pure_wave_(wave_,
phase,
c);
728 if (random_blend_ <= 0.0f)
return base;
729 return base + random_blend_ * (
c.sh - base);
732 RandomChain chains_[2]{};
734 double sample_rate_ = 48000.0;
735 double rate_hz_ = 1.0;
736 double requested_rate_hz_ = 1.0;
737 double increment_ = 1.0 / 48000.0;
740 double delay_ms_ = 0.0;
741 double fade_in_ms_ = 0.0;
742 double fade_out_ms_ = 0.0;
743 long long delay_samples_ = 0;
744 long long fade_in_samples_ = 0;
745 long long fade_out_samples_ = 0;
746 long long stage_pos_ = 0;
748 double phase_offset_ = 0.0;
749 float stereo_offset_ = 0.0f;
750 float shape_morph_ = 0.0f;
751 float pulse_width_ = 0.5f;
752 float tri_bias_ = 0.0f;
753 float random_blend_ = 0.0f;
754 float fade_out_start_ = 1.0f;
755 bool band_limited_ =
false;
757 std::uint32_t seed_ = 0x12345678u;
759 int repeat_count_ = 0;
762 long long cycles_ = 0;
768 bool morph_enabled_ =
false;
769 bool fade_out_enabled_ =
false;
774template <
typename SampleType =
float>
776template <
typename SampleType =
float>
Xorshift32 (Marsaglia, "Xorshift RNGs", J.
Definition rng.hpp:33
Shared implementation selected by the two explicit public LFO types below.
Definition lfo.hpp:75
void set_fade_out_ms(double ms, bool enabled)
Depth ramps back to 0 after the repeat count is exhausted.
Definition lfo.hpp:282
Stage
Definition lfo.hpp:98
@ sustain
Definition lfo.hpp:98
@ fade_out
Definition lfo.hpp:98
@ fade_in
Definition lfo.hpp:98
@ done
Definition lfo.hpp:98
@ delay
Definition lfo.hpp:98
void prepare(double sample_rate)
Definition lfo.hpp:125
static constexpr double kMaxRateFraction
Rate ceiling as a fraction of the sample rate.
Definition lfo.hpp:107
void set_seed(std::uint32_t s)
Seed for the random waveforms and the random blend.
Definition lfo.hpp:245
SampleType next_unipolar()
Unipolar output in [0, 1].
Definition lfo.hpp:395
double period_samples() const
Definition lfo.hpp:178
Wave
Definition lfo.hpp:79
@ square
Definition lfo.hpp:84
@ saw_down
Definition lfo.hpp:83
@ sine
Definition lfo.hpp:80
@ saw_up
Definition lfo.hpp:82
@ sh_random
Definition lfo.hpp:85
@ smooth_random
Definition lfo.hpp:86
@ triangle
Definition lfo.hpp:81
static constexpr int kMaxRepeatCount
Upper bound on set_repeat_count().
Definition lfo.hpp:121
void next_quadrature(SampleType &sine_out, SampleType &cosine_out)
Exact sine/cosine pair at the current phase, regardless of the selected waveform.
Definition lfo.hpp:427
void set_delay_ms(double ms)
Silence (a neutral output) before the LFO starts.
Definition lfo.hpp:268
void set_repeat_count(int n)
0 = run forever.
Definition lfo.hpp:293
Wave wave() const
Definition lfo.hpp:199
void set_band_limited(bool on)
Band-limit the deterministic waves at audio rates: the triangle, saws and square take the polyBLEP / ...
Definition lfo.hpp:307
void set_mode(Mode m)
Definition lfo.hpp:295
bool shape_morph_enabled() const
Definition lfo.hpp:223
void set_random_segments(int n)
Targets latched per cycle in smooth_random.
Definition lfo.hpp:241
Mode
free runs from reset() and ignores retrigger() — that is what "free running" means,...
Definition lfo.hpp:94
@ one_shot
Definition lfo.hpp:94
@ free
Definition lfo.hpp:94
@ retrig
Definition lfo.hpp:94
void set_shape_morph_enabled(bool on)
Definition lfo.hpp:222
static constexpr int kMaxRandomSegments
Definition lfo.hpp:118
void set_tri_bias(float b)
Rise/fall skew of the triangle.
Definition lfo.hpp:230
FadeCurve
Definition lfo.hpp:96
@ linear
Definition lfo.hpp:96
@ quadratic
Definition lfo.hpp:96
bool band_limited() const
Definition lfo.hpp:312
void set_rate_hz(double hz)
Free-running rate.
Definition lfo.hpp:162
void set_fade_in_ms(double ms)
Depth ramps 0 -> 1 over this time once the delay expires.
Definition lfo.hpp:275
double phase() const
Definition lfo.hpp:370
LfoWave wave() const
Definition lfo.hpp:200
void set_fade_curve(FadeCurve c)
Definition lfo.hpp:288
void set_wave(LfoWave w)
Definition lfo.hpp:186
Mode mode() const
Definition lfo.hpp:296
void set_phase_offset(double cycles01)
Output phase offset in cycles (0..1); present a 0-360 degree control.
Definition lfo.hpp:253
bool finished() const
Definition lfo.hpp:368
long long cycles_completed() const
Definition lfo.hpp:369
SampleType next_mean(int samples)
The mean of the next samples outputs, advancing by that many samples: the band-limited value for a co...
Definition lfo.hpp:330
static constexpr double kMinRateHz
Rate floor.
Definition lfo.hpp:102
static constexpr bool kEffectConvention
Definition lfo.hpp:77
void set_random_blend(float b)
Crossfade the chosen waveform against a per-cycle sample-and-hold random value — "how random is this ...
Definition lfo.hpp:235
Stage stage() const
Definition lfo.hpp:367
static constexpr double kMaxRateHz
Ceiling of the bounded effect-LFO lane.
Definition lfo.hpp:111
void next_stereo(SampleType &left, SampleType &right)
The stereo pair: the same LFO evaluated at phase and phase + stereo_offset.
Definition lfo.hpp:407
void set_pulse_width(float pw)
Duty cycle of the square wave.
Definition lfo.hpp:226
SampleType next()
Bipolar output in [-1, 1], scaled by the lifecycle depth envelope.
Definition lfo.hpp:379
double rate_hz() const
Definition lfo.hpp:177
void set_period_samples(double samples)
Synced use.
Definition lfo.hpp:170
static constexpr int kDefaultRandomSegments
Suggested segment count for the N-segment smooth-random mode.
Definition lfo.hpp:116
void set_stereo_offset(double cycles01)
Offset of the right output in next_stereo(), in cycles.
Definition lfo.hpp:257
void retrigger()
Restart phase and the delay/fade lifecycle.
Definition lfo.hpp:148
void set_wave(Wave w)
Definition lfo.hpp:182
void set_shape_morph(float m)
Continuous blend across sine -> triangle -> saw_up -> square as m runs 0 -> 3, by crossfading the adj...
Definition lfo.hpp:217
void reset()
Rewind to a fresh start: phase 0, lifecycle restarted, random streams re-seeded.
Definition lfo.hpp:135
How to SAMPLE an LFO waveform without aliasing, for each kind of consumer.
@ b
Definition pitch.hpp:31
@ index
Definition gpu_pass.hpp:140
Round-2 effect-wave vocabulary.
Definition analysis_frontends.hpp:50
LfoConvention
Selects the waveform/rate convention at the type boundary.
Definition lfo.hpp:68
@ effect
Definition lfo.hpp:68
@ toolkit
Definition lfo.hpp:68
@ whole
Definition units.hpp:287
Definition additive_bank.hpp:218
@ right
Definition multi_channel_meter.hpp:67
@ left
Definition multi_channel_meter.hpp:66
@ peak
Sample peak. Literal, fastest-responding.
Definition feedforward_compressor.hpp:119
@ c
Definition spectrum_trace.hpp:35
constexpr std::uint64_t mix64(std::uint64_t z)
splitmix64 finalizer (Steele, Lea & Flood, OOPSLA 2014).
Definition rng.hpp:140
LfoT< double > Lfo64
Definition lfo.hpp:779
double lfo_wave_bandlimited(LfoWave wave, double phase, double increment, const LfoShapeParams ¶ms={}) noexcept
The band-limited value of wave for a consumer that reads it EVERY sample, at phase with a per-sample ...
Definition lfo_sampling.hpp:196
EffectLfoT< double > EffectLfo64
Definition lfo.hpp:781
LfoT< float > Lfo
Definition lfo.hpp:778
@ a
Definition formant_filter_bank.hpp:20
@ i
Definition formant_filter_bank.hpp:20
LfoWave
The effect-wave vocabulary, shared by these functions and by EffectLfoT (lfo.hpp),...
Definition lfo_sampling.hpp:53
@ sample_hold
Definition lfo_sampling.hpp:59
@ square
Definition lfo_sampling.hpp:58
@ saw_down
Definition lfo_sampling.hpp:57
@ sine
Definition lfo_sampling.hpp:54
@ saw_up
Definition lfo_sampling.hpp:56
@ smooth_random
Definition lfo_sampling.hpp:60
@ triangle
Definition lfo_sampling.hpp:55
float bi_to_uni(float x)
Bipolar [-1, 1] to unipolar [0, 1].
Definition mod_tools.hpp:81
double lfo_wave_mean(LfoWave wave, double from, double to, const LfoShapeParams ¶ms={}) noexcept
The exact mean of wave over the phase interval [from, to], in any units of whole cycles and of any le...
Definition lfo_sampling.hpp:165
EffectLfoT< float > EffectLfo
Definition lfo.hpp:780
@ p
Definition input_events.hpp:40
@ x
Definition input_events.hpp:41
@ w
Definition input_events.hpp:41
Deterministic randomness for modulation: a counter-free PRNG, a Gaussian draw, a stateless purpose-ke...