/[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 1046 - (show annotations) (download)
Sat Feb 10 12:00:55 2007 UTC (17 years, 1 month ago) by persson
File size: 13327 byte(s)
* EG fine tuning: when attack is zero the EG starts at a level above
  max sustain level, which means that there is a decay phase even if
  sustain is 100%

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

  ViewVC Help
Powered by ViewVC