/[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 830 by persson, Sun Jan 15 18:23:11 2006 UTC
# Line 32  namespace LinuxSampler { namespace gig { Line 32  namespace LinuxSampler { namespace gig {
32      }      }
33    
34      void EGADSR::CalculateFadeOutCoeff(float FadeOutTime, float SampleRate) {      void EGADSR::CalculateFadeOutCoeff(float FadeOutTime, float SampleRate) {
35          const float killSteps = FadeOutTime * SampleRate;          const float killSteps = FadeOutTime * SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;
36          FadeOutCoeff = -1.0f / killSteps;          FadeOutCoeff = -1.0f / killSteps;
37      }      }
38    
39      void EGADSR::update(event_t Event, double SamplePos, float CurrentPitch, uint SampleRate) {      void EGADSR::update(event_t Event, uint SampleRate) {
40            if (Event == event_hold_end) HoldAttack = false;
41    
42          switch (Stage) {          switch (Stage) {
43              case stage_attack:              case stage_attack:
44                  if (StepsLeft) {                  switch (Event) {
45                      PostponedEvent = Event;                      case event_release:
                 } else {  
                     if (Event == event_release)  
                         enterReleasePart1Stage();  
                     else if (Event == event_cancel_release)  
                         enterSustainStage();  
                     else if (PostponedEvent == event_release)  
46                          enterReleasePart1Stage();                          enterReleasePart1Stage();
47                      else if (PostponedEvent == event_cancel_release)                          break;
48                        case event_cancel_release:
49                          enterSustainStage();                          enterSustainStage();
50                      else if (HoldAttack)                          break;
51                          enterAttackHoldStage(SamplePos, CurrentPitch);                      case event_stage_end:
52                      else                          if (HoldAttack)
53                          enterDecay1Part1Stage(SampleRate);                              enterAttackHoldStage();
54                            else
55                                enterDecay1Part1Stage(SampleRate);
56                            break;
57                  }                  }
58                  break;                  break;
59              case stage_attack_hold:              case stage_attack_hold:
60                  switch (Event) {                  switch (Event) {
61                      case event_stage_end:                      case event_stage_end: {// just refresh time
62                            const int intMax = (unsigned int) -1 >> 1;
63                            StepsLeft = intMax; // we use the highest possible value
64                            break;
65                        }
66                        case event_hold_end:
67                          enterDecay1Part1Stage(SampleRate);                          enterDecay1Part1Stage(SampleRate);
68                          break;                          break;
69                      case event_release:                      case event_release:
# Line 74  namespace LinuxSampler { namespace gig { Line 79  namespace LinuxSampler { namespace gig {
79                  break;                  break;
80              case stage_decay1_part1:              case stage_decay1_part1:
81                  switch (Event) {                  switch (Event) {
82                      case stage_end:                      case event_stage_end:
83                          enterDecay1Part2Stage();                          enterDecay1Part2Stage(SampleRate);
84                          break;                          break;
85                      case event_release:                      case event_release:
86                          enterReleasePart1Stage();                          enterReleasePart1Stage();
# Line 95  namespace LinuxSampler { namespace gig { Line 100  namespace LinuxSampler { namespace gig {
100                          break;                          break;
101                      case event_stage_end: // fall through                      case event_stage_end: // fall through
102                      case event_cancel_release:                      case event_cancel_release:
103                          if (InfiniteSustain)                          if (Level < CONFIG_EG_BOTTOM)
104                                enterEndStage();
105                            else if (InfiniteSustain)
106                              enterSustainStage();                              enterSustainStage();
107                          else                          else
108                              enterDecay2Stage(SampleRate);                              enterDecay2Stage(SampleRate);
# Line 110  namespace LinuxSampler { namespace gig { Line 117  namespace LinuxSampler { namespace gig {
117                      case event_release:                      case event_release:
118                          enterReleasePart1Stage();                          enterReleasePart1Stage();
119                          break;                          break;
120                        case event_hold_end:
121                            enterDecay1Part1Stage(SampleRate);
122                            break;
123                  }                  }
124                  break;                  break;
125              case stage_sustain:              case stage_sustain:
# Line 122  namespace LinuxSampler { namespace gig { Line 132  namespace LinuxSampler { namespace gig {
132                      case event_release:                      case event_release:
133                          enterReleasePart1Stage();                          enterReleasePart1Stage();
134                          break;                          break;
135                        case event_hold_end:
136                            enterDecay1Part1Stage(SampleRate);
137                            break;
138                  }                  }
139                  break;                  break;
140              case stage_release_part1:              case stage_release_part1:
# Line 160  namespace LinuxSampler { namespace gig { Line 173  namespace LinuxSampler { namespace gig {
173          }          }
174      }      }
175    
176      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) {
177            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;  
         }  
