Shared implementation selected by the two explicit public LFO types below. More...
#include <lfo.hpp>
Public Types | |
| enum class | Wave : std::uint8_t { sine , triangle , saw_up , saw_down , square , sh_random , smooth_random } |
| enum class | Mode : std::uint8_t { free , retrig , one_shot } |
| free runs from reset() and ignores retrigger() — that is what "free running" means, and a free LFO that silently restarts on note-on is the single most common LFO bug. More... | |
| enum class | FadeCurve : std::uint8_t { linear , quadratic } |
| enum class | Stage : std::uint8_t { delay , fade_in , sustain , fade_out , done } |
Public Member Functions | |
| void | prepare (double sample_rate) |
| void | reset () |
| Rewind to a fresh start: phase 0, lifecycle restarted, random streams re-seeded. | |
| void | retrigger () |
| Restart phase and the delay/fade lifecycle. | |
| void | set_rate_hz (double hz) |
| Free-running rate. | |
| void | set_period_samples (double samples) |
| Synced use. | |
| double | rate_hz () const |
| double | period_samples () const |
| void | set_wave (Wave w) |
| void | set_wave (LfoWave w) |
| Wave | wave () const |
| LfoWave | wave () const |
| void | set_shape_morph (float m) |
| Continuous blend across sine -> triangle -> saw_up -> square as m runs 0 -> 3, by crossfading the adjacent pair. | |
| void | set_shape_morph_enabled (bool on) |
| bool | shape_morph_enabled () const |
| void | set_pulse_width (float pw) |
| Duty cycle of the square wave. | |
| void | set_tri_bias (float b) |
| Rise/fall skew of the triangle. | |
| void | set_random_blend (float b) |
| Crossfade the chosen waveform against a per-cycle sample-and-hold random value — "how random is this LFO" as one control. | |
| void | set_random_segments (int n) |
| Targets latched per cycle in smooth_random. | |
| void | set_seed (std::uint32_t s) |
| Seed for the random waveforms and the random blend. | |
| void | set_phase_offset (double cycles01) |
| Output phase offset in cycles (0..1); present a 0-360 degree control. | |
| void | set_stereo_offset (double cycles01) |
| Offset of the right output in next_stereo(), in cycles. | |
| void | set_delay_ms (double ms) |
| Silence (a neutral output) before the LFO starts. | |
| void | set_fade_in_ms (double ms) |
| Depth ramps 0 -> 1 over this time once the delay expires. | |
| void | set_fade_out_ms (double ms, bool enabled) |
| Depth ramps back to 0 after the repeat count is exhausted. | |
| void | set_fade_curve (FadeCurve c) |
| void | set_repeat_count (int n) |
| 0 = run forever. | |
| void | set_mode (Mode m) |
| Mode | mode () const |
| void | set_band_limited (bool on) |
| Band-limit the deterministic waves at audio rates: the triangle, saws and square take the polyBLEP / polyBLAMP corrections of lfo_wave_bandlimited at every corner. | |
| bool | band_limited () const |
| SampleType | next_mean (int samples) |
The mean of the next samples outputs, advancing by that many samples: the band-limited value for a consumer that takes ONE value per block (a spectral mask, a filter restage). | |
| Stage | stage () const |
| bool | finished () const |
| long long | cycles_completed () const |
| double | phase () const |
| SampleType | next () |
| Bipolar output in [-1, 1], scaled by the lifecycle depth envelope. | |
| SampleType | next_unipolar () |
| Unipolar output in [0, 1]. | |
| void | next_stereo (SampleType &left, SampleType &right) |
| The stereo pair: the same LFO evaluated at phase and phase + stereo_offset. | |
| void | next_quadrature (SampleType &sine_out, SampleType &cosine_out) |
| Exact sine/cosine pair at the current phase, regardless of the selected waveform. | |
Static Public Attributes | |
| static constexpr bool | kEffectConvention = Convention == LfoConvention::effect |
| static constexpr double | kMinRateHz = 0.001 |
| Rate floor. | |
| static constexpr double | kMaxRateFraction = 0.45 |
| Rate ceiling as a fraction of the sample rate. | |
| static constexpr double | kMaxRateHz = 200.0 |
| Ceiling of the bounded effect-LFO lane. | |
| static constexpr int | kDefaultRandomSegments = 4 |
| Suggested segment count for the N-segment smooth-random mode. | |
| static constexpr int | kMaxRandomSegments = 16 |
| static constexpr int | kMaxRepeatCount = 128 |
| Upper bound on set_repeat_count(). | |
Shared implementation selected by the two explicit public LFO types below.
Keeping the convention in this internal type preserves the one-parameter public LfoT template identity and makes effect behavior impossible to select through precision or setter history.
|
strong |
|
strong |
free runs from reset() and ignores retrigger() — that is what "free running" means, and a free LFO that silently restarts on note-on is the single most common LFO bug.
retrig restarts phase and the lifecycle on every trigger. one_shot is retrig with an implied repeat count of 1 when none is set.
| Enumerator | |
|---|---|
| free | |
| retrig | |
| one_shot | |
|
strong |
|
strong |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
Bipolar output in [-1, 1], scaled by the lifecycle depth envelope.
|
inline |
The mean of the next samples outputs, advancing by that many samples: the band-limited value for a consumer that takes ONE value per block (a spectral mask, a filter restage).
Closed form (lfo_wave_mean) while the LFO sustains a deterministic wave, so a cycle shorter than the block collapses to its average instead of aliasing and a long block costs the same as a short one; a fading, delayed or random LFO, or a block in which a repeat limit would end the LFO, averages next() over the block instead, so the lifecycle reads exactly as it does sample by sample. Zero samples read the current value without advancing. The closed form integrates over the samples' own centres, so for a curved wave it is the discrete average to within the midpoint rule's error, and for a square or saw to within one sample's share of the block.
|
inline |
Exact sine/cosine pair at the current phase, regardless of the selected waveform.
Orthogonal by construction, which is what single-sideband and barberpole effects need — a "quadrature" pair built by offsetting a triangle or a square is not orthogonal and the sidebands do not cancel.
|
inline |
The stereo pair: the same LFO evaluated at phase and phase + stereo_offset.
A zero offset produces bit-identical channels for every waveform, including the random ones — the second latch stream is only engaged when there is actually an offset to decorrelate.
With a nonzero offset the random waveforms give the right channel its own decorrelated latch stream rather than a time-shifted copy of the left, because a time-shifted random stream would require values the generator has not drawn yet. Two decorrelated random walks locked to one rate is also the more useful stereo behavior.
|
inline |
Unipolar output in [0, 1].
During the delay and after the fade out this sits at 0.5 — the neutral value for a unipolar destination, which is what "silence" means for one.
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
Rewind to a fresh start: phase 0, lifecycle restarted, random streams re-seeded.
Deterministic — two reset() LFOs with the same seed produce bit-identical output forever.
|
inline |
Restart phase and the delay/fade lifecycle.
Ignored in free mode.
The random streams deliberately do not re-seed here: a re-seeding retrigger would make every note's "random" modulation identical, which is the opposite of what a random LFO is for. The whole render stays reproducible because reset() is the only seeding point.
|
inline |
Band-limit the deterministic waves at audio rates: the triangle, saws and square take the polyBLEP / polyBLAMP corrections of lfo_wave_bandlimited at every corner.
Off by default, so an existing patch reads bit for bit as before; on, a slow LFO differs from the trivial waveform only on the two samples straddling each corner, and an audio-rate one no longer folds its harmonics into the band. The sine and the random waves are unchanged either way.
|
inline |
Silence (a neutral output) before the LFO starts.
Phase does not advance during the delay, so the wave always begins at its own start.
|
inline |
|
inline |
Depth ramps 0 -> 1 over this time once the delay expires.
|
inline |
Depth ramps back to 0 after the repeat count is exhausted.
|
inline |
|
inline |
Synced use.
Tempo-to-period conversion is the caller's job so one transport read feeds every synced object in the plugin; units::division_to_samples() does the arithmetic.
|
inline |
Output phase offset in cycles (0..1); present a 0-360 degree control.
|
inline |
Duty cycle of the square wave.
|
inline |
Crossfade the chosen waveform against a per-cycle sample-and-hold random value — "how random is this LFO" as one control.
Works with every wave, including the random ones.
|
inline |
Targets latched per cycle in smooth_random.
1 is the plain one-target-per-cycle glide; higher values latch N targets per cycle and cosine-glide between them at N times the rate, which wanders instead of swinging. Audibly a different animal, not just a faster one.
|
inline |
Free-running rate.
The full range is legal, including audio rate; a caller mapping this to a knob should use units::taper_log(). The requested value is kept separately from the effective one, so a rate clamped by a low sample rate is restored by a later prepare() at a higher one instead of being silently lost.
|
inline |
0 = run forever.
Otherwise the LFO completes N cycles and then fades out or stops. Repeat 1 plus a fade out is how you get a shaped one-shot swell out of an oscillator.
|
inline |
Seed for the random waveforms and the random blend.
Applied at the next reset().
|
inline |
Continuous blend across sine -> triangle -> saw_up -> square as m runs 0 -> 3, by crossfading the adjacent pair.
Enables morph mode, which overrides set_wave(). At integer positions the output is bit-identical to the corresponding pure wave.
|
inline |
|
inline |
Offset of the right output in next_stereo(), in cycles.
Present a +/-180 degree control; 0.25 is quadrature.
|
inline |
Rise/fall skew of the triangle.
0 is symmetric; +1 pushes the peak to the end of the cycle (a ramp up with a cliff), -1 to the start.
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
staticconstexpr |
Suggested segment count for the N-segment smooth-random mode.
The default is 1 (one target per cycle, the plain glide); 4 is the setting that produces the wandering character the mode exists for.
|
staticconstexpr |
|
staticconstexpr |
|
staticconstexpr |
Rate ceiling as a fraction of the sample rate.
Above Nyquist the phase accumulator aliases into nonsense; 0.45 keeps the "extended" audio-rate mode usable right up to the edge without crossing it.
|
staticconstexpr |
Ceiling of the bounded effect-LFO lane.
The modulation-toolkit Wave overload keeps its audio-rate ceiling of kMaxRateFraction * fs.
|
staticconstexpr |
Upper bound on set_repeat_count().
|
staticconstexpr |
Rate floor.
One cycle every ~17 minutes; below this the LFO is a constant with extra steps.