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

Legend:
Removed from v.239  
changed lines
  Added in v.614

  ViewVC Help
Powered by ViewVC