11 enum class Shape { FLEXIBLE, EXPONENTIAL, LINEAR };
14 float attack_slope_ = 0;
16 float decay_slope_ = 0;
17 float sustain_level_ = 0;
19 float release_slope_ = 0;
21 float release_start_ = 0;
22 int sustain_steps_ = 0;
23 bool params_changed_ =
true;
26 enum class State { ATTACK, DECAY, SUSTAIN, RELEASE, DONE };
28 State state_ = State::DONE;
29 Shape shape_ = Shape::LINEAR;
36 init_abc (
float time_s,
float slope)
38 bool positive = slope > 0;
39 slope = std::abs (slope);
41 const float t1y = 0.5f + 0.25f * slope;
43 a_ = slope * ( 1.0135809670870777f + slope * (-1.2970447050283254f + slope * 7.2390617313972063f));
44 b_ = slope * (-5.8998946320566281f + slope * ( 5.7282487210570903f + slope * -15.525953208626062f));
45 c_ = 1 - (t1y * a_ + b_) * t1y;
53 const float time_factor = 1 / (rate_ * time_s);
70 compute_slope_params (
float seconds,
float start_x,
float end_x)
75 int steps = std::max<int> (seconds * rate_, 1);
77 if (shape_ == Shape::LINEAR)
82 c_ = (end_x - start_x) / steps;
84 else if (shape_ == Shape::EXPONENTIAL)
89 const double RATIO = (state_ == State::ATTACK) ? 0.2 : 0.001;
91 const double f = -log ((RATIO + 1) / RATIO) / steps;
92 double factor = exp (f);
93 c_ = (end_x - RATIO * (start_x - end_x)) * (1 - factor);
97 else if (shape_ == Shape::FLEXIBLE)
99 auto pos_time = [] (
auto x) {
return std::max (x, 0.0001f); };
100 if (state_ == State::ATTACK)
102 init_abc (pos_time (attack_), attack_slope_);
104 else if (state_ == State::DECAY)
107 float stretch = 1 / std::max (1 - sustain_level_, 0.01f);
108 init_abc (-pos_time (decay_ * stretch), decay_slope_);
110 else if (state_ == State::RELEASE)
112 init_abc (-pos_time (release_), release_slope_);
115 float l = std::max (release_start_, 0.01f);
120 params_changed_ =
false;
125 set_shape (Shape shape)
128 params_changed_ =
true;
134 params_changed_ =
true;
137 set_attack_slope (
float f)
140 params_changed_ =
true;
146 params_changed_ =
true;
149 set_decay_slope (
float f)
152 params_changed_ =
true;
155 set_sustain (
float f)
157 sustain_level_ = f * 0.01f;
158 params_changed_ =
true;
161 set_release (
float f)
164 params_changed_ =
true;
167 set_release_slope (
float f)
170 params_changed_ =
true;
173 set_rate (
int sample_rate)
176 params_changed_ =
true;
182 state_ = State::ATTACK;
183 params_changed_ =
true;
188 state_ = State::RELEASE;
189 release_start_ = level_;
190 params_changed_ =
true;
193 template<State STATE, Shape SHAPE>
195 process (uint *iptr,
float *samples, uint n_samples)
202 const float sustain_level = sustain_level_;
204 float level = level_;
206 while (i < n_samples)
208 samples[i++] = level;
210 if (SHAPE == Shape::FLEXIBLE)
211 level = (a * level + b) * level + c;
213 if (SHAPE == Shape::EXPONENTIAL)
214 level = b * level + c;
216 if (SHAPE == Shape::LINEAR)
219 if (STATE == State::ATTACK && level > 1)
222 state_ = State::DECAY;
223 params_changed_ =
true;
226 if (STATE == State::DECAY && level < sustain_level)
228 state_ = State::SUSTAIN;
229 level = sustain_level;
230 params_changed_ =
true;
233 if (STATE == State::RELEASE && level < 1e-5f)
235 state_ = State::DONE;
244 template<State STATE>
246 process (uint *iptr,
float *samples, uint n_samples)
248 if (shape_ == Shape::LINEAR)
249 process<STATE, Shape::LINEAR> (iptr, samples, n_samples);
251 if (shape_ == Shape::EXPONENTIAL)
252 process<STATE, Shape::EXPONENTIAL> (iptr, samples, n_samples);
254 if (shape_ == Shape::FLEXIBLE)
255 process<STATE, Shape::FLEXIBLE> (iptr, samples, n_samples);
259 process (
float *samples, uint n_samples)
262 if (state_ == State::ATTACK)
264 compute_slope_params (attack_, 0, 1);
265 process<State::ATTACK> (&i, samples, n_samples);
267 if (state_ == State::DECAY)
269 compute_slope_params (decay_, 1, sustain_level_);
270 process<State::DECAY> (&i, samples, n_samples);
272 if (state_ == State::RELEASE)
274 compute_slope_params (release_, release_start_, 0);
275 process<State::RELEASE> (&i, samples, n_samples);
277 if (state_ == State::SUSTAIN)
281 if (std::abs (sustain_level_ - level_) > 1e-5)
283 sustain_steps_ = std::max<int> (0.020f * rate_, 1);
284 c_ = (sustain_level_ - level_) / sustain_steps_;
290 params_changed_ =
false;
292 while (sustain_steps_ && i < n_samples)
294 samples[i++] = level_;
297 if (sustain_steps_ == 0)
298 level_ = sustain_level_;
300 while (i < n_samples)
301 samples[i++] = level_;
303 if (state_ == State::DONE)
305 while (i < n_samples)
312 if (state_ == State::SUSTAIN)
314 return !params_changed_ && sustain_steps_ == 0;
316 return state_ == State::DONE;
321 return state_ == State::DONE;
Definition: smflexadsr.hh:9