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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 237 by senkov, Sun Sep 12 01:59:40 2004 UTC revision 688 by schoenebeck, Thu Jul 14 12:25:20 2005 UTC
# Line 3  Line 3 
3   *   LinuxSampler - modular, streaming capable sampler                     *   *   LinuxSampler - modular, streaming capable sampler                     *
4   *                                                                         *   *                                                                         *
5   *   Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck   *   *   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  *   *   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  *   *   it under the terms of the GNU General Public License as published by  *
# Line 24  Line 25 
25    
26  namespace LinuxSampler { namespace gig {  namespace LinuxSampler { namespace gig {
27    
28        void EGADSR::CalculateFadeOutCoeff(float FadeOutTime, float SampleRate) {
29            const float killSteps = FadeOutTime * SampleRate;
30            FadeOutCoeff = -1.0f / killSteps;
31        }
32    
33      EGADSR::EGADSR(gig::Engine* pEngine, Event::destination_t ModulationDestination) {      EGADSR::EGADSR(gig::Engine* pEngine, Event::destination_t ModulationDestination) {
34          this->pEngine = pEngine;          this->pEngine = pEngine;
35          this->ModulationDestination = ModulationDestination;          this->ModulationDestination = ModulationDestination;
36          Stage = stage_end;          Stage = stage_end;
37          Level = 0.0;          Level = 0.0;
38            CalculateFadeOutCoeff(CONFIG_EG_MIN_RELEASE_TIME, 44100.0); // even if the sample rate will be 192kHz it won't hurt at all
39      }      }
40    
41      /**      /**
42       * Will be called by the voice for every audio fragment to let the EG       * 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.       * queue it's modulation changes for the current audio fragment.
44       *       *
45       * @param Samples       - total number of sample points to be rendered in this       * @param TotalSamples  - total number of sample points to be rendered in this
46       *                        audio fragment cycle by the audio engine       *                        audio fragment cycle by the audio engine
47       * @param pEvents       - event list with "release" and "cancel release" events       * @param pEvents       - event list with "release" and "cancel release" events
48       * @param pTriggerEvent - event that caused triggering of the voice (only if       * @param itTriggerEvent - event that caused triggering of the voice (only if
49       *                        the voices was triggered in the current audio       *                        the voice was triggered in the current audio
50       *                        fragment, NULL otherwise)       *                        fragment, NULL otherwise)
51       * @param SamplePos     - current playback position       * @param SamplePos     - current playback position
52       * @param CurrentPitch  - current pitch value for playback       * @param CurrentPitch  - current pitch value for playback
53         * @param itKillEvent   - (optional) event which caused this voice to be killed
54       */       */
55      void EGADSR::Process(uint Samples, RTEList<Event>* pEvents, Event* pTriggerEvent, double SamplePos, double CurrentPitch) {      void EGADSR::Process(uint TotalSamples, RTList<Event>* pEvents, RTList<Event>::Iterator itTriggerEvent, double SamplePos, double CurrentPitch, RTList<Event>::Iterator itKillEvent) {
56          Event* pTransitionEvent;          // skip all events which occured before this voice was triggered
57          if (pTriggerEvent) {          RTList<Event>::Iterator itTransitionEvent = (itTriggerEvent) ? ++itTriggerEvent : pEvents->first();
58              pEvents->set_current(pTriggerEvent);  
59              pTransitionEvent = pEvents->next();          // if the voice was killed in this fragment we only process the time before this kill event, then switch to 'stage_fadeout'
60          }          int Samples = (itKillEvent) ? RTMath::Min(itKillEvent->FragmentPos(), pEngine->MaxFadeOutPos) : (int) TotalSamples;
         else {  
             pTransitionEvent = pEvents->first();  
         }  
61    
62          int iSample = TriggerDelay;          int iSample = TriggerDelay;
63          while (iSample < Samples) {  
64            #if CONFIG_DEVMODE
65            if (TriggerDelay > TotalSamples) { // just a sanity check for debugging
66                dmsg(1,("EGADSR: ERROR, TriggerDelay > Totalsamples\n"));
67                int* i = NULL;
68                (*i)++; // force a segfault
69            }
70            #endif // CONFIG_DEVMODE
71    
72            while (iSample < TotalSamples) {
73    
74                // if the voice was killed in this fragment and we already processed the time before this kill event
75                if (itKillEvent && iSample >= Samples) Stage = stage_fadeout;
76    
77              switch (Stage) {              switch (Stage) {
78                  case stage_attack: {                  case stage_attack: {
79                      TriggerDelay = 0;                      TriggerDelay = 0;
# Line 66  namespace LinuxSampler { namespace gig { Line 84  namespace LinuxSampler { namespace gig {
84                          Level += AttackCoeff;                          Level += AttackCoeff;
85                          pEngine->pSynthesisParameters[ModulationDestination][iSample++] *= Level;                          pEngine->pSynthesisParameters[ModulationDestination][iSample++] *= Level;
86                      }                      }
87                      if (iSample == Samples) { // postpone last transition event for the next audio fragment                      if (iSample == TotalSamples && itTransitionEvent) { // postpone last transition event for the next audio fragment
88                          Event* pLastEvent = pEvents->last();                          RTList<Event>::Iterator itLastEvent = pEvents->last();
89                          if (pLastEvent) ReleasePostponed = (pLastEvent->Type == Event::type_release);                          if (itLastEvent) ReleasePostponed = (itLastEvent->Type == Event::type_release);
90                      }                      }
91                      if (!AttackStepsLeft) Stage = (ReleasePostponed) ? stage_release : (HoldAttack) ? stage_attack_hold : stage_decay1;                      if (!AttackStepsLeft) Stage = (ReleasePostponed) ? stage_release_init : (HoldAttack) ? stage_attack_hold : stage_decay1_init;
92                      break;                      break;
93                  }                  }
94                  case stage_attack_hold: {                  case stage_attack_hold: {
95                      if (SamplePos >= LoopStart) {                      if (SamplePos >= LoopStart) {
96                          Stage = stage_decay1;                          Stage = stage_decay1_init;
97                          break;                          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                      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);                      int to_process    = RTMath::Min(holdstepsleft, Samples - iSample);
101                      int process_end   = iSample + to_process;                      int process_end   = iSample + to_process;
102                      if (pTransitionEvent && pTransitionEvent->FragmentPos() <= process_end) {                      if (itTransitionEvent && itTransitionEvent->FragmentPos() <= process_end) {
103                          process_end      = pTransitionEvent->FragmentPos();                          process_end       = itTransitionEvent->FragmentPos();
104                          Stage            = (pTransitionEvent->Type == Event::type_release) ? stage_release : (InfiniteSustain) ? stage_sustain : stage_decay2;                          Stage             = (itTransitionEvent->Type == Event::type_release) ? stage_release_init : (InfiniteSustain) ? stage_sustain : stage_decay2_init;
105                          pTransitionEvent = pEvents->next();                          ++itTransitionEvent;
106                      }                      }
107                      else if (to_process == holdstepsleft) Stage = stage_decay1;                      else if (to_process == holdstepsleft) Stage = stage_decay1_init;
108                      while (iSample < process_end) {                      while (iSample < process_end) {
109                          pEngine->pSynthesisParameters[ModulationDestination][iSample++] *= Level;                          pEngine->pSynthesisParameters[ModulationDestination][iSample++] *= Level;
110                      }                      }
111                      break;                      break;
112                  }                  }
113                    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                  case stage_decay1: {                  case stage_decay1: {
129                      int to_process   = RTMath::Min(Samples - iSample, Decay1StepsLeft);                      int to_process   = RTMath::Min(Samples - iSample, Decay1StepsLeft);
130                      int process_end  = iSample + to_process;                      int process_end  = iSample + to_process;
131                      if (pTransitionEvent && pTransitionEvent->FragmentPos() <= process_end) {                      if (itTransitionEvent && itTransitionEvent->FragmentPos() <= process_end) {
132                          process_end      = pTransitionEvent->FragmentPos();                          process_end       = itTransitionEvent->FragmentPos();
133                          Stage            = (pTransitionEvent->Type == Event::type_release) ? stage_release : (InfiniteSustain) ? stage_sustain : stage_decay2;                          Stage             = (itTransitionEvent->Type == Event::type_release) ? stage_release_init : (InfiniteSustain) ? stage_sustain : stage_decay2_init;
134                          pTransitionEvent = pEvents->next();                          ++itTransitionEvent;
135                      }                      }
136                      else {                      else {
137                          Decay1StepsLeft -= to_process;                          Decay1StepsLeft -= to_process;
138                          if (!Decay1StepsLeft) Stage = (InfiniteSustain) ? stage_sustain : stage_decay2;                          if (!Decay1StepsLeft) Stage = stage_decay1_part2_init;
139                      }                      }
140                      while (iSample < process_end) {                      while (iSample < process_end) {
141                          Level += Level * Decay1Coeff;                          Level += Decay1Coeff;
142                          pEngine->pSynthesisParameters[ModulationDestination][iSample++] *= Level;                          pEngine->pSynthesisParameters[ModulationDestination][iSample++] *= Level;
143                      }                      }
144                      break;                      break;
145                  }                  }
146                    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                  case stage_decay2: {                  case stage_decay2: {
171                      int process_end;                      int to_process   = RTMath::Min(Samples - iSample, Decay2StepsLeft);
172                      if (pTransitionEvent && pTransitionEvent->Type == Event::type_release && pTransitionEvent->FragmentPos() <= Samples) {                      int process_end  = iSample + to_process;
173                          process_end      = pTransitionEvent->FragmentPos();                      if (itTransitionEvent && itTransitionEvent->Type == Event::type_release && itTransitionEvent->FragmentPos() <= process_end) {
174                          pTransitionEvent = pEvents->next();                          process_end       = itTransitionEvent->FragmentPos();
175                          Stage            = stage_release; // switch to release stage soon                          ++itTransitionEvent;
176                            Stage             = stage_release_init; // switch to release stage soon
177                        }
178                        else {
179                            Decay2StepsLeft -= to_process;
180                            if (!Decay2StepsLeft) Stage = stage_fadeout;
181                      }                      }
                     else process_end = Samples;  
182                      while (iSample < process_end) {                      while (iSample < process_end) {
183                          Level += Level * Decay2Coeff;                          Level += Decay2Coeff;
184                          pEngine->pSynthesisParameters[ModulationDestination][iSample++] *= Level;                          pEngine->pSynthesisParameters[ModulationDestination][iSample++] *= Level;
185                      }                      }
                     if (Level <= EG_ENVELOPE_LIMIT) Stage = stage_end;  
186                      break;                      break;
187                  }                  }
188                  case stage_sustain: {                  case stage_sustain: {
189                      int process_end;                      int process_end;
190                      if (pTransitionEvent && pTransitionEvent->Type == Event::type_release && pTransitionEvent->FragmentPos() <= Samples) {                      if (itTransitionEvent && itTransitionEvent->Type == Event::type_release && itTransitionEvent->FragmentPos() <= Samples) {
191                          process_end      = pTransitionEvent->FragmentPos();                          process_end       = itTransitionEvent->FragmentPos();
192                          pTransitionEvent = pEvents->next();                          ++itTransitionEvent;
193                          Stage            = stage_release; // switch to release stage soon                          Stage             = stage_release_init; // switch to release stage soon
194                      }                      }
195                      else process_end = Samples;                      else process_end = Samples;
196                      while (iSample < process_end) {                      while (iSample < process_end) {
# Line 138  namespace LinuxSampler { namespace gig { Line 198  namespace LinuxSampler { namespace gig {
198                      }                      }
199                      break;                      break;
200                  }                  }
201                    case stage_release_init:
202                        ReleaseStepsLeft = int((ReleaseLevel2 - Level) / ReleaseCoeff);
203                        Stage = stage_release;
204                  case stage_release: {                  case stage_release: {
205                      int process_end;                      int to_process   = RTMath::Min(Samples - iSample, ReleaseStepsLeft);
206                      if (pTransitionEvent && pTransitionEvent->Type == Event::type_cancel_release && pTransitionEvent->FragmentPos() <= Samples) {                      int process_end  = iSample + to_process;
207                          process_end      = pTransitionEvent->FragmentPos();                      if (itTransitionEvent && itTransitionEvent->Type == Event::type_cancel_release && itTransitionEvent->FragmentPos() <= process_end) {
208                          pTransitionEvent = pEvents->next();                          process_end       = itTransitionEvent->FragmentPos();
209                          Stage            = (InfiniteSustain) ? stage_sustain : stage_decay2; // switch back to sustain / decay2 stage soon                          ++itTransitionEvent;
210                            Stage             = (InfiniteSustain) ? stage_sustain : stage_decay2_init; // switch back to sustain / decay2 stage soon
211                        }
212                        else {
213                            ReleaseStepsLeft -= to_process;
214                            if (!ReleaseStepsLeft) Stage = stage_release_part2_init;
215                      }                      }
                     else process_end = Samples;  
216                      while (iSample < process_end) {                      while (iSample < process_end) {
217                          Level += Level * ReleaseCoeff;                          Level += ReleaseCoeff;
218                          pEngine->pSynthesisParameters[ModulationDestination][iSample++] *= Level;                          pEngine->pSynthesisParameters[ModulationDestination][iSample++] *= Level;
219                      }                      }
                     if (Level <= EG_ENVELOPE_LIMIT) Stage = stage_end;  
220                      break;                      break;
221                  }                  }
222                  case stage_end: {                  case stage_release_part2_init:
223                      while (iSample < Samples) {                      ReleaseStepsLeft = int(log((CONFIG_EG_BOTTOM - ExpOffset) / (Level - ExpOffset)) / ReleaseSlope);
224                          Level += Level * ReleaseCoeff;                      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                    case stage_fadeout: {
244                        int to_process   = RTMath::Min(int(Level / (-FadeOutCoeff)), TotalSamples - iSample);
245                        int process_end  = iSample + to_process;
246                        while (iSample < process_end) {
247                            Level += FadeOutCoeff;
248                          pEngine->pSynthesisParameters[ModulationDestination][iSample++] *= Level;                          pEngine->pSynthesisParameters[ModulationDestination][iSample++] *= Level;
249                      }                      }
250                        Stage = stage_end;
251                        if (Level > -FadeOutCoeff) dmsg(2,("EGADSR: Warning, final fade out level too high, may result in click sound!\n"));
252                    } //Fall through here instead of breaking otherwise we can get back into stage_fadeout and loop forever!
253                    case stage_end: {
254                        while (iSample < TotalSamples) {
255                            pEngine->pSynthesisParameters[ModulationDestination][iSample++] = 0.0f;
256                        }
257                      break;                      break;
258                  }                  }
259              }              }
260          }          }
261    
262            #if CONFIG_DEVMODE
263            if (itKillEvent && Stage != stage_end) { // just a sanity check for debugging
264                dmsg(1,("EGADSR: ERROR, voice killing not completed !!!\n"));
265                dmsg(1,("EGADSR: Stage=%d,iSample=%d,Samples=%d, TotalSamples=%d, MaxFadoutPos=%d\n",Stage,iSample,Samples,TotalSamples,pEngine->MaxFadeOutPos));
266            }
267            #endif // CONFIG_DEVMODE
268      }      }
269    
270      /**      /**
# Line 177  namespace LinuxSampler { namespace gig { Line 280  namespace LinuxSampler { namespace gig {
280       * @param SustainLevel    - Sustain level of the sample amplitude EG (0 - 1000 permille).       * @param SustainLevel    - Sustain level of the sample amplitude EG (0 - 1000 permille).
281       * @param ReleaseTIme     - Release time for the envelope (0.000 - 60.000s)       * @param ReleaseTIme     - Release time for the envelope (0.000 - 60.000s)
282       * @param Delay           - Number of sample points triggering should be delayed.       * @param Delay           - Number of sample points triggering should be delayed.
283         * @param Volume          - Volume the sample will be played at (0.0 - 1.0). Used when calculating the exponential curve parameters.
284       */       */
285      void EGADSR::Trigger(uint PreAttack, double AttackTime, bool HoldAttack, long LoopStart, double Decay1Time, double Decay2Time, bool InfiniteSustain, uint SustainLevel, double ReleaseTime, uint Delay) {      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          this->TriggerDelay     = Delay;          this->TriggerDelay     = Delay;
287          this->Stage            = stage_attack;          this->Stage            = stage_attack;
288          this->SustainLevel     = (SustainLevel) ? (SustainLevel > EG_ENVELOPE_LIMIT) ? (float) SustainLevel / 1000.0 : EG_ENVELOPE_LIMIT : 1.0;          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          this->InfiniteSustain  = InfiniteSustain;          this->InfiniteSustain  = InfiniteSustain;
297          this->HoldAttack       = HoldAttack;          this->HoldAttack       = HoldAttack;
298          this->LoopStart        = LoopStart;          this->LoopStart        = LoopStart;
299          this->ReleasePostponed = false;          this->ReleasePostponed = false;
300    
301          // calculate attack stage parameters (lin. curve)          // calculate attack stage parameters (lin. curve)
302          AttackStepsLeft = (long) (AttackTime * pEngine->pAudioOutputDevice->SampleRate());  
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          if (AttackStepsLeft) {          if (AttackStepsLeft) {
307              Level       = (float) PreAttack / 1000.0;              Level       = (float) PreAttack / 1000.0;
308              AttackCoeff = (1.0 - Level) / AttackStepsLeft;              AttackCoeff = 0.896 * (1.0 - Level) / AttackStepsLeft; // max level is a bit lower if attack != 0
309          }          }
310          else {          else {
311              Level       = 1.0;              Level       = 1.0;
312              AttackCoeff = 0.0;              AttackCoeff = 0.0;
313          }          }
314    
315          // calculate decay1 stage parameters (exp. curve)          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          Decay1StepsLeft = (long) (Decay1Time * pEngine->pAudioOutputDevice->SampleRate());          Decay1StepsLeft = (long) (Decay1Time * pEngine->pAudioOutputDevice->SampleRate());
330          Decay1Coeff     = (Decay1StepsLeft) ? exp(log(this->SustainLevel) / (double) Decay1StepsLeft) - 1.0          if (Decay1StepsLeft) {
331                                              : 0.0;              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    
339          // calculate decay2 stage parameters (exp. curve)          // calculate decay2 stage parameters (lin. curve)
340          if (!InfiniteSustain) {          if (!InfiniteSustain) {
341              if (Decay2Time < EG_MIN_RELEASE_TIME) Decay2Time = EG_MIN_RELEASE_TIME;              if (Decay2Time < CONFIG_EG_MIN_RELEASE_TIME) Decay2Time = CONFIG_EG_MIN_RELEASE_TIME;
342              long Decay2Steps = (long) (Decay2Time * pEngine->pAudioOutputDevice->SampleRate());              long Decay2Steps = (long) (Decay2Time * pEngine->pAudioOutputDevice->SampleRate());
343              Decay2Coeff      = (Decay2Steps) ? exp((log(EG_ENVELOPE_LIMIT) - log(this->SustainLevel)) / Decay2Steps + log(this->SustainLevel)) - this->SustainLevel              Decay2Coeff = (-1.03 / Decay2Steps) * invVolume;
                                             : 0.0;  
344          }          }
345    
346          // calcuate release stage parameters (exp. curve)          // calculate release stage parameters (lin+exp curve)
347          if (ReleaseTime < EG_MIN_RELEASE_TIME) ReleaseTime = EG_MIN_RELEASE_TIME;  // to avoid click sounds at the end of the sample playback          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          ReleaseStepsLeft = (long) (ReleaseTime * pEngine->pAudioOutputDevice->SampleRate());          ReleaseStepsLeft = (long) (ReleaseTime * pEngine->pAudioOutputDevice->SampleRate());
349          ReleaseCoeff     = exp((log(EG_ENVELOPE_LIMIT) - log(this->SustainLevel)) / ReleaseStepsLeft + log(this->SustainLevel)) - this->SustainLevel;          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    
356          dmsg(4,("PreAttack=%d, AttackLength=%d, AttackCoeff=%f, Decay1Coeff=%f, Decay2Coeff=%f, ReleaseLength=%d, ReleaseCoeff=%f\n",          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));                  PreAttack, AttackStepsLeft, AttackCoeff, Decay1Coeff, Decay2Coeff, ReleaseStepsLeft, ReleaseCoeff));

Legend:
Removed from v.237  
changed lines
  Added in v.688

  ViewVC Help
Powered by ViewVC