Mozzi  version v1.1.0
sound synthesis library for Arduino
ADSR.h
1 /*
2  * ADSR.h
3  *
4  * Copyright 2012 Tim Barrass.
5  *
6  * This file is part of Mozzi.
7  *
8  * Mozzi is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
9  *
10  */
11 
12 #ifndef ADSR_H_
13 #define ADSR_H_
14 
15 #if ARDUINO >= 100
16  #include "Arduino.h"
17 #else
18  #include "WProgram.h"
19 #endif
20 #include "Line.h"
21 #include "mozzi_fixmath.h"
22 
23 
24 /** A simple ADSR envelope generator. This implementation has separate update() and next()
25 methods, where next() interpolates values between each update().
26 The "normal" way to use this would be with update() in updateControl(), where it calculates a new internal state each control step,
27 and then next() is in updateAudio(), called much more often, where it interpolates between the control values.
28 This also allows the ADSR updates to be made even more sparsely if desired, eg. every 3rd control update.
29 @tparam CONTROL_UPDATE_RATE The frequency of control updates.
30 Ordinarily this will be CONTROL_RATE, but an alternative (amongst others) is
31 to set this as well as the LERP_RATE parameter to AUDIO_RATE, and call both update() and next() in updateAudio().
32 Such a use would allow accurate envelopes with finer resolution of the control points than CONTROL_RATE.
33 @tparam LERP_RATE Sets how often next() will be called, to interpolate between updates set by CONTROL_UPDATE_RATE.
34 This will produce the smoothest results if it's set to AUDIO_RATE, but if you need to save processor time and your
35 envelope changes slowly or controls something like a filter where there may not be problems with glitchy or clicking transitions,
36 LERP_RATE could be set to CONTROL_RATE (for instance). Then update() and next() could both be called in updateControl(),
37 greatly reducing the amount of processing required compared to calling next() in updateAudio().
38 @todo Test whether using the template parameters makes any difference to speed,
39 and rationalise which units do and don't need them.
40 Template objects are messy when you try to use pointers to them,
41 you have to include the whole template in the pointer handling.
42 */
43 
44 template <unsigned int CONTROL_UPDATE_RATE, unsigned int LERP_RATE, typename T = unsigned int>
45 class ADSR
46 {
47 private:
48 
49  const unsigned int LERPS_PER_CONTROL;
50 
51  T update_step_counter;
52  T num_update_steps;
53 
54  enum {ATTACK,DECAY,SUSTAIN,RELEASE,IDLE};
55 
56 
57  struct phase{
58  byte phase_type;
59  T update_steps;
60  long lerp_steps; // signed, to match params to transition (line) type Q15n16, below
61  Q8n0 level;
62  }attack,decay,sustain,release,idle;
63 
64  phase * current_phase;
65 
66  // Linear audio rate transitions for envelope
67  //Line <unsigned long> transition;
68  Line <Q15n16> transition; // scale up unsigned char levels for better accuracy, then scale down again for output
69 
70  inline
71  T convertMsecToControlUpdateSteps(unsigned int msec){
72  return (T) (((uint32_t)msec*CONTROL_UPDATE_RATE)>>10); // approximate /1000 with shift
73  }
74 
75 
76  inline
77  void setPhase(phase * next_phase) {
78  update_step_counter = 0;
79  num_update_steps = next_phase->update_steps;
80  transition.set(Q8n0_to_Q15n16(next_phase->level),next_phase->lerp_steps);
81  current_phase = next_phase;
82  }
83 
84 
85  inline
86  void checkForAndSetNextPhase(phase * next_phase) {
87  if (++update_step_counter >= num_update_steps){
88  setPhase(next_phase);
89  }
90  }
91 
92 
93 
94  inline
95  void setTime(phase * p, unsigned int msec)
96  {
97  p->update_steps = convertMsecToControlUpdateSteps(msec);
98  p->lerp_steps = (long) p->update_steps * LERPS_PER_CONTROL;
99  }
100 
101 
102  inline
103  void setUpdateSteps(phase * p, unsigned int steps)
104  {
105  p->update_steps = steps;
106  p->lerp_steps = (long) steps * LERPS_PER_CONTROL;
107  }
108 
109 
110 
111 public:
112 
113  /** Constructor.
114  */
115  ADSR():LERPS_PER_CONTROL(LERP_RATE/CONTROL_UPDATE_RATE)
116  {
117  attack.phase_type = ATTACK;
118  decay.phase_type = DECAY;
119  sustain.phase_type = SUSTAIN;
120  release.phase_type = RELEASE;
121  idle.phase_type = IDLE;
122  release.level = 0;
123  adsr_playing = false;
124  current_phase = &idle;
125  }
126 
127 
128 
129  /** Updates the internal controls of the ADSR.
130  Call this in updateControl().
131  */
132  void update(){ // control rate
133 
134  switch(current_phase->phase_type) {
135 
136  case ATTACK:
137  checkForAndSetNextPhase(&decay);
138  break;
139 
140  case DECAY:
141  checkForAndSetNextPhase(&sustain);
142  break;
143 
144  case SUSTAIN:
145  checkForAndSetNextPhase(&release);
146  break;
147 
148  case RELEASE:
149  checkForAndSetNextPhase(&idle);
150  break;
151 
152  case IDLE:
153  adsr_playing = false;
154  break;
155  }
156  }
157 
158 
159 
160  /** Advances one audio step along the ADSR and returns the level.
161  Call this in updateAudio().
162  @return the next value, as an unsigned char.
163  */
164  inline
165  unsigned char next()
166  {
167  unsigned char out = 0;
168  if (adsr_playing) out = Q15n16_to_Q8n0(transition.next());
169  return out;
170  }
171 
172 
173 
174  /** Start the attack phase of the ADSR. This will restart the ADSR no matter what phase it is up to.
175  @param reset If true, the envelope will start from 0, even if it is still playing (often useful for effect envelopes).
176  If false (default if omitted), the envelope will start rising from the current level, which could be non-zero, if
177  it is still playing (most useful for note envelopes).
178  */
179  inline
180  void noteOn(bool reset=false){
181  if (reset) transition.set(0);
182  setPhase(&attack);
183  adsr_playing = true;
184  }
185 
186 
187 
188  /** Start the release phase of the ADSR.
189  @todo fix release for rate rather than steps (time), so it releases at the same rate whatever the current level.
190  */
191  inline
192  void noteOff(){
193  setPhase(&release);
194  }
195 
196 
197 
198  /** Set the attack level of the ADSR.
199  @param value the attack level.
200  */
201  inline
202  void setAttackLevel(byte value)
203  {
204  attack.level=value;
205  }
206 
207 
208 
209  /** Set the decay level of the ADSR.
210  @param value the decay level.
211  */
212  inline
213  void setDecayLevel(byte value)
214  {
215  decay.level=value;
216  }
217 
218 
219  /** Set the sustain level of the ADSR.
220  @param value the sustain level. Usually the same as the decay level,
221  for a steady sustained note.
222  */
223  inline
224  void setSustainLevel(byte value)
225  {
226  sustain.level=value;
227  }
228 
229  /** Set the release level of the ADSR. Normally you'd make this 0,
230  but you have the option of some other value.
231  @param value the release level (usually 0).
232  */
233  inline
234  void setReleaseLevel(byte value)
235  {
236  release.level=value;
237  }
238 
239 
240  inline
241  void setIdleLevel(byte value)
242  {
243  idle.level=value;
244  }
245 
246 
247  /** Set the attack and decay levels of the ADSR. This assumes a conventional
248  ADSR where the sustain continues at the same level as the decay, till the release ramps to 0.
249  @param attack the new attack level.
250  @param decay the new decay level.
251  */
252  inline
253  void setADLevels(byte attack, byte decay)
254  {
255  setAttackLevel(attack);
256  setDecayLevel(decay);
257  setSustainLevel(decay); // stay at decay level
258  setReleaseLevel(1);
259  setIdleLevel(0);
260  }
261 
262 
263  /** Set the attack, decay, sustain and release levels.
264  @param attack the new attack level.
265  @param decay the new sustain level.
266  @param attack the new sustain level.
267  @param decay the new release level.
268  */
269  inline
270  void setLevels(byte attack, byte decay, byte sustain, byte release)
271  {
272  setAttackLevel(attack);
273  setDecayLevel(decay);
274  setSustainLevel(sustain);
275  setReleaseLevel(release);
276  setIdleLevel(0);
277  }
278 
279 
280  /** Set the attack time of the ADSR in milliseconds.
281  The actual time taken will be resolved within the resolution of CONTROL_RATE.
282  @param msec the unsigned int attack time in milliseconds.
283  @note Beware of low values (less than 20 or so, depending on how many steps are being taken),
284  in case internal step size gets calculated as 0, which would mean nothing happens.
285  */
286  inline
287  void setAttackTime(unsigned int msec)
288  {
289  setTime(&attack, msec);
290  }
291 
292 
293  /** Set the decay time of the ADSR in milliseconds.
294  The actual time taken will be resolved within the resolution of CONTROL_RATE.
295  @param msec the unsigned int decay time in milliseconds.
296  @note Beware of low values (less than 20 or so, depending on how many steps are being taken),
297  in case internal step size gets calculated as 0, which would mean nothing happens.
298  */
299  inline
300  void setDecayTime(unsigned int msec)
301  {
302  setTime(&decay, msec);
303  }
304 
305 
306  /** Set the sustain time of the ADSR in milliseconds.
307  The actual time taken will be resolved within the resolution of CONTROL_RATE.
308  The sustain phase will finish if the ADSR recieves a noteOff().
309  @param msec the unsigned int sustain time in milliseconds.
310  @note Beware of low values (less than 20 or so, depending on how many steps are being taken),
311  in case internal step size gets calculated as 0, which would mean nothing happens.
312  */
313  inline
314  void setSustainTime(unsigned int msec)
315  {
316  setTime(&sustain, msec);
317  }
318 
319 
320 
321  /** Set the release time of the ADSR in milliseconds.
322  The actual time taken will be resolved within the resolution of CONTROL_RATE.
323  @param msec the unsigned int release time in milliseconds.
324  @note Beware of low values (less than 20 or so, depending on how many steps are being taken),
325  in case internal step size gets calculated as 0, which would mean nothing happens.
326  */
327  inline
328  void setReleaseTime(unsigned int msec)
329  {
330  setTime(&release, msec);
331  }
332 
333 
334  inline
335  void setIdleTime(unsigned int msec)
336  {
337  setTime(&idle, msec);
338  }
339 
340 
341  /** Set the attack, decay and release times of the ADSR in milliseconds.
342  The actual times will be resolved within the resolution of CONTROL_RATE.
343  @param attack_ms the new attack time in milliseconds.
344  @param decay_ms the new decay time in milliseconds.
345  @param sustain_ms the new sustain time in milliseconds.
346  @param release_ms the new release time in milliseconds.
347  @note Beware of low values (less than 20 or so, depending on how many steps are being taken),
348  in case internal step size gets calculated as 0, which would mean nothing happens.
349  */
350  inline
351  void setTimes(unsigned int attack_ms, unsigned int decay_ms, unsigned int sustain_ms, unsigned int release_ms)
352  {
353  setAttackTime(attack_ms);
354  setDecayTime(decay_ms);
355  setSustainTime(sustain_ms);
356  setReleaseTime(release_ms);
357  setIdleTime(65535); // guarantee step size of line will be 0
358  }
359 
360 
361 
362  /** Set the attack time of the ADSR, expressed as the number of update steps (not ADSR::next() interpolation steps) in the attack phase.
363  @param steps the number of times ADSR::update() will be called in the attack phase.
364  */
365  inline
366  void setAttackUpdateSteps(unsigned int steps)
367  {
368  setUpdateSteps(&attack, steps);
369  }
370 
371 
372  /** Set the decay time of the ADSR, expressed as the number of update steps (not ADSR::next() interpolation steps) in the decay phase.
373  @param steps the number of times ADSR::update() will be called in the decay phase.
374  */
375  inline
376  void setDecayUpdateSteps(unsigned int steps)
377  {
378  setUpdateSteps(&decay, steps);
379  }
380 
381 
382  /** Set the sustain time of the ADSR, expressed as the number of update steps (not ADSR::next() interpolation steps) in the sustain phase.
383  @param steps the number of times ADSR::update() will be called in the sustain phase.
384  */
385  inline
386  void setSustainUpdateSteps(unsigned int steps)
387  {
388  setUpdateSteps(&sustain, steps);
389  }
390 
391 
392  /** Set the release time of the ADSR, expressed as the number of update steps (not ADSR::next() interpolation steps) in the release phase.
393  @param steps the number of times ADSR::update() will be called in the release phase.
394  */
395  inline
396  void setReleaseUpdateSteps(unsigned int steps)
397  {
398  setUpdateSteps(&release, steps);
399  }
400 
401 
402  inline
403  void setIdleUpdateSteps(unsigned int steps)
404  {
405  setUpdateSteps(&idle, steps);
406  }
407 
408  /** Set the attack, decay and release times of the ADSR, expressed in update steps (not ADSR::next() interpolation steps).
409  @param attack_steps the number of update steps in the attack phase
410  @param decay_steps the number of update steps in the decay phase
411  @param sustain_steps the number of update steps in the sustain phase
412  @param release_steps the number of update steps in the release phase
413  */
414  inline
415  void setAllUpdateSteps(unsigned int attack_steps, unsigned int decay_steps, unsigned int sustain_steps, unsigned int release_steps)
416  {
417  setAttackUpdateSteps(attack_steps);
418  setDecayUpdateSteps(decay_steps);
419  setSustainUpdateSteps(sustain_steps);
420  setReleaseUpdateSteps(release_steps);
421  setIdleUpdateSteps(65535); // guarantee step size of line will be 0
422  }
423 
424 
425 bool adsr_playing;
426 
427  /** Tells if the envelope is currently playing.
428  @return true if playing, false if in IDLE state
429  */
430  inline
431  bool playing()
432  {
433  return adsr_playing;
434  }
435 
436 
437 };
438 
439 
440 /** @example 07.Envelopes/ADSR_Envelope/ADSR_Envelope.ino
441 This is an example of how to use the ADSR class.
442 */
443 
444 #endif /* ADSR_H_ */
void setDecayLevel(byte value)
Set the decay level of the ADSR.
Definition: ADSR.h:213
void noteOn(bool reset=false)
Start the attack phase of the ADSR.
Definition: ADSR.h:180
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:366
void setSustainLevel(byte value)
Set the sustain level of the ADSR.
Definition: ADSR.h:224
int32_t Q15n16
signed fractional number using 15 integer bits and 16 fractional bits, represents -32767...
Definition: mozzi_fixmath.h:40
void setLevels(byte attack, byte decay, byte sustain, byte release)
Set the attack, decay, sustain and release levels.
Definition: ADSR.h:270
unsigned char next()
Advances one audio step along the ADSR and returns the level.
Definition: ADSR.h:165
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:386
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:396
void setReleaseTime(unsigned int msec)
Set the release time of the ADSR in milliseconds.
Definition: ADSR.h:328
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:376
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:415
void noteOff()
Start the release phase of the ADSR.
Definition: ADSR.h:192
For linear changes with a minimum of calculation at each step.
Definition: Line.h:37
void setAttackLevel(byte value)
Set the attack level of the ADSR.
Definition: ADSR.h:202
void setADLevels(byte attack, byte decay)
Set the attack and decay levels of the ADSR.
Definition: ADSR.h:253
bool playing()
Tells if the envelope is currently playing.
Definition: ADSR.h:431
void setAttackTime(unsigned int msec)
Set the attack time of the ADSR in milliseconds.
Definition: ADSR.h:287
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:351
void setReleaseLevel(byte value)
Set the release level of the ADSR.
Definition: ADSR.h:234
void setDecayTime(unsigned int msec)
Set the decay time of the ADSR in milliseconds.
Definition: ADSR.h:300
ADSR()
Constructor.
Definition: ADSR.h:115
uint8_t Q8n0
normal uint8_t with 0 fractional bits, represents 0.0 to 255.0
Definition: mozzi_fixmath.h:28
void setSustainTime(unsigned int msec)
Set the sustain time of the ADSR in milliseconds.
Definition: ADSR.h:314
A simple ADSR envelope generator.
Definition: ADSR.h:45
void update()
Updates the internal controls of the ADSR.
Definition: ADSR.h:132