Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
mod_tools.hpp
Go to the documentation of this file.
1#pragma once
2
18
20#include <pulp/signal/units.hpp>
21
22#include <algorithm>
23#include <cmath>
24#include <cstdint>
25
26namespace pulp::signal {
27
31inline constexpr float kCurveSpan = 8.0f;
32
44inline float stage_curve(float p, float curve) {
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; // linear limit
48 return (1.0f - std::exp(-k * t)) / (1.0f - std::exp(-k));
49}
50
65inline float curve_rise(float p, float curve) { return stage_curve(p, -curve); }
66
70inline float curve_fall(float p, float curve) { return 1.0f - stage_curve(p, curve); }
71
75inline float smoothstep(float p) {
76 const float t = std::clamp(p, 0.0f, 1.0f);
77 return t * t * (3.0f - 2.0f * t);
78}
79
81inline float bi_to_uni(float x) { return x * 0.5f + 0.5f; }
82
84inline float uni_to_bi(float x) { return x * 2.0f - 1.0f; }
85
106enum class SlewMode : std::uint8_t { linear, exponential };
107
108template <typename SampleType = float>
110public:
111 using Mode = SlewMode;
112 static constexpr double kSettleEpsilon = 1e-9;
113
114 SlewLimiterT() { update_coefficients(); }
115
116 void prepare(double sample_rate) {
117 if (std::isfinite(sample_rate) && sample_rate > 0.0)
118 sample_rate_ = sample_rate;
119 update_coefficients();
120 }
121
122 void set_mode(Mode mode) { mode_ = mode; }
123 Mode mode() const { return mode_; }
124
127 void set_time_ms(double ms) {
128 rise_ms_ = fall_ms_ = finite_time(ms);
129 update_coefficients();
130 }
131
132 void set_rise_ms(double ms) {
133 rise_ms_ = finite_time(ms);
134 update_coefficients();
135 }
136 void set_fall_ms(double ms) {
137 fall_ms_ = finite_time(ms);
138 update_coefficients();
139 }
140
141 void set_times_ms(SampleType rise, SampleType fall) {
142 rise_ms_ = finite_time(static_cast<double>(rise));
143 fall_ms_ = finite_time(static_cast<double>(fall));
144 update_coefficients();
145 }
146
147 double rise_ms() const { return rise_ms_; }
148 double fall_ms() const { return fall_ms_; }
149
150 void set_immediate(SampleType value) {
151 const double v = static_cast<double>(value);
152 value_ = std::isfinite(v) ? v : 0.0;
153 target_ = value_;
154 linear_step_ = 0.0;
155 }
156 void reset(SampleType value = SampleType{0}) { set_immediate(value); }
157
158 SampleType value() const { return static_cast<SampleType>(value_); }
159 SampleType current() const { return value(); }
160 bool settled() const { return value_ == target_; }
161
162 SampleType process(SampleType input) {
163 const double in = static_cast<double>(input);
164 if (!std::isfinite(in)) {
165 reset();
166 return SampleType{0};
167 }
168 const double delta = in - value_;
169 if (delta == 0.0) return static_cast<SampleType>(value_);
170 const bool rising = delta > 0.0;
171
172 if (mode_ == Mode::linear) {
173 if (in != target_) {
174 target_ = in;
175 const double samples = rising ? rise_samples_ : fall_samples_;
176 linear_step_ = samples > 0.0 ? 1.0 / samples : 0.0;
177 }
178 if (linear_step_ <= 0.0)
179 value_ = in;
180 else if (rising)
181 value_ = std::min(value_ + linear_step_, in);
182 else
183 value_ = std::max(value_ - linear_step_, in);
184 } else {
185 target_ = in;
186 const double coefficient = rising ? rise_coeff_ : fall_coeff_;
187 value_ += coefficient * delta;
188 if (std::abs(in - value_) < kSettleEpsilon) value_ = in;
189 }
190 value_ = snap_to_zero(value_);
191 return static_cast<SampleType>(value_);
192 }
193
194private:
195 static double finite_time(double ms) {
196 return std::isfinite(ms) ? std::max(0.0, ms) : 0.0;
197 }
198 void update_coefficients() {
199 rise_samples_ = units::ms_to_samples(rise_ms_, sample_rate_);
200 fall_samples_ = units::ms_to_samples(fall_ms_, sample_rate_);
201 rise_coeff_ = units::ms_to_onepole_coef(rise_ms_, sample_rate_);
202 fall_coeff_ = units::ms_to_onepole_coef(fall_ms_, sample_rate_);
203 }
204
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;
212 double value_ = 0.0;
213 double target_ = 0.0;
214 double linear_step_ = 0.0;
215 Mode mode_ = Mode::linear;
216};
217
220
226template <typename SampleType = float>
228public:
229 using Mode = SlewMode;
230 static constexpr double kSettleEpsilon = 1e-9;
231
232 ConstantTimeSlewLimiterT() { update_coefficients(); }
233
234 void prepare(double sample_rate) {
235 if (std::isfinite(sample_rate) && sample_rate > 0.0) sample_rate_ = sample_rate;
236 update_coefficients();
237 }
238
239 void set_mode(Mode mode) { mode_ = mode; }
240 Mode mode() const { return mode_; }
241
242 void set_time_ms(double ms) {
243 rise_ms_ = fall_ms_ = finite_time(ms);
244 update_coefficients();
245 }
246 void set_rise_ms(double ms) {
247 rise_ms_ = finite_time(ms);
248 update_coefficients();
249 }
250 void set_fall_ms(double ms) {
251 fall_ms_ = finite_time(ms);
252 update_coefficients();
253 }
254 void set_times_ms(SampleType rise, SampleType fall) {
255 rise_ms_ = finite_time(static_cast<double>(rise));
256 fall_ms_ = finite_time(static_cast<double>(fall));
257 update_coefficients();
258 }
259
260 double rise_ms() const { return rise_ms_; }
261 double fall_ms() const { return fall_ms_; }
262
263 void set_immediate(SampleType value) {
264 const double candidate = static_cast<double>(value);
265 value_ = std::isfinite(candidate) ? candidate : 0.0;
266 target_ = value_;
267 linear_step_ = 0.0;
268 }
269 void reset(SampleType value = SampleType{0}) { set_immediate(value); }
270
271 SampleType value() const { return static_cast<SampleType>(value_); }
272 SampleType current() const { return value(); }
273 bool settled() const { return value_ == target_; }
274
275 SampleType process(SampleType input) {
276 const double in = static_cast<double>(input);
277 if (!std::isfinite(in)) {
278 reset();
279 return SampleType{0};
280 }
281 const double delta = in - value_;
282 if (delta == 0.0) return value();
283 const bool rising = delta > 0.0;
284
285 if (mode_ == Mode::linear) {
286 if (in != target_) {
287 target_ = in;
288 const double samples = rising ? rise_samples_ : fall_samples_;
289 linear_step_ = samples > 0.0 ? std::abs(delta) / samples : 0.0;
290 }
291 if (linear_step_ <= 0.0)
292 value_ = in;
293 else if (rising)
294 value_ = std::min(value_ + linear_step_, in);
295 else
296 value_ = std::max(value_ - linear_step_, in);
297 } else {
298 target_ = in;
299 const double coefficient = rising ? rise_coeff_ : fall_coeff_;
300 value_ += coefficient * delta;
301 if (std::abs(in - value_) < kSettleEpsilon) value_ = in;
302 }
303 value_ = snap_to_zero(value_);
304 return value();
305 }
306
307private:
308 static double finite_time(double ms) {
309 return std::isfinite(ms) ? std::max(0.0, ms) : 0.0;
310 }
311 void update_coefficients() {
312 rise_samples_ = units::ms_to_samples(rise_ms_, sample_rate_);
313 fall_samples_ = units::ms_to_samples(fall_ms_, sample_rate_);
314 rise_coeff_ = units::ms_to_onepole_coef(rise_ms_, sample_rate_);
315 fall_coeff_ = units::ms_to_onepole_coef(fall_ms_, sample_rate_);
316 }
317
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;
325 double value_ = 0.0;
326 double target_ = 0.0;
327 double linear_step_ = 0.0;
328 Mode mode_ = Mode::linear;
329};
330
333
345template <typename SampleType = float>
347public:
348 static constexpr double kDefaultThreshold = 0.5;
349
350 void prepare(SampleType sample_rate) { glide_.prepare(sample_rate); }
351
352 void set_threshold(SampleType threshold) {
353 const double value = static_cast<double>(threshold);
354 if (std::isfinite(value)) threshold_ = value;
355 }
356
358 void set_glide_ms(SampleType ms) {
359 glide_ms_ = std::max(SampleType{0}, ms);
360 glide_.set_times_ms(glide_ms_, glide_ms_);
361 }
362
363 void set_glide_mode(typename SlewLimiterT<SampleType>::Mode m) { glide_.set_mode(m); }
364
365 void reset(SampleType value = SampleType{0}) {
366 held_ = value;
367 prev_clock_ = false;
368 glide_.reset(value);
369 }
370
373 SampleType process(SampleType input, bool clock) {
374 if (clock && !prev_clock_) held_ = input;
375 prev_clock_ = clock;
376 if (glide_ms_ <= SampleType{0}) {
377 glide_.reset(held_);
378 return held_;
379 }
380 return glide_.process(held_);
381 }
382
386 SampleType process_signal(SampleType input, SampleType trigger) {
387 return process(input, static_cast<double>(trigger) >= threshold_);
388 }
389
391 SampleType held() const { return held_; }
392 SampleType value() const { return held_; }
393
394private:
396 SampleType held_ = SampleType{0};
397 SampleType glide_ms_ = SampleType{0};
398 double threshold_ = kDefaultThreshold;
399 bool prev_clock_ = false;
400};
401
404
416template <typename SampleType = float>
418public:
421 static constexpr SampleType kMaxGain = SampleType{2};
422
423 void set_gain(SampleType g) { gain_ = std::clamp(g, -kMaxGain, kMaxGain); }
424 void set_offset(SampleType o) { offset_ = o; }
425
426 SampleType process(SampleType x) const { return x * gain_ + offset_; }
427 SampleType gain() const { return gain_; }
428 SampleType offset() const { return offset_; }
429
430private:
431 SampleType gain_ = SampleType{1};
432 SampleType offset_ = SampleType{0};
433};
434
437
447template <typename SampleType = float>
449public:
450 enum class Mode : std::uint8_t { full_wave, half_wave };
451
452 void set_mode(Mode m) { mode_ = m; }
453
454 SampleType process(SampleType x) const {
455 if (mode_ == Mode::full_wave) return std::abs(x);
456 return std::max(SampleType{0}, x);
457 }
458
459private:
460 Mode mode_ = Mode::full_wave;
461};
462
465
480template <typename SampleType = float>
482public:
484 static constexpr SampleType kDefaultHysteresisFraction = SampleType{0.05};
485
489 static constexpr SampleType kMinAutoHysteresis = SampleType{0.001};
490
493 void set_threshold(SampleType t) {
494 threshold_ = t;
495 if (auto_hysteresis_)
496 hysteresis_ = std::max(kMinAutoHysteresis,
497 kDefaultHysteresisFraction * std::abs(t));
498 }
499
502 void set_hysteresis(SampleType h) {
503 hysteresis_ = std::abs(h);
504 auto_hysteresis_ = false;
505 }
506
507 void reset(bool gate = false) { gate_ = gate; }
508
509 bool process(SampleType x) {
510 if (!gate_ && x > threshold_ + hysteresis_) gate_ = true;
511 else if (gate_ && x < threshold_ - hysteresis_) gate_ = false;
512 return gate_;
513 }
514
515 bool gate() const { return gate_; }
516 SampleType hysteresis() const { return hysteresis_; }
517
518private:
519 SampleType threshold_ = SampleType{0};
520 SampleType hysteresis_ = kMinAutoHysteresis;
521 bool auto_hysteresis_ = true;
522 bool gate_ = false;
523};
524
527
532template <typename SampleType = float>
534public:
535 void set_thresholds(double high, double low) {
536 high_ = std::isfinite(high) ? high : high_;
537 low_ = std::isfinite(low) ? std::min(low, high_ - 1e-9) : low_;
538 }
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;
542 }
543 void reset() { high_state_ = false; }
544 SampleType process(SampleType input) {
545 const double value = static_cast<double>(input);
546 if (!std::isfinite(value)) {
547 reset();
548 return low_level_;
549 }
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_;
553 }
554 bool high() const { return high_state_; }
555
556private:
557 double high_ = 0.5;
558 double low_ = 0.25;
559 SampleType low_level_ = SampleType{0};
560 SampleType high_level_ = SampleType{1};
561 bool high_state_ = false;
562};
563
566
582template <typename SampleType = float>
584public:
585 void set_range(SampleType lo, SampleType hi) {
586 lo_ = lo;
587 hi_ = hi;
588 }
589
590 void set_steps(int n) { steps_ = std::clamp(n, 1, 1024); }
591
592 SampleType process(SampleType x) const {
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;
600 }
601
602 int steps() const { return steps_; }
603
604private:
605 SampleType lo_ = SampleType{0};
606 SampleType hi_ = SampleType{1};
607 int steps_ = 8;
608};
609
612
623template <typename SampleType = float>
624class CurveT {
625public:
626 enum class Shape : std::uint8_t { stage_curve, smoothstep };
627
628 void set_shape(Shape s) { shape_ = s; }
629
632 void set_curve(SampleType c) { curve_ = std::clamp(c, SampleType{-1}, SampleType{1}); }
633
634 SampleType process(SampleType x) const {
635 const auto p = static_cast<float>(x);
636 if (shape_ == Shape::smoothstep) return static_cast<SampleType>(pulp::signal::smoothstep(p));
637 return static_cast<SampleType>(curve_rise(p, static_cast<float>(curve_)));
638 }
639
640private:
641 SampleType curve_ = SampleType{0};
642 Shape shape_ = Shape::stage_curve;
643};
644
647
648} // namespace pulp::signal
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.