andrewm@0
|
1 //
|
andrewm@0
|
2 // ADRS.h
|
andrewm@0
|
3 //
|
andrewm@0
|
4 // Created by Nigel Redmon on 12/18/12.
|
andrewm@0
|
5 // EarLevel Engineering: earlevel.com
|
andrewm@0
|
6 // Copyright 2012 Nigel Redmon
|
andrewm@0
|
7 //
|
andrewm@0
|
8 // For a complete explanation of the ADSR envelope generator and code,
|
andrewm@0
|
9 // read the series of articles by the author, starting here:
|
andrewm@0
|
10 // http://www.earlevel.com/main/2013/06/01/envelope-generators/
|
andrewm@0
|
11 //
|
andrewm@0
|
12 // License:
|
andrewm@0
|
13 //
|
andrewm@0
|
14 // This source code is provided as is, without warranty.
|
andrewm@0
|
15 // You may copy and distribute verbatim copies of this document.
|
andrewm@0
|
16 // You may modify and use this source code to create binary code for your own purposes, free or commercial.
|
andrewm@0
|
17 //
|
andrewm@0
|
18
|
andrewm@0
|
19 #ifndef ADRS_h
|
andrewm@0
|
20 #define ADRS_h
|
andrewm@0
|
21
|
andrewm@0
|
22 #include <stdio.h>
|
andrewm@0
|
23 #include <string>
|
andrewm@0
|
24
|
andrewm@0
|
25 using namespace std;
|
andrewm@0
|
26
|
andrewm@0
|
27 enum envState {
|
andrewm@0
|
28 env_idle = 0,
|
andrewm@0
|
29 env_attack,
|
andrewm@0
|
30 env_decay,
|
andrewm@0
|
31 env_sustain,
|
andrewm@0
|
32 env_release
|
andrewm@0
|
33 };
|
andrewm@0
|
34
|
andrewm@0
|
35 class ADSR {
|
andrewm@0
|
36 public:
|
andrewm@0
|
37 ADSR(void);
|
andrewm@0
|
38 ~ADSR(void);
|
andrewm@0
|
39 float process(void);
|
andrewm@0
|
40 float process(int sampleCount);
|
andrewm@0
|
41 float getOutput(void);
|
andrewm@0
|
42 int getState(void);
|
andrewm@0
|
43 void gate(int on);
|
andrewm@0
|
44 void setAttackRate(float rate);
|
andrewm@0
|
45 void setDecayRate(float rate);
|
andrewm@0
|
46 void setReleaseRate(float rate);
|
andrewm@0
|
47 void setSustainLevel(float level);
|
andrewm@0
|
48 void setTargetRatioA(float targetRatio);
|
andrewm@0
|
49 void setTargetRatioDR(float targetRatio);
|
andrewm@0
|
50 void reset(void);
|
andrewm@0
|
51
|
andrewm@0
|
52 protected:
|
andrewm@0
|
53 int state;
|
andrewm@0
|
54 float output;
|
andrewm@0
|
55 float attackRate;
|
andrewm@0
|
56 float decayRate;
|
andrewm@0
|
57 float releaseRate;
|
andrewm@0
|
58 float attackCoef;
|
andrewm@0
|
59 float decayCoef;
|
andrewm@0
|
60 float releaseCoef;
|
andrewm@0
|
61 float sustainLevel;
|
andrewm@0
|
62 float targetRatioA;
|
andrewm@0
|
63 float targetRatioDR;
|
andrewm@0
|
64 float attackBase;
|
andrewm@0
|
65 float decayBase;
|
andrewm@0
|
66 float releaseBase;
|
andrewm@0
|
67 string name;
|
andrewm@0
|
68 float calcCoef(float rate, float targetRatio);
|
andrewm@0
|
69 };
|
andrewm@0
|
70
|
andrewm@0
|
71 inline float ADSR::process() {
|
andrewm@0
|
72 switch (state) {
|
andrewm@0
|
73 case env_idle:
|
andrewm@0
|
74 break;
|
andrewm@0
|
75 case env_attack:
|
andrewm@0
|
76 output = attackBase + output * attackCoef;
|
andrewm@0
|
77 if (output >= 1.0) {
|
andrewm@0
|
78 output = 1.0;
|
andrewm@0
|
79 state = env_decay;
|
andrewm@0
|
80 }
|
andrewm@0
|
81 break;
|
andrewm@0
|
82 case env_decay:
|
andrewm@0
|
83 output = decayBase + output * decayCoef;
|
andrewm@0
|
84 if (output <= sustainLevel) {
|
andrewm@0
|
85 output = sustainLevel;
|
andrewm@0
|
86 state = env_sustain;
|
andrewm@0
|
87 }
|
andrewm@0
|
88 break;
|
andrewm@0
|
89 case env_sustain:
|
andrewm@0
|
90 break;
|
andrewm@0
|
91 case env_release:
|
andrewm@0
|
92 output = releaseBase + output * releaseCoef;
|
andrewm@0
|
93 if (output <= 0.0) {
|
andrewm@0
|
94 output = 0.0;
|
andrewm@0
|
95 state = env_idle;
|
andrewm@0
|
96 }
|
andrewm@0
|
97 break;
|
andrewm@0
|
98 }
|
andrewm@0
|
99 return output;
|
andrewm@0
|
100 }
|
andrewm@0
|
101
|
andrewm@0
|
102 inline float ADSR::process(int sampleCount)
|
andrewm@0
|
103 {
|
andrewm@0
|
104 float retVal = 0;
|
andrewm@0
|
105
|
andrewm@0
|
106 if(state != env_idle)
|
andrewm@0
|
107 {
|
andrewm@0
|
108 for(int i=0; i<sampleCount; i++)
|
andrewm@0
|
109 retVal = process();
|
andrewm@0
|
110 }
|
andrewm@0
|
111
|
andrewm@0
|
112 return retVal;
|
andrewm@0
|
113 }
|
andrewm@0
|
114
|
andrewm@0
|
115 inline void ADSR::gate(int gate) {
|
andrewm@0
|
116
|
andrewm@0
|
117 if (gate)
|
andrewm@0
|
118 state = env_attack;
|
andrewm@0
|
119 else if (state != env_idle)
|
andrewm@0
|
120 state = env_release;
|
andrewm@0
|
121 }
|
andrewm@0
|
122
|
andrewm@0
|
123 inline int ADSR::getState() {
|
andrewm@0
|
124 return state;
|
andrewm@0
|
125 }
|
andrewm@0
|
126
|
andrewm@0
|
127 inline void ADSR::reset() {
|
andrewm@0
|
128 state = env_idle;
|
andrewm@0
|
129 output = 0.0;
|
andrewm@0
|
130 }
|
andrewm@0
|
131
|
andrewm@0
|
132 inline float ADSR::getOutput() {
|
andrewm@0
|
133 return output;
|
andrewm@0
|
134 }
|
andrewm@0
|
135
|
andrewm@0
|
136
|
andrewm@0
|
137 #endif
|