-
Notifications
You must be signed in to change notification settings - Fork 24
Expand file tree
/
Copy pathAdsrEnvelope.h
More file actions
174 lines (169 loc) · 4.1 KB
/
AdsrEnvelope.h
File metadata and controls
174 lines (169 loc) · 4.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
#ifndef __ADSR_ENVELOPE_H
#define __ADSR_ENVELOPE_H
#include "Envelope.h"
/**
* ADSR Envelope, either linear or exponential
*/
template<bool linear>
class AdsrEnvelope : public Envelope {
protected:
static const float MINLEVEL;
enum EnvelopeStage { kAttack, kDecay, kSustain, kRelease, kIdle };
enum EnvelopeTrigger { kGate, kTrigger };
float calculateIncrement(float startValue, float endValue, float time);
float increment(float level, float amount);
float decrement(float level, float amount);
public:
AdsrEnvelope(float sampleRate) :
sampleRate(sampleRate),
stage(kIdle),
trig(kGate),
level(MINLEVEL),
gateState(false),
gateTime(-1) {
setAttack(1/sampleRate);
setDecay(1/sampleRate);
setSustain(1.0);
setRelease(1/sampleRate);
setRetrigger(false);
}
using Envelope::process;
using Envelope::trigger;
using SignalGenerator::generate;
void setSampleRate(float value){
sampleRate = value;
}
void setAttack(float value){
attackIncrement = calculateIncrement(MINLEVEL, 1, value);
}
void setDecay(float value){
decayIncrement = calculateIncrement(1, MINLEVEL, value);
}
void setRelease(float value){
releaseIncrement = calculateIncrement(1, MINLEVEL, value);
}
void setSustain(float newSustain){
sustain = newSustain;
}
void trigger(bool state, int delay){
gate(state, delay);
trig = kTrigger;
}
void setRetrigger(bool state){
retrigger = state;
}
void gate(bool state){
gate(state, 0);
}
void gate(bool state, int delay){
if(gateState != state){
gateTime = delay;
gateState = state;
}
trig = kGate;
}
float getLevel(){
return level;
}
void setLevel(float newLevel){
level = newLevel;
}
/**
* Produce the next envelope sample.
*/
float generate(){
if(gateTime == 0){
stage = kAttack;
if(trig == kTrigger){
gateState = false;
}
}
if(gateTime >= 0){
gateTime--; // this will stop at -1
}
switch (stage) {
case kAttack:
// attack ramp
level = increment(level, attackIncrement);
if(level >= 1.0){
level = 1.0;
stage = kDecay;
}else if(gateState == false && trig == kGate){
stage = kRelease;
}
break;
case kDecay:
// decay ramp
level = decrement(level, decayIncrement);
if(level <= sustain){
level = sustain;
if(trig == kGate){
stage = kSustain;
} else { // (trig == kTrigger)
stage = kRelease;
}
} else if(gateState == false && trig == kGate){
stage = kRelease;
}
break;
case kSustain:
level = sustain;
if(gateState == false){
stage = kRelease;
}
break;
case kRelease:
// release ramp
level = decrement(level, releaseIncrement);
if(level <= MINLEVEL){
level = MINLEVEL;
if (retrigger == true)
trigger();
else // (retrigger == false)
stage = kIdle;
}else if(gateState == true ){ // if during release the gate is on again, start over from the current level
stage = kAttack;
}
break;
case kIdle:
level = MINLEVEL;
if(gateState == true)
stage = kAttack;
break;
}
return level;
}
[[deprecated("use generate() instead.")]]
float getNextSample(){
return generate(); // increments envelope one step
}
[[deprecated("use generate() instead.")]]
void getEnvelope(FloatArray output){
generate(output); // increments envelope by output buffer length
}
[[deprecated("use process() instead.")]]
void attenuate(FloatArray buf){
process(buf, buf); // increments envelope by buffer length
}
static AdsrEnvelope<linear>* create(float sampleRate){
return new AdsrEnvelope<linear>(sampleRate);
}
static void destroy(AdsrEnvelope<linear>* env){
delete env;
}
protected:
float sampleRate;
EnvelopeStage stage;
EnvelopeTrigger trig;
bool retrigger;
float level;
float attackIncrement;
float decayIncrement;
float releaseIncrement;
float sustain;
bool gateState;
int gateTime;
};
typedef AdsrEnvelope<true> LinearAdsrEnvelope;
typedef AdsrEnvelope<false> ExponentialAdsrEnvelope;
#endif /* __ADSR_ENVELOPE_H */