Skip to content

Commit 68314ff

Browse files
author
mars
committed
Refactored. Updates to trigger and retrigger modes
1 parent b833235 commit 68314ff

2 files changed

Lines changed: 199 additions & 0 deletions

File tree

LibSource/Envelope.cpp

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
#include "Envelope.h"
2+
#include "message.h"
3+
4+
/*
5+
void EnvelopeGenerator::calculateMultiplier(double startLevel,
6+
double endLevel,
7+
unsigned long long lengthInSamples) {
8+
multiplier = 1.0 + (log(endLevel) - log(startLevel)) / (lengthInSamples);
9+
}
10+
*/
11+
12+
const float AdsrEnvelope::minTime = 0.005;
13+
14+
AdsrEnvelope::AdsrEnvelope(float sampleRate) :
15+
samplePeriod(1.0/sampleRate),
16+
stage(kIdle),
17+
trig(kGate),
18+
level(0.0),
19+
gateState(false),
20+
gateTime(0) {
21+
setAttack(0.0);
22+
setDecay(0.0);
23+
setSustain(1.0);
24+
setRelease(0.0);
25+
}
26+
27+
void AdsrEnvelope::updateStage(){
28+
if(gateState)
29+
stage = kAttack;
30+
// else if(trig == kGate)
31+
// stage = kRelease;
32+
}
33+
34+
void AdsrEnvelope::setAttack(float newAttack){
35+
newAttack = newAttack > minTime ? newAttack : minTime;
36+
attackIncrement = samplePeriod / newAttack;
37+
}
38+
39+
void AdsrEnvelope::setDecay(float newDecay){
40+
newDecay = newDecay > minTime ? newDecay : minTime;
41+
decayIncrement = - samplePeriod / newDecay;
42+
}
43+
44+
void AdsrEnvelope::setRelease(float newRelease){
45+
newRelease = newRelease > minTime ? newRelease : minTime;
46+
releaseIncrement = - samplePeriod / newRelease;
47+
}
48+
49+
void AdsrEnvelope::setSustain(float newSustain){
50+
sustain = newSustain;
51+
// TODO: in the real world, you would probably glide to the new sustain level at a rate determined by either decay or attack
52+
}
53+
54+
void AdsrEnvelope::setRetrigger(bool state){
55+
if(state)
56+
trig = kRetrigger;
57+
else
58+
trig = kGate;
59+
}
60+
61+
void AdsrEnvelope::retrigger(bool state, int delay){
62+
gate(state, delay);
63+
setRetrigger(state);
64+
}
65+
66+
void AdsrEnvelope::trigger(){
67+
trigger(true, 0);
68+
}
69+
70+
void AdsrEnvelope::trigger(bool state){
71+
trigger(state, 0);
72+
}
73+
74+
void AdsrEnvelope::trigger(bool state, int delay){
75+
gate(state, delay);
76+
trig = kTrigger;
77+
}
78+
79+
void AdsrEnvelope::gate(bool state){
80+
gate(state, 0);
81+
}
82+
83+
void AdsrEnvelope::gate(bool state, int delay){
84+
if(gateState != state){
85+
gateTime = delay;
86+
gateState = state;
87+
if(gateTime == 0)
88+
updateStage();
89+
}
90+
trig = kGate;
91+
}
92+
93+
void AdsrEnvelope::setLevel(float newLevel){
94+
level = newLevel;
95+
}
96+
97+
void AdsrEnvelope::attenuate(FloatArray &output){
98+
for(int n = 0; n < output.getSize(); n++)
99+
output[n] *= getNextSample();
100+
}
101+
102+
void AdsrEnvelope::getEnvelope(FloatArray &output){
103+
for(int n = 0; n < output.getSize(); n++)
104+
output[n] = getNextSample();
105+
}
106+
107+
float AdsrEnvelope::getNextSample(){
108+
if(gateTime && --gateTime == 0)
109+
updateStage();
110+
switch (stage) {
111+
case kAttack:
112+
// attack ramp
113+
level += attackIncrement;
114+
if(level >= 1.0){
115+
level = 1.0;
116+
stage = kDecay;
117+
}else if(gateState == false && trig == kGate){
118+
stage = kRelease;
119+
}
120+
break;
121+
case kDecay:
122+
// decay ramp
123+
level += decayIncrement;
124+
if(level <= sustain){
125+
level = sustain;
126+
stage = kSustain;
127+
}else if(gateState == false && trig == kGate){
128+
stage = kRelease;
129+
}
130+
break;
131+
case kSustain:
132+
level = sustain;
133+
if(gateState == false || trig != kGate)
134+
stage = kRelease;
135+
break;
136+
case kRelease:
137+
// release ramp
138+
level += releaseIncrement;
139+
if(level <= 0.0){
140+
level = 0.0;
141+
stage = kIdle;
142+
}else if(gateState == true){
143+
stage = kAttack;
144+
}
145+
break;
146+
case kIdle:
147+
level = 0.0;
148+
if(gateState == true || trig == kRetrigger)
149+
stage = kAttack;
150+
break;
151+
}
152+
return level;
153+
}

LibSource/Envelope.h

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#ifndef ENVELOPE_HPP
2+
#define ENVELOPE_HPP
3+
4+
#include "FloatArray.h"
5+
6+
/**
7+
* Linear ADSR Envelope
8+
*/
9+
class AdsrEnvelope {
10+
private:
11+
enum EnvelopeStage { kAttack, kDecay, kSustain, kRelease, kIdle };
12+
enum EnvelopeTrigger { kGate, kTrigger, kRetrigger };
13+
14+
public:
15+
AdsrEnvelope(float newSampleRate);
16+
void setAttack(float newAttack);
17+
void setDecay(float newDecay);
18+
void setRelease(float newRelase);
19+
void setSustain(float newSustain);
20+
void trigger();
21+
void trigger(bool state);
22+
void trigger(bool state, int triggerDelay);
23+
void setRetrigger(bool on);
24+
void retrigger(bool on, int triggerDelay);
25+
void gate(bool state);
26+
void gate(bool state, int gateDelay);
27+
void setLevel(float newLevel);
28+
float getNextSample(); // increments envelope one step
29+
void getEnvelope(FloatArray &output); // increments envelope by output buffer length
30+
void attenuate(FloatArray &buf); // increments envelope by buffer length
31+
private:
32+
void updateStage();
33+
static const float minTime;
34+
const float samplePeriod;
35+
EnvelopeStage stage;
36+
EnvelopeTrigger trig;
37+
float level;
38+
float attackIncrement;
39+
float decayIncrement;
40+
float releaseIncrement;
41+
float sustain;
42+
bool gateState;
43+
int gateTime;
44+
};
45+
46+
#endif /* ENVELOPE_HPP */

0 commit comments

Comments
 (0)