Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
pulp::signal::EffectLfoT< SampleType > Class Template Reference

#include <lfo.hpp>

Public Types

enum  Wave
enum  Mode
 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  FadeCurve
enum  Stage

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)
Wave 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
float 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
float next ()
 Bipolar output in [-1, 1], scaled by the lifecycle depth envelope.
float next_unipolar ()
 Unipolar output in [0, 1].
void next_stereo (float &left, float &right)
 The stereo pair: the same LFO evaluated at phase and phase + stereo_offset.
void next_quadrature (float &sine_out, float &cosine_out)
 Exact sine/cosine pair at the current phase, regardless of the selected waveform.

Static Public Attributes

static constexpr bool kEffectConvention
static constexpr double kMinRateHz
 Rate floor.
static constexpr double kMaxRateFraction
 Rate ceiling as a fraction of the sample rate.
static constexpr double kMaxRateHz
 Ceiling of the bounded effect-LFO lane.
static constexpr int kDefaultRandomSegments
 Suggested segment count for the N-segment smooth-random mode.
static constexpr int kMaxRandomSegments
static constexpr int kMaxRepeatCount
 Upper bound on set_repeat_count().

Member Enumeration Documentation

◆ FadeCurve

enum pulp::signal::detail::BasicLfoT::FadeCurve : std::uint8_t
stronginherited

◆ Mode

enum pulp::signal::detail::BasicLfoT::Mode : std::uint8_t
stronginherited

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.

◆ Stage

enum pulp::signal::detail::BasicLfoT::Stage : std::uint8_t
stronginherited

◆ Wave

enum pulp::signal::detail::BasicLfoT::Wave : std::uint8_t
stronginherited

Member Function Documentation

◆ band_limited()

bool pulp::signal::detail::BasicLfoT< float, Convention >::band_limited ( ) const
inlineinherited

◆ cycles_completed()

long long pulp::signal::detail::BasicLfoT< float, Convention >::cycles_completed ( ) const
inlineinherited

◆ finished()

bool pulp::signal::detail::BasicLfoT< float, Convention >::finished ( ) const
inlineinherited

◆ mode()

Mode pulp::signal::detail::BasicLfoT< float, Convention >::mode ( ) const
inlineinherited

◆ next()

float pulp::signal::detail::BasicLfoT< float, Convention >::next ( )
inlineinherited

Bipolar output in [-1, 1], scaled by the lifecycle depth envelope.

◆ next_mean()

float pulp::signal::detail::BasicLfoT< float, Convention >::next_mean ( int samples)
inlineinherited

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.

◆ next_quadrature()

void pulp::signal::detail::BasicLfoT< float, Convention >::next_quadrature ( float & sine_out,
float & cosine_out )
inlineinherited

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.

◆ next_stereo()

void pulp::signal::detail::BasicLfoT< float, Convention >::next_stereo ( float & left,
float & right )
inlineinherited

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.

◆ next_unipolar()

float pulp::signal::detail::BasicLfoT< float, Convention >::next_unipolar ( )
inlineinherited

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.

◆ period_samples()

double pulp::signal::detail::BasicLfoT< float, Convention >::period_samples ( ) const
inlineinherited

◆ phase()

double pulp::signal::detail::BasicLfoT< float, Convention >::phase ( ) const
inlineinherited

◆ prepare()

void pulp::signal::detail::BasicLfoT< float, Convention >::prepare ( double sample_rate)
inlineinherited

◆ rate_hz()

double pulp::signal::detail::BasicLfoT< float, Convention >::rate_hz ( ) const
inlineinherited

◆ reset()

void pulp::signal::detail::BasicLfoT< float, Convention >::reset ( )
inlineinherited

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.

◆ retrigger()

void pulp::signal::detail::BasicLfoT< float, Convention >::retrigger ( )
inlineinherited

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.

◆ set_band_limited()

void pulp::signal::detail::BasicLfoT< float, Convention >::set_band_limited ( bool on)
inlineinherited

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.

◆ set_delay_ms()

void pulp::signal::detail::BasicLfoT< float, Convention >::set_delay_ms ( double ms)
inlineinherited

Silence (a neutral output) before the LFO starts.

Phase does not advance during the delay, so the wave always begins at its own start.

◆ set_fade_curve()

void pulp::signal::detail::BasicLfoT< float, Convention >::set_fade_curve ( FadeCurve c)
inlineinherited

◆ set_fade_in_ms()

void pulp::signal::detail::BasicLfoT< float, Convention >::set_fade_in_ms ( double ms)
inlineinherited

