/[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 830 - (hide annotations) (download)
Sun Jan 15 18:23:11 2006 UTC (18 years, 3 months ago) by persson
File size: 13228 byte(s)
* added linear interpolation of volume modulation inside a
  subfragment; this prevents clicks during voice stealing. Can be
  switched off with the --disable-interpolate-volume configure option.

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 schoenebeck 554 * Copyright (C) 2005 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     namespace LinuxSampler { namespace gig {
27    
28 schoenebeck 738 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 schoenebeck 688 void EGADSR::CalculateFadeOutCoeff(float FadeOutTime, float SampleRate) {
35 persson 796 const float killSteps = FadeOutTime * SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;
36 schoenebeck 688 FadeOutCoeff = -1.0f / killSteps;
37 schoenebeck 239 }
38    
39 persson 783 void EGADSR::update(event_t Event, uint SampleRate) {
40     if (Event == event_hold_end) HoldAttack = false;
41    
42 schoenebeck 738 switch (Stage) {
43     case stage_attack:
44 persson 783 switch (Event) {
45     case event_release:
46 schoenebeck 738 enterReleasePart1Stage();
47 persson 783 break;
48     case event_cancel_release:
49 schoenebeck 738 enterSustainStage();
50 persson 783 break;
51     case event_stage_end:
52     if (HoldAttack)
53     enterAttackHoldStage();
54     else
55     enterDecay1Part1Stage(SampleRate);
56     break;
57 schoenebeck 53 }
58 schoenebeck 738 break;
59     case stage_attack_hold:
60     switch (Event) {
61 persson 783 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 schoenebeck 738 enterDecay1Part1Stage(SampleRate);
68 schoenebeck 53 break;
69 schoenebeck 738 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 schoenebeck 53 }
79 schoenebeck 738 break;
80     case stage_decay1_part1:
81     switch (Event) {
82 persson 768 case event_stage_end:
83     enterDecay1Part2Stage(SampleRate);
84 persson 614 break;
85 schoenebeck 738 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 persson 614 }
95 schoenebeck 738 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 persson 783 if (Level < CONFIG_EG_BOTTOM)
104     enterEndStage();
105     else if (InfiniteSustain)
106 schoenebeck 738 enterSustainStage();
107     else
108     enterDecay2Stage(SampleRate);
109     break;
110 schoenebeck 53 }
111 schoenebeck 738 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 persson 783 case event_hold_end:
121     enterDecay1Part1Stage(SampleRate);
122     break;
123 persson 614 }
124 schoenebeck 738 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 schoenebeck 53 }
132 schoenebeck 738 case event_release:
133     enterReleasePart1Stage();
134     break;
135 persson 783 case event_hold_end:
136     enterDecay1Part1Stage(SampleRate);
137     break;
138 schoenebeck 53 }
139 schoenebeck 738 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 schoenebeck 53 }
152 schoenebeck 738 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 schoenebeck 53 }
165 schoenebeck 738 break;
166     case stage_fadeout:
167     switch (Event) {
168     case event_stage_end:
169     enterEndStage();
170     break;
171 persson 614 }
172 schoenebeck 738 break;
173 schoenebeck 53 }
174     }
175    
176 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) {
177     this->SustainLevel = SustainLevel / 1000.0;
178 schoenebeck 53 this->InfiniteSustain = InfiniteSustain;
179     this->HoldAttack = HoldAttack;
180    
181 schoenebeck 738 this->Decay1Time = Decay1Time;
182     this->Decay2Time = Decay2Time;
183 persson 614
184 schoenebeck 738 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 persson 768
197 persson 783 enterAttackStage(PreAttack, AttackTime, SampleRate);
198 schoenebeck 738 }
199    
200 persson 783 void EGADSR::enterAttackStage(const uint PreAttack, const float AttackTime, const uint SampleRate) {
201 schoenebeck 738 Stage = stage_attack;
202     Segment = segment_lin;
203 persson 797
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 schoenebeck 738 Level = (float) PreAttack / 1000.0;
210     Coeff = 0.896f * (1.0f - Level) / StepsLeft; // max level is a bit lower if attack != 0
211 persson 797 } else { // attack is zero - immediately jump to the next stage
212 persson 768 Level = 1.0;
213 persson 783 if (HoldAttack) enterAttackHoldStage();
214 schoenebeck 738 else enterDecay1Part1Stage(SampleRate);
215 schoenebeck 53 }
216 schoenebeck 738 }
217 schoenebeck 53
218 persson 783 void EGADSR::enterAttackHoldStage() {
219 schoenebeck 738 Stage = stage_attack_hold;
220     Segment = segment_lin;
221     Coeff = 0.0f; // don't rise anymore
222 persson 783 const int intMax = (unsigned int) -1 >> 1;
223     StepsLeft = intMax; // we use the highest value possible (we refresh StepsLeft in update() in case)
224 schoenebeck 738 }
225 persson 614
226 schoenebeck 738 void EGADSR::enterDecay1Part1Stage(const uint SampleRate) {
227 persson 614 // 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 schoenebeck 738 StepsLeft = (int) (Decay1Time * SampleRate);
237 persson 783 if (StepsLeft && SustainLevel < 1.0 && Level > SustainLevel) {
238 schoenebeck 738 Stage = stage_decay1_part1;
239     Segment = segment_lin;
240     Decay1Slope = 1.365 * (SustainLevel - 1.0) / StepsLeft;
241     Coeff = Decay1Slope * invVolume;
242 persson 614 Decay1Level2 = 0.25 * invVolume;
243 persson 768 if (Level < Decay1Level2) enterDecay1Part2Stage(SampleRate);
244     else StepsLeft = int((RTMath::Max(Decay1Level2, SustainLevel) - Level) / Coeff);
245 schoenebeck 738 } else {
246     if (InfiniteSustain) enterSustainStage();
247     else enterDecay2Stage(SampleRate);
248 persson 614 }
249 schoenebeck 738 }
250 schoenebeck 53
251 persson 768 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 schoenebeck 738 }
264 schoenebeck 53
265 schoenebeck 738 void EGADSR::enterDecay2Stage(const uint SampleRate) {
266     Stage = stage_decay2;
267     Segment = segment_lin;
268     Decay2Time = RTMath::Max(Decay2Time, CONFIG_EG_MIN_RELEASE_TIME);
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 persson 768 if (StepsLeft == 0) enterEndStage();
274 schoenebeck 738 }
275 schoenebeck 53
276 schoenebeck 738 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 schoenebeck 53 }
283    
284 schoenebeck 738 void EGADSR::enterReleasePart1Stage() {
285     Stage = stage_release_part1;
286     Segment = segment_lin;
287     StepsLeft = int((ReleaseLevel2 - Level) / ReleaseCoeff);
288     Coeff = ReleaseCoeff;
289     }
290    
291     void EGADSR::enterReleasePart2Stage() {
292     Stage = stage_release_part2;
293     Segment = segment_exp;
294     StepsLeft = int(log((CONFIG_EG_BOTTOM - ExpOffset) / (Level - ExpOffset)) / ReleaseSlope);
295     Coeff = ReleaseCoeff2;
296     Offset = ReleaseCoeff3;
297     }
298    
299     void EGADSR::enterFadeOutStage() {
300     Stage = stage_fadeout;
301     Segment = segment_lin;
302     StepsLeft = int(Level / (-FadeOutCoeff));
303     Coeff = FadeOutCoeff;
304 persson 768 if (StepsLeft == 0) enterEndStage();
305 schoenebeck 738 }
306    
307     void EGADSR::enterEndStage() {
308     Stage = stage_end;
309     Segment = segment_end;
310 persson 830 Level = 0;
311 schoenebeck 738 }
312    
313 schoenebeck 53 }} // namespace LinuxSampler::gig

  ViewVC Help
Powered by ViewVC