43 void seed(std::uint32_t s) {
67 std::uint32_t x = state_;
82 return static_cast<float>(
next_u32() >> 8) * (1.0f / 16777216.0f);
90 return static_cast<T
>(
static_cast<double>(
next_u32()) *
91 (1.0 / 2147483648.0) -
100 return static_cast<T
>(
static_cast<double>(
next_u32()) *
101 (1.0 / 4294967296.0));
117 if (u1 <= 0.0f) u1 = 1.0f / 16777216.0f;
119 const float radius = std::sqrt(-2.0f * std::log(u1));
120 const float angle = 6.2831853071795864769f * u2;
121 cached_ = radius * std::sin(angle);
123 return radius * std::cos(angle);
133 float cached_ = 0.0f;
134 bool has_cached_ =
false;
140constexpr std::uint64_t
mix64(std::uint64_t z) {
142 z *= 0xBF58476D1CE4E5B9ull;
144 z *= 0x94D049BB133111EBull;
151constexpr std::uint64_t
mix64(std::uint64_t seed,
153 std::uint64_t field = 0
u) {
154 return mix64(seed + index * 0x9E3779B97F4A7C15ull +
155 field * 0xBF58476D1CE4E5B9ull);
165 return static_cast<float>(
mix64(key) >> 40) * (1.0f / 16777216.0f);
170 return static_cast<T
>(
static_cast<double>(
mix64(key) >> 11) *
171 (1.0 / 9007199254740992.0));
174template <
typename T =
float>
187constexpr std::uint64_t
rng_key(std::uint64_t purpose, std::uint64_t index) {
213template <
typename SampleType =
float>
219 static constexpr SampleType
kClamp = SampleType{1.5};
228 rate_ = update_rate_hz > 0.0 ? update_rate_hz : 1.0;
230 update_coefficients_();
234 if (!std::isfinite(theta_per_second))
return;
236 update_coefficients_();
239 if (!std::isfinite(
sigma))
return;
240 sigma_ = std::max(0.0,
sigma);
241 update_coefficients_();
244 if (std::isfinite(mu)) mu_ = mu;
246 void seed(std::uint32_t s) { rng_.seed(s); }
250 if (!(std::isfinite(seconds) && seconds > 0.0 &&
251 std::isfinite(sample_rate) && sample_rate > 0.0))
268 const double diffusion = innovation_std_ *
static_cast<double>(rng_.gaussian());
269 value_ = std::clamp(mu_ + decay_ * (value_ - mu_) + diffusion,
270 -
static_cast<double>(
kClamp),
271 static_cast<double>(
kClamp));
272 return static_cast<SampleType
>(value_);
275 SampleType
current()
const {
return static_cast<SampleType
>(value_); }
277 double theta()
const {
return theta_; }
278 double sigma()
const {
return sigma_; }
287 void update_coefficients_() {
288 decay_ = std::exp(-theta_ * dt_);
292 innovation_std_ = sigma_ * std::sqrt(std::max(0.0, 1.0 - decay_ * decay_));
306 double innovation_std_ =
332template <
typename SampleType =
float>
342 const double sr = sample_rate > 0.0 ? sample_rate : 1.0;
343 const double control_rate = sr /
static_cast<double>(
kDecimation);
344 pitch_walk_.prepare(control_rate);
345 fraction_walk_.prepare(control_rate);
346 multiplier_walk_.prepare(control_rate);
347 multiplier_walk_.set_theta(1.0 / correlation_s_);
348 multiplier_walk_.set_sigma(depth_percent_ * 0.01);
356 pitch_walk_.set_theta(theta_per_second);
357 fraction_walk_.set_theta(theta_per_second);
361 pitch_walk_.set_sigma(sigma);
362 fraction_walk_.set_sigma(sigma);
369 pitch_walk_.seed(
static_cast<std::uint32_t
>(
mix64(s) & 0xFFFFFFFFu));
370 fraction_walk_.seed(
static_cast<std::uint32_t
>(
mix64(s ^ 0xA5A5A5A5u) >> 32));
371 multiplier_walk_.seed(
static_cast<std::uint32_t
>(
mix64(s ^ 0xC6BC2796u) & 0xFFFFFFFFu));
377 if (!std::isfinite(percent))
return;
378 depth_percent_ = std::max(0.0, percent);
379 multiplier_walk_.set_sigma(depth_percent_ * 0.01);
383 if (!(std::isfinite(seconds) && seconds > 0.0))
return;
384 correlation_s_ = seconds;
385 multiplier_walk_.set_theta(1.0 / correlation_s_);
390 fraction_walk_.reset();
391 multiplier_walk_.reset();
393 pitch_prev_ = pitch_next_ = pitch_walk_.current();
394 fraction_prev_ = fraction_next_ = fraction_walk_.current();
395 multiplier_prev_ = multiplier_next_ = multiplier_walk_.current();
396 pitch_now_ = pitch_prev_;
397 fraction_now_ = fraction_prev_;
398 multiplier_now_ = multiplier_prev_;
404 pitch_prev_ = pitch_next_;
405 fraction_prev_ = fraction_next_;
406 pitch_next_ = pitch_walk_.next();
407 fraction_next_ = fraction_walk_.next();
408 multiplier_prev_ = multiplier_next_;
409 multiplier_next_ = multiplier_walk_.next();
411 const SampleType t =
static_cast<SampleType
>(counter_)
413 pitch_now_ = pitch_prev_ + (pitch_next_ - pitch_prev_) * t;
414 fraction_now_ = fraction_prev_ + (fraction_next_ - fraction_prev_) * t;
415 multiplier_now_ = multiplier_prev_ + (multiplier_next_ - multiplier_prev_) * t;
417 return static_cast<SampleType
>(
418 std::max(kMinMultiplier, 1.0 +
static_cast<double>(multiplier_now_)));
423 return static_cast<SampleType
>(
424 std::exp2(cents_ *
static_cast<double>(pitch_now_) / 1200.0));
432 return std::clamp(fraction_now_, SampleType{-1}, SampleType{1});
436 static constexpr double kMinMultiplier = 1
e-3;
438 OuWalkT<SampleType> fraction_walk_{};
439 OuWalkT<SampleType> multiplier_walk_{};
444 SampleType pitch_prev_{};
445 SampleType pitch_next_{};
446 SampleType fraction_prev_{};
447 SampleType fraction_next_{};
448 SampleType pitch_now_{};
449 SampleType fraction_now_{};
450 SampleType multiplier_prev_{};
451 SampleType multiplier_next_{};
452 SampleType multiplier_now_{};
Two decorrelated OU walks presented as the two things drift is actually wired to: a pitch ratio and a...
Definition rng.hpp:333
SampleType fraction() const
Signed unit drift, independent of the pitch walk.
Definition rng.hpp:431
static constexpr double kDefaultCorrelationSeconds
Definition rng.hpp:339
SampleType next()
Advance one audio sample. Call once per sample; read the outputs after.
Definition rng.hpp:402
void set_cents(double cents)
Peak-ish pitch excursion in cents, scaled by the walk's unit output.
Definition rng.hpp:353
void reset()
Definition rng.hpp:388
void set_seed(std::uint32_t s)
Definition rng.hpp:374
void set_correlation_time(double seconds)
Definition rng.hpp:382
void set_sigma(double sigma)
Definition rng.hpp:360
void set_theta(double theta_per_second)
Definition rng.hpp:355
void prepare(double sample_rate)
Definition rng.hpp:341
void seed(std::uint32_t s)
The two walks are seeded from one user-facing seed through mix64 so they are decorrelated by construc...
Definition rng.hpp:368
static constexpr double kDefaultDepthPercent
Definition rng.hpp:338
void set_depth_percent(double percent)
Definition rng.hpp:376
static constexpr int kDecimation
Definition rng.hpp:337
SampleType pitch_factor() const
Multiplicative pitch ratio: 2 ^ (cents * x / 1200).
Definition rng.hpp:422
Ornstein-Uhlenbeck walk (Uhlenbeck & Ornstein, Phys.
Definition rng.hpp:214
void set_mu(double mu)
Definition rng.hpp:243
void set_correlation_time(double seconds, double sample_rate)
Definition rng.hpp:249
static constexpr float kClamp
Definition rng.hpp:219
static constexpr double kDefaultTheta
Definition rng.hpp:222
double sigma() const
Definition rng.hpp:278
void reset()
Definition rng.hpp:257
double stationary_std() const
Closed-form stationary standard deviation, for tests and for callers sizing a modulation depth from a...
Definition rng.hpp:282
static constexpr double kMinTheta
Definition rng.hpp:220
SampleType next()
Definition rng.hpp:265
void set_sigma(double sigma)
Definition rng.hpp:238
void set_theta(double theta_per_second)
Definition rng.hpp:233
void set_seed(std::uint32_t s)
Definition rng.hpp:247
void reset_value()
Reset to the mean without disturbing the stream position.
Definition rng.hpp:263
SampleType current() const
Definition rng.hpp:275
void seed(std::uint32_t s)
Definition rng.hpp:246
SampleType value() const
Definition rng.hpp:276
double theta() const
Definition rng.hpp:277
static constexpr double kMaxTheta
Definition rng.hpp:221
void prepare(double update_rate_hz)
Definition rng.hpp:227
std::uint32_t next_u32()
Definition rng.hpp:66
float next_bipolar()
Uniform in [-1, 1).
Definition rng.hpp:86
T next_bipolar()
Definition rng.hpp:89
constexpr Xorshift32(std::uint32_t s)
Definition rng.hpp:40
void seed(std::uint32_t s)
Definition rng.hpp:43
std::uint32_t seed() const
Definition rng.hpp:128
void reset()
Rewind to the seeded stream position.
Definition rng.hpp:60
float next_unit()
Uniform in [0, 1), with the caller-selected result precision.
Definition rng.hpp:96
float next_unipolar()
Uniform in [0, 1).
Definition rng.hpp:81
static constexpr std::uint32_t kDefaultSeed
Any nonzero constant works; this is the 32-bit golden-ratio odd constant, which is also what seed(0) ...
Definition rng.hpp:37
std::uint32_t state() const
Definition rng.hpp:126
std::uint32_t next_uint()
Compatibility spelling used by the Round 2 DSP blocks.
Definition rng.hpp:77
float gaussian()
Standard normal via the polar-free Box-Muller transform (Box & Muller, Ann.
Definition rng.hpp:111
T next_unit()
Definition rng.hpp:99
void set_seed(std::uint32_t s)
Compatibility spelling used by the Round 2 DSP blocks.
Definition rng.hpp:54
constexpr Xorshift32()=default
Definition additive_bank.hpp:218
constexpr std::uint64_t kGoldenGamma
The 64-bit golden-ratio odd constant that splitmix64 steps its state by.
Definition rng.hpp:180
OuWalkT< float > OuWalk
Definition rng.hpp:310
constexpr std::uint64_t mix64(std::uint64_t z)
splitmix64 finalizer (Steele, Lea & Flood, OOPSLA 2014).
Definition rng.hpp:140
constexpr std::uint64_t rng_key(std::uint64_t purpose, std::uint64_t index)
Combine a purpose tag and an index into a key for unit_from().
Definition rng.hpp:187
DriftT< double > Drift64
Definition rng.hpp:456
DriftT< float > Drift
Definition rng.hpp:455
@ u
Definition formant_filter_bank.hpp:20
@ e
Definition formant_filter_bank.hpp:20
OuWalkT< double > OuWalk64
Definition rng.hpp:311
T bipolar_from(std::uint64_t key)
Definition rng.hpp:175
float unit_from(std::uint64_t key)
Stateless purpose-keyed draw in [0, 1).
Definition rng.hpp:164