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

Legend:
Removed from v.285  
changed lines
  Added in v.3331

  ViewVC Help
Powered by ViewVC