Mozzi  version v2.0
sound synthesis library for Arduino
ADSR.h
1 /*
2  * ADSR.h
3  *
4  * This file is part of Mozzi.
5  *
6  * Copyright 2012-2024 Tim Barrass and the Mozzi Team
7  *
8  * Mozzi is licensed under the GNU Lesser General Public Licence (LGPL) Version 2.1 or later.
9  *
10  */
11 
12 #ifndef ADSR_H_
13 #define ADSR_H_
14 
15 #include <Arduino.h>
16 #include "Line.h"
17 #include "mozzi_fixmath.h"
18 
19 
40 template <unsigned int CONTROL_UPDATE_RATE, unsigned int LERP_RATE, typename T = unsigned int>
41 class ADSR
42 {
43 private:
44 
45  const unsigned int LERPS_PER_CONTROL;
46 
47  T update_step_counter;
48  T num_update_steps;
49 
50  enum {ATTACK,DECAY,SUSTAIN,RELEASE,IDLE};
51 
52 
53  struct phase{
54  byte phase_type;
55  T update_steps;
56  long lerp_steps; // signed, to match params to transition (line) type Q15n16, below
57  Q8n0 level;
58  }attack,decay,sustain,release,idle;
59 
60  phase * current_phase;
61 
62  // Linear audio rate transitions for envelope
63  //Line <unsigned long> transition;
64  Line <Q15n16> transition; // scale up unsigned char levels for better accuracy, then scale down again for output
65 
66  inline
67  T convertMsecToControlUpdateSteps(unsigned int msec){
68  return (T) (((uint32_t)msec*CONTROL_UPDATE_RATE)>>10); // approximate /1000 with shift
69  }
70 
71 
72  inline
73  void setPhase(phase * next_phase) {
74  update_step_counter = 0;
75  num_update_steps = next_phase->update_steps;
76  transition.set(Q8n0_to_Q15n16(next_phase->level),next_phase->lerp_steps);
77  current_phase = next_phase;
78  }
79 
80 
81  inline
82  void checkForAndSetNextPhase(phase * next_phase) {
83  if (++update_step_counter >= num_update_steps){
84  setPhase(next_phase);
85  }
86  }
87 
88 
89 
90  inline
91  void setTime(phase * p, unsigned int msec)
92  {
93  p->update_steps = convertMsecToControlUpdateSteps(msec);
94  p->lerp_steps = (long) p->update_steps * LERPS_PER_CONTROL;
95  }
96 
97 
98  inline
99  void setUpdateSteps(phase * p, unsigned int steps)
100  {
101  p->update_steps = steps;
102  p->lerp_steps = (long) steps * LERPS_PER_CONTROL;
103  }
104 
105 
106 
107 public:
108 
111  ADSR():LERPS_PER_CONTROL(LERP_RATE/CONTROL_UPDATE_RATE)
112  {
113  attack.phase_type = ATTACK;
114  decay.phase_type = DECAY;
115  sustain.phase_type = SUSTAIN;
116  release.phase_type = RELEASE;
117  idle.phase_type = IDLE;
118  release.level = 0;
119  adsr_playing = false;
120  current_phase = &idle;
121  }
122 
123 
124 
128  void update(){ // control rate
129 
130  switch(current_phase->phase_type) {
131 
132  case ATTACK:
133  checkForAndSetNextPhase(&decay);
134  break;
135 
136  case DECAY:
137  checkForAndSetNextPhase(&sustain);
138  break;
139 
140  case SUSTAIN:
141  checkForAndSetNextPhase(&release);
142  break;
143 
144  case RELEASE:
145  checkForAndSetNextPhase(&idle);
146  break;
147 
148  case IDLE:
149  adsr_playing = false;
150  break;
151  }
152  }
153 
154 
155 
160  inline
161  unsigned char next()
162  {
163  unsigned char out = 0;
164  if (adsr_playing) out = Q15n16_to_Q8n0(transition.next());
165  return out;
166  }
167 
168 
169 
175  inline
176  void noteOn(bool reset=false){
177  if (reset) transition.set(0);
178  setPhase(&attack);
179  adsr_playing = true;
180  }
181 
182 
183 
187  inline
188  void noteOff(){
189  setPhase(&release);
190  }
191 
192 
193 
197  inline
198  void setAttackLevel(byte value)
199  {
200  attack.level=value;
201  }
202 
203 
204 
208  inline
209  void setDecayLevel(byte value)
210  {
211  decay.level=value;
212  }
213 
214 
219  inline
220  void setSustainLevel(byte value)
221  {
222  sustain.level=value;
223  }
224 
229  inline
230  void setReleaseLevel(byte value)
231  {
232  release.level=value;
233  }
234 
235 
236  inline
237  void setIdleLevel(byte value)
238  {
239  idle.level=value;
240  }
241 
242 
248  inline
249  void setADLevels(byte attack, byte decay)
250  {
251  setAttackLevel(attack);
252  setDecayLevel(decay);
253  setSustainLevel(decay); // stay at decay level
254  setReleaseLevel(1);
255  setIdleLevel(0);
256  }
257 
258 
265  inline
266  void setLevels(byte attack, byte decay, byte sustain, byte release)
267  {
268  setAttackLevel(attack);
269  setDecayLevel(decay);
270  setSustainLevel(sustain);
271  setReleaseLevel(release);
272  setIdleLevel(0);
273  }
274 
275 
282  inline
283  void setAttackTime(unsigned int msec)
284  {
285  setTime(&attack, msec);
286  }
287 
288 
295  inline
296  void setDecayTime(unsigned int msec)
297  {
298  setTime(&decay, msec);
299  }
300 
301 
309  inline
310  void setSustainTime(unsigned int msec)
311  {
312  setTime(&sustain, msec);
313  }
314 
315 
316 
323  inline
324  void setReleaseTime(unsigned int msec)
325  {
326  setTime(&release, msec);
327  }
328 
329 
330  inline
331  void setIdleTime(unsigned int msec)
332  {
333  setTime(&idle, msec);
334  }
335 
336 
346  inline
347  void setTimes(unsigned int attack_ms, unsigned int decay_ms, unsigned int sustain_ms, unsigned int release_ms)
348  {
349  setAttackTime(attack_ms);
350  setDecayTime(decay_ms);
351  setSustainTime(sustain_ms);
352  setReleaseTime(release_ms);
353  setIdleTime(65535); // guarantee step size of line will be 0
354  }
355 
356 
357 
361  inline
362  void setAttackUpdateSteps(unsigned int steps)
363  {
364  setUpdateSteps(&attack, steps);
365  }
366 
367 
371  inline
372  void setDecayUpdateSteps(unsigned int steps)
373  {
374  setUpdateSteps(&decay, steps);
375  }
376 
377 
381  inline
382  void setSustainUpdateSteps(unsigned int steps)
383  {
384  setUpdateSteps(&sustain, steps);
385  }
386 
387 
391  inline
392  void setReleaseUpdateSteps(unsigned int steps)
393  {
394  setUpdateSteps(&release, steps);
395  }
396 
397 
398  inline
399  void setIdleUpdateSteps(unsigned int steps)
400  {
401  setUpdateSteps(&idle, steps);
402  }
403 
410  inline
411  void setAllUpdateSteps(unsigned int attack_steps, unsigned int decay_steps, unsigned int sustain_steps, unsigned int release_steps)
412  {
413  setAttackUpdateSteps(attack_steps);
414  setDecayUpdateSteps(decay_steps);
415  setSustainUpdateSteps(sustain_steps);
416  setReleaseUpdateSteps(release_steps);
417  setIdleUpdateSteps(65535); // guarantee step size of line will be 0
418  }
419 
420 
421 bool adsr_playing;
422 
426  inline
427  bool playing()
428  {
429  return adsr_playing;
430  }
431 
432 
433 };
434 
435 
440 #endif /* ADSR_H_ */
A simple ADSR envelope generator.
Definition: ADSR.h:42
void setAttackUpdateSteps(unsigned int steps)
Set the attack time of the ADSR, expressed as the number of update steps (not ADSR::next() interpolat...
Definition: ADSR.h:362
void setDecayLevel(byte value)
Set the decay level of the ADSR.
Definition: ADSR.h:209
void setReleaseUpdateSteps(unsigned int steps)
Set the release time of the ADSR, expressed as the number of update steps (not ADSR::next() interpola...
Definition: ADSR.h:392
void setDecayTime(unsigned int msec)
Set the decay time of the ADSR in milliseconds.
Definition: ADSR.h:296
void update()
Updates the internal controls of the ADSR.
Definition: ADSR.h:128
void noteOff()
Start the release phase of the ADSR.
Definition: ADSR.h:188
void setADLevels(byte attack, byte decay)
Set the attack and decay levels of the ADSR.
Definition: ADSR.h:249
ADSR()
Constructor.
Definition: ADSR.h:111
void setLevels(byte attack, byte decay, byte sustain, byte release)
Set the attack, decay, sustain and release levels.
Definition: ADSR.h:266
void setTimes(unsigned int attack_ms, unsigned int decay_ms, unsigned int sustain_ms, unsigned int release_ms)
Set the attack, decay and release times of the ADSR in milliseconds.
Definition: ADSR.h:347
void setAttackLevel(byte value)
Set the attack level of the ADSR.
Definition: ADSR.h:198
void setReleaseLevel(byte value)
Set the release level of the ADSR.
Definition: ADSR.h:230
void setAllUpdateSteps(unsigned int attack_steps, unsigned int decay_steps, unsigned int sustain_steps, unsigned int release_steps)
Set the attack, decay and release times of the ADSR, expressed in update steps (not ADSR::next() inte...
Definition: ADSR.h:411
unsigned char next()
Advances one audio step along the ADSR and returns the level.
Definition: ADSR.h:161
void setReleaseTime(unsigned int msec)
Set the release time of the ADSR in milliseconds.
Definition: ADSR.h:324
void setAttackTime(unsigned int msec)
Set the attack time of the ADSR in milliseconds.
Definition: ADSR.h:283
bool playing()
Tells if the envelope is currently playing.
Definition: ADSR.h:427
void setSustainTime(unsigned int msec)
Set the sustain time of the ADSR in milliseconds.
Definition: ADSR.h:310
void setDecayUpdateSteps(unsigned int steps)
Set the decay time of the ADSR, expressed as the number of update steps (not ADSR::next() interpolati...
Definition: ADSR.h:372
void setSustainLevel(byte value)
Set the sustain level of the ADSR.
Definition: ADSR.h:220
void setSustainUpdateSteps(unsigned int steps)
Set the sustain time of the ADSR, expressed as the number of update steps (not ADSR::next() interpola...
Definition: ADSR.h:382
void noteOn(bool reset=false)
Start the attack phase of the ADSR.
Definition: ADSR.h:176
T next()
Increments one step along the line.
Definition: Line.h:60
void set(T value)
Set the current value of the line.
Definition: Line.h:75
Q8n0 Q15n16_to_Q8n0(Q15n16 a)
Convert Q15n16 fixed to Q8n0 uint8_t.
Q15n16 Q8n0_to_Q15n16(Q8n0 a)
Convert Q8n0 uint8_t to Q15n16 fix.
uint8_t Q8n0
normal uint8_t with 0 fractional bits, represents 0.0 to 255.0
Definition: mozzi_fixmath.h:34