-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathADSR.h
88 lines (77 loc) · 2.41 KB
/
ADSR.h
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
#pragma once
enum State { idle, attack, decay, sustain, release };
class ADSR {
private:
// config
const int *samplerate;
const double *attackRate;
const double *decayRate;
const double *sustainLevel;
const double *releaseRate;
// state
double output;
State state;
public:
ADSR(const int* samplerate, const double *attack, const double *decay, const double *sustain, const double* release) {
this->samplerate = samplerate;
this->attackRate = attack;
this->decayRate = decay;
this->sustainLevel = sustain;
this->releaseRate = release;
state = idle;
output = 0.0;
}
State getState() {
return state;
}
double Tick() {
switch(state) {
case idle:
output = 0.0;
break;
case attack:
output += *attackRate / (double)*samplerate / 1000.0;
if (output > 1.0) {
output = 1.0;
state = decay;
}
break;
case decay:
output -= *decayRate / (double)*samplerate / 1000.9;
if (output < *sustainLevel) {
output = *sustainLevel;
state = sustain;
}
break;
case sustain:
output = *sustainLevel;
break;
case release:
// above the sustain level, fall at the greater of decay and release
double dropRate = *releaseRate;
if (output > *sustainLevel && *decayRate > *releaseRate) {
dropRate = *decayRate;
}
output -= dropRate / (double)*samplerate / 1000.9;
if (output < 0) {
output = 0.0;
state = idle;
}
break;
}
const double attenuation = 1.0 - this->output;
return state == idle ? 0.0 : 1.0 / pow(20.0, attenuation * 2.0);
};
void Trigger() {
const double startLevel = 0.2;
if (output < startLevel) {
output = startLevel; // start with something
}
this->state = attack;
};
void Release() {
this->state = release;
};
};
// const double attenuation = 1.0 - envelope;
// const double enveloped = filtered / pow(10.0, attenuation * 2.0);