/[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 738 by schoenebeck, Tue Aug 16 17:14:25 2005 UTC revision 1909 by persson, Wed Jun 3 17:21:42 2009 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                              *   *   Copyright (C) 2005 - 2009 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 23  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      EGADSR::EGADSR() {      EGADSR::EGADSR() {
# Line 32  namespace LinuxSampler { namespace gig { Line 34  namespace LinuxSampler { namespace gig {
34      }      }
35    
36      void EGADSR::CalculateFadeOutCoeff(float FadeOutTime, float SampleRate) {      void EGADSR::CalculateFadeOutCoeff(float FadeOutTime, float SampleRate) {
37          const float killSteps = FadeOutTime * SampleRate;          const float killSteps = FadeOutTime * SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;
38          FadeOutCoeff = -1.0f / killSteps;          FadeOutCoeff = -1.0f / killSteps;
39      }      }
40    
41      void EGADSR::update(event_t Event, double SamplePos, float CurrentPitch, uint SampleRate) {      void EGADSR::update(event_t Event, uint SampleRate) {
42            if (Event == event_hold_end) HoldAttack = false;
43    
44          switch (Stage) {          switch (Stage) {
45              case stage_attack:              case stage_attack:
46                  if (StepsLeft) {                  switch (Event) {
47                      PostponedEvent = Event;                      case event_release:
                 } else {  
                     if (Event == event_release)  
                         enterReleasePart1Stage();  
                     else if (Event == event_cancel_release)  
                         enterSustainStage();  
                     else if (PostponedEvent == event_release)  
48                          enterReleasePart1Stage();                          enterReleasePart1Stage();
49                      else if (PostponedEvent == event_cancel_release)                          break;
50                          enterSustainStage();                      case event_stage_end:
51                      else if (HoldAttack)                          if (HoldAttack)
52                          enterAttackHoldStage(SamplePos, CurrentPitch);                              enterAttackHoldStage();
53                      else                          else
54                          enterDecay1Part1Stage(SampleRate);                              enterDecay1Part1Stage(SampleRate);
55                            break;
56                  }                  }
57                  break;                  break;
58              case stage_attack_hold:              case stage_attack_hold:
59                  switch (Event) {                  switch (Event) {
60                      case event_stage_end:                      case event_stage_end: {// just refresh time
61                            const int intMax = (unsigned int) -1 >> 1;
62                            StepsLeft = intMax; // we use the highest possible value
63                            break;
64                        }
65                        case event_hold_end:
66                          enterDecay1Part1Stage(SampleRate);                          enterDecay1Part1Stage(SampleRate);
67                          break;                          break;
68                      case event_release:                      case event_release:
69                          enterReleasePart1Stage();                          enterReleasePart1Stage();
70                          break;                          break;
                     case event_cancel_release:  
                         if (InfiniteSustain)  
                             enterSustainStage();  
                         else  
                             enterDecay1Part1Stage(SampleRate);  
                         break;  
71                  }                  }
72                  break;                  break;
73              case stage_decay1_part1:              case stage_decay1_part1:
74                  switch (Event) {                  switch (Event) {
75                      case stage_end:                      case event_stage_end:
76                          enterDecay1Part2Stage();                          enterDecay1Part2Stage(SampleRate);
77                          break;                          break;
78                      case event_release:                      case event_release:
79                          enterReleasePart1Stage();                          enterReleasePart1Stage();
80                          break;                          break;
                     case event_cancel_release:  
                         if (InfiniteSustain)  
                             enterSustainStage();  
                         else  
                             enterDecay2Stage(SampleRate);  
                         break;  
81                  }                  }
82                  break;                  break;
83              case stage_decay1_part2:              case stage_decay1_part2:
# Line 93  namespace LinuxSampler { namespace gig { Line 85  namespace LinuxSampler { namespace gig {
85                      case event_release:                      case event_release:
86                          enterReleasePart1Stage();                          enterReleasePart1Stage();
87                          break;                          break;
88                      case event_stage_end: // fall through                      case event_stage_end:
89                      case event_cancel_release:                          if (Level < CONFIG_EG_BOTTOM)
90                          if (InfiniteSustain)                              enterEndStage();
91                            else if (InfiniteSustain)
92                              enterSustainStage();                              enterSustainStage();
93                          else                          else
94                              enterDecay2Stage(SampleRate);                              enterDecay2Stage(SampleRate);
# Line 110  namespace LinuxSampler { namespace gig { Line 103  namespace LinuxSampler { namespace gig {
103                      case event_release:                      case event_release:
104                          enterReleasePart1Stage();                          enterReleasePart1Stage();
105                          break;                          break;
106                        case event_hold_end:
107                            enterDecay1Part1Stage(SampleRate);
108                            break;
109                  }                  }
110                  break;                  break;
111              case stage_sustain:              case stage_sustain:
# Line 122  namespace LinuxSampler { namespace gig { Line 118  namespace LinuxSampler { namespace gig {
118                      case event_release:                      case event_release:
119                          enterReleasePart1Stage();                          enterReleasePart1Stage();
120                          break;                          break;
121                        case event_hold_end:
122                            enterDecay1Part1Stage(SampleRate);
123                            break;
124                  }                  }
125                  break;                  break;
126              case stage_release_part1:              case stage_release_part1:
# Line 160  namespace LinuxSampler { namespace gig { Line 159  namespace LinuxSampler { namespace gig {
159          }          }
160      }      }
161    
162      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) {      void EGADSR::trigger(uint PreAttack, float AttackTime, bool HoldAttack, float Decay1Time, double Decay2Time, bool InfiniteSustain, uint SustainLevel, float ReleaseTime, float Volume, uint SampleRate) {
163            this->SustainLevel     = SustainLevel / 1000.0;
         enterAttackStage(PreAttack, AttackTime, SampleRate, 0.0, 1.0f);  
   
         if (SustainLevel) {  
             this->SustainLevel = SustainLevel / 1000.0;  
         } else {  
             // sustain level 0 means that voice dies after decay 1  
             this->SustainLevel = CONFIG_EG_BOTTOM;  
             InfiniteSustain    = false;  
             Decay2Time         = CONFIG_EG_MIN_RELEASE_TIME;  
         }  
164          this->InfiniteSustain  = InfiniteSustain;          this->InfiniteSustain  = InfiniteSustain;
165          this->HoldAttack       = HoldAttack;          this->HoldAttack       = HoldAttack;
         this->LoopStart        = LoopStart;  
166    
167          this->Decay1Time = Decay1Time;          this->Decay1Time = Decay1Time;
168          this->Decay2Time = Decay2Time;          this->Decay2Time = Decay2Time;
# Line 191  namespace LinuxSampler { namespace gig { Line 179  namespace LinuxSampler { namespace gig {
179          ReleaseCoeff2 = exp(ReleaseSlope);          ReleaseCoeff2 = exp(ReleaseSlope);
180          ReleaseCoeff3 = ExpOffset * (1 - ReleaseCoeff2);          ReleaseCoeff3 = ExpOffset * (1 - ReleaseCoeff2);
181          ReleaseLevel2 = 0.25 * invVolume;          ReleaseLevel2 = 0.25 * invVolume;
182    
183            enterAttackStage(PreAttack, AttackTime, SampleRate);
184      }      }
185    
186      void EGADSR::enterAttackStage(const uint PreAttack, const float AttackTime, const uint SampleRate, const double SamplePos, const float CurrentPitch) {      void EGADSR::enterAttackStage(const uint PreAttack, const float AttackTime, const uint SampleRate) {
187          Stage   = stage_attack;          Stage   = stage_attack;
188          Segment = segment_lin;          Segment = segment_lin;
189          // Measurements of GSt output shows that the real attack time  
190          // is about 65.5% of the value specified in the gig file.          if (AttackTime >= 0.0005f) {
191          StepsLeft = (int) (0.655f * AttackTime * SampleRate);              // Measurements of GSt output shows that the real attack time
192          if (StepsLeft) {              // is about 65.5% of the value specified in the gig file.
193                // The minimum attack value used is 0.032.
194                StepsLeft = int(0.655f * RTMath::Max(AttackTime, 0.032f) * SampleRate);
195              Level = (float) PreAttack / 1000.0;              Level = (float) PreAttack / 1000.0;
196              Coeff = 0.896f * (1.0f - Level) / StepsLeft; // 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
197          } else { // immediately jump to the next stage          } else { // attack is zero - immediately jump to the next stage
198              if (HoldAttack) enterAttackHoldStage(SamplePos, CurrentPitch);              Level = 1.029f; // a bit higher than max sustain
199                if (HoldAttack) enterAttackHoldStage();
200              else            enterDecay1Part1Stage(SampleRate);              else            enterDecay1Part1Stage(SampleRate);
201          }          }
         PostponedEvent = (event_t) -1; // init with anything except release or cancel_release  
202      }      }
203    
204      void EGADSR::enterAttackHoldStage(const double SamplePos, const float CurrentPitch) {      void EGADSR::enterAttackHoldStage() {
205          Stage     = stage_attack_hold;          Stage     = stage_attack_hold;
206          Segment   = segment_lin;          Segment   = segment_lin;
207          Coeff     = 0.0f; // don't rise anymore          Coeff     = 0.0f; // don't rise anymore
208          StepsLeft = (int) (LoopStart - SamplePos / CurrentPitch); // FIXME: just an approximation, inaccuracy grows with higher audio fragment size, sufficient for usual fragment sizes though          const int intMax = (unsigned int) -1 >> 1;
209            StepsLeft = intMax; // we use the highest value possible (we refresh StepsLeft in update() in case)
210      }      }
211    
212      void EGADSR::enterDecay1Part1Stage(const uint SampleRate) {      void EGADSR::enterDecay1Part1Stage(const uint SampleRate) {
# Line 227  namespace LinuxSampler { namespace gig { Line 220  namespace LinuxSampler { namespace gig {
220          // (where d is 1/SampleRate). The transition from f to g is          // (where d is 1/SampleRate). The transition from f to g is
221          // done when f(x) has reached Level2 = 25% of full volume.          // done when f(x) has reached Level2 = 25% of full volume.
222          StepsLeft = (int) (Decay1Time * SampleRate);          StepsLeft = (int) (Decay1Time * SampleRate);
223          if (StepsLeft && SustainLevel < 1.0) {          if (StepsLeft && Level > SustainLevel) {
224              Stage        = stage_decay1_part1;              Stage        = stage_decay1_part1;
225              Segment      = segment_lin;              Segment      = segment_lin;
226              Decay1Slope  = 1.365 * (SustainLevel - 1.0) / StepsLeft;              Decay1Slope = (1.347f * SustainLevel - 1.361f) / StepsLeft;
227              Coeff        = Decay1Slope * invVolume;              Coeff        = Decay1Slope * invVolume;
228              Decay1Level2 = 0.25 * invVolume;              Decay1Level2 = 0.25 * invVolume;
229              StepsLeft    = int((RTMath::Max(Decay1Level2, SustainLevel) - Level) / Coeff);              StepsLeft = int((RTMath::Max(Decay1Level2, SustainLevel) - Level) / Coeff);
230                if (StepsLeft <= 0) enterDecay1Part2Stage(SampleRate);
231          } else {          } else {
             Level = SustainLevel;  
232              if (InfiniteSustain) enterSustainStage();              if (InfiniteSustain) enterSustainStage();
233              else                 enterDecay2Stage(SampleRate);              else                 enterDecay2Stage(SampleRate);
234          }          }
235      }      }
236    
237      void EGADSR::enterDecay1Part2Stage() {      void EGADSR::enterDecay1Part2Stage(const uint SampleRate) {
238          Stage   = stage_decay1_part2;          if (SustainLevel < Decay1Level2) {
239          Segment = segment_exp;              Stage   = stage_decay1_part2;
240          Decay1Slope *= 3.55;              Segment = segment_exp;
241          Coeff  = exp(Decay1Slope);              Decay1Slope *= 3.55;
242          Offset = ExpOffset * (1 - Coeff);              Coeff  = exp(Decay1Slope);
243          Level  = Decay1Level2;              Offset = ExpOffset * (1 - Coeff);
244          StepsLeft = int(log((SustainLevel - ExpOffset) / (Level - ExpOffset)) / Decay1Slope);              StepsLeft = int(log((SustainLevel - ExpOffset) / (Level - ExpOffset)) / Decay1Slope);
245                if (StepsLeft > 0) return;
246            }
247            if (InfiniteSustain) enterSustainStage();
248            else                 enterDecay2Stage(SampleRate);
249      }      }
250    
251      void EGADSR::enterDecay2Stage(const uint SampleRate) {      void EGADSR::enterDecay2Stage(const uint SampleRate) {
252          Stage      = stage_decay2;          Stage      = stage_decay2;
253          Segment    = segment_lin;          Segment    = segment_lin;
254          Decay2Time = RTMath::Max(Decay2Time, CONFIG_EG_MIN_RELEASE_TIME);          Decay2Time = RTMath::Max(Decay2Time, 0.05f);
255          StepsLeft  = (int) (Decay2Time * SampleRate);          StepsLeft  = (int) (Decay2Time * SampleRate);
256          Coeff      = (-1.03 / StepsLeft) * invVolume;          Coeff      = (-1.03 / StepsLeft) * invVolume;
257          //FIXME: do we really have to calculate 'StepsLeft' two times?          //FIXME: do we really have to calculate 'StepsLeft' two times?
258          StepsLeft  = int((CONFIG_EG_BOTTOM - Level) / Coeff);          StepsLeft  = int((CONFIG_EG_BOTTOM - Level) / Coeff);
259            if (StepsLeft <= 0) enterEndStage();
260      }      }
261    
262      void EGADSR::enterSustainStage() {      void EGADSR::enterSustainStage() {
# Line 274  namespace LinuxSampler { namespace gig { Line 272  namespace LinuxSampler { namespace gig {
272          Segment   = segment_lin;          Segment   = segment_lin;
273          StepsLeft = int((ReleaseLevel2 - Level) / ReleaseCoeff);          StepsLeft = int((ReleaseLevel2 - Level) / ReleaseCoeff);
274          Coeff     = ReleaseCoeff;          Coeff     = ReleaseCoeff;
275            if (StepsLeft <= 0) enterReleasePart2Stage();
276      }      }
277    
278      void EGADSR::enterReleasePart2Stage() {      void EGADSR::enterReleasePart2Stage() {
# Line 282  namespace LinuxSampler { namespace gig { Line 281  namespace LinuxSampler { namespace gig {
281          StepsLeft = int(log((CONFIG_EG_BOTTOM - ExpOffset) / (Level - ExpOffset)) / ReleaseSlope);          StepsLeft = int(log((CONFIG_EG_BOTTOM - ExpOffset) / (Level - ExpOffset)) / ReleaseSlope);
282          Coeff     = ReleaseCoeff2;          Coeff     = ReleaseCoeff2;
283          Offset    = ReleaseCoeff3;          Offset    = ReleaseCoeff3;
284            if (StepsLeft <= 0) enterFadeOutStage();
285      }      }
286    
287      void EGADSR::enterFadeOutStage() {      void EGADSR::enterFadeOutStage() {
# Line 289  namespace LinuxSampler { namespace gig { Line 289  namespace LinuxSampler { namespace gig {
289          Segment   = segment_lin;          Segment   = segment_lin;
290          StepsLeft = int(Level / (-FadeOutCoeff));          StepsLeft = int(Level / (-FadeOutCoeff));
291          Coeff     = FadeOutCoeff;          Coeff     = FadeOutCoeff;
292            if (StepsLeft <= 0) enterEndStage();
293        }
294    
295        void EGADSR::enterFadeOutStage(int maxFadeOutSteps) {
296            Stage     = stage_fadeout;
297            Segment   = segment_lin;
298            StepsLeft = int(Level / (-FadeOutCoeff));
299            if (StepsLeft > maxFadeOutSteps) {
300                StepsLeft = maxFadeOutSteps;
301                Coeff = -Level / maxFadeOutSteps;
302            } else {
303                Coeff = FadeOutCoeff;
304            }
305            if (StepsLeft <= 0) enterEndStage();
306      }      }
307    
308      void EGADSR::enterEndStage() {      void EGADSR::enterEndStage() {
309          Stage   = stage_end;          Stage   = stage_end;
310          Segment = segment_end;          Segment = segment_end;
311            Level   = 0;
312      }      }
313    
314  }} // namespace LinuxSampler::gig  }} // namespace LinuxSampler::gig

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

  ViewVC Help
Powered by ViewVC