-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathenvelope.ino
195 lines (166 loc) · 7.46 KB
/
envelope.ino
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
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
// remove glitches
// do so that you change only the next phase params via midi
unsigned int adsr_attack(unsigned long attack_time,
unsigned long current_time,
unsigned long trig_time,
unsigned int wave_table[][wave_table_resolution],
int wave_table_type ) {
if (attack_time < 0){
Serial.println("adsr_attack input out of range");
}
if (current_time < trig_time){
Serial.println("adsr_attack current_time too small");
}
// avoid division by 0
if (attack_time == 0){
return 0;
} else {
float wave_table_index_float = get_wave_table_index_float(wave_table_resolution,
(current_time - trig_time),
attack_time);
int wave_table_index = (int)wave_table_index_float;
int wave_table_index_next = next_index(wave_table_index,
wave_table_resolution);
unsigned int interpolated_value = line_by_two_points(wave_table_index_float,
wave_table_index,
wave_table_index_next,
(int)wave_table[wave_table_type][wave_table_index],
(int)wave_table[wave_table_type][wave_table_index_next]);
return interpolated_value;
}
}
unsigned int adsr_decay( unsigned long decay_time,
unsigned long current_time,
unsigned long trig_time,
unsigned long attack_time,
unsigned long sustain_value,
unsigned int wave_table[][wave_table_resolution],
int wave_table_type
) {
if (decay_time < 0 ){
Serial.println("adsr_decay input out of range");
}
if (current_time < (trig_time + attack_time)){
Serial.println("adsr_decay current_time too small");
}
// avoid division by 0
if (decay_time == 0){
return sustain_value;
}
float wave_table_index_float = get_wave_table_index_float(wave_table_resolution,
(current_time - (trig_time+attack_time)),
decay_time);
int wave_table_index = (int)wave_table_index_float;
int wave_table_index_next = next_index(wave_table_index,
wave_table_resolution);
unsigned int interpolated_value = line_by_two_points(wave_table_index_float,
wave_table_index,
wave_table_index_next,
(int)wave_table[wave_table_type][wave_table_index],
(int)wave_table[wave_table_type][wave_table_index_next]);
return sustain_value + ((interpolated_value *
(dac_max - sustain_value)) / dac_max);
}
unsigned int adsr_sustain( unsigned long sustain_value
){
if (sustain_value < 0 or sustain_value > dac_max){
Serial.println("adsr_sustain input out of range");
}
return sustain_value ;
}
unsigned int adsr_release( unsigned long release_time,
unsigned long current_time,
unsigned long untrig_time,
unsigned long note_off_value,
unsigned int wave_table[][wave_table_resolution],
int wave_table_type
){
if ((release_time < 0 ) and
(current_time < untrig_time)){
Serial.println("adsr_release wrong input");
}
if (release_time == 0) {
return 0;
}
if ((current_time - untrig_time) <= (release_time)) {
float wave_table_index_float = get_wave_table_index_float(wave_table_resolution,
(current_time - untrig_time),
release_time);
int wave_table_index = (int)wave_table_index_float;
int wave_table_index_next = next_index(wave_table_index,
wave_table_resolution);
unsigned int interpolated_value = line_by_two_points(wave_table_index_float,
wave_table_index,
wave_table_index_next,
(int)wave_table[wave_table_type][wave_table_index],
(int)wave_table[wave_table_type][wave_table_index_next]);
return (interpolated_value * note_off_value) / dac_max ;
}
else return wave_table[wave_table_type][wave_table_resolution-1];
}
// this function returns the adsr value at a given time
unsigned long adsr( bool note_stack_is_empty, // or gate state
unsigned long now_msec,
unsigned long env_trig_time_msec,
unsigned long env_attack_msec,
bool note_on,
adsr_states adsr_state,
unsigned long env_sustain,
unsigned long env_decay_msec,
unsigned long env_release_msec,
unsigned int env_at_note_off
//unsigned long env_value
) {
unsigned long env_value=0;
if (!note_stack_is_empty) {
unsigned long env_trig_time_diff_msec = now_msec - env_trig_time_msec;
// modify the state according to current time
if (( env_trig_time_diff_msec <= env_attack_msec) && note_on){
adsr_state = Attack; // SIDE EFFECTS? CHECK
}
else if ((env_trig_time_diff_msec > env_attack_msec) &&
(env_trig_time_diff_msec <= (env_attack_msec + env_decay_msec)) &&
note_on) {
adsr_state = Decay;
}
else if ((env_trig_time_diff_msec >
(env_attack_msec + env_decay_msec)) && note_on ) {
adsr_state = Sustain;
}
}
else {
adsr_state = Release;
}
// compute envelope
switch(adsr_state) {
case Attack:
env_value = adsr_attack( env_attack_msec,
now_msec,
env_trig_time_msec,
wave_table,
6 );
break;
case Decay:
env_value = adsr_decay( env_decay_msec,
now_msec,
env_trig_time_msec,
env_attack_msec,
env_sustain,
wave_table,
5 );
break;
case Sustain:
env_value = adsr_sustain( env_sustain);
break;
case Release:
env_value = adsr_release( env_release_msec,
now_msec,
note_off_time_msec ,
env_at_note_off,
wave_table,
5); //TODO change hardcoded exponential
//type on wavetable
break;
}
return env_value;
}