-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathEnvelopeWindow.h
145 lines (117 loc) · 2.5 KB
/
EnvelopeWindow.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
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
/*
* EnvelopeWindow.h
*
* Created on: 02 dic 2017
* Author: Andrea993
*/
#ifndef ENVELOPEWINDOW_H_
#define ENVELOPEWINDOW_H_
#include "WaveTable/WaveTable.h"
#include <cmath>
struct Envelope
{
enum class Type { linear, exponential };
float attack_dur;
float attack_max;
Type attack_type;
float decay_dur;
float decay_min;
Type decay_type;
float release_dur;
Type release_type;
float tauFactor;
};
template <class TP>
class EnvelopeWindow
{
private:
Envelope e;
WaveTable<TP> att_dec;
WaveTable<TP> rel;
void WriteWave()
{
double dt = 1.0/WINSR;
double t=0;
unsigned i;
for (i=0; i<WINSR*e.attack_dur; i++)
{
switch (e.attack_type)
{
case Envelope::Type::linear:
att_dec[i]=e.attack_max/e.attack_dur*t;
break;
case Envelope::Type::exponential:
att_dec[i]=e.attack_max*(1-exp(-t/(e.attack_dur/e.tauFactor)));
break;
}
t+=dt;
}
t=0;
for (; i<att_dec.Length(); i++)
{
switch (e.decay_type)
{
case Envelope::Type::linear:
att_dec[i]=-(e.attack_max-e.decay_min)/e.decay_dur*t+e.attack_max;
break;
case Envelope::Type::exponential:
att_dec[i]=(e.attack_max-e.decay_min)*exp(-t/(e.decay_dur/e.tauFactor))+e.decay_min;
break;
}
t+=dt;
}
t=0;
for (i=0; i<rel.Length(); i++)
{
switch (e.release_type)
{
case Envelope::Type::linear:
rel[i]=-e.decay_min/e.release_dur*t+e.decay_min;
break;
case Envelope::Type::exponential:
rel[i]=e.decay_min*exp(-t/(e.release_dur/e.tauFactor));
break;
}
t+=dt;
}
}
public:
const double WINSR = 200; // window sampling rate
EnvelopeWindow<TP>() {}
EnvelopeWindow<TP>(const Envelope& envelope):
e(envelope),
att_dec(WINSR*(e.attack_dur+e.decay_dur), e.attack_dur+e.decay_dur,true),
rel(WINSR*e.release_dur,e.release_dur,true)
{
WriteWave();
}
Envelope getEnvelope() const { return e; }
void setEnvelope(const Envelope& envelope)
{
e=envelope;
att_dec.Resize((WINSR*(e.attack_dur+e.decay_dur)));
att_dec.setPeriod(e.attack_dur+e.decay_dur);
att_dec.setOneShot(true);
rel.Resize(WINSR*e.release_dur);
rel.setPeriod(e.release_dur);
rel.setOneShot(true);
WriteWave();
}
float Value(double t, double releasedAt = -1) // if releaseAt is negative it assumes that the key is pressed
{
if (releasedAt > 0)
{
t-=releasedAt;
if (t > e.release_dur)
return 0;
return rel(t);
}
else
{
if (t > (e.attack_dur + e.decay_dur))
return e.decay_min;
return att_dec(t);
}
}
};
#endif /* ENVELOPEWINDOW_H_ */