178          this->InfiniteSustain  = InfiniteSustain;          this->InfiniteSustain  = InfiniteSustain;
179          this->HoldAttack       = HoldAttack;          this->HoldAttack       = HoldAttack;
         this->LoopStart        = LoopStart;  
180    
181          this->Decay1Time = Decay1Time;          this->Decay1Time = Decay1Time;
182          this->Decay2Time = Decay2Time;          this->Decay2Time = Decay2Time;
# Line 191  namespace LinuxSampler { namespace gig { Line 193  namespace LinuxSampler { namespace gig {
193          ReleaseCoeff2 = exp(ReleaseSlope);          ReleaseCoeff2 = exp(ReleaseSlope);
194          ReleaseCoeff3 = ExpOffset * (1 - ReleaseCoeff2);          ReleaseCoeff3 = ExpOffset * (1 - ReleaseCoeff2);
195          ReleaseLevel2 = 0.25 * invVolume;          ReleaseLevel2 = 0.25 * invVolume;
196    
197            enterAttackStage(PreAttack, AttackTime, SampleRate);
198      }      }
199    
200      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) {
201          Stage   = stage_attack;          Stage   = stage_attack;
202          Segment = segment_lin;          Segment = segment_lin;
203          // Measurements of GSt output shows that the real attack time  
204          // is about 65.5% of the value specified in the gig file.          if (AttackTime >= 0.0005f) {
205          StepsLeft = (int) (0.655f * AttackTime * SampleRate);              // Measurements of GSt output shows that the real attack time
206          if (StepsLeft) {              // is about 65.5% of the value specified in the gig file.
207                // The minimum attack value used is 0.032.
208                StepsLeft = int(0.655f * RTMath::Max(AttackTime, 0.032f) * SampleRate);
209              Level = (float) PreAttack / 1000.0;              Level = (float) PreAttack / 1000.0;
210              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
211          } else { // immediately jump to the next stage          } else { // attack is zero - immediately jump to the next stage
212              if (HoldAttack) enterAttackHoldStage(SamplePos, CurrentPitch);              Level = 1.0;
213                if (HoldAttack) enterAttackHoldStage();
214              else            enterDecay1Part1Stage(SampleRate);              else            enterDecay1Part1Stage(SampleRate);
215          }          }
         PostponedEvent = (event_t) -1; // init with anything except release or cancel_release  
