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

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

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

revision 237 by senkov, Sun Sep 12 01:59:40 2004 UTC revision 768 by persson, Fri Sep 2 20:11:55 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      EGADSR::EGADSR(gig::Engine* pEngine, Event::destination_t ModulationDestination) {      EGADSR::EGADSR() {
29          this->pEngine = pEngine;          enterEndStage();
         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
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 Samples       - 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 pTriggerEvent - event that caused triggering of the voice (only if  
      *                        the voices was triggered in the current audio  
      *                        fragment, NULL otherwise)  
      * @param SamplePos     - current playback position  
      * @param CurrentPitch  - current pitch value for playback  
      */  
     void EGADSR::Process(uint Samples, RTEList<Event>* pEvents, Event* pTriggerEvent, double SamplePos, double CurrentPitch) {  
         Event* pTransitionEvent;  
         if (pTriggerEvent) {  
             pEvents->set_current(pTriggerEvent);  
             pTransitionEvent = pEvents->next();  
         }  
         else {  
             pTransitionEvent = pEvents->first();  
         }  
38    
39          int iSample = TriggerDelay;      void EGADSR::update(event_t Event, double SamplePos, float CurrentPitch, uint SampleRate) {
40          while (iSample < Samples) {          switch (Stage) {
41              switch (Stage) {              case stage_attack:
42                  case stage_attack: {                  if (StepsLeft) {
43                      TriggerDelay = 0;                      PostponedEvent = Event;
44                      int to_process   = RTMath::Min(AttackStepsLeft, Samples - iSample);                  } else {
45                      int process_end  = iSample + to_process;                      if (Event == event_release)
46                      AttackStepsLeft -= to_process;                          enterReleasePart1Stage();
47                      while (iSample < process_end) {                      else if (Event == event_cancel_release)
48                          Level += AttackCoeff;                          enterSustainStage();
49                          pEngine->pSynthesisParameters[ModulationDestination][iSample++] *= Level;                      else if (PostponedEvent == event_release)
50                      }                          enterReleasePart1Stage();
51                      if (iSample == Samples) { // postpone last transition event for the next audio fragment                      else if (PostponedEvent == event_cancel_release)
52                          Event* pLastEvent = pEvents->last();                          enterSustainStage();
53                          if (pLastEvent) ReleasePostponed = (pLastEvent->Type == Event::type_release);                      else if (HoldAttack)
54                      }                          enterAttackHoldStage(SamplePos, CurrentPitch);
55                      if (!AttackStepsLeft) Stage = (ReleasePostponed) ? stage_release : (HoldAttack) ? stage_attack_hold : stage_decay1;                      else
56                      break;                          enterDecay1Part1Stage(SampleRate);
57                  }                  }
58                  case stage_attack_hold: {                  break;
59                      if (SamplePos >= LoopStart) {              case stage_attack_hold:
60                          Stage = stage_decay1;                  switch (Event) {
61                        case event_stage_end:
62                            enterDecay1Part1Stage(SampleRate);
63                            break;
64                        case event_release:
65                            enterReleasePart1Stage();
66                            break;
67                        case event_cancel_release:
68                            if (InfiniteSustain)
69                                enterSustainStage();
70                            else
71                                enterDecay1Part1Stage(SampleRate);
72                          break;                          break;
                     }  
                     int holdstepsleft = (int) (LoopStart - SamplePos / CurrentPitch); // FIXME: just an approximation, inaccuracy grows with higher audio fragment size, sufficient for usual fragment sizes though  
                     int to_process    = RTMath::Min(holdstepsleft, Samples - iSample);  
                     int process_end   = iSample + to_process;  
                     if (pTransitionEvent && pTransitionEvent->FragmentPos() <= process_end) {  
                         process_end      = pTransitionEvent->FragmentPos();  
                         Stage            = (pTransitionEvent->Type == Event::type_release) ? stage_release : (InfiniteSustain) ? stage_sustain : stage_decay2;  
                         pTransitionEvent = pEvents->next();  
                     }  
                     else if (to_process == holdstepsleft) Stage = stage_decay1;  
                     while (iSample < process_end) {  
                         pEngine->pSynthesisParameters[ModulationDestination][iSample++] *= Level;  
                     }  
                     break;  
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 (pTransitionEvent && pTransitionEvent->FragmentPos() <= process_end) {                      case event_stage_end:
78                          process_end      = pTransitionEvent->FragmentPos();                          enterDecay1Part2Stage(SampleRate);
79                          Stage            = (pTransitionEvent->Type == Event::type_release) ? stage_release : (InfiniteSustain) ? stage_sustain : stage_decay2;                          break;
80                          pTransitionEvent = pEvents->next();                      case event_release:
81                      }                          enterReleasePart1Stage();
82                      else {                          break;
83                          Decay1StepsLeft -= to_process;                      case event_cancel_release:
84                          if (!Decay1StepsLeft) Stage = (InfiniteSustain) ? stage_sustain : stage_decay2;                          if (InfiniteSustain)
85                      }                              enterSustainStage();
86                      while (iSample < process_end) {                          else
87                          Level += Level * Decay1Coeff;                              enterDecay2Stage(SampleRate);
88                          pEngine->pSynthesisParameters[ModulationDestination][iSample++] *= Level;                          break;
                     }  
                     break;  
89                  }                  }
90                  case stage_decay2: {                  break;
91                      int process_end;              case stage_decay1_part2:
92                      if (pTransitionEvent && pTransitionEvent->Type == Event::type_release && pTransitionEvent->FragmentPos() <= Samples) {                  switch (Event) {
93                          process_end      = pTransitionEvent->FragmentPos();                      case event_release:
94                          pTransitionEvent = pEvents->next();                          enterReleasePart1Stage();
95                          Stage            = stage_release; // switch to release stage soon                          break;
96                      }                      case event_stage_end: // fall through
97                      else process_end = Samples;                      case event_cancel_release:
98                      while (iSample < process_end) {                          if (InfiniteSustain)
99                          Level += Level * Decay2Coeff;                              enterSustainStage();
100                          pEngine->pSynthesisParameters[ModulationDestination][iSample++] *= Level;                          else
101                      }                              enterDecay2Stage(SampleRate);
102                      if (Level <= EG_ENVELOPE_LIMIT) Stage = stage_end;                          break;
                     break;  
103                  }                  }
104                  case stage_sustain: {                  break;
105                      int process_end;              case stage_decay2:
106                      if (pTransitionEvent && pTransitionEvent->Type == Event::type_release && pTransitionEvent->FragmentPos() <= Samples) {                  switch (Event) {
107                          process_end      = pTransitionEvent->FragmentPos();                      case event_stage_end:
108                          pTransitionEvent = pEvents->next();                          enterFadeOutStage();
109                          Stage            = stage_release; // switch to release stage soon                          break;
110                      }                      case event_release:
111                      else process_end = Samples;                          enterReleasePart1Stage();
112                      while (iSample < process_end) {                          break;
                        pEngine->pSynthesisParameters[ModulationDestination][iSample++] *= Level;  
                     }  
                     break;  
113                  }                  }
114                  case stage_release: {                  break;
115                      int process_end;              case stage_sustain:
116                      if (pTransitionEvent && pTransitionEvent->Type == Event::type_cancel_release && pTransitionEvent->FragmentPos() <= Samples) {                  switch (Event) {
117                          process_end      = pTransitionEvent->FragmentPos();                      case event_stage_end: {// just refresh time
118                          pTransitionEvent = pEvents->next();                          const int intMax = (unsigned int) -1 >> 1;
119                          Stage            = (InfiniteSustain) ? stage_sustain : stage_decay2; // switch back to sustain / decay2 stage soon                          StepsLeft = intMax; // we use the highest possible value
120                      }                          break;
                     else process_end = Samples;  
                     while (iSample < process_end) {  
                         Level += Level * ReleaseCoeff;  
                         pEngine->pSynthesisParameters[ModulationDestination][iSample++] *= Level;  
121                      }                      }
122                      if (Level <= EG_ENVELOPE_LIMIT) Stage = stage_end;                      case event_release:
123                      break;                          enterReleasePart1Stage();
124                            break;
125                  }                  }
126                  case stage_end: {                  break;
127                      while (iSample < Samples) {              case stage_release_part1:
128                          Level += Level * ReleaseCoeff;                  switch (Event) {
129                          pEngine->pSynthesisParameters[ModulationDestination][iSample++] *= Level;                      case event_stage_end:
130                      }                          enterReleasePart2Stage();
131                      break;                          break;
132                        case event_cancel_release:
133                            if (InfiniteSustain)
134                                enterSustainStage();
135                            else
136                                enterDecay2Stage(SampleRate);
137                            break;
138                    }
139                    break;
140                case stage_release_part2:
141                    switch (Event) {
142                        case event_stage_end:
143                            enterFadeOutStage();
144                            break;
145                        case event_cancel_release:
146                            if (InfiniteSustain)
147                                enterSustainStage();
148                            else
149                                enterDecay2Stage(SampleRate);
150                            break;
151                  }                  }
152              }                  break;
153                case stage_fadeout:
154                    switch (Event) {
155                        case event_stage_end:
156                            enterEndStage();
157                            break;
158                    }
159                    break;
160          }          }
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       *          if (SustainLevel) {
166       * @param PreAttack       - Preattack value for the envelope (0 - 1000 permille)              this->SustainLevel = SustainLevel / 1000.0;
167       * @param AttackTime      - Attack time for the envelope (0.000 - 60.000s)          } else {
168       * @param HoldAttack      - If true, Decay1 will be postponed until the sample reached the sample loop start.              // sustain level 0 means that voice dies after decay 1
169       * @param LoopStart       - Sample position where sample loop starts (if any)              this->SustainLevel = CONFIG_EG_BOTTOM;
170       * @param Decay1Time      - Decay1 time of the sample amplitude EG (0.000 - 60.000s).              InfiniteSustain    = false;
171       * @param Decay2Time      - Only if !InfiniteSustain: 2nd decay stage time of the sample amplitude EG (0.000 - 60.000s).              Decay2Time         = CONFIG_EG_MIN_RELEASE_TIME;
172       * @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.  
      */  
     void EGADSR::Trigger(uint PreAttack, double AttackTime, bool HoldAttack, long LoopStart, double Decay1Time, double Decay2Time, bool InfiniteSustain, uint SustainLevel, double ReleaseTime, uint Delay) {  
         this->TriggerDelay     = Delay;  
         this->Stage            = stage_attack;  
         this->SustainLevel     = (SustainLevel) ? (SustainLevel > EG_ENVELOPE_LIMIT) ? (float) SustainLevel / 1000.0 : EG_ENVELOPE_LIMIT : 1.0;  
173          this->InfiniteSustain  = InfiniteSustain;          this->InfiniteSustain  = InfiniteSustain;
174          this->HoldAttack       = HoldAttack;          this->HoldAttack       = HoldAttack;
175          this->LoopStart        = LoopStart;          this->LoopStart        = LoopStart;
         this->ReleasePostponed = false;  
176    
177          // calculate attack stage parameters (lin. curve)          this->Decay1Time = Decay1Time;
178          AttackStepsLeft = (long) (AttackTime * pEngine->pAudioOutputDevice->SampleRate());          this->Decay2Time = Decay2Time;
179          if (AttackStepsLeft) {  
180              Level       = (float) PreAttack / 1000.0;          invVolume = 1 / Volume;
181              AttackCoeff = (1.0 - Level) / AttackStepsLeft;          ExpOffset = (0.25 - 1 / 3.55) * invVolume;
182    
183            // calculate release stage parameters (lin+exp curve)
184            if (ReleaseTime < CONFIG_EG_MIN_RELEASE_TIME) ReleaseTime = CONFIG_EG_MIN_RELEASE_TIME;  // to avoid click sounds at the end of the sample playback
185            const float ReleaseStepsLeft = (long) (ReleaseTime * SampleRate);
186            ReleaseSlope  = 1.365 * (0 - 1) / ReleaseStepsLeft;
187            ReleaseCoeff  = ReleaseSlope * invVolume;
188            ReleaseSlope  *= 3.55;
189            ReleaseCoeff2 = exp(ReleaseSlope);
190            ReleaseCoeff3 = ExpOffset * (1 - ReleaseCoeff2);
191            ReleaseLevel2 = 0.25 * invVolume;
192    
193            enterAttackStage(PreAttack, AttackTime, SampleRate, 0.0, 1.0f);
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
200            // is about 65.5% of the value specified in the gig file.
201            StepsLeft = (int) (0.655f * AttackTime * SampleRate);
202            if (StepsLeft) {
203                Level = (float) PreAttack / 1000.0;
204                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                Level = 1.0;
207                if (HoldAttack) enterAttackHoldStage(SamplePos, CurrentPitch);
208                else            enterDecay1Part1Stage(SampleRate);
209          }          }
210          else {          PostponedEvent = (event_t) -1; // init with anything except release or cancel_release
211              Level       = 1.0;      }
212              AttackCoeff = 0.0;  
213        void EGADSR::enterAttackHoldStage(const double SamplePos, const float CurrentPitch) {
214            Stage     = stage_attack_hold;
215            Segment   = segment_lin;
216            Coeff     = 0.0f; // don't rise anymore
217            StepsLeft = (int) (LoopStart - SamplePos / CurrentPitch); // FIXME: just an approximation, inaccuracy grows with higher audio fragment size, sufficient for usual fragment sizes though
218        }
219    
220        void EGADSR::enterDecay1Part1Stage(const uint SampleRate) {
221            // The decay1 and release stage both consist of two parts,
222            // first a linear curve, f, followed by an exponential curve,
223            // g:
224            //
225            // f(x + d) = f(x) + Coeff
226            // g(x + d) = Coeff2 * g(x) + Coeff3
227            //
228            // (where d is 1/SampleRate). The transition from f to g is
229            // done when f(x) has reached Level2 = 25% of full volume.
230            StepsLeft = (int) (Decay1Time * SampleRate);
231            if (StepsLeft && SustainLevel < 1.0) {
232                Stage        = stage_decay1_part1;
233                Segment      = segment_lin;
234                Decay1Slope  = 1.365 * (SustainLevel - 1.0) / StepsLeft;
235                Coeff        = Decay1Slope * invVolume;
236                Decay1Level2 = 0.25 * invVolume;
237                if (Level < Decay1Level2) enterDecay1Part2Stage(SampleRate);
238                else StepsLeft = int((RTMath::Max(Decay1Level2, SustainLevel) - Level) / Coeff);
239            } else {
240                if (InfiniteSustain) enterSustainStage();
241                else                 enterDecay2Stage(SampleRate);
242          }          }
243        }
244    
245          // calculate decay1 stage parameters (exp. curve)      void EGADSR::enterDecay1Part2Stage(const uint SampleRate) {
246          Decay1StepsLeft = (long) (Decay1Time * pEngine->pAudioOutputDevice->SampleRate());          if (SustainLevel < Decay1Level2) {
247          Decay1Coeff     = (Decay1StepsLeft) ? exp(log(this->SustainLevel) / (double) Decay1StepsLeft) - 1.0              Stage   = stage_decay1_part2;
248                                              : 0.0;              Segment = segment_exp;
249                Decay1Slope *= 3.55;
250          // calculate decay2 stage parameters (exp. curve)              Coeff  = exp(Decay1Slope);
251          if (!InfiniteSustain) {              Offset = ExpOffset * (1 - Coeff);
252              if (Decay2Time < EG_MIN_RELEASE_TIME) Decay2Time = EG_MIN_RELEASE_TIME;              StepsLeft = int(log((SustainLevel - ExpOffset) / (Level - ExpOffset)) / Decay1Slope);
253              long Decay2Steps = (long) (Decay2Time * pEngine->pAudioOutputDevice->SampleRate());          } else {
254              Decay2Coeff      = (Decay2Steps) ? exp((log(EG_ENVELOPE_LIMIT) - log(this->SustainLevel)) / Decay2Steps + log(this->SustainLevel)) - this->SustainLevel              if (InfiniteSustain) enterSustainStage();
255                                              : 0.0;              else                 enterDecay2Stage(SampleRate);
256          }          }
257        }
258    
259        void EGADSR::enterDecay2Stage(const uint SampleRate) {
260            Stage      = stage_decay2;
261            Segment    = segment_lin;
262            Decay2Time = RTMath::Max(Decay2Time, CONFIG_EG_MIN_RELEASE_TIME);
263            StepsLeft  = (int) (Decay2Time * SampleRate);
264            Coeff      = (-1.03 / StepsLeft) * invVolume;
265            //FIXME: do we really have to calculate 'StepsLeft' two times?
266            StepsLeft  = int((CONFIG_EG_BOTTOM - Level) / Coeff);
267            if (StepsLeft == 0) enterEndStage();
268        }
269    
270          // calcuate release stage parameters (exp. curve)      void EGADSR::enterSustainStage() {
271          if (ReleaseTime < EG_MIN_RELEASE_TIME) ReleaseTime = EG_MIN_RELEASE_TIME;  // to avoid click sounds at the end of the sample playback          Stage   = stage_sustain;
272          ReleaseStepsLeft = (long) (ReleaseTime * pEngine->pAudioOutputDevice->SampleRate());          Segment = segment_lin;
273          ReleaseCoeff     = exp((log(EG_ENVELOPE_LIMIT) - log(this->SustainLevel)) / ReleaseStepsLeft + log(this->SustainLevel)) - this->SustainLevel;          Coeff   = 0.0f; // don't change the envelope level in this stage
274            const int intMax = (unsigned int) -1 >> 1;
275            StepsLeft = intMax; // we use the highest value possible (we refresh StepsLeft in update() in case)
276        }
277    
278        void EGADSR::enterReleasePart1Stage() {
279            Stage     = stage_release_part1;
280            Segment   = segment_lin;
281            StepsLeft = int((ReleaseLevel2 - Level) / ReleaseCoeff);
282            Coeff     = ReleaseCoeff;
283        }
284    
285        void EGADSR::enterReleasePart2Stage() {
286            Stage     = stage_release_part2;
287            Segment   = segment_exp;
288            StepsLeft = int(log((CONFIG_EG_BOTTOM - ExpOffset) / (Level - ExpOffset)) / ReleaseSlope);
289            Coeff     = ReleaseCoeff2;
290            Offset    = ReleaseCoeff3;
291        }
292    
293        void EGADSR::enterFadeOutStage() {
294            Stage     = stage_fadeout;
295            Segment   = segment_lin;
296            StepsLeft = int(Level / (-FadeOutCoeff));
297            Coeff     = FadeOutCoeff;
298            if (StepsLeft == 0) enterEndStage();
299        }
300    
301          dmsg(4,("PreAttack=%d, AttackLength=%d, AttackCoeff=%f, Decay1Coeff=%f, Decay2Coeff=%f, ReleaseLength=%d, ReleaseCoeff=%f\n",      void EGADSR::enterEndStage() {
302                  PreAttack, AttackStepsLeft, AttackCoeff, Decay1Coeff, Decay2Coeff, ReleaseStepsLeft, ReleaseCoeff));          Stage   = stage_end;
303            Segment = segment_end;
304      }      }
305    
306  }} // namespace LinuxSampler::gig  }} // namespace LinuxSampler::gig

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

  ViewVC Help
Powered by ViewVC