/[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 252 by schoenebeck, Thu Sep 23 21:33:43 2004 UTC
# Line 24  Line 24 
24    
25  namespace LinuxSampler { namespace gig {  namespace LinuxSampler { namespace gig {
26    
27        const float EGADSR::FadeOutCoeff(CalculateFadeOutCoeff());
28    
29        float EGADSR::CalculateFadeOutCoeff() {
30            const float sampleRate = 44100.0; // even if the sample rate will be 192kHz it won't hurt at all
31            const float killSteps  = EG_MIN_RELEASE_TIME * sampleRate;
32            return 1.0f / killSteps;
33        }
34    
35      EGADSR::EGADSR(gig::Engine* pEngine, Event::destination_t ModulationDestination) {      EGADSR::EGADSR(gig::Engine* pEngine, Event::destination_t ModulationDestination) {
36          this->pEngine = pEngine;          this->pEngine = pEngine;
37          this->ModulationDestination = ModulationDestination;          this->ModulationDestination = ModulationDestination;
# Line 35  namespace LinuxSampler { namespace gig { Line 43  namespace LinuxSampler { namespace gig {
43       * Will be called by the voice for every audio fragment to let the EG       * Will be called by the voice for every audio fragment to let the EG
44       * queue it's modulation changes for the current audio fragment.       * queue it's modulation changes for the current audio fragment.
45       *       *
46       * @param Samples       - total number of sample points to be rendered in this       * @param TotalSamples  - total number of sample points to be rendered in this
47       *                        audio fragment cycle by the audio engine       *                        audio fragment cycle by the audio engine
48       * @param pEvents       - event list with "release" and "cancel release" events       * @param pEvents       - event list with "release" and "cancel release" events
49       * @param pTriggerEvent - event that caused triggering of the voice (only if       * @param pTriggerEvent - event that caused triggering of the voice (only if
50       *                        the voices was triggered in the current audio       *                        the voice was triggered in the current audio
51       *                        fragment, NULL otherwise)       *                        fragment, NULL otherwise)
52       * @param SamplePos     - current playback position       * @param SamplePos     - current playback position
53       * @param CurrentPitch  - current pitch value for playback       * @param CurrentPitch  - current pitch value for playback
54         * @param pKillEvent    - (optional) event which caused this voice to be killed
55       */       */
56      void EGADSR::Process(uint Samples, RTEList<Event>* pEvents, Event* pTriggerEvent, double SamplePos, double CurrentPitch) {      void EGADSR::Process(uint TotalSamples, RTEList<Event>* pEvents, Event* pTriggerEvent, double SamplePos, double CurrentPitch, Event* pKillEvent) {
57          Event* pTransitionEvent;          Event* pTransitionEvent;
58          if (pTriggerEvent) {          if (pTriggerEvent) { // skip all events which occured before this voice was triggered
59              pEvents->set_current(pTriggerEvent);              pEvents->set_current(pTriggerEvent);
60              pTransitionEvent = pEvents->next();              pTransitionEvent = pEvents->next();
61          }          }
# Line 54  namespace LinuxSampler { namespace gig { Line 63  namespace LinuxSampler { namespace gig {
63              pTransitionEvent = pEvents->first();              pTransitionEvent = pEvents->first();
64          }          }
65    
66            // if the voice was killed in this fragment we only process the time before this kill event, then switch to 'stage_fadeout'
67            int Samples = (pKillEvent) ? pKillEvent->FragmentPos() : (int) TotalSamples;
68    
69          int iSample = TriggerDelay;          int iSample = TriggerDelay;
70          while (iSample < Samples) {          while (iSample < TotalSamples) {
71    
72                // if the voice was killed in this fragment and we already processed the time before this kill event
73                if (pKillEvent && iSample >= Samples) Stage = stage_fadeout;
74    
75              switch (Stage) {              switch (Stage) {
76                  case stage_attack: {                  case stage_attack: {
77                      TriggerDelay = 0;                      TriggerDelay = 0;
# Line 66  namespace LinuxSampler { namespace gig { Line 82  namespace LinuxSampler { namespace gig {
82                          Level += AttackCoeff;                          Level += AttackCoeff;
83                          pEngine->pSynthesisParameters[ModulationDestination][iSample++] *= Level;                          pEngine->pSynthesisParameters[ModulationDestination][iSample++] *= Level;
84                      }                      }
85                      if (iSample == Samples) { // postpone last transition event for the next audio fragment                      if (iSample == TotalSamples) { // postpone last transition event for the next audio fragment
86                          Event* pLastEvent = pEvents->last();                          Event* pLastEvent = pEvents->last();
87                          if (pLastEvent) ReleasePostponed = (pLastEvent->Type == Event::type_release);                          if (pLastEvent) ReleasePostponed = (pLastEvent->Type == Event::type_release);
88                      }                      }
# Line 122  namespace LinuxSampler { namespace gig { Line 138  namespace LinuxSampler { namespace gig {
138                          Level += Level * Decay2Coeff;                          Level += Level * Decay2Coeff;
139                          pEngine->pSynthesisParameters[ModulationDestination][iSample++] *= Level;                          pEngine->pSynthesisParameters[ModulationDestination][iSample++] *= Level;
140                      }                      }
141                      if (Level <= EG_ENVELOPE_LIMIT) Stage = stage_end;                      if (Level <= EG_ENVELOPE_LIMIT) Stage = stage_fadeout;
142                      break;                      break;
143                  }                  }
144                  case stage_sustain: {                  case stage_sustain: {
# Line 150  namespace LinuxSampler { namespace gig { Line 166  namespace LinuxSampler { namespace gig {
166                          Level += Level * ReleaseCoeff;                          Level += Level * ReleaseCoeff;
167                          pEngine->pSynthesisParameters[ModulationDestination][iSample++] *= Level;                          pEngine->pSynthesisParameters[ModulationDestination][iSample++] *= Level;
168                      }                      }
169                      if (Level <= EG_ENVELOPE_LIMIT) Stage = stage_end;                      if (Level <= EG_ENVELOPE_LIMIT) Stage = stage_fadeout;
170                      break;                      break;
171                  }                  }
172                  case stage_end: {                  case stage_fadeout: {
173                      while (iSample < Samples) {                      int to_process   = RTMath::Min(int(Level / (-FadeOutCoeff)), TotalSamples - iSample);
174                          Level += Level * ReleaseCoeff;                      int process_end  = iSample + to_process;
175                        while (iSample < process_end) {
176                            Level += FadeOutCoeff;
177                          pEngine->pSynthesisParameters[ModulationDestination][iSample++] *= Level;                          pEngine->pSynthesisParameters[ModulationDestination][iSample++] *= Level;
178                      }                      }
179                        if (Level <= FadeOutCoeff) Stage = stage_end;
180                        break;
181                    }
182                    case stage_end: {
183                        while (iSample < TotalSamples) {
184                            pEngine->pSynthesisParameters[ModulationDestination][iSample++] = 0.0f;
185                        }
186                      break;                      break;
187                  }                  }
188              }              }
# Line 208  namespace LinuxSampler { namespace gig { Line 233  namespace LinuxSampler { namespace gig {
233              if (Decay2Time < EG_MIN_RELEASE_TIME) Decay2Time = EG_MIN_RELEASE_TIME;              if (Decay2Time < EG_MIN_RELEASE_TIME) Decay2Time = EG_MIN_RELEASE_TIME;
234              long Decay2Steps = (long) (Decay2Time * pEngine->pAudioOutputDevice->SampleRate());              long Decay2Steps = (long) (Decay2Time * pEngine->pAudioOutputDevice->SampleRate());
235              Decay2Coeff      = (Decay2Steps) ? exp((log(EG_ENVELOPE_LIMIT) - log(this->SustainLevel)) / Decay2Steps + log(this->SustainLevel)) - this->SustainLevel              Decay2Coeff      = (Decay2Steps) ? exp((log(EG_ENVELOPE_LIMIT) - log(this->SustainLevel)) / Decay2Steps + log(this->SustainLevel)) - this->SustainLevel
236                                              : 0.0;                                               : 0.0;
237          }          }
238    
239          // calcuate release stage parameters (exp. curve)          // calculate release stage parameters (exp. curve)
240          if (ReleaseTime < EG_MIN_RELEASE_TIME) ReleaseTime = EG_MIN_RELEASE_TIME;  // to avoid click sounds at the end of the sample playback          if (ReleaseTime < EG_MIN_RELEASE_TIME) ReleaseTime = EG_MIN_RELEASE_TIME;  // to avoid click sounds at the end of the sample playback
241          ReleaseStepsLeft = (long) (ReleaseTime * pEngine->pAudioOutputDevice->SampleRate());          ReleaseStepsLeft = (long) (ReleaseTime * pEngine->pAudioOutputDevice->SampleRate());
242          ReleaseCoeff     = exp((log(EG_ENVELOPE_LIMIT) - log(this->SustainLevel)) / ReleaseStepsLeft + log(this->SustainLevel)) - this->SustainLevel;          ReleaseCoeff     = exp((log(EG_ENVELOPE_LIMIT) - log(this->SustainLevel)) / ReleaseStepsLeft + log(this->SustainLevel)) - this->SustainLevel;

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

  ViewVC Help
Powered by ViewVC