216      }      }
217    
218      void EGADSR::enterAttackHoldStage(const double SamplePos, const float CurrentPitch) {      void EGADSR::enterAttackHoldStage() {
219          Stage     = stage_attack_hold;          Stage     = stage_attack_hold;
220          Segment   = segment_lin;          Segment   = segment_lin;
221          Coeff     = 0.0f; // don't rise anymore          Coeff     = 0.0f; // don't rise anymore
222          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;
223            StepsLeft = intMax; // we use the highest value possible (we refresh StepsLeft in update() in case)
224      }      }
225    
226      void EGADSR::enterDecay1Part1Stage(const uint SampleRate) {      void EGADSR::enterDecay1Part1Stage(const uint SampleRate) {
# Line 227  namespace LinuxSampler { namespace gig { Line 234  namespace LinuxSampler { namespace gig {
234          // (where d is 1/SampleRate). The transition from f to g is          // (where d is 1/SampleRate). The transition from f to g is
235          // done when f(x) has reached Level2 = 25% of full volume.          // done when f(x) has reached Level2 = 25% of full volume.
236          StepsLeft = (int) (Decay1Time * SampleRate);          StepsLeft = (int) (Decay1Time * SampleRate);
237          if (StepsLeft && SustainLevel < 1.0) {          if (StepsLeft && SustainLevel < 1.0 && Level > SustainLevel) {
238              Stage        = stage_decay1_part1;              Stage        = stage_decay1_part1;
239              Segment      = segment_lin;              Segment      = segment_lin;
240              Decay1Slope  = 1.365 * (SustainLevel - 1.0) / StepsLeft;              Decay1Slope  = 1.365 * (SustainLevel - 1.0) / StepsLeft;
241              Coeff        = Decay1Slope * invVolume;              Coeff        = Decay1Slope * invVolume;
242              Decay1Level2 = 0.25 * invVolume;              Decay1Level2 = 0.25 * invVolume;
243              StepsLeft    = int((RTMath::Max(Decay1Level2, SustainLevel) - Level) / Coeff);              if (Level < Decay1Level2) enterDecay1Part2Stage(SampleRate);
244                else StepsLeft = int((RTMath::Max(Decay1Level2, SustainLevel) - Level) / Coeff);
245          } else {          } else {
             Level = SustainLevel;  
246              if (InfiniteSustain) enterSustainStage();              if (InfiniteSustain) enterSustainStage();
247              else                 enterDecay2Stage(SampleRate);              else                 enterDecay2Stage(SampleRate);
248          }          }
249      }      }
250    
251      void EGADSR::enterDecay1Part2Stage() {      void EGADSR::enterDecay1Part2Stage(const uint SampleRate) {
252          Stage   = stage_decay1_part2;          if (SustainLevel < Decay1Level2) {
253          Segment = segment_exp;              Stage   = stage_decay1_part2;
254          Decay1Slope *= 3.55;              Segment = segment_exp;
255          Coeff  = exp(Decay1Slope);              Decay1Slope *= 3.55;
256          Offset = ExpOffset * (1 - Coeff);              Coeff  = exp(Decay1Slope);
257          Level  = Decay1Level2;              Offset = ExpOffset * (1 - Coeff);
258          StepsLeft = int(log((SustainLevel - ExpOffset) / (Level - ExpOffset)) / Decay1Slope);              StepsLeft = int(log((SustainLevel - ExpOffset) / (Level - ExpOffset)) / Decay1Slope);
259            } else {
260                if (InfiniteSustain) enterSustainStage();
261                else                 enterDecay2Stage(SampleRate);
262            }
263      }      }
264    
265      void EGADSR::enterDecay2Stage(const uint SampleRate) {      void EGADSR::enterDecay2Stage(const uint SampleRate) {
# Line 259  namespace LinuxSampler { namespace gig { Line 270  namespace LinuxSampler { namespace gig {
270          Coeff      = (-1.03 / StepsLeft) * invVolume;          Coeff      = (-1.03 / StepsLeft) * invVolume;
271          //FIXME: do we really have to calculate 'StepsLeft' two times?          //FIXME: do we really have to calculate 'StepsLeft' two times?
272          StepsLeft  = int((CONFIG_EG_BOTTOM - Level) / Coeff);          StepsLeft  = int((CONFIG_EG_BOTTOM - Level) / Coeff);
273            if (StepsLeft == 0) enterEndStage();
274      }      }
275    
276      void EGADSR::enterSustainStage() {      void EGADSR::enterSustainStage() {
# Line 289  namespace LinuxSampler { namespace gig { Line 301  namespace LinuxSampler { namespace gig {
301          Segment   = segment_lin;          Segment   = segment_lin;
302          StepsLeft = int(Level / (-FadeOutCoeff));          StepsLeft = int(Level / (-FadeOutCoeff));
303          Coeff     = FadeOutCoeff;          Coeff     = FadeOutCoeff;
304            if (StepsLeft == 0) enterEndStage();
305      }      }
306    
307      void EGADSR::enterEndStage() {      void EGADSR::enterEndStage() {
308          Stage   = stage_end;          Stage   = stage_end;
309          Segment = segment_end;          Segment = segment_end;
310            Level   = 0;
311      }      }
312    
313  }} // namespace LinuxSampler::gig  }} // namespace LinuxSampler::gig

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

  ViewVC Help
Powered by ViewVC