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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1909 - (hide annotations) (download)
Wed Jun 3 17:21:42 2009 UTC (14 years, 10 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 schoenebeck 53 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5 schoenebeck 56 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 persson 1906 * Copyright (C) 2005 - 2009 Christian Schoenebeck *
7 schoenebeck 53 * *
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 schoenebeck 1424 #include "../../common/global_private.h"
27    
28 schoenebeck 53 namespace LinuxSampler { namespace gig {
29    
30 schoenebeck 738 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 schoenebeck 688 void EGADSR::CalculateFadeOutCoeff(float FadeOutTime, float SampleRate) {
37 persson 796 const float killSteps = FadeOutTime * SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;
38 schoenebeck 688 FadeOutCoeff = -1.0f / killSteps;
39 schoenebeck 239 }
40    
41 persson 783 void EGADSR::update(event_t Event, uint SampleRate) {
42     if (Event == event_hold_end) HoldAttack = false;
43    
44 schoenebeck 738 switch (Stage) {
45     case stage_attack:
46 persson 783 switch (Event) {
47     case event_release:
48 schoenebeck 738 enterReleasePart1Stage();
49 persson 783 break;
50     case event_stage_end:
51     if (HoldAttack)
52     enterAttackHoldStage();
53     else
54     enterDecay1Part1Stage(SampleRate);
55     break;
56 schoenebeck 53 }
57 schoenebeck 738 break;
58     case stage_attack_hold:
59     switch (Event) {
60 persson 783 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 schoenebeck 738 enterDecay1Part1Stage(SampleRate);
67 schoenebeck 53 break;
68 schoenebeck 738 case event_release:
69     enterReleasePart1Stage();
70     break;
71 schoenebeck 53 }
72 schoenebeck 738 break;
73     case stage_decay1_part1:
74     switch (Event) {
75 persson 768 case event_stage_end:
76     enterDecay1Part2Stage(SampleRate);
77 persson 614 break;
78 persson 1909 case event_release:
79     enterReleasePart1Stage();
80 schoenebeck 738 break;
81 persson 614 }
82 schoenebeck 738 break;
83     case stage_decay1_part2:
84     switch (Event) {
85     case event_release:
86     enterReleasePart1Stage();
87     break;
88 persson 1906 case event_stage_end:
89 persson 783 if (Level < CONFIG_EG_BOTTOM)
90     enterEndStage();
91     else if (InfiniteSustain)
92 schoenebeck 738 enterSustainStage();
93     else
94     enterDecay2Stage(SampleRate);
95     break;
96 schoenebeck 53 }
97 schoenebeck 738 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 persson 783 case event_hold_end:
107     enterDecay1Part1Stage(SampleRate);
108     break;
109 persson 614 }
110 schoenebeck 738 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 schoenebeck 53 }
118 schoenebeck 738 case event_release:
119     enterReleasePart1Stage();
120     break;
121 persson 783 case event_hold_end:
122     enterDecay1Part1Stage(SampleRate);
123     break;
124 schoenebeck 53 }
125 schoenebeck 738 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 schoenebeck 53 }
138 schoenebeck 738 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 schoenebeck 53 }
151 schoenebeck 738 break;
152     case stage_fadeout:
153     switch (Event) {
154     case event_stage_end:
155     enterEndStage();
156     break;
157 persson 614 }
158 schoenebeck 738 break;
159 schoenebeck 53 }
160     }
161    
162 persson 783 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 schoenebeck 53 this->InfiniteSustain = InfiniteSustain;
165     this->HoldAttack = HoldAttack;
166    
167 schoenebeck 738 this->Decay1Time = Decay1Time;
168     this->Decay2Time = Decay2Time;
169 persson 614
170 schoenebeck 738 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 persson 768
183 persson 783 enterAttackStage(PreAttack, AttackTime, SampleRate);
184 schoenebeck 738 }
185    
186 persson 783 void EGADSR::enterAttackStage(const uint PreAttack, const float AttackTime, const uint SampleRate) {
187 schoenebeck 738 Stage = stage_attack;
188     Segment = segment_lin;
189 persson 797
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 schoenebeck 738 Level = (float) PreAttack / 1000.0;
196     Coeff = 0.896f * (1.0f - Level) / StepsLeft; // max level is a bit lower if attack != 0
197 persson 797 } else { // attack is zero - immediately jump to the next stage
198 persson 1046 Level = 1.029f; // a bit higher than max sustain
199 persson 783 if (HoldAttack) enterAttackHoldStage();
200 schoenebeck 738 else enterDecay1Part1Stage(SampleRate);
201 schoenebeck 53 }
202 schoenebeck 738 }
203 schoenebeck 53
204 persson 783 void EGADSR::enterAttackHoldStage() {
205 schoenebeck 738 Stage = stage_attack_hold;
206     Segment = segment_lin;
207     Coeff = 0.0f; // don't rise anymore
208 persson 783 const int intMax = (unsigned int) -1 >> 1;
209     StepsLeft = intMax; // we use the highest value possible (we refresh StepsLeft in update() in case)
210 schoenebeck 738 }
211 persson 614
212 schoenebeck 738 void EGADSR::enterDecay1Part1Stage(const uint SampleRate) {
213 persson 614 // 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 schoenebeck 738 StepsLeft = (int) (Decay1Time * SampleRate);
223 persson 1046 if (StepsLeft && Level > SustainLevel) {
224 schoenebeck 738 Stage = stage_decay1_part1;
225     Segment = segment_lin;
226 persson 1046 Decay1Slope = (1.347f * SustainLevel - 1.361f) / StepsLeft;
227 schoenebeck 738 Coeff = Decay1Slope * invVolume;
228 persson 614 Decay1Level2 = 0.25 * invVolume;
229 persson 1147 StepsLeft = int((RTMath::Max(Decay1Level2, SustainLevel) - Level) / Coeff);
230     if (StepsLeft <= 0) enterDecay1Part2Stage(SampleRate);
231 schoenebeck 738 } else {
232     if (InfiniteSustain) enterSustainStage();
233     else enterDecay2Stage(SampleRate);
234 persson 614 }
235 schoenebeck 738 }
236 schoenebeck 53
237 persson 768 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 persson 1147 if (StepsLeft > 0) return;
246 persson 768 }
247 persson 1147 if (InfiniteSustain) enterSustainStage();
248     else enterDecay2Stage(SampleRate);
249 schoenebeck 738 }
250 schoenebeck 53
251 schoenebeck 738 void EGADSR::enterDecay2Stage(const uint SampleRate) {
252     Stage = stage_decay2;
253     Segment = segment_lin;
254 persson 1046 Decay2Time = RTMath::Max(Decay2Time, 0.05f);
255 schoenebeck 738 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 persson 1147 if (StepsLeft <= 0) enterEndStage();
260 schoenebeck 738 }
261 schoenebeck 53
262 schoenebeck 738 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 schoenebeck 53 }
269    
270 schoenebeck 738 void EGADSR::enterReleasePart1Stage() {
271     Stage = stage_release_part1;
272     Segment = segment_lin;
273     StepsLeft = int((ReleaseLevel2 - Level) / ReleaseCoeff);
274     Coeff = ReleaseCoeff;
275 persson 1147 if (StepsLeft <= 0) enterReleasePart2Stage();
276 schoenebeck 738 }
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 persson 1147 if (StepsLeft <= 0) enterFadeOutStage();
285 schoenebeck 738 }
286    
287     void EGADSR::enterFadeOutStage() {
288     Stage = stage_fadeout;
289     Segment = segment_lin;
290     StepsLeft = int(Level / (-FadeOutCoeff));
291     Coeff = FadeOutCoeff;
292 persson 1147 if (StepsLeft <= 0) enterEndStage();
293 schoenebeck 738 }
294    
295 persson 1748 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 schoenebeck 738 void EGADSR::enterEndStage() {
309     Stage = stage_end;
310     Segment = segment_end;
311 persson 830 Level = 0;
312 schoenebeck 738 }
313    
314 schoenebeck 53 }} // namespace LinuxSampler::gig

  ViewVC Help
Powered by ViewVC