LMMS
Loading...
Searching...
No Matches
envelope.h
Go to the documentation of this file.
1/* Calf DSP Library
2 * ADSR envelope class (and other envelopes in future)
3 *
4 * Copyright (C) 2007-2008 Krzysztof Foltman
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General
17 * Public License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301 USA
20 */
21#ifndef __CALF_ENVELOPE_H
22#define __CALF_ENVELOPE_H
23
24#include "primitives.h"
25
26namespace dsp {
27
32class adsr
33{
34public:
43
51 double value;
57 double thiss;
59 double old_value;
60
62 {
64 reset();
65 }
66
67 inline void reset()
68 {
69 old_value = value = 0.0;
70 thiss = 0.0;
71 state = STOP;
72 }
73
80 inline void set(float a, float d, float s, float r, float er, float f = 0.f)
81 {
82 attack = 1.0 / (a * er);
83 decay = (1 - s) / (d * er);
84 sustain = s;
85 release_time = r * er;
87 if (fabs(f) > small_value<float>())
88 fade = 1.0 / (f * er);
89 else
90 fade = 0.0;
91 // in release:
92 // lock thiss setting (start of release for current note) and unlock thisrelease setting (current note's release rate)
93 if (state != RELEASE)
94 thiss = s;
95 else
97 }
98
99 inline bool released() const
100 {
101 return state == LOCKDECAY || state == RELEASE || state == STOP;
102 }
103
104 inline bool stopped() const
105 {
106 return state == STOP;
107 }
108
109 inline void note_on()
110 {
111 state = ATTACK;
112 thiss = sustain;
113 }
114
115 inline void note_off()
116 {
117 // Do nothing if envelope is already stopped
118 if (state == STOP)
119 return;
120 // XXXKF what if envelope is already released? (doesn't happen in any current synth, but who knows?)
121 // Raise sustain value if it has been changed... I'm not sure if it's needed
122 thiss = std::max(sustain, value);
123 // Calculate release rate from sustain level
125 // we're in attack or decay, and if decay is faster than release
126 if (value > sustain && decay > thisrelease) {
127 // use standard release time later (because we'll be switching at sustain point)
130 } else {
131 // in attack/decay, but use fixed release time
132 // in case value fell below sustain, assume it didn't (for the purpose of calculating release rate only)
133 state = RELEASE;
134 }
135 }
136
137 inline void advance()
138 {
140 // XXXKF This may use a state array instead of a switch some day (at least for phases other than attack and possibly sustain)
141 switch(state)
142 {
143 case ATTACK:
144 value += attack;
145 if (value >= 1.0) {
146 value = 1.0;
147 state = DECAY;
148 }
149 break;
150 case DECAY:
151 value -= decay;
152 if (value < sustain)
153 {
154 value = sustain;
155 state = SUSTAIN;
156 }
157 break;
158 case LOCKDECAY:
159 value -= decay;
160 if (value < sustain)
161 {
162 if (value < 0.f)
163 value = 0.f;
164 state = RELEASE;
166 }
167 break;
168 case SUSTAIN:
169 if (fade != 0.f)
170 {
171 value -= fade;
172 if (value > 1.f)
173 value = 1.f;
174 }
175 else
176 value = sustain;
177 if (value < 0.00001f) {
178 value = 0;
179 state = STOP;
180 }
181 break;
182 case RELEASE:
184 if (value <= 0.f) {
185 value = 0.f;
186 state = STOP;
187 }
188 break;
189 case STOP:
190 value = 0.f;
191 break;
192 }
193 }
194
196 inline double interpolate(double pos)
197 {
198 return old_value + (value - old_value) * pos;
199 }
200 inline float get_amp_value()
201 {
202 if (state == RELEASE && sustain > 0 && value < sustain)
203 {
204 return value * value * value / (sustain * sustain);
205 }
206 return value;
207 }
208};
209
212{
213 float value;
216
217 fadeout(int steps = 256)
218 {
219 step_orig = (float)(1.f / steps);
220 value = 1.f;
221 reset();
222 }
223
225 void reset()
226 {
227 value = 1.f;
228 step = -step_orig;
229 done = false;
230 undoing = false;
231 }
232
234 void undo()
235 {
236 step = step_orig;
237 done = false;
238 undoing = true;
239 }
240
243 {
245 reset();
246 else
247 undo();
248 }
249
250 void process(float *buffer, int len)
251 {
252 int i = 0;
253 if (!done)
254 {
255 for (; value > 0 && value <= 1.0 && i < len; i++)
256 {
257 buffer[i] *= value;
258 value += step;
259 }
261 done = true;
262 }
263 if (done && value <= 0)
264 {
265 while (i < len)
266 buffer[i++] = 0.f;
267 }
268 if (done && undoing && value >= 1)
269 {
270 undoing = false;
271 done = false;
272 // prepare for the next fade-out
273 value = 1.f;
274 }
275 }
276};
277
278};
279
280#endif
281
282
uint8_t a
Definition Spc_Cpu.h:141
double old_value
Value from the time before advance() was called last time.
Definition envelope.h:59
double release
Definition envelope.h:47
float get_amp_value()
Definition envelope.h:200
double fade
Definition envelope.h:47
double decay
Definition envelope.h:47
void note_off()
Release the envelope.
Definition envelope.h:115
double interpolate(double pos)
Definition envelope.h:196
void advance()
Calculate next envelope value.
Definition envelope.h:137
double thiss
Definition envelope.h:57
adsr()
Definition envelope.h:61
env_state
Definition envelope.h:35
@ LOCKDECAY
locked decay
Definition envelope.h:41
@ SUSTAIN
sustain - remain at sustain level (unless sustain is 0 - then it gets stopped); with fade !...
Definition envelope.h:39
@ ATTACK
attack - rise from 0 to 1
Definition envelope.h:37
@ STOP
envelope is stopped
Definition envelope.h:36
@ DECAY
decay - fall from 1 to sustain level
Definition envelope.h:38
@ RELEASE
release - fall from sustain (or pre-sustain) level to 0
Definition envelope.h:40
double value
Current envelope (output) level.
Definition envelope.h:51
double attack
Definition envelope.h:47
bool released() const
Definition envelope.h:99
void note_on()
Start the envelope.
Definition envelope.h:109
bool stopped() const
Definition envelope.h:104
void set(float a, float d, float s, float r, float er, float f=0.f)
Definition envelope.h:80
double sustain
Definition envelope.h:47
void reset()
Stop (reset) the envelope.
Definition envelope.h:67
double thisrelease
Definition envelope.h:54
double release_time
Requested release time (not the rate!) in frames, used for recalculating the rate if sustain is chang...
Definition envelope.h:49
env_state state
Current envelope stage.
Definition envelope.h:45
unsigned d
Definition inflate.c:940
register unsigned i
Definition inflate.c:1575
unsigned s
Definition inflate.c:1555
unsigned f
Definition inflate.c:1572
Definition audio_fx.h:36
T small_value()
'Small value' for integer and other types
Definition primitives.h:201
bool undoing
Definition envelope.h:215
float step
Definition envelope.h:214
fadeout(int steps=256)
Definition envelope.h:217
void reset()
Prepare fade out.
Definition envelope.h:225
float step_orig
Definition envelope.h:214
void reset_soft()
Reset if fully faded out; fade back in if in the middle of fading out.
Definition envelope.h:242
float value
Definition envelope.h:213
void undo()
Fade back in with double speed (to prevent click on note restart).
Definition envelope.h:234
void process(float *buffer, int len)
Definition envelope.h:250
bool done
Definition envelope.h:215
int r
Definition crypt.c:458