| 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_ */
ADSR::setDecayLevel
void setDecayLevel(byte value)
Set the decay level of the ADSR.
Definition: ADSR.h:213
ADSR::noteOn
void noteOn(bool reset=false)
Start the attack phase of the ADSR.
Definition: ADSR.h:180
ADSR::setAttackUpdateSteps
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
ADSR::setSustainLevel
void setSustainLevel(byte value)
Set the sustain level of the ADSR.
Definition: ADSR.h:224
Q15n16
int32_t Q15n16
signed fractional number using 15 integer bits and 16 fractional bits, represents -32767...
Definition: mozzi_fixmath.h:40
ADSR::setLevels
void setLevels(byte attack, byte decay, byte sustain, byte release)
Set the attack, decay, sustain and release levels.
Definition: ADSR.h:270
ADSR::next
unsigned char next()
Advances one audio step along the ADSR and returns the level.
Definition: ADSR.h:165
ADSR::setSustainUpdateSteps
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
ADSR::setReleaseUpdateSteps
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
ADSR::setReleaseTime
void setReleaseTime(unsigned int msec)
Set the release time of the ADSR in milliseconds.
Definition: ADSR.h:328
ADSR::setDecayUpdateSteps
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
ADSR::setAllUpdateSteps
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
ADSR::noteOff
void noteOff()
Start the release phase of the ADSR.
Definition: ADSR.h:192
Line
For linear changes with a minimum of calculation at each step.
Definition: Line.h:37
ADSR::setAttackLevel
void setAttackLevel(byte value)
Set the attack level of the ADSR.
Definition: ADSR.h:202
ADSR::setADLevels
void setADLevels(byte attack, byte decay)
Set the attack and decay levels of the ADSR.
Definition: ADSR.h:253
ADSR::playing
bool playing()
Tells if the envelope is currently playing.
Definition: ADSR.h:431
ADSR::setAttackTime
void setAttackTime(unsigned int msec)
Set the attack time of the ADSR in milliseconds.
Definition: ADSR.h:287
ADSR::setTimes
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
ADSR::setReleaseLevel
void setReleaseLevel(byte value)
Set the release level of the ADSR.
Definition: ADSR.h:234
ADSR::setDecayTime
void setDecayTime(unsigned int msec)
Set the decay time of the ADSR in milliseconds.
Definition: ADSR.h:300
ADSR::ADSR
ADSR()
Constructor.
Definition: ADSR.h:115
Q8n0
uint8_t Q8n0
normal uint8_t with 0 fractional bits, represents 0.0 to 255.0
Definition: mozzi_fixmath.h:28
ADSR::setSustainTime
void setSustainTime(unsigned int msec)
Set the sustain time of the ADSR in milliseconds.
Definition: ADSR.h:314
ADSR
A simple ADSR envelope generator.
Definition: ADSR.h:45
ADSR::update
void update()
Updates the internal controls of the ADSR.
Definition: ADSR.h:132