Depth ramps 0 -> 1 over this time once the delay expires.

◆ set_fade_out_ms()

void pulp::signal::detail::BasicLfoT< float, Convention >::set_fade_out_ms ( double ms,
bool enabled )
inlineinherited

Depth ramps back to 0 after the repeat count is exhausted.

◆ set_mode()

void pulp::signal::detail::BasicLfoT< float, Convention >::set_mode ( Mode m)
inlineinherited

◆ set_period_samples()

void pulp::signal::detail::BasicLfoT< float, Convention >::set_period_samples ( double samples)
inlineinherited

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.

◆ set_phase_offset()

void pulp::signal::detail::BasicLfoT< float, Convention >::set_phase_offset ( double cycles01)
inlineinherited

Output phase offset in cycles (0..1); present a 0-360 degree control.

◆ set_pulse_width()

void pulp::signal::detail::BasicLfoT< float, Convention >::set_pulse_width ( float pw)
inlineinherited

Duty cycle of the square wave.

◆ set_random_blend()

void pulp::signal::detail::BasicLfoT< float, Convention >::set_random_blend ( float b)
inlineinherited

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.

◆ set_random_segments()

void pulp::signal::detail::BasicLfoT< float, Convention >::set_random_segments ( int n)
inlineinherited

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.

◆ set_rate_hz()

void pulp::signal::detail::BasicLfoT< float, Convention >::set_rate_hz ( double hz)
inlineinherited

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.

◆ set_repeat_count()

void pulp::signal::detail::BasicLfoT< float, Convention >::set_repeat_count ( int n)
inlineinherited

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.

◆ set_seed()

void pulp::signal::detail::BasicLfoT< float, Convention >::set_seed ( std::uint32_t s)
inlineinherited

Seed for the random waveforms and the random blend.

Applied at the next reset().

◆ set_shape_morph()

void pulp::signal::detail::BasicLfoT< float, Convention >::set_shape_morph ( float m)
inlineinherited

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.

◆ set_shape_morph_enabled()

void pulp::signal::detail::BasicLfoT< float, Convention >::set_shape_morph_enabled ( bool on)
inlineinherited

◆ set_stereo_offset()

void pulp::signal::detail::BasicLfoT< float, Convention >::set_stereo_offset ( double cycles01)
inlineinherited

Offset of the right output in next_stereo(), in cycles.

Present a +/-180 degree control; 0.25 is quadrature.

◆ set_tri_bias()

void pulp::signal::detail::BasicLfoT< float, Convention >::set_tri_bias ( float b)
inlineinherited

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.

◆ set_wave()

void pulp::signal::detail::BasicLfoT< float, Convention >::set_wave ( Wave w)
inlineinherited

◆ shape_morph_enabled()

bool pulp::signal::detail::BasicLfoT< float, Convention >::shape_morph_enabled ( ) const
inlineinherited

◆ stage()

Stage pulp::signal::detail::BasicLfoT< float, Convention >::stage ( ) const
inlineinherited

◆ wave()

Wave pulp::signal::detail::BasicLfoT< float, Convention >::wave ( ) const
inlineinherited

Member Data Documentation

◆ kDefaultRandomSegments

int pulp::signal::detail::BasicLfoT< float, Convention >::kDefaultRandomSegments
staticconstexprinherited

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.

◆ kEffectConvention

bool pulp::signal::detail::BasicLfoT< float, Convention >::kEffectConvention
staticconstexprinherited

◆ kMaxRandomSegments

int pulp::signal::detail::BasicLfoT< float, Convention >::kMaxRandomSegments
staticconstexprinherited

◆ kMaxRateFraction

double pulp::signal::detail::BasicLfoT< float, Convention >::kMaxRateFraction
staticconstexprinherited

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.

◆ kMaxRateHz

double pulp::signal::detail::BasicLfoT< float, Convention >::kMaxRateHz
staticconstexprinherited

Ceiling of the bounded effect-LFO lane.

The modulation-toolkit Wave overload keeps its audio-rate ceiling of kMaxRateFraction * fs.

◆ kMaxRepeatCount

int pulp::signal::detail::BasicLfoT< float, Convention >::kMaxRepeatCount
staticconstexprinherited

Upper bound on set_repeat_count().

◆ kMinRateHz

double pulp::signal::detail::BasicLfoT< float, Convention >::kMinRateHz
staticconstexprinherited

Rate floor.

One cycle every ~17 minutes; below this the LFO is a constant with extra steps.


The documentation for this class was generated from the following file:
  • /home/runner/work/pulp/pulp/core/signal/include/pulp/signal/lfo.hpp