45 const float t = std::clamp(p, 0.0f, 1.0f);
46 const float k =
kCurveSpan * std::clamp(curve, -1.0f, 1.0f);
47 if (std::abs(k) < 1.0e-4f)
return t;
48 return (1.0f - std::exp(-k * t)) / (1.0f - std::exp(-k));
76 const float t = std::clamp(p, 0.0f, 1.0f);
77 return t * t * (3.0f - 2.0f * t);
81inline float bi_to_uni(
float x) {
return x * 0.5f + 0.5f; }
84inline float uni_to_bi(
float x) {
return x * 2.0f - 1.0f; }
108template <
typename SampleType =
float>
117 if (std::isfinite(sample_rate) && sample_rate > 0.0)
118 sample_rate_ = sample_rate;
119 update_coefficients();
128 rise_ms_ = fall_ms_ = finite_time(ms);
129 update_coefficients();
133 rise_ms_ = finite_time(ms);
134 update_coefficients();
137 fall_ms_ = finite_time(ms);
138 update_coefficients();
142 rise_ms_ = finite_time(
static_cast<double>(rise));
143 fall_ms_ = finite_time(
static_cast<double>(fall));
144 update_coefficients();
151 const double v =
static_cast<double>(
value);
152 value_ = std::isfinite(v) ? v : 0.0;
158 SampleType
value()
const {
return static_cast<SampleType
>(value_); }
160 bool settled()
const {
return value_ == target_; }
163 const double in =
static_cast<double>(input);
164 if (!std::isfinite(in)) {
166 return SampleType{0};
168 const double delta = in - value_;
169 if (delta == 0.0)
return static_cast<SampleType
>(value_);
170 const bool rising = delta > 0.0;
172 if (mode_ == Mode::linear) {
175 const double samples =
rising ? rise_samples_ : fall_samples_;
176 linear_step_ = samples > 0.0 ? 1.0 / samples : 0.0;
178 if (linear_step_ <= 0.0)
181 value_ = std::min(value_ + linear_step_, in);
183 value_ = std::max(value_ - linear_step_, in);
186 const double coefficient =
rising ? rise_coeff_ : fall_coeff_;
187 value_ += coefficient * delta;
191 return static_cast<SampleType
>(value_);
195 static double finite_time(
double ms) {
196 return std::isfinite(ms) ? std::max(0.0, ms) : 0.0;
198 void update_coefficients() {
205 double sample_rate_ = 48000.0;
206 double rise_ms_ = 10.0;
207 double fall_ms_ = 10.0;
208 double rise_samples_ = 480.0;
209 double fall_samples_ = 480.0;
210 double rise_coeff_ = 1.0;
211 double fall_coeff_ = 1.0;
213 double target_ = 0.0;
214 double linear_step_ = 0.0;
215 Mode mode_ = Mode::linear;
226template <
typename SampleType =
float>
235 if (std::isfinite(sample_rate) && sample_rate > 0.0) sample_rate_ = sample_rate;
236 update_coefficients();
243 rise_ms_ = fall_ms_ = finite_time(ms);
244 update_coefficients();
247 rise_ms_ = finite_time(ms);
248 update_coefficients();
251 fall_ms_ = finite_time(ms);
252 update_coefficients();
255 rise_ms_ = finite_time(
static_cast<double>(rise));
256 fall_ms_ = finite_time(
static_cast<double>(fall));
257 update_coefficients();
264 const double candidate =
static_cast<double>(
value);
265 value_ = std::isfinite(candidate) ? candidate : 0.0;
271 SampleType
value()
const {
return static_cast<SampleType
>(value_); }
273 bool settled()
const {
return value_ == target_; }
276 const double in =
static_cast<double>(input);
277 if (!std::isfinite(in)) {
279 return SampleType{0};
281 const double delta = in - value_;
282 if (delta == 0.0)
return value();
283 const bool rising = delta > 0.0;
285 if (mode_ == Mode::linear) {
288 const double samples =
rising ? rise_samples_ : fall_samples_;
289 linear_step_ = samples > 0.0 ? std::abs(delta) / samples : 0.0;
291 if (linear_step_ <= 0.0)
294 value_ = std::min(value_ + linear_step_, in);
296 value_ = std::max(value_ - linear_step_, in);
299 const double coefficient =
rising ? rise_coeff_ : fall_coeff_;
300 value_ += coefficient * delta;
308 static double finite_time(
double ms) {
309 return std::isfinite(ms) ? std::max(0.0, ms) : 0.0;
311 void update_coefficients() {
318 double sample_rate_ = 48000.0;
319 double rise_ms_ = 10.0;
320 double fall_ms_ = 10.0;
321 double rise_samples_ = 480.0;
322 double fall_samples_ = 480.0;
323 double rise_coeff_ = 1.0;
324 double fall_coeff_ = 1.0;
326 double target_ = 0.0;
327 double linear_step_ = 0.0;
328 Mode mode_ = Mode::linear;
345template <
typename SampleType =
float>
350 void prepare(SampleType sample_rate) { glide_.prepare(sample_rate); }
353 const double value =
static_cast<double>(threshold);
359 glide_ms_ = std::max(SampleType{0}, ms);
360 glide_.set_times_ms(glide_ms_, glide_ms_);
373 SampleType
process(SampleType input,
bool clock) {
374 if (clock && !prev_clock_) held_ = input;
376 if (glide_ms_ <= SampleType{0}) {
380 return glide_.process(held_);
387 return process(input,
static_cast<double>(trigger) >= threshold_);
391 SampleType
held()
const {
return held_; }
392 SampleType
value()
const {
return held_; }
396 SampleType held_ = SampleType{0};
397 SampleType glide_ms_ = SampleType{0};
399 bool prev_clock_ =
false;
416template <
typename SampleType =
float>
421 static constexpr SampleType
kMaxGain = SampleType{2};
426 SampleType
process(SampleType x)
const {
return x * gain_ + offset_; }
427 SampleType
gain()
const {
return gain_; }
428 SampleType
offset()
const {
return offset_; }
431 SampleType gain_ = SampleType{1};
432 SampleType offset_ = SampleType{0};
447template <
typename SampleType =
float>
456 return std::max(SampleType{0}, x);
480template <
typename SampleType =
float>
495 if (auto_hysteresis_)
503 hysteresis_ = std::abs(h);
504 auto_hysteresis_ =
false;
510 if (!gate_ && x > threshold_ + hysteresis_) gate_ =
true;
511 else if (gate_ && x < threshold_ - hysteresis_) gate_ =
false;
515 bool gate()
const {
return gate_; }
519 SampleType threshold_ = SampleType{0};
521 bool auto_hysteresis_ =
true;
532template <
typename SampleType =
float>
536 high_ = std::isfinite(
high) ?
high : high_;
537 low_ = std::isfinite(low) ? std::min(low, high_ - 1
e-9) : low_;
539 void set_levels(SampleType low_level, SampleType high_level) {
540 if (std::isfinite(
static_cast<double>(low_level))) low_level_ = low_level;
541 if (std::isfinite(
static_cast<double>(high_level))) high_level_ = high_level;
543 void reset() { high_state_ =
false; }
545 const double value =
static_cast<double>(input);
546 if (!std::isfinite(value)) {
550 if (!high_state_ && value >= high_) high_state_ =
true;
551 else if (high_state_ && value <= low_) high_state_ =
false;
552 return high_state_ ? high_level_ : low_level_;
554 bool high()
const {
return high_state_; }
559 SampleType low_level_ = SampleType{0};
560 SampleType high_level_ = SampleType{1};
561 bool high_state_ =
false;
582template <
typename SampleType =
float>
590 void set_steps(
int n) { steps_ = std::clamp(n, 1, 1024); }
593 if (steps_ <= 1)
return lo_;
594 const SampleType span = hi_ - lo_;
595 if (span == SampleType{0})
return lo_;
596 const SampleType t = std::clamp((x - lo_) / span, SampleType{0}, SampleType{1});
597 const auto divisions =
static_cast<SampleType
>(steps_ - 1);
598 const auto index =
static_cast<SampleType
>(std::lround(t * divisions));
599 return lo_ + index * span / divisions;
602 int steps()
const {
return steps_; }
605 SampleType lo_ = SampleType{0};
606 SampleType hi_ = SampleType{1};
623template <
typename SampleType =
float>
632 void set_curve(SampleType
c) { curve_ = std::clamp(
c, SampleType{-1}, SampleType{1}); }
635 const auto p =
static_cast<float>(x);
637 return static_cast<SampleType
>(
curve_rise(p,
static_cast<float>(curve_)));
641 SampleType curve_ = SampleType{0};
y = x * gain + offset, with gain allowed to go negative.
Definition mod_tools.hpp:417
static constexpr float kMaxGain
Definition mod_tools.hpp:421
SampleType offset() const
Definition mod_tools.hpp:428
SampleType process(SampleType x) const
Definition mod_tools.hpp:426
SampleType gain() const
Definition mod_tools.hpp:427
void set_offset(SampleType o)
Definition mod_tools.hpp:424
void set_gain(SampleType g)
Definition mod_tools.hpp:423
Threshold comparator with hysteresis — the bridge from the signal domain to the event domain.
Definition mod_tools.hpp:481
void reset(bool gate=false)
Definition mod_tools.hpp:507
SampleType hysteresis() const
Definition mod_tools.hpp:516
static constexpr float kDefaultHysteresisFraction
Definition mod_tools.hpp:484
static constexpr float kMinAutoHysteresis
Definition mod_tools.hpp:489
bool process(SampleType x)
Definition mod_tools.hpp:509
void set_hysteresis(SampleType h)
Absolute dead band, in the input's units.
Definition mod_tools.hpp:502
void set_threshold(SampleType t)
Setting a threshold re-derives the default hysteresis unless an explicit one was set first.
Definition mod_tools.hpp:493
bool gate() const
Definition mod_tools.hpp:515
Distance-independent portamento used by the Round-2 effect and sequencing lane.
Definition mod_tools.hpp:227
void set_immediate(SampleType value)
Definition mod_tools.hpp:263
double fall_ms() const
Definition mod_tools.hpp:261
float value() const
Definition mod_tools.hpp:271
void set_time_ms(double ms)
Definition mod_tools.hpp:242
Mode mode() const
Definition mod_tools.hpp:240
void reset(SampleType value=SampleType{0})
Definition mod_tools.hpp:269
static constexpr double kSettleEpsilon
Definition mod_tools.hpp:230
SlewMode Mode
Definition mod_tools.hpp:229
double rise_ms() const
Definition mod_tools.hpp:260
void set_fall_ms(double ms)
Definition mod_tools.hpp:250
bool settled() const
Definition mod_tools.hpp:273
SampleType current() const
Definition mod_tools.hpp:272
void set_rise_ms(double ms)
Definition mod_tools.hpp:246
void set_times_ms(SampleType rise, SampleType fall)
Definition mod_tools.hpp:254
SampleType process(SampleType input)
Definition mod_tools.hpp:275
void set_mode(Mode mode)
Definition mod_tools.hpp:239
ConstantTimeSlewLimiterT()
Definition mod_tools.hpp:232
void prepare(double sample_rate)
Definition mod_tools.hpp:234
Response shaper for a unit control: the stage-curve law, or smoothstep.
Definition mod_tools.hpp:624
Shape
Definition mod_tools.hpp:626
@ smoothstep
Definition mod_tools.hpp:626
@ stage_curve
Definition mod_tools.hpp:626
void set_shape(Shape s)
Definition mod_tools.hpp:628
SampleType process(SampleType x) const
Definition mod_tools.hpp:634
void set_curve(SampleType c)
-1 logarithmic .
Definition mod_tools.hpp:632
Snap a control value to N equally spaced levels across a range.
Definition mod_tools.hpp:583
int steps() const
Definition mod_tools.hpp:602
void set_steps(int n)
Definition mod_tools.hpp:590
void set_range(SampleType lo, SampleType hi)
Definition mod_tools.hpp:585
SampleType process(SampleType x) const
Definition mod_tools.hpp:592
Full- or half-wave rectification.
Definition mod_tools.hpp:448
Mode
Definition mod_tools.hpp:450
@ full_wave
Definition mod_tools.hpp:450
@ half_wave
Definition mod_tools.hpp:450
void set_mode(Mode m)
Definition mod_tools.hpp:452
SampleType process(SampleType x) const
Definition mod_tools.hpp:454
Latch a value on a clock's rising edge, with optional glide to the new value instead of a step.
Definition mod_tools.hpp:346
void prepare(SampleType sample_rate)
Definition mod_tools.hpp:350
SampleType process(SampleType input, bool clock)
Definition mod_tools.hpp:373
void set_glide_mode(typename SlewLimiterT< SampleType >::Mode m)
Definition mod_tools.hpp:363
void set_glide_ms(SampleType ms)
0 disables the glide entirely (the output steps).
Definition mod_tools.hpp:358
void reset(SampleType value=SampleType{0})
Definition mod_tools.hpp:365
float value() const
Definition mod_tools.hpp:392
SampleType process_signal(SampleType input, SampleType trigger)
Explicit signal-threshold spelling used by the Round-2 sequencing kit.
Definition mod_tools.hpp:386
void set_threshold(SampleType threshold)
Definition mod_tools.hpp:352
SampleType held() const
The latched value before any glide — what the last clock actually saw.
Definition mod_tools.hpp:391
static constexpr double kDefaultThreshold
Definition mod_tools.hpp:348
Signal-valued comparator from the Round-2 patching lane.
Definition mod_tools.hpp:533
bool high() const
Definition mod_tools.hpp:554
void reset()
Definition mod_tools.hpp:543
void set_levels(SampleType low_level, SampleType high_level)
Definition mod_tools.hpp:539
SampleType process(SampleType input)
Definition mod_tools.hpp:544
void set_thresholds(double high, double low)
Definition mod_tools.hpp:535
Definition mod_tools.hpp:109
void set_time_ms(double ms)
Symmetric spelling for the toolkit's full-scale rate limiter.
Definition mod_tools.hpp:127
static constexpr double kSettleEpsilon
Definition mod_tools.hpp:112
double rise_ms() const
Definition mod_tools.hpp:147
SlewMode Mode
Definition mod_tools.hpp:111
double fall_ms() const
Definition mod_tools.hpp:148
SampleType process(SampleType input)
Definition mod_tools.hpp:162
void set_rise_ms(double ms)
Definition mod_tools.hpp:132
Mode mode() const
Definition mod_tools.hpp:123
void set_fall_ms(double ms)
Definition mod_tools.hpp:136
void reset(SampleType value=SampleType{0})
Definition mod_tools.hpp:156
void set_immediate(SampleType value)
Definition mod_tools.hpp:150
bool settled() const
Definition mod_tools.hpp:160
void prepare(double sample_rate)
Definition mod_tools.hpp:116
void set_mode(Mode mode)
Definition mod_tools.hpp:122
SampleType current() const
Definition mod_tools.hpp:159
SlewLimiterT()
Definition mod_tools.hpp:114
void set_times_ms(SampleType rise, SampleType fall)
Definition mod_tools.hpp:141
float value() const
Definition mod_tools.hpp:158
T ms_to_onepole_coef(T ms, T sample_rate)
A time constant in ms → the a in the one-pole smoother y += a·(x − y), i.e.
Definition units.hpp:202
T ms_to_samples(T ms, T sample_rate)
Milliseconds → samples at sample_rate Hz.
Definition units.hpp:147
Definition additive_bank.hpp:218
SlewLimiterT< double > SlewLimiter64
Definition mod_tools.hpp:219
float curve_fall(float p, float curve)
Shape a falling stage: 1 -> 0 over p.
Definition mod_tools.hpp:70
@ smoothstep
Smoothstep, which leaves the threshold with zero slope so the onset of audibility is gradual rather t...
Definition lofi_chain.hpp:53
float smoothstep(float p)
Cubic smoothstep, 3t^2 - 2t^3.
Definition mod_tools.hpp:75
SlewLimiterT< float > SlewLimiter
Definition mod_tools.hpp:218
SlewMode
Rate limiter with independent rise and fall speeds.
Definition mod_tools.hpp:106
@ exponential
Definition mod_tools.hpp:106
SignalComparatorT< float > SignalComparator
Definition mod_tools.hpp:564
RectifierT< float > Rectifier
Definition mod_tools.hpp:463
@ rising
Definition rise_fall_generator.hpp:19
SampleHoldT< float > SampleHold
Definition mod_tools.hpp:402
@ c
Definition spectrum_trace.hpp:35
ComparatorT< float > Comparator
Definition mod_tools.hpp:525
SampleHoldT< double > SampleHold64
Definition mod_tools.hpp:403
CurveT< double > Curve64
Definition mod_tools.hpp:646
QuantizerT< float > Quantizer
Definition mod_tools.hpp:610
ConstantTimeSlewLimiterT< float > ConstantTimeSlewLimiter
Definition mod_tools.hpp:331
ComparatorT< double > Comparator64
Definition mod_tools.hpp:526
ConstantTimeSlewLimiterT< double > ConstantTimeSlewLimiter64
Definition mod_tools.hpp:332
float curve_rise(float p, float curve)
Shape a rising stage: 0 -> 1 over p, with curve in [-1, +1].
Definition mod_tools.hpp:65
T snap_to_zero(T x)
Returns 0 if |x| < snap_threshold, else x.
Definition denormal.hpp:45
float stage_curve(float p, float curve)
The shared stage-shaping law:
Definition mod_tools.hpp:44
@ o
Definition formant_filter_bank.hpp:20
@ e
Definition formant_filter_bank.hpp:20
@ linear
2-point. Cheapest; audible imaging when pitching up.
Definition granular.hpp:133
RectifierT< double > Rectifier64
Definition mod_tools.hpp:464
SignalComparatorT< double > SignalComparator64
Definition mod_tools.hpp:565
float bi_to_uni(float x)
Bipolar [-1, 1] to unipolar [0, 1].
Definition mod_tools.hpp:81
AttenuverterT< float > Attenuverter
Definition mod_tools.hpp:435
float uni_to_bi(float x)
Unipolar [0, 1] to bipolar [-1, 1].
Definition mod_tools.hpp:84
constexpr float kCurveSpan
Curve span for the shared stage-shaping law.
Definition mod_tools.hpp:31
CurveT< float > Curve
Definition mod_tools.hpp:645
QuantizerT< double > Quantizer64
Definition mod_tools.hpp:611
AttenuverterT< double > Attenuverter64
Definition mod_tools.hpp:436
The real-unit vocabulary shared by every DSP block in the catalog.