Mozzi  version 2016-12-11-17:03
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 <util/atomic.h>
21 #include "Line.h"
22 #include "mozzi_fixmath.h"
23 
24 
45 template <unsigned int CONTROL_UPDATE_RATE, unsigned int LERP_RATE>
46 class ADSR
47 {
48 private:
49 
50  const unsigned int LERPS_PER_CONTROL;
51 
52  unsigned int update_step_counter;
53  unsigned int num_update_steps;
54 
55  enum {ATTACK,DECAY,SUSTAIN,RELEASE,IDLE};
56 
57 
58  struct phase{
59  byte phase_type;
60  unsigned int update_steps;
61  long lerp_steps; // signed, to match params to transition (line) type Q15n16, below
62  Q8n0 level;
63  }attack,decay,sustain,release,idle;
64 
65  phase * current_phase;
66 
67  // Linear audio rate transitions for envelope
68  //Line <unsigned long> transition;
69  Line <Q15n16> transition; // scale up unsigned char levels for better accuracy, then scale down again for output
70 
71  inline
72  unsigned int convertMsecToControlUpdateSteps(unsigned int msec){
73  return (uint16_t) (((uint32_t)msec*CONTROL_UPDATE_RATE)>>10); // approximate /1000 with shift
74  }
75 
76 
77  inline
78  void setPhase(phase * next_phase) {
79  update_step_counter = 0;
80  num_update_steps = next_phase->update_steps;
81  transition.set(Q8n0_to_Q15n16(next_phase->level),next_phase->lerp_steps);
82  current_phase = next_phase;
83  }
84 
85 
86  inline
87  void checkForAndSetNextPhase(phase * next_phase) {
88  if (++update_step_counter >= num_update_steps){
89  setPhase(next_phase);
90  }
91  }
92 
93 
94 
95  inline
96  void setTime(phase * p, unsigned int msec)
97  {
98  p->update_steps = convertMsecToControlUpdateSteps(msec);
99  p->lerp_steps = (long) p->update_steps * LERPS_PER_CONTROL;
100  }
101 
102 
103  inline
104  void setUpdateSteps(phase * p, unsigned int steps)
105  {
106  p->update_steps = steps;
107  p->lerp_steps = (long) steps * LERPS_PER_CONTROL;
108  }
109 
110 
111 
112 public:
113 
116  ADSR():LERPS_PER_CONTROL(LERP_RATE/CONTROL_UPDATE_RATE)
117  {
118  attack.phase_type = ATTACK;
119  decay.phase_type = DECAY;
120  sustain.phase_type = SUSTAIN;
121  release.phase_type = RELEASE;
122  idle.phase_type = IDLE;
123  release.level = 0;
124  }
125 
126 
127 
131  void update(){ // control rate
132 
133  switch(current_phase->phase_type) {
134 
135  case ATTACK:
136  checkForAndSetNextPhase(&decay);
137  break;
138 
139  case DECAY:
140  checkForAndSetNextPhase(&sustain);
141  break;
142 
143  case SUSTAIN:
144  checkForAndSetNextPhase(&release);
145  break;
146 
147  case RELEASE:
148  checkForAndSetNextPhase(&idle);
149  break;
150 
151  case IDLE:
152  adsr_playing = false;
153  break;
154  }
155  }
156 
157 
158 
163  inline
164  unsigned char next()
165  {
166  unsigned char out = 0;
167  if (adsr_playing) out = Q15n16_to_Q8n0(transition.next());
168  return out;
169  }
170 
171 
172 
175  inline
176  void noteOn(){
177  setPhase(&attack);
178  adsr_playing = true;
179  }
180 
181 
182 
186  inline
187  void noteOff(){
188  setPhase(&release);
189  }
190 
191 
192 
196  inline
197  void setAttackLevel(byte value)
198  {
199  attack.level=value;
200  }
201 
202 
203 
207  inline
208  void setDecayLevel(byte value)
209  {
210  decay.level=value;
211  }
212 
213 
218  inline
219  void setSustainLevel(byte value)
220  {
221  sustain.level=value;
222  }
223 
228  inline
229  void setReleaseLevel(byte value)
230  {
231  release.level=value;
232  }
233 
234 
235  inline
236  void setIdleLevel(byte value)
237  {
238  idle.level=value;
239  }
240 
241 
247  inline
248  void setADLevels(byte attack, byte decay)
249  {
250  setAttackLevel(attack);
251  setDecayLevel(decay);
252  setSustainLevel(decay); // stay at decay level
253  setReleaseLevel(1);
254  setIdleLevel(0);
255  }
256 
257 
264  inline
265  void setLevels(byte attack, byte decay, byte sustain, byte release)
266  {
267  setAttackLevel(attack);
268  setDecayLevel(decay);
269  setSustainLevel(sustain);
270  setReleaseLevel(release);
271  setIdleLevel(0);
272  }
273 
274 
281  inline
282  void setAttackTime(unsigned int msec)
283  {
284  setTime(&attack, msec);
285  }
286 
287 
294  inline
295  void setDecayTime(unsigned int msec)
296  {
297  setTime(&decay, msec);
298  }
299 
300 
308  inline
309  void setSustainTime(unsigned int msec)
310  {
311  setTime(&sustain, msec);
312  }
313 
314 
315 
322  inline
323  void setReleaseTime(unsigned int msec)
324  {
325  setTime(&release, msec);
326  }
327 
328 
329  inline
330  void setIdleTime(unsigned int msec)
331  {
332  setTime(&idle, msec);
333  }
334 
335 
345  inline
346  void setTimes(unsigned int attack_ms, unsigned int decay_ms, unsigned int sustain_ms, unsigned int release_ms)
347  {
348  setAttackTime(attack_ms);
349  setDecayTime(decay_ms);
350  setSustainTime(sustain_ms);
351  setReleaseTime(release_ms);
352  setIdleTime(65535); // guarantee step size of line will be 0
353  }
354 
355 
356 
360  inline
361  void setAttackUpdateSteps(unsigned int steps)
362  {
363  setUpdateSteps(&attack, steps);
364  }
365 
366 
370  inline
371  void setDecayUpdateSteps(unsigned int steps)
372  {
373  setUpdateSteps(&decay, steps);
374  }
375 
376 
380  inline
381  void setSustainUpdateSteps(unsigned int steps)
382  {
383  setUpdateSteps(&sustain, steps);
384  }
385 
386 
390  inline
391  void setReleaseUpdateSteps(unsigned int steps)
392  {
393  setUpdateSteps(&release, steps);
394  }
395 
396 
397  inline
398  void setIdleUpdateSteps(unsigned int steps)
399  {
400  setUpdateSteps(&idle, steps);
401  }
402 
409  inline
410  void setAllUpdateSteps(unsigned int attack_steps, unsigned int decay_steps, unsigned int sustain_steps, unsigned int release_steps)
411  {
412  setAttackUpdateSteps(attack_steps);
413  setDecayUpdateSteps(decay_steps);
414  setSustainUpdateSteps(sustain_steps);
415  setReleaseUpdateSteps(release_steps);
416  setIdleUpdateSteps(65535); // guarantee step size of line will be 0
417  }
418 
419 
420 bool adsr_playing;
421 
425  inline
426  bool playing()
427  {
428  return adsr_playing;
429  }
430 
431 
432 };
433 
434 
439 #endif /* ADSR_H_ */
void set(T value)
Set the current value of the line.
Definition: Line.h:77
unsigned char next()
Advances one audio step along the ADSR and returns the level.
Definition: ADSR.h:164
void setSustainLevel(byte value)
Set the sustain level of the ADSR.
Definition: ADSR.h:219
void setDecayLevel(byte value)
Set the decay level of the ADSR.
Definition: ADSR.h:208
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:391
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:346
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:361
void setLevels(byte attack, byte decay, byte sustain, byte release)
Set the attack, decay, sustain and release levels.
Definition: ADSR.h:265
void setReleaseTime(unsigned int msec)
Set the release time of the ADSR in milliseconds.
Definition: ADSR.h:323
Q8n0 Q15n16_to_Q8n0(Q15n16 a)
Convert Q15n16 fixed to Q8n0 uint8_t.
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:410
void setSustainTime(unsigned int msec)
Set the sustain time of the ADSR in milliseconds.
Definition: ADSR.h:309
void noteOff()
Start the release phase of the ADSR.
Definition: ADSR.h:187
void setAttackTime(unsigned int msec)
Set the attack time of the ADSR in milliseconds.
Definition: ADSR.h:282
Q15n16 Q8n0_to_Q15n16(Q8n0 a)
Convert Q8n0 uint8_t to Q15n16 fix.
void setDecayTime(unsigned int msec)
Set the decay time of the ADSR in milliseconds.
Definition: ADSR.h:295
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:371
void setReleaseLevel(byte value)
Set the release level of the ADSR.
Definition: ADSR.h:229
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:381
void update()
Updates the internal controls of the ADSR.
Definition: ADSR.h:131
void setADLevels(byte attack, byte decay)
Set the attack and decay levels of the ADSR.
Definition: ADSR.h:248
uint8_t Q8n0
normal uint8_t with 0 fractional bits, represents 0.0 to 255.0
Definition: mozzi_fixmath.h:28
void noteOn()
Start the attack phase of the ADSR.
Definition: ADSR.h:176
ADSR()
Constructor.
Definition: ADSR.h:116
void setAttackLevel(byte value)
Set the attack level of the ADSR.
Definition: ADSR.h:197
A simple ADSR envelope generator.
Definition: ADSR.h:46
T next()
Increments one step along the line.
Definition: Line.h:59
bool playing()
Tells if the envelope is currently playing.
Definition: ADSR.h:426