/[svn]/linuxsampler/trunk/src/engines/gig/EGADSR.cpp
ViewVC logotype

Contents of /linuxsampler/trunk/src/engines/gig/EGADSR.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3331 - (show annotations) (download)
Sun Jul 23 18:56:37 2017 UTC (3 years, 8 months ago) by schoenebeck
File size: 15810 byte(s)
- Fixed compilation error.

1 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 * Copyright (C) 2005 - 2017 Christian Schoenebeck *
7 * *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the Free Software *
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21 * MA 02111-1307 USA *
22 ***************************************************************************/
23
24 #include "EGADSR.h"
25
26 #include "../../common/global_private.h"
27
28 namespace LinuxSampler { namespace gig {
29
30 EGADSR::EGADSR() : EG() {
31 AttackCancel = true;
32 AttackHoldCancel = true;
33 Decay1Cancel = true;
34 Decay2Cancel = true;
35 ReleaseCancel = true;
36 }
37
38 #define isTransitionEvent(type) \
39 ( type == event_release || type == event_cancel_release )
40
41 void EGADSR::update(event_t Event, uint SampleRate) {
42 if (atEnd(Event)) return;
43
44 if (Event == event_hold_end) HoldAttack = false;
45
46 switch (Stage) {
47 case stage_attack:
48 switch (Event) {
49 case event_release:
50 if (AttackCancel)
51 enterNextStageForReleaseEvent(SampleRate);
52 else
53 PostponedEvent = Event;
54 break;
55 case event_stage_end:
56 if (PostponedEvent == event_release)
57 enterNextStageForReleaseEvent(SampleRate);
58 else if (HoldAttack)
59 enterAttackHoldStage();
60 else
61 enterDecay1Part1Stage(SampleRate);
62 break;
63 default: ; // noop
64 }
65 break;
66 case stage_attack_hold:
67 switch (Event) {
68 case event_stage_end: {// just refresh time
69 const int intMax = (unsigned int) -1 >> 1;
70 StepsLeft = intMax; // we use the highest possible value
71 break;
72 }
73 case event_hold_end:
74 if (PostponedEvent == event_release)
75 enterNextStageForReleaseEvent(SampleRate);
76 else
77 enterDecay1Part1Stage(SampleRate);
78 break;
79 case event_release:
80 if (AttackHoldCancel)
81 enterNextStageForReleaseEvent(SampleRate);
82 else
83 PostponedEvent = Event;
84 break;
85 default: ; // noop
86 }
87 break;
88 case stage_decay1_part1:
89 switch (Event) {
90 case event_stage_end:
91 enterDecay1Part2Stage(SampleRate);
92 break;
93 case event_release:
94 if (Decay1Cancel)
95 enterNextStageForReleaseEvent(SampleRate);
96 else
97 PostponedEvent = Event;
98 break;
99 default: ; // noop
100 }
101 break;
102 case stage_decay1_part2:
103 switch (Event) {
104 case event_release:
105 if (Decay1Cancel)
106 enterNextStageForReleaseEvent(SampleRate);
107 else
108 PostponedEvent = Event;
109 break;
110 case event_stage_end:
111 if (Level < CONFIG_EG_BOTTOM)
112 enterEndStage();
113 else if (PostponedEvent == event_release)
114 enterNextStageForReleaseEvent(SampleRate);
115 else if (InfiniteSustain)
116 enterSustainStage();
117 else
118 enterDecay2Stage(SampleRate);
119 break;
120 default: ; // noop
121 }
122 break;
123 case stage_decay2:
124 switch (Event) {
125 case event_stage_end:
126 enterFadeOutStage();
127 break;
128 case event_release:
129 if (Decay2Cancel)
130 enterReleasePart1Stage();
131 else
132 PostponedEvent = Event;
133 break;
134 case event_hold_end:
135 if (PostponedEvent == event_release && Decay1Cancel)
136 enterReleasePart1Stage();
137 else
138 enterDecay1Part1Stage(SampleRate);
139 break;
140 default: ; // noop
141 }
142 break;
143 case stage_sustain:
144 switch (Event) {
145 case event_stage_end: {// just refresh time
146 const int intMax = (unsigned int) -1 >> 1;
147 StepsLeft = intMax; // we use the highest possible value
148 break;
149 }
150 case event_release:
151 enterReleasePart1Stage();
152 break;
153 case event_hold_end:
154 enterDecay1Part1Stage(SampleRate);
155 break;
156 default: ; // noop
157 }
158 break;
159 case stage_release_part1:
160 switch (Event) {
161 case event_stage_end:
162 enterReleasePart2Stage();
163 break;
164 case event_cancel_release:
165 if (!ReleaseCancel)
166 break;
167 if (InfiniteSustain)
168 enterSustainStage();
169 else
170 enterDecay2Stage(SampleRate);
171 break;
172 default: ; // noop
173 }
174 break;
175 case stage_release_part2:
176 switch (Event) {
177 case event_stage_end:
178 enterFadeOutStage();
179 break;
180 case event_cancel_release:
181 if (!ReleaseCancel)
182 break;
183 if (InfiniteSustain)
184 enterSustainStage();
185 else
186 enterDecay2Stage(SampleRate);
187 break;
188 default: ; // noop
189 }
190 break;
191 case stage_fadeout:
192 case stage_end:
193 ; // noop
194 }
195 }
196
197 void EGADSR::trigger(uint PreAttack, float AttackTime, bool HoldAttack, float Decay1Time, double Decay2Time, bool InfiniteSustain, uint SustainLevel, float ReleaseTime, float Volume, uint SampleRate) {
198 this->SustainLevel = SustainLevel / 1000.0;
199 this->InfiniteSustain = InfiniteSustain;
200 this->HoldAttack = HoldAttack;
201
202 this->Decay1Time = Decay1Time;
203 this->Decay2Time = Decay2Time;
204
205 invVolume = 1 / Volume;
206 ExpOffset = (0.25 - 1 / 3.55) * invVolume;
207
208 // calculate release stage parameters (lin+exp curve)
209 if (ReleaseTime < CONFIG_EG_MIN_RELEASE_TIME) ReleaseTime = CONFIG_EG_MIN_RELEASE_TIME; // to avoid click sounds at the end of the sample playback
210 const float ReleaseStepsLeft = (long) (ReleaseTime * SampleRate);
211 ReleaseSlope = 1.365 * (0 - 1) / ReleaseStepsLeft;
212 ReleaseCoeff = ReleaseSlope * invVolume;
213 ReleaseSlope *= 3.55;
214 ReleaseCoeff2 = exp(ReleaseSlope);
215 ReleaseCoeff3 = ExpOffset * (1 - ReleaseCoeff2);
216 ReleaseLevel2 = 0.25 * invVolume;
217
218 PostponedEvent = (event_t) -1; // init with anything except release or cancel_release
219
220 enterFirstStage();
221 enterAttackStage(PreAttack, AttackTime, SampleRate);
222 }
223
224 void EGADSR::setStateOptions(bool AttackCancel, bool AttackHoldCancel, bool Decay1Cancel, bool Decay2Cancel, bool ReleaseCancel) {
225 this->AttackCancel = AttackCancel;
226 this->AttackHoldCancel = AttackHoldCancel;
227 this->Decay1Cancel = Decay1Cancel;
228 this->Decay2Cancel = Decay2Cancel;
229 this->ReleaseCancel = ReleaseCancel;
230 }
231
232 void EGADSR::enterNextStageForReleaseEvent(uint SampleRate) {
233 switch (Stage) {
234 case stage_attack:
235 if (HoldAttack && !AttackHoldCancel) {
236 enterAttackHoldStage();
237 return;
238 }
239 case stage_attack_hold:
240 if (!Decay1Cancel) {
241 enterDecay1Part1Stage(SampleRate);
242 return;
243 }
244 case stage_decay1_part1:
245 case stage_decay1_part2:
246 if (InfiniteSustain) {
247 enterReleasePart1Stage();
248 return;
249 } else if (!Decay2Cancel) {
250 enterDecay2Stage(SampleRate);
251 return;
252 }
253 default:
254 enterReleasePart1Stage();
255 }
256 }
257
258 void EGADSR::enterAttackStage(const uint PreAttack, const float AttackTime, const uint SampleRate) {
259 Stage = stage_attack;
260 Segment = segment_lin;
261
262 if (AttackTime >= 1e-8) {
263 // Measurements of GSt output shows that the real attack time
264 // is about 65.5% of the value specified in the gig file.
265 // The minimum attack value used is 0.0316.
266 StepsLeft = int(0.655f * RTMath::Max(AttackTime, 0.0316f) * SampleRate);
267 Level = (float) PreAttack / 1000.0;
268 Coeff = 0.896f * (1.0f - Level) / StepsLeft; // max level is a bit lower if attack != 0
269 } else { // attack is zero - immediately jump to the next stage
270 Level = 1.029f; // a bit higher than max sustain
271 if (HoldAttack) enterAttackHoldStage();
272 else enterDecay1Part1Stage(SampleRate);
273 }
274 }
275
276 void EGADSR::enterAttackHoldStage() {
277 Stage = stage_attack_hold;
278 Segment = segment_lin;
279 Coeff = 0.0f; // don't rise anymore
280 const int intMax = (unsigned int) -1 >> 1;
281 StepsLeft = intMax; // we use the highest value possible (we refresh StepsLeft in update() in case)
282 }
283
284 void EGADSR::enterDecay1Part1Stage(const uint SampleRate) {
285 // The decay1 and release stage both consist of two parts,
286 // first a linear curve, f, followed by an exponential curve,
287 // g:
288 //
289 // f(x + d) = f(x) + Coeff
290 // g(x + d) = Coeff2 * g(x) + Coeff3
291 //
292 // (where d is 1/SampleRate). The transition from f to g is
293 // done when f(x) has reached Level2 = 25% of full volume.
294 StepsLeft = (int) (Decay1Time * SampleRate);
295 if (StepsLeft && Level > SustainLevel) {
296 Stage = stage_decay1_part1;
297 Segment = segment_lin;
298 Decay1Slope = (1.347f * SustainLevel - 1.361f) / StepsLeft;
299 Coeff = Decay1Slope * invVolume;
300 Decay1Level2 = 0.25 * invVolume;
301 StepsLeft = int((RTMath::Max(Decay1Level2, SustainLevel) - Level) / Coeff);
302 if (StepsLeft <= 0) enterDecay1Part2Stage(SampleRate);
303 } else {
304 if (PostponedEvent == event_release) {
305 Stage = stage_decay1_part2; // pretend decay 1 part 2 was completed
306 enterNextStageForReleaseEvent(SampleRate);
307 } else if (InfiniteSustain) {
308 enterSustainStage();
309 } else {
310 enterDecay2Stage(SampleRate);
311 }
312 }
313 }
314
315 void EGADSR::enterDecay1Part2Stage(const uint SampleRate) {
316 if (SustainLevel < Decay1Level2) {
317 Stage = stage_decay1_part2;
318 Segment = segment_exp;
319 Decay1Slope *= 3.55;
320 Coeff = exp(Decay1Slope);
321 Offset = ExpOffset * (1 - Coeff);
322 StepsLeft = int(log((SustainLevel - ExpOffset) / (Level - ExpOffset)) / Decay1Slope);
323 if (StepsLeft > 0) return;
324 }
325 if (PostponedEvent == event_release) {
326 Stage = stage_decay1_part2;
327 enterNextStageForReleaseEvent(SampleRate);
328 } else if (InfiniteSustain) {
329 enterSustainStage();
330 } else {
331 enterDecay2Stage(SampleRate);
332 }
333 }
334
335 void EGADSR::enterDecay2Stage(const uint SampleRate) {
336 Stage = stage_decay2;
337 Segment = segment_lin;
338 Decay2Time = RTMath::Max(Decay2Time, 0.05f);
339 StepsLeft = (int) (Decay2Time * SampleRate);
340 Coeff = (-1.03 / StepsLeft) * invVolume;
341 //FIXME: do we really have to calculate 'StepsLeft' two times?
342 StepsLeft = int((CONFIG_EG_BOTTOM - Level) / Coeff);
343 if (StepsLeft <= 0) enterEndStage();
344 }
345
346 void EGADSR::enterSustainStage() {
347 Stage = stage_sustain;
348 Segment = segment_lin;
349 Coeff = 0.0f; // don't change the envelope level in this stage
350 const int intMax = (unsigned int) -1 >> 1;
351 StepsLeft = intMax; // we use the highest value possible (we refresh StepsLeft in update() in case)
352 PostponedEvent = (event_t) -1; // reset with anything except release or cancel_release
353 }
354
355 void EGADSR::enterReleasePart1Stage() {
356 Stage = stage_release_part1;
357 Segment = segment_lin;
358 StepsLeft = int((ReleaseLevel2 - Level) / ReleaseCoeff);
359 Coeff = ReleaseCoeff;
360 PostponedEvent = (event_t) -1; // reset with anything except release or cancel_release
361 if (StepsLeft <= 0) enterReleasePart2Stage();
362 }
363
364 void EGADSR::enterReleasePart2Stage() {
365 Stage = stage_release_part2;
366 Segment = segment_exp;
367 StepsLeft = int(log((CONFIG_EG_BOTTOM - ExpOffset) / (Level - ExpOffset)) / ReleaseSlope);
368 Coeff = ReleaseCoeff2;
369 Offset = ReleaseCoeff3;
370 if (StepsLeft <= 0) enterFadeOutStage();
371 }
372
373 }} // namespace LinuxSampler::gig

  ViewVC Help
Powered by ViewVC