/[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 688 by schoenebeck, Thu Jul 14 12:25:20 2005 UTC revision 738 by schoenebeck, Tue Aug 16 17:14:25 2005 UTC
# Line 25  Line 25 
25    
26  namespace LinuxSampler { namespace gig {  namespace LinuxSampler { namespace gig {
27    
28      void EGADSR::CalculateFadeOutCoeff(float FadeOutTime, float SampleRate) {      EGADSR::EGADSR() {
29          const float killSteps = FadeOutTime * SampleRate;          enterEndStage();
         FadeOutCoeff = -1.0f / killSteps;  
     }  
   
     EGADSR::EGADSR(gig::Engine* pEngine, Event::destination_t ModulationDestination) {  
         this->pEngine = pEngine;  
         this->ModulationDestination = ModulationDestination;  
         Stage = stage_end;  
30          Level = 0.0;          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          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      /**      void EGADSR::CalculateFadeOutCoeff(float FadeOutTime, float SampleRate) {
35       * Will be called by the voice for every audio fragment to let the EG          const float killSteps = FadeOutTime * SampleRate;
36       * queue it's modulation changes for the current audio fragment.          FadeOutCoeff = -1.0f / killSteps;
37       *      }
      * @param TotalSamples  - total number of sample points to be rendered in this  
      *                        audio fragment cycle by the audio engine  
      * @param pEvents       - event list with "release" and "cancel release" events  
      * @param itTriggerEvent - event that caused triggering of the voice (only if  
      *                        the voice was triggered in the current audio  
      *                        fragment, NULL otherwise)  
      * @param SamplePos     - current playback position  
      * @param CurrentPitch  - current pitch value for playback  
      * @param itKillEvent   - (optional) event which caused this voice to be killed  
      */  
     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;  
   
         #if CONFIG_DEVMODE  
         if (TriggerDelay > TotalSamples) { // just a sanity check for debugging  
             dmsg(1,("EGADSR: ERROR, TriggerDelay > Totalsamples\n"));  
             int* i = NULL;  
             (*i)++; // force a segfault  
         }  
         #endif // CONFIG_DEVMODE  
   
         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;  
38    
39              switch (Stage) {      void EGADSR::update(event_t Event, double SamplePos, float CurrentPitch, uint SampleRate) {
40                  case stage_attack: {          switch (Stage) {
41                      TriggerDelay = 0;              case stage_attack:
42                      int to_process   = RTMath::Min(AttackStepsLeft, Samples - iSample);                  if (StepsLeft) {
43                      int process_end  = iSample + to_process;                      PostponedEvent = Event;
44                      AttackStepsLeft -= to_process;                  } else {
45                      while (iSample < process_end) {                      if (Event == event_release)
46                          Level += AttackCoeff;                          enterReleasePart1Stage();
47                          pEngine->pSynthesisParameters[ModulationDestination][iSample++] *= Level;                      else if (Event == event_cancel_release)
48                      }                          enterSustainStage();
49                      if (iSample == TotalSamples && itTransitionEvent) { // postpone last transition event for the next audio fragment                      else if (PostponedEvent == event_release)
50                          RTList<Event>::Iterator itLastEvent = pEvents->last();                          enterReleasePart1Stage();
51                          if (itLastEvent) ReleasePostponed = (itLastEvent->Type == Event::type_release);                      else if (PostponedEvent == event_cancel_release)
52                      }                          enterSustainStage();
53                      if (!AttackStepsLeft) Stage = (ReleasePostponed) ? stage_release_init : (HoldAttack) ? stage_attack_hold : stage_decay1_init;                      else if (HoldAttack)
54                      break;                          enterAttackHoldStage(SamplePos, CurrentPitch);
55                        else
56                            enterDecay1Part1Stage(SampleRate);
57                  }                  }
58                  case stage_attack_hold: {                  break;
59                      if (SamplePos >= LoopStart) {              case stage_attack_hold:
60                          Stage = stage_decay1_init;                  switch (Event) {
61                        case event_stage_end:
62                            enterDecay1Part1Stage(SampleRate);
63                          break;                          break;
64                      }                      case event_release:
65                      int holdstepsleft = (int) (LoopStart - SamplePos / CurrentPitch); // FIXME: just an approximation, inaccuracy grows with higher audio fragment size, sufficient for usual fragment sizes though                          enterReleasePart1Stage();
66                      int to_process    = RTMath::Min(holdstepsleft, Samples - iSample);                          break;
67                      int process_end   = iSample + to_process;                      case event_cancel_release:
68                      if (itTransitionEvent && itTransitionEvent->FragmentPos() <= process_end) {                          if (InfiniteSustain)
69                          process_end       = itTransitionEvent->FragmentPos();                              enterSustainStage();
70                          Stage             = (itTransitionEvent->Type == Event::type_release) ? stage_release_init : (InfiniteSustain) ? stage_sustain : stage_decay2_init;                          else
71                          ++itTransitionEvent;                              enterDecay1Part1Stage(SampleRate);
                     }  
                     else if (to_process == holdstepsleft) Stage = stage_decay1_init;  
                     while (iSample < process_end) {  
                         pEngine->pSynthesisParameters[ModulationDestination][iSample++] *= Level;  
                     }  
                     break;  
                 }  
                 case stage_decay1_init: {  
                     if (Decay1StepsLeft) {  
                         if (SustainLevel < 1.0) {  
                             Decay1StepsLeft = int((RTMath::Max(Decay1Level2, SustainLevel) - Level) / Decay1Coeff);  
                         } else {  
                             Stage = (InfiniteSustain) ? stage_sustain : stage_decay2_init;  
                             break;  
                         }  
                     } else {  
                         Level = SustainLevel;  
                         Stage = (InfiniteSustain) ? stage_sustain : stage_decay2_init;  
72                          break;                          break;
                     }  
                     Stage = stage_decay1;  
73                  }                  }
74                  case stage_decay1: {                  break;
75                      int to_process   = RTMath::Min(Samples - iSample, Decay1StepsLeft);              case stage_decay1_part1:
76                      int process_end  = iSample + to_process;                  switch (Event) {
77                      if (itTransitionEvent && itTransitionEvent->FragmentPos() <= process_end) {                      case stage_end:
78                          process_end       = itTransitionEvent->FragmentPos();                          enterDecay1Part2Stage();
79                          Stage             = (itTransitionEvent->Type == Event::type_release) ? stage_release_init : (InfiniteSustain) ? stage_sustain : stage_decay2_init;                          break;
80                          ++itTransitionEvent;                      case event_release:
81                      }                          enterReleasePart1Stage();
82                      else {                          break;
83                          Decay1StepsLeft -= to_process;                      case event_cancel_release:
84                          if (!Decay1StepsLeft) Stage = stage_decay1_part2_init;                          if (InfiniteSustain)
85                      }                              enterSustainStage();
86                      while (iSample < process_end) {                          else
87                          Level += Decay1Coeff;                              enterDecay2Stage(SampleRate);
88                          pEngine->pSynthesisParameters[ModulationDestination][iSample++] *= Level;                          break;
                     }  
                     break;  
89                  }                  }
90                  case stage_decay1_part2_init:                  break;
91                      Decay1StepsLeft = int(log((SustainLevel - ExpOffset) / (Level - ExpOffset)) / Decay1Slope);              case stage_decay1_part2:
92                      Stage = stage_decay1_part2;                  switch (Event) {
93                  case stage_decay1_part2: {                      case event_release:
94                      int to_process   = RTMath::Min(Samples - iSample, Decay1StepsLeft);                          enterReleasePart1Stage();
95                      int process_end  = iSample + to_process;                          break;
96                      if (itTransitionEvent && itTransitionEvent->FragmentPos() <= process_end) {                      case event_stage_end: // fall through
97                          process_end       = itTransitionEvent->FragmentPos();                      case event_cancel_release:
98                          Stage             = (itTransitionEvent->Type == Event::type_release) ? stage_release_init : (InfiniteSustain) ? stage_sustain : stage_decay2_init;                          if (InfiniteSustain)
99                          ++itTransitionEvent;                              enterSustainStage();
100                      }                          else
101                      else {                              enterDecay2Stage(SampleRate);
102                          Decay1StepsLeft -= to_process;                          break;
                         if (!Decay1StepsLeft) Stage = (InfiniteSustain) ? stage_sustain : stage_decay2_init;  
                     }  
                     while (iSample < process_end) {  
                         Level = Level * Decay1Coeff2 + Decay1Coeff3;  
                         pEngine->pSynthesisParameters[ModulationDestination][iSample++] *= Level;  
                     }  
                     break;  
103                  }                  }
104                  case stage_decay2_init:                  break;
105                      Decay2StepsLeft = int((CONFIG_EG_BOTTOM - Level) / Decay2Coeff);              case stage_decay2:
106                      Stage = stage_decay2;                  switch (Event) {
107                  case stage_decay2: {                      case event_stage_end:
108                      int to_process   = RTMath::Min(Samples - iSample, Decay2StepsLeft);                          enterFadeOutStage();
109                      int process_end  = iSample + to_process;                          break;
110                      if (itTransitionEvent && itTransitionEvent->Type == Event::type_release && itTransitionEvent->FragmentPos() <= process_end) {                      case event_release:
111                          process_end       = itTransitionEvent->FragmentPos();                          enterReleasePart1Stage();
112                          ++itTransitionEvent;                          break;
                         Stage             = stage_release_init; // switch to release stage soon  
                     }  
                     else {  
                         Decay2StepsLeft -= to_process;  
                         if (!Decay2StepsLeft) Stage = stage_fadeout;  
                     }  
                     while (iSample < process_end) {  
                         Level += Decay2Coeff;  
                         pEngine->pSynthesisParameters[ModulationDestination][iSample++] *= Level;  
                     }  
                     break;  
113                  }                  }
114                  case stage_sustain: {                  break;
115                      int process_end;              case stage_sustain:
116                      if (itTransitionEvent && itTransitionEvent->Type == Event::type_release && itTransitionEvent->FragmentPos() <= Samples) {                  switch (Event) {
117                          process_end       = itTransitionEvent->FragmentPos();                      case event_stage_end: {// just refresh time
118                          ++itTransitionEvent;                          const int intMax = (unsigned int) -1 >> 1;
119                          Stage             = stage_release_init; // switch to release stage soon                          StepsLeft = intMax; // we use the highest possible value
120                      }                          break;
                     else process_end = Samples;  
                     while (iSample < process_end) {  
                        pEngine->pSynthesisParameters[ModulationDestination][iSample++] *= Level;  
121                      }                      }
122                      break;                      case event_release:
123                            enterReleasePart1Stage();
124                            break;
125                  }                  }
126                  case stage_release_init:                  break;
127                      ReleaseStepsLeft = int((ReleaseLevel2 - Level) / ReleaseCoeff);              case stage_release_part1:
128                      Stage = stage_release;                  switch (Event) {
129                  case stage_release: {                      case event_stage_end:
130                      int to_process   = RTMath::Min(Samples - iSample, ReleaseStepsLeft);                          enterReleasePart2Stage();
131                      int process_end  = iSample + to_process;                          break;
132                      if (itTransitionEvent && itTransitionEvent->Type == Event::type_cancel_release && itTransitionEvent->FragmentPos() <= process_end) {                      case event_cancel_release:
133                          process_end       = itTransitionEvent->FragmentPos();                          if (InfiniteSustain)
134                          ++itTransitionEvent;                              enterSustainStage();
135                          Stage             = (InfiniteSustain) ? stage_sustain : stage_decay2_init; // switch back to sustain / decay2 stage soon                          else
136                      }                              enterDecay2Stage(SampleRate);
137                      else {                          break;
                         ReleaseStepsLeft -= to_process;  
                         if (!ReleaseStepsLeft) Stage = stage_release_part2_init;  
                     }  
                     while (iSample < process_end) {  
                         Level += ReleaseCoeff;  
                         pEngine->pSynthesisParameters[ModulationDestination][iSample++] *= Level;  
                     }  
                     break;  
138                  }                  }
139                  case stage_release_part2_init:                  break;
140                      ReleaseStepsLeft = int(log((CONFIG_EG_BOTTOM - ExpOffset) / (Level - ExpOffset)) / ReleaseSlope);              case stage_release_part2:
141                      Stage = stage_release_part2;                  switch (Event) {
142                  case stage_release_part2: {                      case event_stage_end:
143                      int to_process   = RTMath::Min(Samples - iSample, ReleaseStepsLeft);                          enterFadeOutStage();
144                      int process_end  = iSample + to_process;                          break;
145                      if (itTransitionEvent && itTransitionEvent->Type == Event::type_cancel_release && itTransitionEvent->FragmentPos() <= process_end) {                      case event_cancel_release:
146                          process_end       = itTransitionEvent->FragmentPos();                          if (InfiniteSustain)
147                          ++itTransitionEvent;                              enterSustainStage();
148                          Stage             = (InfiniteSustain) ? stage_sustain : stage_decay2_init; // switch back to sustain / decay2 stage soon                          else
149                      }                              enterDecay2Stage(SampleRate);
150                      else {                          break;
                         ReleaseStepsLeft -= to_process;  
                         if (!ReleaseStepsLeft) Stage = stage_fadeout;  
                     }  
                     while (iSample < process_end) {  
                         Level = Level * ReleaseCoeff2 + ReleaseCoeff3;  
                         pEngine->pSynthesisParameters[ModulationDestination][iSample++] *= Level;  
                     }  
                     break;  
151                  }                  }
152                  case stage_fadeout: {                  break;
153                      int to_process   = RTMath::Min(int(Level / (-FadeOutCoeff)), TotalSamples - iSample);              case stage_fadeout:
154                      int process_end  = iSample + to_process;                  switch (Event) {
155                      while (iSample < process_end) {                      case event_stage_end:
156                          Level += FadeOutCoeff;                          enterEndStage();
157                          pEngine->pSynthesisParameters[ModulationDestination][iSample++] *= Level;                          break;
                     }  
                     Stage = stage_end;  
                     if (Level > -FadeOutCoeff) dmsg(2,("EGADSR: Warning, final fade out level too high, may result in click sound!\n"));  
                 } //Fall through here instead of breaking otherwise we can get back into stage_fadeout and loop forever!  
                 case stage_end: {  
                     while (iSample < TotalSamples) {  
                         pEngine->pSynthesisParameters[ModulationDestination][iSample++] = 0.0f;  
                     }  
                     break;  
158                  }                  }
159              }                  break;
         }  
   
         #if CONFIG_DEVMODE  
         if (itKillEvent && Stage != stage_end) { // just a sanity check for debugging  
             dmsg(1,("EGADSR: ERROR, voice killing not completed !!!\n"));  
             dmsg(1,("EGADSR: Stage=%d,iSample=%d,Samples=%d, TotalSamples=%d, MaxFadoutPos=%d\n",Stage,iSample,Samples,TotalSamples,pEngine->MaxFadeOutPos));  
160          }          }
         #endif // CONFIG_DEVMODE  
161      }      }
162    
163      /**      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       * Will be called by the voice when the key / voice was triggered.  
165       *          enterAttackStage(PreAttack, AttackTime, SampleRate, 0.0, 1.0f);
166       * @param PreAttack       - Preattack value for the envelope (0 - 1000 permille)  
      * @param AttackTime      - Attack time for the envelope (0.000 - 60.000s)  
      * @param HoldAttack      - If true, Decay1 will be postponed until the sample reached the sample loop start.  
      * @param LoopStart       - Sample position where sample loop starts (if any)  
      * @param Decay1Time      - Decay1 time of the sample amplitude EG (0.000 - 60.000s).  
      * @param Decay2Time      - Only if !InfiniteSustain: 2nd decay stage time of the sample amplitude EG (0.000 - 60.000s).  
      * @param InfiniteSustain - If true, instead of going into Decay2 phase, Decay1 level will be hold until note will be released.  
      * @param SustainLevel    - Sustain level of the sample amplitude EG (0 - 1000 permille).  
      * @param ReleaseTIme     - Release time for the envelope (0.000 - 60.000s)  
      * @param Delay           - Number of sample points triggering should be delayed.  
      * @param Volume          - Volume the sample will be played at (0.0 - 1.0). Used when calculating the exponential curve parameters.  
      */  
     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) {  
         this->TriggerDelay     = Delay;  
         this->Stage            = stage_attack;  
167          if (SustainLevel) {          if (SustainLevel) {
168              this->SustainLevel = SustainLevel / 1000.0;              this->SustainLevel = SustainLevel / 1000.0;
169          } else {          } else {
# Line 296  namespace LinuxSampler { namespace gig { Line 175  namespace LinuxSampler { namespace gig {
175          this->InfiniteSustain  = InfiniteSustain;          this->InfiniteSustain  = InfiniteSustain;
176          this->HoldAttack       = HoldAttack;          this->HoldAttack       = HoldAttack;
177          this->LoopStart        = LoopStart;          this->LoopStart        = LoopStart;
         this->ReleasePostponed = false;  
178    
179          // calculate attack stage parameters (lin. curve)          this->Decay1Time = Decay1Time;
180            this->Decay2Time = Decay2Time;
181    
182            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          // Measurements of GSt output shows that the real attack time          // Measurements of GSt output shows that the real attack time
200          // is about 65.5% of the value specified in the gig file.          // is about 65.5% of the value specified in the gig file.
201          AttackStepsLeft = (long) (0.655 * AttackTime * pEngine->pAudioOutputDevice->SampleRate());          StepsLeft = (int) (0.655f * AttackTime * SampleRate);
202          if (AttackStepsLeft) {          if (StepsLeft) {
203              Level       = (float) PreAttack / 1000.0;              Level = (float) PreAttack / 1000.0;
204              AttackCoeff = 0.896 * (1.0 - Level) / AttackStepsLeft; // max level is a bit lower if attack != 0              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          else {              if (HoldAttack) enterAttackHoldStage(SamplePos, CurrentPitch);
207              Level       = 1.0;              else            enterDecay1Part1Stage(SampleRate);
             AttackCoeff = 0.0;  
208          }          }
209            PostponedEvent = (event_t) -1; // init with anything except release or cancel_release
210        }
211    
212          const float invVolume = 1 / Volume;      void EGADSR::enterAttackHoldStage(const double SamplePos, const float CurrentPitch) {
213          ExpOffset = (0.25 - 1 / 3.55) * invVolume;          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    
219        void EGADSR::enterDecay1Part1Stage(const uint SampleRate) {
220          // The decay1 and release stage both consist of two parts,          // The decay1 and release stage both consist of two parts,
221          // first a linear curve, f, followed by an exponential curve,          // first a linear curve, f, followed by an exponential curve,
222          // g:          // g:
# Line 324  namespace LinuxSampler { namespace gig { Line 226  namespace LinuxSampler { namespace gig {
226          //          //
227          // (where d is 1/SampleRate). The transition from f to g is          // (where d is 1/SampleRate). The transition from f to g is
228          // done when f(x) has reached Level2 = 25% of full volume.          // done when f(x) has reached Level2 = 25% of full volume.
229            StepsLeft = (int) (Decay1Time * SampleRate);
230          // calculate decay1 stage parameters (lin+exp curve)          if (StepsLeft && SustainLevel < 1.0) {
231          Decay1StepsLeft = (long) (Decay1Time * pEngine->pAudioOutputDevice->SampleRate());              Stage        = stage_decay1_part1;
232          if (Decay1StepsLeft) {              Segment      = segment_lin;
233              Decay1Slope  = 1.365 * (this->SustainLevel - 1.0) / Decay1StepsLeft;              Decay1Slope  = 1.365 * (SustainLevel - 1.0) / StepsLeft;
234              Decay1Coeff  = Decay1Slope * invVolume;              Coeff        = Decay1Slope * invVolume;
             Decay1Slope  *= 3.55;  
             Decay1Coeff2 = exp(Decay1Slope);  
             Decay1Coeff3 = ExpOffset * (1 - Decay1Coeff2);  
235              Decay1Level2 = 0.25 * invVolume;              Decay1Level2 = 0.25 * invVolume;
236                StepsLeft    = int((RTMath::Max(Decay1Level2, SustainLevel) - Level) / Coeff);
237            } else {
238                Level = SustainLevel;
239                if (InfiniteSustain) enterSustainStage();
240                else                 enterDecay2Stage(SampleRate);
241          }          }
242        }
243    
244          // calculate decay2 stage parameters (lin. curve)      void EGADSR::enterDecay1Part2Stage() {
245          if (!InfiniteSustain) {          Stage   = stage_decay1_part2;
246              if (Decay2Time < CONFIG_EG_MIN_RELEASE_TIME) Decay2Time = CONFIG_EG_MIN_RELEASE_TIME;          Segment = segment_exp;
247              long Decay2Steps = (long) (Decay2Time * pEngine->pAudioOutputDevice->SampleRate());          Decay1Slope *= 3.55;
248              Decay2Coeff = (-1.03 / Decay2Steps) * invVolume;          Coeff  = exp(Decay1Slope);
249          }          Offset = ExpOffset * (1 - Coeff);
250            Level  = Decay1Level2;
251            StepsLeft = int(log((SustainLevel - ExpOffset) / (Level - ExpOffset)) / Decay1Slope);
252        }
253    
254          // calculate release stage parameters (lin+exp curve)      void EGADSR::enterDecay2Stage(const uint SampleRate) {
255          if (ReleaseTime < CONFIG_EG_MIN_RELEASE_TIME) ReleaseTime = CONFIG_EG_MIN_RELEASE_TIME;  // to avoid click sounds at the end of the sample playback          Stage      = stage_decay2;
256          ReleaseStepsLeft = (long) (ReleaseTime * pEngine->pAudioOutputDevice->SampleRate());          Segment    = segment_lin;
257          ReleaseSlope  = 1.365 * (0 - 1) / ReleaseStepsLeft;          Decay2Time = RTMath::Max(Decay2Time, CONFIG_EG_MIN_RELEASE_TIME);
258          ReleaseCoeff  = ReleaseSlope * invVolume;          StepsLeft  = (int) (Decay2Time * SampleRate);
259          ReleaseSlope  *= 3.55;          Coeff      = (-1.03 / StepsLeft) * invVolume;
260          ReleaseCoeff2 = exp(ReleaseSlope);          //FIXME: do we really have to calculate 'StepsLeft' two times?
261          ReleaseCoeff3 = ExpOffset * (1 - ReleaseCoeff2);          StepsLeft  = int((CONFIG_EG_BOTTOM - Level) / Coeff);
262          ReleaseLevel2 = 0.25 * invVolume;      }
263    
264        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        }
271    
272        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          dmsg(4,("PreAttack=%d, AttackLength=%d, AttackCoeff=%f, Decay1Coeff=%f, Decay2Coeff=%f, ReleaseLength=%d, ReleaseCoeff=%f\n",      void EGADSR::enterEndStage() {
295                  PreAttack, AttackStepsLeft, AttackCoeff, Decay1Coeff, Decay2Coeff, ReleaseStepsLeft, ReleaseCoeff));          Stage   = stage_end;
296            Segment = segment_end;
297      }      }
298    
299  }} // namespace LinuxSampler::gig  }} // namespace LinuxSampler::gig

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

  ViewVC Help
Powered by ViewVC