/[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 613 by schoenebeck, Sun May 22 20:43:32 2005 UTC revision 614 by persson, Mon Jun 6 16:54:20 2005 UTC
# Line 90  namespace LinuxSampler { namespace gig { Line 90  namespace LinuxSampler { namespace gig {
90                          RTList<Event>::Iterator itLastEvent = pEvents->last();                          RTList<Event>::Iterator itLastEvent = pEvents->last();
91                          if (itLastEvent) ReleasePostponed = (itLastEvent->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
# Line 103  namespace LinuxSampler { namespace gig { Line 103  namespace LinuxSampler { namespace gig {
103                      int process_end   = iSample + to_process;                      int process_end   = iSample + to_process;
104                      if (itTransitionEvent && itTransitionEvent->FragmentPos() <= process_end) {                      if (itTransitionEvent && itTransitionEvent->FragmentPos() <= process_end) {
105                          process_end       = itTransitionEvent->FragmentPos();                          process_end       = itTransitionEvent->FragmentPos();
106                          Stage             = (itTransitionEvent->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                          ++itTransitionEvent;                          ++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 (itTransitionEvent && itTransitionEvent->FragmentPos() <= process_end) {                      if (itTransitionEvent && itTransitionEvent->FragmentPos() <= process_end) {
134                          process_end       = itTransitionEvent->FragmentPos();                          process_end       = itTransitionEvent->FragmentPos();
135                          Stage             = (itTransitionEvent->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                            ++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;                          ++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 (itTransitionEvent && itTransitionEvent->Type == Event::type_release && itTransitionEvent->FragmentPos() <= Samples) {                      int process_end  = iSample + to_process;
175                        if (itTransitionEvent && itTransitionEvent->Type == Event::type_release && itTransitionEvent->FragmentPos() <= process_end) {
176                          process_end       = itTransitionEvent->FragmentPos();                          process_end       = itTransitionEvent->FragmentPos();
177                          ++itTransitionEvent;                          ++itTransitionEvent;
178                          Stage             = stage_release; // switch to release stage soon                          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 <= CONFIG_EG_BOTTOM) Stage = stage_fadeout;  
188                      break;                      break;
189                  }                  }
190                  case stage_sustain: {                  case stage_sustain: {
# Line 150  namespace LinuxSampler { namespace gig { Line 192  namespace LinuxSampler { namespace gig {
192                      if (itTransitionEvent && itTransitionEvent->Type == Event::type_release && itTransitionEvent->FragmentPos() <= Samples) {                      if (itTransitionEvent && itTransitionEvent->Type == Event::type_release && itTransitionEvent->FragmentPos() <= Samples) {
193                          process_end       = itTransitionEvent->FragmentPos();                          process_end       = itTransitionEvent->FragmentPos();
194                          ++itTransitionEvent;                          ++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 158  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 (itTransitionEvent && itTransitionEvent->Type == Event::type_cancel_release && itTransitionEvent->FragmentPos() <= Samples) {                      int process_end  = iSample + to_process;
209                        if (itTransitionEvent && itTransitionEvent->Type == Event::type_cancel_release && itTransitionEvent->FragmentPos() <= process_end) {
210                          process_end       = itTransitionEvent->FragmentPos();                          process_end       = itTransitionEvent->FragmentPos();
211                          ++itTransitionEvent;                          ++itTransitionEvent;
212                          Stage             = (InfiniteSustain) ? stage_sustain : stage_decay2; // switch back to sustain / decay2 stage soon                          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 <= CONFIG_EG_BOTTOM) Stage = stage_fadeout;  
243                      break;                      break;
244                  }                  }
245                  case stage_fadeout: {                  case stage_fadeout: {
# Line 213  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 > CONFIG_EG_BOTTOM) ? (float) SustainLevel / 1000.0 : CONFIG_EG_BOTTOM : 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 < CONFIG_EG_MIN_RELEASE_TIME) Decay2Time = CONFIG_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(CONFIG_EG_BOTTOM) - 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 < CONFIG_EG_MIN_RELEASE_TIME) ReleaseTime = CONFIG_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(CONFIG_EG_BOTTOM) - 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.613  
changed lines
  Added in v.614

  ViewVC Help
Powered by ViewVC