Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
adsr.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <algorithm>
4#include <cmath>
5
6namespace pulp::signal {
7
8// ADSR envelope generator.
9//
10// RT contract: fixed-state and allocation-free. Call set_params() /
11// set_sample_rate() from prepare/control code, then note_on(), note_off(),
12// next(), apply_to_buffer(), reset(), and accessors are audio-thread safe.
13template <typename SampleType = float>
14class AdsrT {
15public:
16 struct Params {
17 SampleType attack = SampleType{0.01f}; // seconds
18 SampleType decay = SampleType{0.1f}; // seconds
19 SampleType sustain = SampleType{0.7f}; // level 0-1
20 SampleType release = SampleType{0.3f}; // seconds
21 };
22
23 void set_params(const Params& p) { params_ = p; }
24 void set_sample_rate(SampleType sr) { sample_rate_ = sr; }
25
26 void note_on() {
27 stage_ = Stage::attack;
28 // Don't reset level_ — allows retriggering from current position
29 }
30
31 void note_off() {
32 if (stage_ != Stage::idle)
33 stage_ = Stage::release;
34 }
35
36 void reset() {
37 stage_ = Stage::idle;
38 level_ = SampleType{0.0f};
39 }
40
41 SampleType next() {
42 switch (stage_) {
43 case Stage::idle:
44 return SampleType{0.0f};
45
46 case Stage::attack: {
47 SampleType rate = rate_for(params_.attack);
48 level_ += rate;
49 if (level_ >= SampleType{1.0f}) {
50 level_ = SampleType{1.0f};
51 stage_ = Stage::decay;
52 }
53 return level_;
54 }
55
56 case Stage::decay: {
57 SampleType rate = rate_for(params_.decay);
58 level_ -= rate;
59 if (level_ <= params_.sustain) {
60 level_ = params_.sustain;
61 stage_ = Stage::sustain;
62 }
63 return level_;
64 }
65
66 case Stage::sustain:
67 return level_;
68
69 case Stage::release: {
70 SampleType rate = rate_for(params_.release);
71 level_ -= rate;
72 if (level_ <= SampleType{0.0f}) {
73 level_ = SampleType{0.0f};
74 stage_ = Stage::idle;
75 }
76 return level_;
77 }
78 }
79 return SampleType{0.0f};
80 }
81
82 bool is_active() const { return stage_ != Stage::idle; }
83
84 enum class Stage { idle, attack, decay, sustain, release };
85 Stage stage() const { return stage_; }
86
94 void apply_to_buffer(SampleType* buffer, int start_sample, int num_samples) {
95 for (int i = 0; i < num_samples; ++i)
96 buffer[start_sample + i] *= next();
97 }
98
102 void apply_to_buffer(SampleType* const* channels, int num_channels,
103 int start_sample, int num_samples) {
104 for (int i = 0; i < num_samples; ++i) {
105 const SampleType env = next();
106 for (int ch = 0; ch < num_channels; ++ch)
107 channels[ch][start_sample + i] *= env;
108 }
109 }
110
111private:
112 Params params_;
113 SampleType sample_rate_ = SampleType{44100.0f};
114 SampleType level_ = SampleType{0.0f};
115 Stage stage_ = Stage::idle;
116
117 SampleType rate_for(SampleType time_seconds) const {
118 if (time_seconds <= SampleType{0.0f}) return SampleType{1.0f};
119 return SampleType{1.0f} / (time_seconds * sample_rate_);
120 }
121};
122
125
126} // namespace pulp::signal
Definition adsr.hpp:14
void reset()
Definition adsr.hpp:36
void note_off()
Definition adsr.hpp:31
void apply_to_buffer(SampleType *buffer, int start_sample, int num_samples)
Multiply num_samples of buffer (starting at start_sample) by successive envelope values.
Definition adsr.hpp:94
void set_sample_rate(SampleType sr)
Definition adsr.hpp:24
void apply_to_buffer(SampleType *const *channels, int num_channels, int start_sample, int num_samples)
Multiply each channel of a planar multi-channel buffer by the same envelope.
Definition adsr.hpp:102
SampleType next()
Definition adsr.hpp:41
void note_on()
Definition adsr.hpp:26
Stage stage() const
Definition adsr.hpp:85
bool is_active() const
Definition adsr.hpp:82
Stage
Definition adsr.hpp:84
@ sustain
Definition adsr.hpp:84
@ release
Definition adsr.hpp:84
@ decay
Definition adsr.hpp:84
@ idle
Definition adsr.hpp:84
@ attack
Definition adsr.hpp:84
void set_params(const Params &p)
Definition adsr.hpp:23
Definition additive_bank.hpp:218
@ buffer
A borrowed static buffer with a traversable playhead.
Definition granular.hpp:110
AdsrT< float > Adsr
Definition adsr.hpp:123
@ i
Definition formant_filter_bank.hpp:20
AdsrT< double > Adsr64
Definition adsr.hpp:124
Definition adsr.hpp:16
SampleType release
Definition adsr.hpp:20
SampleType attack
Definition adsr.hpp:17
SampleType sustain
Definition adsr.hpp:19
SampleType decay
Definition adsr.hpp:18