1 /*
2 * Author: Nigel Redmon on 12/18/12.
3 * Adapted: Harry van Haaren 2013
4 * harryhaaren@gmail.com
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 //
21 // Original work granted under permissive license below:
22 //
23 // Created by Nigel Redmon on 12/18/12.
24 // EarLevel Engineering: earlevel.com
25 // Copyright 2012 Nigel Redmon
26 //
27 // For a complete explanation of the ADSR envelope generator and code,
28 // read the series of articles by the author, starting here:
29 // http://www.earlevel.com/main/2013/06/01/envelope-generators/
30 //
31 // License:
32 //
33 // This source code is provided as is, without warranty.
34 // You may copy and distribute verbatim copies of this document.
35 // You may modify and use this source code to create binary code for your own purposes, free or commercial.
36 //
37
38 #ifndef ADSR_H
39 #define ADSR_H
40
41
42 class ADSR
43 {
44 public:
45 ADSR();
46 ~ADSR();
47 float process(void);
48 float getOutput(void);
49 int getState(void);
50 void gate(int on);
51 void setAttackRate(float rate);
52 void setDecayRate(float rate);
53 void setReleaseRate(float rate);
54 void setSustainLevel(float level);
55 void setTargetRatioA(float targetRatio);
56 void setTargetRatioDR(float targetRatio);
57 void reset(void);
58
59 enum envState {
60 ENV_IDLE = 0,
61 ENV_ATTACK,
62 ENV_DECAY,
63 ENV_SUSTAIN,
64 ENV_RELEASE,
65 };
66
67 protected:
68 int state;
69 float output;
70 float attackRate;
71 float decayRate;
72 float releaseRate;
73 float attackCoef;
74 float decayCoef;
75 float releaseCoef;
76 float sustainLevel;
77 float targetRatioA;
78 float targetRatioDR;
79 float attackBase;
80 float decayBase;
81 float releaseBase;
82
83 float calcCoef(float rate, float targetRatio);
84 };
85
process()86 inline float ADSR::process()
87 {
88 switch (state) {
89 case ENV_IDLE:
90 break;
91 case ENV_ATTACK:
92 output = attackBase + output * attackCoef;
93 if (output >= 1.0) {
94 output = 1.0;
95 state = ENV_DECAY;
96 }
97 break;
98 case ENV_DECAY:
99 output = decayBase + output * decayCoef;
100 if (output <= sustainLevel) {
101 output = sustainLevel;
102 state = ENV_SUSTAIN;
103 }
104 break;
105 case ENV_SUSTAIN:
106 break;
107 case ENV_RELEASE:
108 output = releaseBase + output * releaseCoef;
109 if (output <= 0.0) {
110 output = 0.0;
111 state = ENV_IDLE;
112 }
113 }
114 return output;
115 }
116
gate(int gate)117 inline void ADSR::gate(int gate)
118 {
119 if (gate)
120 state = ENV_ATTACK;
121 else if (state != ENV_IDLE)
122 state = ENV_RELEASE;
123 }
124
getState()125 inline int ADSR::getState()
126 {
127 return state;
128 }
129
reset()130 inline void ADSR::reset()
131 {
132 state = ENV_IDLE;
133 output = 0.0;
134 }
135
getOutput()136 inline float ADSR::getOutput()
137 {
138 return output;
139 }
140
141 #endif // ASDR_H
142