/[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 688 - (hide annotations) (download)
Thu Jul 14 12:25:20 2005 UTC (18 years, 9 months ago) by schoenebeck
File size: 20390 byte(s)
* if period time of chosen audio device is too small (< MIN_RELEASE_TIME)
  then simply show a warning about possible click sounds and reduce the
  volume ramp down appropriately instead of cancelling the audio device
  connection

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 688 void EGADSR::CalculateFadeOutCoeff(float FadeOutTime, float SampleRate) {
29     const float killSteps = FadeOutTime * SampleRate;
30     FadeOutCoeff = -1.0f / killSteps;
31 schoenebeck 239 }
32    
33 schoenebeck 53 EGADSR::EGADSR(gig::Engine* pEngine, Event::destination_t ModulationDestination) {
34     this->pEngine = pEngine;
35     this->ModulationDestination = ModulationDestination;
36     Stage = stage_end;
37     Level = 0.0;
38 schoenebeck 688 CalculateFadeOutCoeff(CONFIG_EG_MIN_RELEASE_TIME, 44100.0); // even if the sample rate will be 192kHz it won't hurt at all
39 schoenebeck 53 }
40    
41     /**
42     * Will be called by the voice for every audio fragment to let the EG
43     * queue it's modulation changes for the current audio fragment.
44     *
45 schoenebeck 239 * @param TotalSamples - total number of sample points to be rendered in this
46 schoenebeck 53 * audio fragment cycle by the audio engine
47     * @param pEvents - event list with "release" and "cancel release" events
48 schoenebeck 271 * @param itTriggerEvent - event that caused triggering of the voice (only if
49 schoenebeck 239 * the voice was triggered in the current audio
50 schoenebeck 53 * fragment, NULL otherwise)
51     * @param SamplePos - current playback position
52     * @param CurrentPitch - current pitch value for playback
53 schoenebeck 271 * @param itKillEvent - (optional) event which caused this voice to be killed
54 schoenebeck 53 */
55 schoenebeck 271 void EGADSR::Process(uint TotalSamples, RTList<Event>* pEvents, RTList<Event>::Iterator itTriggerEvent, double SamplePos, double CurrentPitch, RTList<Event>::Iterator itKillEvent) {
56     // skip all events which occured before this voice was triggered
57     RTList<Event>::Iterator itTransitionEvent = (itTriggerEvent) ? ++itTriggerEvent : pEvents->first();
58 schoenebeck 53
59 schoenebeck 252 // if the voice was killed in this fragment we only process the time before this kill event, then switch to 'stage_fadeout'
60 schoenebeck 285 int Samples = (itKillEvent) ? RTMath::Min(itKillEvent->FragmentPos(), pEngine->MaxFadeOutPos) : (int) TotalSamples;
61 schoenebeck 239
62 schoenebeck 53 int iSample = TriggerDelay;
63 schoenebeck 286
64 schoenebeck 554 #if CONFIG_DEVMODE
65 schoenebeck 563 if (TriggerDelay > TotalSamples) { // just a sanity check for debugging
66 schoenebeck 286 dmsg(1,("EGADSR: ERROR, TriggerDelay > Totalsamples\n"));
67     int* i = NULL;
68     (*i)++; // force a segfault
69     }
70 schoenebeck 554 #endif // CONFIG_DEVMODE
71 schoenebeck 286
72 schoenebeck 239 while (iSample < TotalSamples) {
73    
74     // if the voice was killed in this fragment and we already processed the time before this kill event
75 schoenebeck 271 if (itKillEvent && iSample >= Samples) Stage = stage_fadeout;
76 schoenebeck 239
77 schoenebeck 53 switch (Stage) {
78     case stage_attack: {
79     TriggerDelay = 0;
80     int to_process = RTMath::Min(AttackStepsLeft, Samples - iSample);
81     int process_end = iSample + to_process;
82     AttackStepsLeft -= to_process;
83     while (iSample < process_end) {
84     Level += AttackCoeff;
85     pEngine->pSynthesisParameters[ModulationDestination][iSample++] *= Level;
86     }
87 persson 396 if (iSample == TotalSamples && itTransitionEvent) { // postpone last transition event for the next audio fragment
88 schoenebeck 271 RTList<Event>::Iterator itLastEvent = pEvents->last();
89     if (itLastEvent) ReleasePostponed = (itLastEvent->Type == Event::type_release);
90 schoenebeck 53 }
91 persson 614 if (!AttackStepsLeft) Stage = (ReleasePostponed) ? stage_release_init : (HoldAttack) ? stage_attack_hold : stage_decay1_init;
92 schoenebeck 53 break;
93     }
94     case stage_attack_hold: {
95     if (SamplePos >= LoopStart) {
96 persson 614 Stage = stage_decay1_init;
97 schoenebeck 53 break;
98     }
99     int holdstepsleft = (int) (LoopStart - SamplePos / CurrentPitch); // FIXME: just an approximation, inaccuracy grows with higher audio fragment size, sufficient for usual fragment sizes though
100     int to_process = RTMath::Min(holdstepsleft, Samples - iSample);
101     int process_end = iSample + to_process;
102 schoenebeck 271 if (itTransitionEvent && itTransitionEvent->FragmentPos() <= process_end) {
103     process_end = itTransitionEvent->FragmentPos();
104 persson 614 Stage = (itTransitionEvent->Type == Event::type_release) ? stage_release_init : (InfiniteSustain) ? stage_sustain : stage_decay2_init;
105 schoenebeck 271 ++itTransitionEvent;
106 schoenebeck 53 }
107 persson 614 else if (to_process == holdstepsleft) Stage = stage_decay1_init;
108 schoenebeck 53 while (iSample < process_end) {
109     pEngine->pSynthesisParameters[ModulationDestination][iSample++] *= Level;
110     }
111     break;
112     }
113 persson 614 case stage_decay1_init: {
114     if (Decay1StepsLeft) {
115     if (SustainLevel < 1.0) {
116     Decay1StepsLeft = int((RTMath::Max(Decay1Level2, SustainLevel) - Level) / Decay1Coeff);
117     } else {
118     Stage = (InfiniteSustain) ? stage_sustain : stage_decay2_init;
119     break;
120     }
121     } else {
122     Level = SustainLevel;
123     Stage = (InfiniteSustain) ? stage_sustain : stage_decay2_init;
124     break;
125     }
126     Stage = stage_decay1;
127     }
128 schoenebeck 53 case stage_decay1: {
129     int to_process = RTMath::Min(Samples - iSample, Decay1StepsLeft);
130     int process_end = iSample + to_process;
131 schoenebeck 271 if (itTransitionEvent && itTransitionEvent->FragmentPos() <= process_end) {
132     process_end = itTransitionEvent->FragmentPos();
133 persson 614 Stage = (itTransitionEvent->Type == Event::type_release) ? stage_release_init : (InfiniteSustain) ? stage_sustain : stage_decay2_init;
134 schoenebeck 271 ++itTransitionEvent;
135 schoenebeck 53 }
136     else {
137     Decay1StepsLeft -= to_process;
138 persson 614 if (!Decay1StepsLeft) Stage = stage_decay1_part2_init;
139 schoenebeck 53 }
140     while (iSample < process_end) {
141 persson 614 Level += Decay1Coeff;
142 schoenebeck 53 pEngine->pSynthesisParameters[ModulationDestination][iSample++] *= Level;
143     }
144     break;
145     }
146 persson 614 case stage_decay1_part2_init:
147     Decay1StepsLeft = int(log((SustainLevel - ExpOffset) / (Level - ExpOffset)) / Decay1Slope);
148     Stage = stage_decay1_part2;
149     case stage_decay1_part2: {
150     int to_process = RTMath::Min(Samples - iSample, Decay1StepsLeft);
151     int process_end = iSample + to_process;
152     if (itTransitionEvent && itTransitionEvent->FragmentPos() <= process_end) {
153     process_end = itTransitionEvent->FragmentPos();
154     Stage = (itTransitionEvent->Type == Event::type_release) ? stage_release_init : (InfiniteSustain) ? stage_sustain : stage_decay2_init;
155     ++itTransitionEvent;
156     }
157     else {
158     Decay1StepsLeft -= to_process;
159     if (!Decay1StepsLeft) Stage = (InfiniteSustain) ? stage_sustain : stage_decay2_init;
160     }
161     while (iSample < process_end) {
162     Level = Level * Decay1Coeff2 + Decay1Coeff3;
163     pEngine->pSynthesisParameters[ModulationDestination][iSample++] *= Level;
164     }
165     break;
166     }
167     case stage_decay2_init:
168     Decay2StepsLeft = int((CONFIG_EG_BOTTOM - Level) / Decay2Coeff);
169     Stage = stage_decay2;
170 schoenebeck 53 case stage_decay2: {
171 persson 614 int to_process = RTMath::Min(Samples - iSample, Decay2StepsLeft);
172     int process_end = iSample + to_process;
173     if (itTransitionEvent && itTransitionEvent->Type == Event::type_release && itTransitionEvent->FragmentPos() <= process_end) {
174 schoenebeck 271 process_end = itTransitionEvent->FragmentPos();
175     ++itTransitionEvent;
176 persson 614 Stage = stage_release_init; // switch to release stage soon
177 schoenebeck 53 }
178 persson 614 else {
179     Decay2StepsLeft -= to_process;
180     if (!Decay2StepsLeft) Stage = stage_fadeout;
181     }
182 schoenebeck 53 while (iSample < process_end) {
183 persson 614 Level += Decay2Coeff;
184 schoenebeck 53 pEngine->pSynthesisParameters[ModulationDestination][iSample++] *= Level;
185     }
186     break;
187     }
188     case stage_sustain: {
189     int process_end;
190 schoenebeck 271 if (itTransitionEvent && itTransitionEvent->Type == Event::type_release && itTransitionEvent->FragmentPos() <= Samples) {
191     process_end = itTransitionEvent->FragmentPos();
192     ++itTransitionEvent;
193 persson 614 Stage = stage_release_init; // switch to release stage soon
194 schoenebeck 53 }
195     else process_end = Samples;
196     while (iSample < process_end) {
197     pEngine->pSynthesisParameters[ModulationDestination][iSample++] *= Level;
198     }
199     break;
200     }
201 persson 614 case stage_release_init:
202     ReleaseStepsLeft = int((ReleaseLevel2 - Level) / ReleaseCoeff);
203     Stage = stage_release;
204 schoenebeck 53 case stage_release: {
205 persson 614 int to_process = RTMath::Min(Samples - iSample, ReleaseStepsLeft);
206     int process_end = iSample + to_process;
207     if (itTransitionEvent && itTransitionEvent->Type == Event::type_cancel_release && itTransitionEvent->FragmentPos() <= process_end) {
208 schoenebeck 271 process_end = itTransitionEvent->FragmentPos();
209     ++itTransitionEvent;
210 persson 614 Stage = (InfiniteSustain) ? stage_sustain : stage_decay2_init; // switch back to sustain / decay2 stage soon
211 schoenebeck 53 }
212 persson 614 else {
213     ReleaseStepsLeft -= to_process;
214     if (!ReleaseStepsLeft) Stage = stage_release_part2_init;
215     }
216 schoenebeck 53 while (iSample < process_end) {
217 persson 614 Level += ReleaseCoeff;
218 schoenebeck 53 pEngine->pSynthesisParameters[ModulationDestination][iSample++] *= Level;
219     }
220     break;
221     }
222 persson 614 case stage_release_part2_init:
223     ReleaseStepsLeft = int(log((CONFIG_EG_BOTTOM - ExpOffset) / (Level - ExpOffset)) / ReleaseSlope);
224     Stage = stage_release_part2;
225     case stage_release_part2: {
226     int to_process = RTMath::Min(Samples - iSample, ReleaseStepsLeft);
227     int process_end = iSample + to_process;
228     if (itTransitionEvent && itTransitionEvent->Type == Event::type_cancel_release && itTransitionEvent->FragmentPos() <= process_end) {
229     process_end = itTransitionEvent->FragmentPos();
230     ++itTransitionEvent;
231     Stage = (InfiniteSustain) ? stage_sustain : stage_decay2_init; // switch back to sustain / decay2 stage soon
232     }
233     else {
234     ReleaseStepsLeft -= to_process;
235     if (!ReleaseStepsLeft) Stage = stage_fadeout;
236     }
237     while (iSample < process_end) {
238     Level = Level * ReleaseCoeff2 + ReleaseCoeff3;
239     pEngine->pSynthesisParameters[ModulationDestination][iSample++] *= Level;
240     }
241     break;
242     }
243 schoenebeck 252 case stage_fadeout: {
244     int to_process = RTMath::Min(int(Level / (-FadeOutCoeff)), TotalSamples - iSample);
245 schoenebeck 251 int process_end = iSample + to_process;
246     while (iSample < process_end) {
247 schoenebeck 252 Level += FadeOutCoeff;
248 schoenebeck 53 pEngine->pSynthesisParameters[ModulationDestination][iSample++] *= Level;
249     }
250 schoenebeck 285 Stage = stage_end;
251 schoenebeck 688 if (Level > -FadeOutCoeff) dmsg(2,("EGADSR: Warning, final fade out level too high, may result in click sound!\n"));
252 senkov 259 } //Fall through here instead of breaking otherwise we can get back into stage_fadeout and loop forever!
253 schoenebeck 252 case stage_end: {
254 schoenebeck 251 while (iSample < TotalSamples) {
255     pEngine->pSynthesisParameters[ModulationDestination][iSample++] = 0.0f;
256     }
257 schoenebeck 53 break;
258     }
259     }
260     }
261 schoenebeck 285
262 schoenebeck 554 #if CONFIG_DEVMODE
263 schoenebeck 563 if (itKillEvent && Stage != stage_end) { // just a sanity check for debugging
264 schoenebeck 286 dmsg(1,("EGADSR: ERROR, voice killing not completed !!!\n"));
265 schoenebeck 285 dmsg(1,("EGADSR: Stage=%d,iSample=%d,Samples=%d, TotalSamples=%d, MaxFadoutPos=%d\n",Stage,iSample,Samples,TotalSamples,pEngine->MaxFadeOutPos));
266     }
267 schoenebeck 554 #endif // CONFIG_DEVMODE
268 schoenebeck 53 }
269    
270     /**
271     * Will be called by the voice when the key / voice was triggered.
272     *
273     * @param PreAttack - Preattack value for the envelope (0 - 1000 permille)
274     * @param AttackTime - Attack time for the envelope (0.000 - 60.000s)
275     * @param HoldAttack - If true, Decay1 will be postponed until the sample reached the sample loop start.
276     * @param LoopStart - Sample position where sample loop starts (if any)
277     * @param Decay1Time - Decay1 time of the sample amplitude EG (0.000 - 60.000s).
278     * @param Decay2Time - Only if !InfiniteSustain: 2nd decay stage time of the sample amplitude EG (0.000 - 60.000s).
279     * @param InfiniteSustain - If true, instead of going into Decay2 phase, Decay1 level will be hold until note will be released.
280     * @param SustainLevel - Sustain level of the sample amplitude EG (0 - 1000 permille).
281     * @param ReleaseTIme - Release time for the envelope (0.000 - 60.000s)
282     * @param Delay - Number of sample points triggering should be delayed.
283 persson 614 * @param Volume - Volume the sample will be played at (0.0 - 1.0). Used when calculating the exponential curve parameters.
284 schoenebeck 53 */
285 persson 614 void EGADSR::Trigger(uint PreAttack, double AttackTime, bool HoldAttack, long LoopStart, double Decay1Time, double Decay2Time, bool InfiniteSustain, uint SustainLevel, double ReleaseTime, uint Delay, float Volume) {
286 schoenebeck 53 this->TriggerDelay = Delay;
287     this->Stage = stage_attack;
288 persson 614 if (SustainLevel) {
289     this->SustainLevel = SustainLevel / 1000.0;
290     } else {
291     // sustain level 0 means that voice dies after decay 1
292     this->SustainLevel = CONFIG_EG_BOTTOM;
293     InfiniteSustain = false;
294     Decay2Time = CONFIG_EG_MIN_RELEASE_TIME;
295     }
296 schoenebeck 53 this->InfiniteSustain = InfiniteSustain;
297     this->HoldAttack = HoldAttack;
298     this->LoopStart = LoopStart;
299     this->ReleasePostponed = false;
300    
301     // calculate attack stage parameters (lin. curve)
302 persson 614
303     // Measurements of GSt output shows that the real attack time
304     // is about 65.5% of the value specified in the gig file.
305     AttackStepsLeft = (long) (0.655 * AttackTime * pEngine->pAudioOutputDevice->SampleRate());
306 schoenebeck 53 if (AttackStepsLeft) {
307     Level = (float) PreAttack / 1000.0;
308 persson 614 AttackCoeff = 0.896 * (1.0 - Level) / AttackStepsLeft; // max level is a bit lower if attack != 0
309 schoenebeck 53 }
310     else {
311     Level = 1.0;
312     AttackCoeff = 0.0;
313     }
314    
315 persson 614 const float invVolume = 1 / Volume;
316     ExpOffset = (0.25 - 1 / 3.55) * invVolume;
317    
318     // The decay1 and release stage both consist of two parts,
319     // first a linear curve, f, followed by an exponential curve,
320     // g:
321     //
322     // f(x + d) = f(x) + Coeff
323     // g(x + d) = Coeff2 * g(x) + Coeff3
324     //
325     // (where d is 1/SampleRate). The transition from f to g is
326     // done when f(x) has reached Level2 = 25% of full volume.
327    
328     // calculate decay1 stage parameters (lin+exp curve)
329 schoenebeck 53 Decay1StepsLeft = (long) (Decay1Time * pEngine->pAudioOutputDevice->SampleRate());
330 persson 614 if (Decay1StepsLeft) {
331     Decay1Slope = 1.365 * (this->SustainLevel - 1.0) / Decay1StepsLeft;
332     Decay1Coeff = Decay1Slope * invVolume;
333     Decay1Slope *= 3.55;
334     Decay1Coeff2 = exp(Decay1Slope);
335     Decay1Coeff3 = ExpOffset * (1 - Decay1Coeff2);
336     Decay1Level2 = 0.25 * invVolume;
337     }
338 schoenebeck 53
339 persson 614 // calculate decay2 stage parameters (lin. curve)
340 schoenebeck 53 if (!InfiniteSustain) {
341 schoenebeck 554 if (Decay2Time < CONFIG_EG_MIN_RELEASE_TIME) Decay2Time = CONFIG_EG_MIN_RELEASE_TIME;
342 schoenebeck 53 long Decay2Steps = (long) (Decay2Time * pEngine->pAudioOutputDevice->SampleRate());
343 persson 614 Decay2Coeff = (-1.03 / Decay2Steps) * invVolume;
344 schoenebeck 53 }
345    
346 persson 614 // calculate release stage parameters (lin+exp curve)
347 schoenebeck 554 if (ReleaseTime < CONFIG_EG_MIN_RELEASE_TIME) ReleaseTime = CONFIG_EG_MIN_RELEASE_TIME; // to avoid click sounds at the end of the sample playback
348 schoenebeck 53 ReleaseStepsLeft = (long) (ReleaseTime * pEngine->pAudioOutputDevice->SampleRate());
349 persson 614 ReleaseSlope = 1.365 * (0 - 1) / ReleaseStepsLeft;
350     ReleaseCoeff = ReleaseSlope * invVolume;
351     ReleaseSlope *= 3.55;
352     ReleaseCoeff2 = exp(ReleaseSlope);
353     ReleaseCoeff3 = ExpOffset * (1 - ReleaseCoeff2);
354     ReleaseLevel2 = 0.25 * invVolume;
355 schoenebeck 53
356     dmsg(4,("PreAttack=%d, AttackLength=%d, AttackCoeff=%f, Decay1Coeff=%f, Decay2Coeff=%f, ReleaseLength=%d, ReleaseCoeff=%f\n",
357     PreAttack, AttackStepsLeft, AttackCoeff, Decay1Coeff, Decay2Coeff, ReleaseStepsLeft, ReleaseCoeff));
358     }
359    
360     }} // namespace LinuxSampler::gig

  ViewVC Help
Powered by ViewVC