/[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 738 - (hide annotations) (download)
Tue Aug 16 17:14:25 2005 UTC (18 years, 8 months ago) by schoenebeck
File size: 12798 byte(s)
* extensive synthesis optimization: reimplementation of EGs and LFO(s),
  removed synthesis parameter prerendering and the synthesis parameter
  matrix in general, splitting each audio fragment into subfragments now
  where each subfragment uses constant synthesis parameters
  (everything's still very buggy ATM)

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

  ViewVC Help
Powered by ViewVC