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

Ornstein-Uhlenbeck walk (Uhlenbeck & Ornstein, Phys. More...

#include <rng.hpp>

Public Member Functions

void prepare (double update_rate_hz)
void set_theta (double theta_per_second)
void set_sigma (double sigma)
void set_mu (double mu)
void seed (std::uint32_t s)
void set_seed (std::uint32_t s)
void set_correlation_time (double seconds, double sample_rate)
void reset ()
void reset_value ()
 Reset to the mean without disturbing the stream position.
SampleType next ()
SampleType current () const
SampleType value () const
double theta () const
double sigma () const
double stationary_std () const
 Closed-form stationary standard deviation, for tests and for callers sizing a modulation depth from a target excursion.

Static Public Attributes

static constexpr SampleType kClamp = SampleType{1.5}
 A Gaussian walk has unbounded tails; downstream consumers (pitch ratios, delay lengths) do not.
static constexpr double kMinTheta = 1e-6
static constexpr double kMaxTheta = 1.0
static constexpr double kDefaultTheta = 0.05

Detailed Description

template<typename SampleType = float>
class pulp::signal::OuWalkT< SampleType >

Ornstein-Uhlenbeck walk (Uhlenbeck & Ornstein, Phys.

Rev. 36, 1930):

y[n+1] = mu + e^(-theta*dt) * (y[n] - mu)
         + sigma * sqrt(1 - e^(-2*theta*dt)) * g

This is the exact discrete transition, not Euler-Maruyama: both the decay and innovation scale are solved for the configured update interval.

A random walk with a restoring force. Unlike filtered white noise it has a defined mean it returns to, and unlike an LFO it never repeats. The stationary standard deviation is the caller-facing sigma, independent of update rate and theta.

RT contract: prepare() recomputes dt and the noise scale; next(), reset(), and accessors allocate nothing.

USE: the one primitive behind tape wow, filter-cutoff drift, and feedback-network delay-length walks. Anywhere the answer to "why does this sound static?" is "because nothing is moving that the listener did not ask for". theta is how hard it is pulled home (small = long slow excursions), sigma is how far it gets. Output is clamped to +/-kClamp so a large sigma cannot hand a downstream pitch or delay control an absurd value.

Member Function Documentation

◆ current()

template<typename SampleType = float>
SampleType pulp::signal::OuWalkT< SampleType >::current ( ) const
inline

◆ next()

template<typename SampleType = float>
SampleType pulp::signal::OuWalkT< SampleType >::next ( )
inline

◆ prepare()

template<typename SampleType = float>
void pulp::signal::OuWalkT< SampleType >::prepare ( double update_rate_hz)
inline
Parameters
update_rate_hzRate at which next() will be called — the audio sample rate for per-sample use, or the control rate for a decimated one. The walk's statistics are rate-independent.

◆ reset()

template<typename SampleType = float>
void pulp::signal::OuWalkT< SampleType >::reset ( )
inline

◆ reset_value()

template<typename SampleType = float>
void pulp::signal::OuWalkT< SampleType >::reset_value ( )
inline

Reset to the mean without disturbing the stream position.

◆ seed()

template<typename SampleType = float>
void pulp::signal::OuWalkT< SampleType >::seed ( std::uint32_t s)
inline

◆ set_correlation_time()

template<typename SampleType = float>
void pulp::signal::OuWalkT< SampleType >::set_correlation_time ( double seconds,
double sample_rate )
inline

◆ set_mu()

template<typename SampleType = float>
void pulp::signal::OuWalkT< SampleType >::set_mu ( double mu)
inline

◆ set_seed()

template<typename SampleType = float>
void pulp::signal::OuWalkT< SampleType >::set_seed ( std::uint32_t s)
inline

◆ set_sigma()

template<typename SampleType = float>
void pulp::signal::OuWalkT< SampleType >::set_sigma ( double sigma)
inline

◆ set_theta()

template<typename SampleType = float>
void pulp::signal::OuWalkT< SampleType >::set_theta ( double theta_per_second)
inline

◆ sigma()

template<typename SampleType = float>
double pulp::signal::OuWalkT< SampleType >::sigma ( ) const
inline

◆ stationary_std()

template<typename SampleType = float>
double pulp::signal::OuWalkT< SampleType >::stationary_std ( ) const
inline

Closed-form stationary standard deviation, for tests and for callers sizing a modulation depth from a target excursion.

◆ theta()

template<typename SampleType = float>
double pulp::signal::OuWalkT< SampleType >::theta ( ) const
inline

◆ value()

template<typename SampleType = float>
SampleType pulp::signal::OuWalkT< SampleType >::value ( ) const
inline

Member Data Documentation

◆ kClamp

template<typename SampleType = float>
SampleType pulp::signal::OuWalkT< SampleType >::kClamp = SampleType{1.5}
staticconstexpr

A Gaussian walk has unbounded tails; downstream consumers (pitch ratios, delay lengths) do not.

1.5 sits far enough out that clipping is rare at sane settings but the bound still exists.

◆ kDefaultTheta

template<typename SampleType = float>
double pulp::signal::OuWalkT< SampleType >::kDefaultTheta = 0.05
staticconstexpr

◆ kMaxTheta

template<typename SampleType = float>
double pulp::signal::OuWalkT< SampleType >::kMaxTheta = 1.0
staticconstexpr

◆ kMinTheta

template<typename SampleType = float>
double pulp::signal::OuWalkT< SampleType >::kMinTheta = 1e-6
staticconstexpr

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