Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
trigger.hpp
Go to the documentation of this file.
1#pragma once
2
19
21
22#include <algorithm>
23#include <array>
24#include <cmath>
25#include <concepts>
26#include <cstdint>
27#include <type_traits>
28
29namespace pulp::signal {
30
31inline constexpr double kTriggerHighThreshold = 0.5;
32inline constexpr double kTriggerLowThreshold = 0.25;
33
38template <typename SampleType = float>
40public:
41 void set_thresholds(double high, double low) {
42 if (!std::isfinite(high) || !std::isfinite(low)) return;
43 high_threshold_ = high;
44 low_threshold_ = std::min(low, high - 1e-9);
45 }
46
47 void reset() { armed_ = true; }
48
49 bool process(SampleType input) {
50 const double x = static_cast<double>(input);
51 if (armed_ && x >= high_threshold_) {
52 armed_ = false;
53 return true;
54 }
55 if (!armed_ && x <= low_threshold_) armed_ = true;
56 return false;
57 }
58
59 void process(SampleType input, bool& rising, bool& falling) {
60 const bool was_high = !armed_;
61 rising = process(input);
62 falling = was_high && armed_;
63 }
64
65 bool high() const { return !armed_; }
66
67private:
68 double high_threshold_ = kTriggerHighThreshold;
69 double low_threshold_ = kTriggerLowThreshold;
70 bool armed_ = true;
71};
72
75
89template <typename SampleType = float>
91public:
95 static constexpr double kDefaultRefractoryMs = 1.0;
96
97 void prepare(double sample_rate) {
98 sample_rate_ = sample_rate > 0.0 ? sample_rate : 1.0;
99 update_refractory_();
100 reset();
101 }
102
103 void set_refractory_ms(double ms) {
104 refractory_ms_ = std::max(0.0, ms);
105 update_refractory_();
106 }
107
110 void set_threshold(SampleType t) { threshold_ = t; }
111
112 void reset() {
113 prev_ = false;
114 countdown_ = 0;
115 }
116
118 bool process(bool gate) {
119 if (countdown_ > 0) --countdown_;
120 const bool rising = gate && !prev_;
121 prev_ = gate;
122 if (!rising || countdown_ > 0) return false;
123 countdown_ = refractory_samples_;
124 return true;
125 }
126
130 template <typename Value>
131 requires(!std::same_as<std::remove_cvref_t<Value>, bool>)
132 bool process(Value) = delete;
133
137 bool process_signal(SampleType input) { return process(input > threshold_); }
138
139 void process_signal(SampleType input, bool& rising, bool& falling) {
140 const bool was_high = prev_;
141 rising = process_signal(input);
142 falling = was_high && !prev_;
143 }
144
145 bool armed() const { return countdown_ == 0; }
146
147private:
148 void update_refractory_() {
149 refractory_samples_ =
150 static_cast<long long>(std::lround(refractory_ms_ * 0.001 * sample_rate_));
151 }
152
153 double sample_rate_ = 48000.0;
154 double refractory_ms_ = kDefaultRefractoryMs;
155 long long refractory_samples_ = 48;
156 long long countdown_ = 0;
157 SampleType threshold_ = SampleType{0.5};
158 bool prev_ = false;
159};
160
163
174template <typename SampleType = float>
175class GateGenT {
176public:
177 static constexpr double kMinLengthMs = 0.1;
178 static constexpr double kMaxLengthMs = 10000.0;
179 static constexpr double kDefaultLengthMs = 10.0;
180
181 enum class Retrigger : std::uint8_t {
189 };
190
191 void prepare(double sample_rate) {
192 sample_rate_ = sample_rate > 0.0 ? sample_rate : 1.0;
193 update_length_();
194 reset();
195 }
196
197 void set_length_ms(double ms) {
198 length_ms_ = std::fmin(std::fmax(ms, kMinLengthMs), kMaxLengthMs);
199 update_length_();
200 }
201 double length_ms() const { return length_ms_; }
202
208 void set_length_samples(double samples) {
209 length_samples_ = static_cast<long long>(std::lround(std::max(0.0, samples)));
210 length_ms_ = static_cast<double>(length_samples_) * 1000.0 / sample_rate_;
211 }
212
213 void set_retrigger(Retrigger policy) { retrigger_ = policy; }
214
215 void set_levels(SampleType low_level, SampleType high_level) {
216 low_level_ = low_level;
217 high_level_ = high_level;
218 }
219
220 void reset() {
221 remaining_ = 0;
222 detector_.reset();
223 }
224
226 bool process(bool trigger) {
227 if (trigger && length_samples_ > 0) {
228 switch (retrigger_) {
230 if (remaining_ <= 0) remaining_ = length_samples_;
231 break;
233 remaining_ += length_samples_;
234 break;
236 default:
237 remaining_ = length_samples_;
238 break;
239 }
240 }
241 if (remaining_ <= 0) return false;
242 --remaining_;
243 return true;
244 }
245
246 SampleType process(SampleType trigger) {
247 if (detector_.process(trigger)) remaining_ = length_samples_;
248 if (remaining_ <= 0) return low_level_;
249 --remaining_;
250 return high_level_;
251 }
252
253 bool gate() const { return remaining_ > 0; }
254 bool open() const { return gate(); }
255
256private:
257 void update_length_() {
258 length_samples_ = static_cast<long long>(std::lround(length_ms_ * 0.001 * sample_rate_));
259 }
260
261 double sample_rate_ = 48000.0;
262 double length_ms_ = kDefaultLengthMs;
263 long long length_samples_ = 2400;
264 long long remaining_ = 0;
265 Retrigger retrigger_ = Retrigger::restart;
266 HystereticTriggerDetectT<SampleType> detector_{};
267 SampleType low_level_ = SampleType{0};
268 SampleType high_level_ = SampleType{1};
269};
270
273
283template <typename SampleType = float>
285public:
286 static constexpr int kMinDivision = 1;
287 static constexpr int kMaxDivision = 64;
288 static constexpr int kDefaultDivision = 2;
289
290 void set_division(int n) { division_ = std::clamp(n, 1, kMaxDivision); }
291 int division() const { return division_; }
292
294 void reset_phase() {
295 counter_ = 0;
296 detector_.reset();
297 }
298 void reset() { reset_phase(); }
299
300 bool process(bool trigger) {
301 if (!trigger) return false;
302 const bool pass = (counter_ == 0);
303 if (++counter_ >= division_) counter_ = 0;
304 return pass;
305 }
306
307 bool process(SampleType clock) {
308 if (!detector_.process(clock)) return false;
309 const bool pass = counter_ == 0;
310 counter_ = (counter_ + 1) % division_;
311 return pass;
312 }
313
314private:
315 int division_ = kDefaultDivision;
316 int counter_ = 0;
318};
319
322
340public:
341 static constexpr int kMaxMultiplier = 16;
342
343 void set_multiplier(int n) { multiplier_ = std::clamp(n, 1, kMaxMultiplier); }
344 int multiplier() const { return multiplier_; }
345
346 void reset() {
347 period_ = 0;
348 since_trigger_ = 0;
349 ticks_emitted_ = 0;
350 have_period_ = false;
351 have_first_ = false;
352 }
353
355 bool process(bool trigger) {
356 // Counted before the trigger test, so the measured period is the true
357 // sample distance between two triggers rather than one short.
358 ++since_trigger_;
359 if (trigger) {
360 if (have_first_) {
361 period_ = since_trigger_;
362 have_period_ = true;
363 }
364 since_trigger_ = 0;
365 have_first_ = true;
366 ticks_emitted_ = 1;
367 return true;
368 }
369 if (!have_period_ || multiplier_ <= 1) return false;
370 if (ticks_emitted_ >= multiplier_) return false;
371 const long long due = tick_offset_(ticks_emitted_);
372 if (since_trigger_ < due) return false;
373 ++ticks_emitted_;
374 return true;
375 }
376
378 long long period_samples() const { return have_period_ ? period_ : 0; }
379
380private:
381 long long tick_offset_(int tick_index) const {
382 return static_cast<long long>(
383 std::llround(static_cast<double>(tick_index) * static_cast<double>(period_)
384 / static_cast<double>(multiplier_)));
385 }
386
387 long long period_ = 0;
388 long long since_trigger_ = 0;
389 int multiplier_ = 1;
390 int ticks_emitted_ = 0;
391 bool have_period_ = false;
392 bool have_first_ = false;
393};
394
400
404namespace round2 {
405template <typename SampleType = float>
407} // namespace round2
408
416template <typename SampleType = float>
418public:
419 static constexpr int kMinMultiple = 1;
420 static constexpr int kMaxMultiple = 32;
421 static constexpr int kDefaultMultiple = 2;
422 static constexpr double kMaxPeriodMs = 4000.0;
423
424 void prepare(double sample_rate) {
425 sample_rate_ = sample_rate > 0.0 ? sample_rate : sample_rate_;
426 max_period_samples_ = sample_rate_ * kMaxPeriodMs * 0.001;
427 }
428
429 void set_multiple(int n) {
430 const int next = std::clamp(n, kMinMultiple, kMaxMultiple);
431 if (next == multiple_) return;
432 multiple_ = next;
433 if (!(period_ > 0.0) || since_edge_ >= period_) {
434 pending_ = 0;
435 next_at_ = 0.0;
436 return;
437 }
438 const double spacing = period_ / static_cast<double>(multiple_);
439 const int next_index = static_cast<int>(std::floor(since_edge_ / spacing)) + 1;
440 pending_ = std::max(0, multiple_ - next_index);
441 next_at_ = static_cast<double>(next_index) * spacing;
442 }
443 int multiple() const { return multiple_; }
444
445 void reset() {
446 detector_.reset();
447 since_edge_ = 0.0;
448 period_ = 0.0;
449 next_at_ = 0.0;
450 pending_ = 0;
451 have_edge_ = false;
452 }
453
454 bool process(SampleType clock) {
455 since_edge_ += 1.0;
456 if (detector_.process(clock)) {
457 const bool usable = have_edge_ && since_edge_ <= max_period_samples_;
458 period_ = usable ? since_edge_ : 0.0;
459 have_edge_ = true;
460 since_edge_ = 0.0;
461 pending_ = period_ > 0.0 ? multiple_ - 1 : 0;
462 next_at_ = period_ / static_cast<double>(multiple_);
463 return true;
464 }
465 bool fired = false;
466 while (pending_ > 0 && period_ > 0.0 && since_edge_ >= next_at_) {
467 --pending_;
468 next_at_ += period_ / static_cast<double>(multiple_);
469 fired = true;
470 }
471 return fired;
472 }
473
476 template <std::integral Integer>
477 bool process(Integer) = delete;
478
479private:
480 double sample_rate_ = 44100.0;
481 double max_period_samples_ = 44100.0 * 4.0;
482 int multiple_ = kDefaultMultiple;
483 double since_edge_ = 0.0;
484 double period_ = 0.0;
485 double next_at_ = 0.0;
486 int pending_ = 0;
487 bool have_edge_ = false;
489};
490
493
508template <typename SampleType = float>
510public:
511 static constexpr int kMinCount = 1;
512 static constexpr int kMaxCount = 64;
513 static constexpr int kDefaultCount = 4;
514 static constexpr double kMinIntervalMs = 1.0;
515 static constexpr double kMaxIntervalMs = 2000.0;
516 static constexpr double kDefaultIntervalMs = 50.0;
517
518 struct Hit {
519 bool fired = false;
521 SampleType level = SampleType{0};
523 int index = 0;
524 };
525
526 void prepare(double sample_rate) {
527 sample_rate_ = sample_rate > 0.0 ? sample_rate : 1.0;
528 update_interval_();
529 reset();
530 }
531
536 void set_count(int n) {
537 const bool idle = next_index_ >= count_;
538 count_ = std::clamp(n, 1, kMaxCount);
539 if (idle) next_index_ = count_;
540 }
541 int count() const { return count_; }
542 void set_spacing_ms(double ms) { spacing_ms_ = std::max(0.0, ms); }
543 void set_spacing_curve(float c) { spacing_curve_ = std::clamp(c, -1.0f, 1.0f); }
544
545 void set_levels(SampleType first, SampleType last) {
546 level_first_ = first;
547 level_last_ = last;
548 }
549
550 void set_interval_ms(double ms) {
551 interval_ms_ = std::fmin(std::fmax(ms, kMinIntervalMs), kMaxIntervalMs);
552 update_interval_();
553 }
554 double interval_ms() const { return interval_ms_; }
555
556 void reset() {
557 next_index_ = count_;
558 elapsed_ = 0;
559 remaining_ = 0;
560 countdown_ = 0;
561 detector_.reset();
562 }
563
567 Hit process(bool trigger) {
568 Hit hit{};
569 if (trigger) {
570 next_index_ = 0;
571 elapsed_ = 0;
572 }
573 if (next_index_ >= count_) return hit;
574 if (elapsed_ >= hit_offset_(next_index_)) {
575 hit.fired = true;
576 hit.index = next_index_;
577 hit.level = level_for_(next_index_);
578 ++next_index_;
579 }
580 ++elapsed_;
581 return hit;
582 }
583
584 bool process(SampleType trigger) {
585 if (detector_.process(trigger)) {
586 remaining_ = count_ - 1;
587 countdown_ = interval_samples_;
588 return true;
589 }
590 if (remaining_ <= 0) return false;
591 if (--countdown_ <= 0) {
592 --remaining_;
593 countdown_ = interval_samples_;
594 return true;
595 }
596 return false;
597 }
598
602 long long hit_offset_samples(int index) const { return hit_offset_(index); }
603
604 bool active() const { return next_index_ < count_; }
605 bool busy() const { return remaining_ > 0; }
606
607private:
608 void update_interval_() {
609 interval_samples_ = static_cast<long long>(
610 std::llround(interval_ms_ * 0.001 * sample_rate_));
611 if (interval_samples_ < 1) interval_samples_ = 1;
612 }
613
614 long long hit_offset_(int index) const {
615 if (count_ <= 1 || index <= 0) return 0;
616 const double span = static_cast<double>(count_ - 1) * spacing_ms_ * 0.001 * sample_rate_;
617 const float p = static_cast<float>(index) / static_cast<float>(count_ - 1);
618 return static_cast<long long>(
619 std::llround(span * static_cast<double>(stage_curve(p, spacing_curve_))));
620 }
621
622 SampleType level_for_(int index) const {
623 if (count_ <= 1) return level_first_;
624 const SampleType t = static_cast<SampleType>(index) / static_cast<SampleType>(count_ - 1);
625 return level_first_ + (level_last_ - level_first_) * t;
626 }
627
628 double sample_rate_ = 48000.0;
629 double spacing_ms_ = 60.0;
630 long long elapsed_ = 0;
631 SampleType level_first_ = SampleType{1};
632 SampleType level_last_ = SampleType{1};
633 float spacing_curve_ = 0.0f;
634 int count_ = 4;
635 int next_index_ = 4;
636 double interval_ms_ = kDefaultIntervalMs;
637 long long interval_samples_ = 1;
638 long long remaining_ = 0;
639 long long countdown_ = 0;
640 HystereticTriggerDetectT<SampleType> detector_{};
641};
642
645
659template <typename SampleType = float>
661public:
665 static constexpr int kCapacity = 8;
666 static constexpr double kMinDelayMs = 0.0;
667 static constexpr double kMaxDelayMs = 10000.0;
668 static constexpr double kDefaultDelayMs = 0.0;
669
670 void prepare(double sample_rate) {
671 sample_rate_ = sample_rate > 0.0 ? sample_rate : 1.0;
672 update_delay_();
673 reset();
674 }
675
676 void set_delay_ms(double ms) {
677 delay_ms_ = std::fmin(std::fmax(ms, kMinDelayMs), kMaxDelayMs);
678 update_delay_();
679 }
680 double delay_ms() const { return delay_ms_; }
681
684 void set_delay_samples(double samples) {
685 delay_samples_ = static_cast<long long>(std::lround(std::max(0.0, samples)));
686 delay_ms_ = static_cast<double>(delay_samples_) * 1000.0 / sample_rate_;
687 }
688
689 void reset() {
690 pending_.fill(0);
691 dropped_ = 0;
692 countdown_ = -1;
693 detector_.reset();
694 }
695
697 bool process(bool trigger) {
698 bool fired = false;
699 // 0 is the empty marker, so a zero-initialized queue is an empty one.
700 for (auto& slot : pending_) {
701 if (slot <= 0) continue;
702 if (--slot == 0) fired = true;
703 }
704 if (trigger) {
705 if (delay_samples_ <= 0) {
706 fired = true;
707 } else if (!enqueue_(delay_samples_)) {
708 ++dropped_;
709 }
710 }
711 return fired;
712 }
713
714 bool process(SampleType trigger) {
715 if (detector_.process(trigger)) countdown_ = delay_samples_;
716 if (countdown_ < 0) return false;
717 if (countdown_ == 0) {
718 countdown_ = -1;
719 return true;
720 }
721 --countdown_;
722 return false;
723 }
724
726 long long dropped() const { return dropped_; }
727
728private:
729 bool enqueue_(long long samples) {
730 for (auto& slot : pending_) {
731 if (slot <= 0) {
732 slot = samples;
733 return true;
734 }
735 }
736 return false;
737 }
738
739 void update_delay_() {
740 delay_samples_ = static_cast<long long>(std::lround(delay_ms_ * 0.001 * sample_rate_));
741 }
742
743 std::array<long long, kCapacity> pending_{};
744 double sample_rate_ = 48000.0;
745 double delay_ms_ = 0.0;
746 long long delay_samples_ = 0;
747 long long dropped_ = 0;
748 long long countdown_ = -1;
749 HystereticTriggerDetectT<SampleType> detector_{};
750};
751
754
755} // namespace pulp::signal
One trigger in, a burst of N triggers out, with a spacing curve and a level ramp.
Definition trigger.hpp:509
void set_interval_ms(double ms)
Definition trigger.hpp:550
static constexpr double kDefaultIntervalMs
Definition trigger.hpp:516
double interval_ms() const
Definition trigger.hpp:554
void set_spacing_ms(double ms)
Definition trigger.hpp:542
static constexpr int kDefaultCount
Definition trigger.hpp:513
void reset()
Definition trigger.hpp:556
static constexpr int kMaxCount
Definition trigger.hpp:512
static constexpr int kMinCount
Definition trigger.hpp:511
static constexpr double kMinIntervalMs
Definition trigger.hpp:514
void set_spacing_curve(float c)
Definition trigger.hpp:543
void set_count(int n)
Changing the count while the burst is idle keeps it idle: next_index_ marks "finished" by sitting at ...
Definition trigger.hpp:536
bool active() const
Definition trigger.hpp:604
void set_levels(SampleType first, SampleType last)
Definition trigger.hpp:545
static constexpr double kMaxIntervalMs
Definition trigger.hpp:515
Hit process(bool trigger)
At most one hit fires per sample.
Definition trigger.hpp:567
void prepare(double sample_rate)
Definition trigger.hpp:526
bool busy() const
Definition trigger.hpp:605
int count() const
Definition trigger.hpp:541
bool process(SampleType trigger)
Definition trigger.hpp:584
long long hit_offset_samples(int index) const
Sample offset of hit index from the burst's trigger.
Definition trigger.hpp:602
Pass every Nth trigger.
Definition trigger.hpp:284
bool process(bool trigger)
Definition trigger.hpp:300
bool process(SampleType clock)
Definition trigger.hpp:307
void set_division(int n)
Definition trigger.hpp:290
int division() const
Definition trigger.hpp:291
static constexpr int kMinDivision
Definition trigger.hpp:286
void reset_phase()
Realign so the next trigger passes.
Definition trigger.hpp:294
static constexpr int kMaxDivision
Definition trigger.hpp:287
void reset()
Definition trigger.hpp:298
static constexpr int kDefaultDivision
Definition trigger.hpp:288
Emit N evenly spaced event triggers per measured input period.
Definition trigger.hpp:339
long long period_samples() const
Measured input period in samples; 0 until two triggers have arrived.
Definition trigger.hpp:378
int multiplier() const
Definition trigger.hpp:344
bool process(bool trigger)
Definition trigger.hpp:355
static constexpr int kMaxMultiplier
Definition trigger.hpp:341
void reset()
Definition trigger.hpp:346
void set_multiplier(int n)
Definition trigger.hpp:343
Trigger in, fixed-length gate out.
Definition trigger.hpp:175
Retrigger
Definition trigger.hpp:181
@ ignore
Drop triggers while the gate is high.
Definition trigger.hpp:186
@ restart
Reset the countdown to full length.
Definition trigger.hpp:184
@ extend
Add another full length to whatever remains.
Definition trigger.hpp:188
static constexpr double kMaxLengthMs
Definition trigger.hpp:178
void set_length_samples(double samples)
Direct sample length, for synced use via units::division_to_samples().
Definition trigger.hpp:208
double length_ms() const
Definition trigger.hpp:201
static constexpr double kMinLengthMs
Definition trigger.hpp:177
bool open() const
Definition trigger.hpp:254
void set_levels(SampleType low_level, SampleType high_level)
Definition trigger.hpp:215
SampleType process(SampleType trigger)
Definition trigger.hpp:246
static constexpr double kDefaultLengthMs
Definition trigger.hpp:179
bool gate() const
Definition trigger.hpp:253
void set_retrigger(Retrigger policy)
Definition trigger.hpp:213
void prepare(double sample_rate)
Definition trigger.hpp:191
void set_length_ms(double ms)
Definition trigger.hpp:197
void reset()
Definition trigger.hpp:220
bool process(bool trigger)
Definition trigger.hpp:226
Hysteretic continuous-CV edge detector.
Definition trigger.hpp:39
bool process(SampleType input)
Definition trigger.hpp:49
bool high() const
Definition trigger.hpp:65
void process(SampleType input, bool &rising, bool &falling)
Definition trigger.hpp:59
void set_thresholds(double high, double low)
Definition trigger.hpp:41
void reset()
Definition trigger.hpp:47
Continuous-signal clock multiplier.
Definition trigger.hpp:417
bool process(SampleType clock)
Definition trigger.hpp:454
static constexpr double kMaxPeriodMs
Definition trigger.hpp:422
int multiple() const
Definition trigger.hpp:443
static constexpr int kDefaultMultiple
Definition trigger.hpp:421
static constexpr int kMaxMultiple
Definition trigger.hpp:420
void reset()
Definition trigger.hpp:445
void set_multiple(int n)
Definition trigger.hpp:429
void prepare(double sample_rate)
Definition trigger.hpp:424
bool process(Integer)=delete
Reject ambiguous integral clock samples; use bool with ClockMultT or an explicit floating-point sampl...
static constexpr int kMinMultiple
Definition trigger.hpp:419
Delay a trigger by a fixed time, through a small fixed-capacity queue.
Definition trigger.hpp:660
static constexpr int kCapacity
Definition trigger.hpp:665
static constexpr double kDefaultDelayMs
Definition trigger.hpp:668
bool process(SampleType trigger)
Definition trigger.hpp:714
long long dropped() const
Triggers discarded because the queue was full since the last reset().
Definition trigger.hpp:726
void set_delay_samples(double samples)
Direct sample delay, for synced use.
Definition trigger.hpp:684
void set_delay_ms(double ms)
Definition trigger.hpp:676
static constexpr double kMinDelayMs
Definition trigger.hpp:666
static constexpr double kMaxDelayMs
Definition trigger.hpp:667
double delay_ms() const
Definition trigger.hpp:680
void reset()
Definition trigger.hpp:689
void prepare(double sample_rate)
Definition trigger.hpp:670
bool process(bool trigger)
Definition trigger.hpp:697
Rising-edge detector with a refractory period.
Definition trigger.hpp:90
bool armed() const
Definition trigger.hpp:145
void reset()
Definition trigger.hpp:112
bool process_signal(SampleType input)
Established single-threshold signal lane.
Definition trigger.hpp:137
void set_threshold(SampleType t)
Threshold for the refractory process_signal() lane.
Definition trigger.hpp:110
void set_refractory_ms(double ms)
Definition trigger.hpp:103
bool process(Value)=delete
Prevent continuous values from silently selecting the decoded-event lane through implicit conversion ...
void process_signal(SampleType input, bool &rising, bool &falling)
Definition trigger.hpp:139
void prepare(double sample_rate)
Definition trigger.hpp:97
bool process(bool gate)
Definition trigger.hpp:118
static constexpr double kDefaultRefractoryMs
Definition trigger.hpp:95
The small modular utilities every patch reaches for between a modulation source and its destination: ...
Migration namespace for the unshipped Round-2 spelling whose template arity conflicts with the establ...
Definition mod_matrix.hpp:184
::pulp::signal::ClockMultT ClockMultT
Definition trigger.hpp:406
Definition additive_bank.hpp:218
TriggerDetectT< double > TriggerDetect64
Definition trigger.hpp:162
ClockMultT ClockMult64
Definition trigger.hpp:397
@ first
Definition dither.hpp:23
ClockMultT EventClockMult
Definition trigger.hpp:398
GateGenT< float > GateGen
Definition trigger.hpp:271
SignalClockMultT< float > SignalClockMult
Definition trigger.hpp:491
HystereticTriggerDetectT< float > HystereticTriggerDetect
Definition trigger.hpp:73
ClockDividerT< double > ClockDivider64
Definition trigger.hpp:321
@ falling
Definition rise_fall_generator.hpp:19
@ rising
Definition rise_fall_generator.hpp:19
BurstGenT< float > BurstGen
Definition trigger.hpp:643
constexpr double kTriggerHighThreshold
Definition trigger.hpp:31
@ c
Definition spectrum_trace.hpp:35
@ idle
Definition envelope.hpp:56
ClockMultT EventClockMult64
Definition trigger.hpp:399
TrigDelayT< double > TrigDelay64
Definition trigger.hpp:753
ClockDividerT< float > ClockDivider
Definition trigger.hpp:320
TriggerDetectT< float > TriggerDetect
Definition trigger.hpp:161
float stage_curve(float p, float curve)
The shared stage-shaping law:
Definition mod_tools.hpp:44
@ e
Definition formant_filter_bank.hpp:20
constexpr double kTriggerLowThreshold
Definition trigger.hpp:32
HystereticTriggerDetectT< double > HystereticTriggerDetect64
Definition trigger.hpp:74
TrigDelayT< float > TrigDelay
Definition trigger.hpp:752
ClockMultT ClockMult
Backward-compatible name for the already-decoded event adapter.
Definition trigger.hpp:396
SignalClockMultT< double > SignalClockMult64
Definition trigger.hpp:492
BurstGenT< double > BurstGen64
Definition trigger.hpp:644
GateGenT< double > GateGen64
Definition trigger.hpp:272
Definition trigger.hpp:518
bool fired
Definition trigger.hpp:519
int index
0-based index within the burst; meaningful only when fired.
Definition trigger.hpp:523
SampleType level
Level for this hit, interpolated between the start and end levels.
Definition trigger.hpp:521