/[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 1748 - (show annotations) (download)
Sun Jun 22 14:46:46 2008 UTC (15 years, 10 months ago) by persson
File size: 13791 byte(s)
* bugfix: notes triggered at position 0 in the audio buffer were
  sometimes wrongly killed in the same buffer, causing no sound to be
  played
* fixes for audio drivers with varying buffer sizes
* Makefile fix: JACK_CFLAGS wasn't used
* JACK driver: use jack_client_open instead of the deprecated
  jack_client_new

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

  ViewVC Help
Powered by ViewVC