/[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 1909 - (show annotations) (download)
Wed Jun 3 17:21:42 2009 UTC (10 years, 7 months ago) by persson
File size: 13082 byte(s)
* bugfix: note off was ignored when EG was in decay stage (bug
  introduced 2009-05-16)

1 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 * Copyright (C) 2005 - 2009 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() {
31 enterEndStage();
32 Level = 0.0;
33 CalculateFadeOutCoeff(CONFIG_EG_MIN_RELEASE_TIME, 44100.0); // even if the sample rate will be 192kHz it won't hurt at all
34 }
35
36 void EGADSR::CalculateFadeOutCoeff(float FadeOutTime, float SampleRate) {
37 const float killSteps = FadeOutTime * SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;
38 FadeOutCoeff = -1.0f / killSteps;
39 }
40
41 void EGADSR::update(event_t Event, uint SampleRate) {
42 if (Event == event_hold_end) HoldAttack = false;
43
44 switch (Stage) {
45 case stage_attack:
46 switch (Event) {
47 case event_release:
48 enterReleasePart1Stage();
49 break;
50 case event_stage_end:
51 if (HoldAttack)
52 enterAttackHoldStage();
53 else
54 enterDecay1Part1Stage(SampleRate);
55 break;
56 }
57 break;
58 case stage_attack_hold:
59 switch (Event) {
60 case event_stage_end: {// just refresh time
61 const int intMax = (unsigned int) -1 >> 1;
62 StepsLeft = intMax; // we use the highest possible value
63 break;
64 }
65 case event_hold_end:
66 enterDecay1Part1Stage(SampleRate);
67 break;
68 case event_release:
69 enterReleasePart1Stage();
70 break;
71 }
72 break;
73 case stage_decay1_part1:
74 switch (Event) {
75 case event_stage_end:
76 enterDecay1Part2Stage(SampleRate);
77 break;
78 case event_release:
79 enterReleasePart1Stage();
80 break;
81 }
82 break;
83 case stage_decay1_part2:
84 switch (Event) {
85 case event_release:
86 enterReleasePart1Stage();
87 break;
88 case event_stage_end:
89 if (Level < CONFIG_EG_BOTTOM)
90 enterEndStage();
91 else if (InfiniteSustain)
92 enterSustainStage();
93 else
94 enterDecay2Stage(SampleRate);
95 break;
96 }
97 break;
98 case stage_decay2:
99 switch (Event) {
100 case event_stage_end:
101 enterFadeOutStage();
102 break;
103 case event_release:
104 enterReleasePart1Stage();
105 break;
106 case event_hold_end:
107 enterDecay1Part1Stage(SampleRate);
108 break;
109 }
110 break;
111 case stage_sustain:
112 switch (Event) {
113 case event_stage_end: {// just refresh time
114 const int intMax = (unsigned int) -1 >> 1;
115 StepsLeft = intMax; // we use the highest possible value
116 break;
117 }
118 case event_release:
119 enterReleasePart1Stage();
120 break;
121 case event_hold_end:
122 enterDecay1Part1Stage(SampleRate);
123 break;
124 }
125 break;
126 case stage_release_part1:
127 switch (Event) {
128 case event_stage_end:
129 enterReleasePart2Stage();
130 break;
131 case event_cancel_release:
132 if (InfiniteSustain)
133 enterSustainStage();
134 else
135 enterDecay2Stage(SampleRate);
136 break;
137 }
138 break;
139 case stage_release_part2:
140 switch (Event) {
141 case event_stage_end:
142 enterFadeOutStage();
143 break;
144 case event_cancel_release:
145 if (InfiniteSustain)
146 enterSustainStage();
147 else
148 enterDecay2Stage(SampleRate);
149 break;
150 }
151 break;
152 case stage_fadeout:
153 switch (Event) {
154 case event_stage_end:
155 enterEndStage();
156 break;
157 }
158 break;
159 }
160 }
161
162 void EGADSR::trigger(uint PreAttack, float AttackTime, bool HoldAttack, float Decay1Time, double Decay2Time, bool InfiniteSustain, uint SustainLevel, float ReleaseTime, float Volume, uint SampleRate) {
163 this->SustainLevel = SustainLevel / 1000.0;
164 this->InfiniteSustain = InfiniteSustain;
165 this->HoldAttack = HoldAttack;
166
167 this->Decay1Time = Decay1Time;
168 this->Decay2Time = Decay2Time;
169
170 invVolume = 1 / Volume;
171 ExpOffset = (0.25 - 1 / 3.55) * invVolume;
172
173 // calculate release stage parameters (lin+exp curve)
174 if (ReleaseTime < CONFIG_EG_MIN_RELEASE_TIME) ReleaseTime = CONFIG_EG_MIN_RELEASE_TIME; // to avoid click sounds at the end of the sample playback
175 const float ReleaseStepsLeft = (long) (ReleaseTime * SampleRate);
176 ReleaseSlope = 1.365 * (0 - 1) / ReleaseStepsLeft;
177 ReleaseCoeff = ReleaseSlope * invVolume;
178 ReleaseSlope *= 3.55;
179 ReleaseCoeff2 = exp(ReleaseSlope);
180 ReleaseCoeff3 = ExpOffset * (1 - ReleaseCoeff2);
181 ReleaseLevel2 = 0.25 * invVolume;
182
183 enterAttackStage(PreAttack, AttackTime, SampleRate);
184 }
185
186 void EGADSR::enterAttackStage(const uint PreAttack, const float AttackTime, const uint SampleRate) {
187 Stage = stage_attack;
188 Segment = segment_lin;
189
190 if (AttackTime >= 0.0005f) {
191 // Measurements of GSt output shows that the real attack time
192 // is about 65.5% of the value specified in the gig file.
193 // The minimum attack value used is 0.032.
194 StepsLeft = int(0.655f * RTMath::Max(AttackTime, 0.032f) * SampleRate);
195 Level = (float) PreAttack / 1000.0;
196 Coeff = 0.896f * (1.0f - Level) / StepsLeft; // max level is a bit lower if attack != 0
197 } else { // attack is zero - immediately jump to the next stage
198 Level = 1.029f; // a bit higher than max sustain
199 if (HoldAttack) enterAttackHoldStage();
200 else enterDecay1Part1Stage(SampleRate);
201 }
202 }
203
204 void EGADSR::enterAttackHoldStage() {
205 Stage = stage_attack_hold;
206 Segment = segment_lin;
207 Coeff = 0.0f; // don't rise anymore
208 const int intMax = (unsigned int) -1 >> 1;
209 StepsLeft = intMax; // we use the highest value possible (we refresh StepsLeft in update() in case)
210 }
211
212 void EGADSR::enterDecay1Part1Stage(const uint SampleRate) {
213 // The decay1 and release stage both consist of two parts,
214 // first a linear curve, f, followed by an exponential curve,
215 // g:
216 //
217 // f(x + d) = f(x) + Coeff
218 // g(x + d) = Coeff2 * g(x) + Coeff3
219 //
220 // (where d is 1/SampleRate). The transition from f to g is
221 // done when f(x) has reached Level2 = 25% of full volume.
222 StepsLeft = (int) (Decay1Time * SampleRate);
223 if (StepsLeft && Level > SustainLevel) {
224 Stage = stage_decay1_part1;
225 Segment = segment_lin;
226 Decay1Slope = (1.347f * SustainLevel - 1.361f) / StepsLeft;
227 Coeff = Decay1Slope * invVolume;
228 Decay1Level2 = 0.25 * invVolume;
229 StepsLeft = int((RTMath::Max(Decay1Level2, SustainLevel) - Level) / Coeff);
230 if (StepsLeft <= 0) enterDecay1Part2Stage(SampleRate);
231 } else {
232 if (InfiniteSustain) enterSustainStage();
233 else enterDecay2Stage(SampleRate);
234 }
235 }
236
237 void EGADSR::enterDecay1Part2Stage(const uint SampleRate) {
238 if (SustainLevel < Decay1Level2) {
239 Stage = stage_decay1_part2;
240 Segment = segment_exp;
241 Decay1Slope *= 3.55;
242 Coeff = exp(Decay1Slope);
243 Offset = ExpOffset * (1 - Coeff);
244 StepsLeft = int(log((SustainLevel - ExpOffset) / (Level - ExpOffset)) / Decay1Slope);
245 if (StepsLeft > 0) return;
246 }
247 if (InfiniteSustain) enterSustainStage();
248 else enterDecay2Stage(SampleRate);
249 }
250
251 void EGADSR::enterDecay2Stage(const uint SampleRate) {
252 Stage = stage_decay2;
253 Segment = segment_lin;
254 Decay2Time = RTMath::Max(Decay2Time, 0.05f);
255 StepsLeft = (int) (Decay2Time * SampleRate);
256 Coeff = (-1.03 / StepsLeft) * invVolume;
257 //FIXME: do we really have to calculate 'StepsLeft' two times?
258 StepsLeft = int((CONFIG_EG_BOTTOM - Level) / Coeff);
259 if (StepsLeft <= 0) enterEndStage();
260 }
261
262 void EGADSR::enterSustainStage() {
263 Stage = stage_sustain;
264 Segment = segment_lin;
265 Coeff = 0.0f; // don't change the envelope level in this stage
266 const int intMax = (unsigned int) -1 >> 1;
267 StepsLeft = intMax; // we use the highest value possible (we refresh StepsLeft in update() in case)
268 }
269
270 void EGADSR::enterReleasePart1Stage() {
271 Stage = stage_release_part1;
272 Segment = segment_lin;
273 StepsLeft = int((ReleaseLevel2 - Level) / ReleaseCoeff);
274 Coeff = ReleaseCoeff;
275 if (StepsLeft <= 0) enterReleasePart2Stage();
276 }
277
278 void EGADSR::enterReleasePart2Stage() {
279 Stage = stage_release_part2;
280 Segment = segment_exp;
281 StepsLeft = int(log((CONFIG_EG_BOTTOM - ExpOffset) / (Level - ExpOffset)) / ReleaseSlope);
282 Coeff = ReleaseCoeff2;
283 Offset = ReleaseCoeff3;
284 if (StepsLeft <= 0) enterFadeOutStage();
285 }
286
287 void EGADSR::enterFadeOutStage() {
288 Stage = stage_fadeout;
289 Segment = segment_lin;
290 StepsLeft = int(Level / (-FadeOutCoeff));
291 Coeff = FadeOutCoeff;
292 if (StepsLeft <= 0) enterEndStage();
293 }
294
295 void EGADSR::enterFadeOutStage(int maxFadeOutSteps) {
296 Stage = stage_fadeout;
297 Segment = segment_lin;
298 StepsLeft = int(Level / (-FadeOutCoeff));
299 if (StepsLeft > maxFadeOutSteps) {
300 StepsLeft = maxFadeOutSteps;
301 Coeff = -Level / maxFadeOutSteps;
302 } else {
303 Coeff = FadeOutCoeff;
304 }
305 if (StepsLeft <= 0) enterEndStage();
306 }
307
308 void EGADSR::enterEndStage() {
309 Stage = stage_end;
310 Segment = segment_end;
311 Level = 0;
312 }
313
314 }} // namespace LinuxSampler::gig

  ViewVC Help
Powered by ViewVC