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