/[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 239 by schoenebeck, Sun Sep 12 14:48:19 2004 UTC
# Line 24  Line 24 
24    
25  namespace LinuxSampler { namespace gig {  namespace LinuxSampler { namespace gig {
26    
27        const float EGADSR::EndCoeff(CalculateEndCoeff());
28    
29        float EGADSR::CalculateEndCoeff() {
30            const double sampleRate = 44100.0; // even if the sample rate will be 192kHz it won't hurt at all
31            const double killSteps  = EG_MIN_RELEASE_TIME * sampleRate;
32            return float(exp(1.0 / killSteps) - 1.0);
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 and then switch to 'stage_end'
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_end;
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 154  namespace LinuxSampler { namespace gig { Line 170  namespace LinuxSampler { namespace gig {
170                      break;                      break;
171                  }                  }
172                  case stage_end: {                  case stage_end: {
173                      while (iSample < Samples) {                      while (iSample < TotalSamples) {
174                          Level += Level * ReleaseCoeff;                          Level += Level * EndCoeff;
175                          pEngine->pSynthesisParameters[ModulationDestination][iSample++] *= Level;                          pEngine->pSynthesisParameters[ModulationDestination][iSample++] *= Level;
176                      }                      }
177                      break;                      break;
# Line 208  namespace LinuxSampler { namespace gig { Line 224  namespace LinuxSampler { namespace gig {
224              if (Decay2Time < EG_MIN_RELEASE_TIME) Decay2Time = EG_MIN_RELEASE_TIME;              if (Decay2Time < EG_MIN_RELEASE_TIME) Decay2Time = EG_MIN_RELEASE_TIME;
225              long Decay2Steps = (long) (Decay2Time * pEngine->pAudioOutputDevice->SampleRate());              long Decay2Steps = (long) (Decay2Time * pEngine->pAudioOutputDevice->SampleRate());
226              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
227                                              : 0.0;                                               : 0.0;
228          }          }
229    
230          // calcuate release stage parameters (exp. curve)          // calculate release stage parameters (exp. curve)
231          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
232          ReleaseStepsLeft = (long) (ReleaseTime * pEngine->pAudioOutputDevice->SampleRate());          ReleaseStepsLeft = (long) (ReleaseTime * pEngine->pAudioOutputDevice->SampleRate());
233          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.239

  ViewVC Help
Powered by ViewVC