/[svn]/linuxsampler/trunk/src/eg_vca.cpp
ViewVC logotype

Diff of /linuxsampler/trunk/src/eg_vca.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 32 by schoenebeck, Tue Feb 3 13:21:19 2004 UTC revision 33 by schoenebeck, Mon Feb 16 19:30:42 2004 UTC
# Line 31  EG_VCA::EG_VCA() { Line 31  EG_VCA::EG_VCA() {
31   * 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
32   * queue it's modulation changes for the current audio fragment.   * queue it's modulation changes for the current audio fragment.
33   *   *
34   * @param Samples - total number of sample points to be rendered in this   * @param Samples       - total number of sample points to be rendered in this
35   *                  audio fragment cycle by the audio engine   *                        audio fragment cycle by the audio engine
36     * @param pEvents       - event list with "release" and "cancel release" events
37     * @param pTriggerEvent - event that caused triggering of the voice (only if
38     *                        the voices was triggered in the current audio
39     *                        fragment, NULL otherwise)
40     * @param SamplePos     - current playback position
41     * @param CurrentPitch  - current pitch value for playback
42   */   */
43  void EG_VCA::Process(uint Samples) {  void EG_VCA::Process(uint Samples, RTEList<ModulationSystem::Event>* pEvents, ModulationSystem::Event* pTriggerEvent, double SamplePos, double CurrentPitch) {
44      if (Stage == stage_sustain && !ReleaseSignalReceived) return; // nothing to do      ModulationSystem::Event* pReleaseTransitionEvent;
45        if (pTriggerEvent) {
46            pEvents->set_current(pTriggerEvent);
47            pReleaseTransitionEvent = pEvents->next();
48        }
49        else {
50            pReleaseTransitionEvent = pEvents->first();
51        }
52    
53      int iSample = TriggerDelay;      int iSample = TriggerDelay;
54      while (iSample < Samples) {      while (iSample < Samples) {
55          switch (Stage) {          switch (Stage) {
56              case stage_attack: {              case stage_attack: {
57                  int to_process    = Min(Samples - iSample, AttackStepsLeft);                  int to_process   = Min(Samples - iSample, AttackStepsLeft);
58                  int process_end   = iSample + to_process;                  int process_end  = iSample + to_process;
59                  AttackStepsLeft  -= to_process;                  AttackStepsLeft -= to_process;
60                  while (iSample < process_end) {                  while (iSample < process_end) {
61                      Level += AttackCoeff;                      Level += AttackCoeff;
62                      ModulationSystem::pDestinationParameter[ModulationSystem::destination_vca][iSample++] *= Level;                      ModulationSystem::pDestinationParameter[ModulationSystem::destination_vca][iSample++] *= Level;
63                  }                  }
64                  TriggerDelay = 0;                  TriggerDelay = 0;
65                  if (!AttackStepsLeft) Stage = (ReleaseSignalReceived) ? stage_release : stage_sustain;                  if (!AttackStepsLeft) Stage = (HoldAttack) ? stage_attack_hold : stage_decay1;
66                    if (iSample == Samples) { // postpone last transition event for the next audio fragment
67                        ModulationSystem::Event* pLastEvent = pEvents->last();
68                        if (pLastEvent) ReleasePostponed = (pLastEvent->Type == ModulationSystem::event_type_release);
69                    }
70                    break;
71                }
72                case stage_attack_hold: {
73                    if (SamplePos >= LoopStart) {
74                        Stage = stage_decay1;
75                        break;
76                    }
77                    int holdstepsleft = (int) (LoopStart - SamplePos / CurrentPitch); // FIXME: just an approximation, inaccuracy grows with higher audio fragment size, sufficient for usual fragment sizes though
78                    int to_process    = Min(Samples - iSample, holdstepsleft);
79                    int process_end   = iSample + to_process;
80                    while (iSample < process_end) {
81                        ModulationSystem::pDestinationParameter[ModulationSystem::destination_vca][iSample++] *= Level;
82                    }
83                    if (to_process == holdstepsleft) Stage = stage_decay1;
84                    if (iSample == Samples) { // postpone last transition event for the next audio fragment
85                        ModulationSystem::Event* pLastEvent = pEvents->last();
86                        if (pLastEvent) ReleasePostponed = (pLastEvent->Type == ModulationSystem::event_type_release);
87                    }
88                    break;
89                }
90                case stage_decay1: {
91                    int to_process   = Min(Samples - iSample, Decay1StepsLeft);
92                    int process_end  = iSample + to_process;
93                    Decay1StepsLeft -= to_process;
94                    while (iSample < process_end) {
95                        Level += Decay1Coeff;
96                        ModulationSystem::pDestinationParameter[ModulationSystem::destination_vca][iSample++] *= Level;
97                    }
98                    if (iSample == Samples) { // postpone last transition event for the next audio fragment
99                        ModulationSystem::Event* pLastEvent = pEvents->last();
100                        if (pLastEvent) ReleasePostponed = (pLastEvent->Type == ModulationSystem::event_type_release);
101                    }
102                    if (!Decay1StepsLeft) {
103                        Stage = (ReleasePostponed) ? stage_release
104                                                   : (InfiniteSustain) ? stage_sustain
105                                                                       : stage_decay2;
106                    }
107                    break;
108                }
109                case stage_decay2: {
110                    int process_end;
111                    if (pReleaseTransitionEvent && pReleaseTransitionEvent->Type == ModulationSystem::event_type_release) {
112                        process_end             = pReleaseTransitionEvent->FragmentPos();
113                        pReleaseTransitionEvent = pEvents->next();
114                        Stage                   = stage_release; // switch to release stage soon
115                    }
116                    else process_end = Samples;
117                    while (iSample < process_end) {
118                        Level += Level * Decay2Coeff;
119                        ModulationSystem::pDestinationParameter[ModulationSystem::destination_vca][iSample++] *= Level;
120                    }
121                    if (Level <= EG_ENVELOPE_LIMIT) Stage = stage_end;
122                  break;                  break;
123              }              }
124              case stage_sustain: {              case stage_sustain: {
125                  if (!ReleaseSignalReceived) return; // nothing to do                  int process_end;
126                  Stage = stage_release;                  if (pReleaseTransitionEvent && pReleaseTransitionEvent->Type == ModulationSystem::event_type_release) {
127                        process_end             = pReleaseTransitionEvent->FragmentPos();
128                        pReleaseTransitionEvent = pEvents->next();
129                        Stage                   = stage_release; // switch to release stage soon
130                    }
131                    else process_end = Samples;
132                    while (iSample < process_end) {
133                        ModulationSystem::pDestinationParameter[ModulationSystem::destination_vca][iSample++] *= Level;
134                    }
135                  break;                  break;
136              }              }
137              case stage_release: {              case stage_release: {
138                  iSample = ReleaseDelay;                  int process_end;
139                  while (iSample < Samples) {                  if (pReleaseTransitionEvent && pReleaseTransitionEvent->Type == ModulationSystem::event_type_cancel_release) {
140                      Level -= Level * ReleaseCoeff;                      process_end             = pReleaseTransitionEvent->FragmentPos();
141                        pReleaseTransitionEvent = pEvents->next();
142                        Stage                   = (InfiniteSustain) ? stage_sustain : stage_decay2; // switch back to sustain / decay2 stage soon
143                    }
144                    else process_end = Samples;
145                    while (iSample < process_end) {
146                        Level += Level * ReleaseCoeff;
147                      ModulationSystem::pDestinationParameter[ModulationSystem::destination_vca][iSample++] *= Level;                      ModulationSystem::pDestinationParameter[ModulationSystem::destination_vca][iSample++] *= Level;
148                  }                  }
149                  if (Level <= EG_ENVELOPE_LIMIT) Stage = stage_end;                  if (Level <= EG_ENVELOPE_LIMIT) Stage = stage_end;
150                  ReleaseDelay = 0;                  break;
                 return;  
151              }              }
152              case stage_end: {              case stage_end: {
153                  while (iSample < Samples) {                  while (iSample < Samples) {
154                        Level += Level * ReleaseCoeff;
155                      ModulationSystem::pDestinationParameter[ModulationSystem::destination_vca][iSample++] *= Level;                      ModulationSystem::pDestinationParameter[ModulationSystem::destination_vca][iSample++] *= Level;
156                  }                  }
157                  return;                  break;
158              }              }
159          }          }
160      }      }
# Line 80  void EG_VCA::Process(uint Samples) { Line 163  void EG_VCA::Process(uint Samples) {
163  /**  /**
164   * Will be called by the voice when the key / voice was triggered.   * Will be called by the voice when the key / voice was triggered.
165   *   *
166   * @param PreAttack   - Preattack value for the envelope (0 - 1000 permille)   * @param PreAttack       - Preattack value for the envelope (0 - 1000 permille)
167   * @param AttackTime  - Attack time for the envelope (0.000 - 60.000s)   * @param AttackTime      - Attack time for the envelope (0.000 - 60.000s)
168   * @param ReleaseTIme - Release time for the envelope (0.000 - 60.000s)   * @param HoldAttack      - If true, Decay1 will be postponed until the sample reached the sample loop start.
169   * @param Delay       - number of sample points triggering should be delayed   * @param LoopStart       - Sample position where sample loop starts (if any)
170     * @param Decay1Time      - Decay1 time of the sample amplitude EG (0.000 - 60.000s).
171     * @param Decay2Time      - Only if !InfiniteSustain: 2nd decay stage time of the sample amplitude EG (0.000 - 60.000s).
172     * @param InfiniteSustain - If true, instead of going into Decay2 phase, Decay1 level will be hold until note will be released.
173     * @param SustainLevel    - Sustain level of the sample amplitude EG (0 - 1000 permille).
174     * @param ReleaseTIme     - Release time for the envelope (0.000 - 60.000s)
175     * @param Delay           - Number of sample points triggering should be delayed.
176   */   */
177  void EG_VCA::Trigger(uint PreAttack, double AttackTime, double ReleaseTime, uint Delay) {  void EG_VCA::Trigger(uint PreAttack, double AttackTime, bool HoldAttack, long LoopStart, double Decay1Time, double Decay2Time, bool InfiniteSustain, uint SustainLevel, double ReleaseTime, uint Delay) {
178      ReleaseSignalReceived = false;      this->TriggerDelay     = Delay;
179      TriggerDelay = Delay;      this->Stage            = stage_attack;
180      Stage = stage_attack;      this->SustainLevel     = (SustainLevel) ? (SustainLevel > EG_ENVELOPE_LIMIT) ? (float) SustainLevel / 1000.0 : EG_ENVELOPE_LIMIT : 1.0;
181        this->InfiniteSustain  = InfiniteSustain;
182        this->HoldAttack       = HoldAttack;
183        this->LoopStart        = LoopStart;
184        this->ReleasePostponed = false;
185    
186      // calculate attack stage parameters      // calculate attack stage parameters (lin. curve)
187      AttackStepsLeft = (long) (AttackTime * ModulationSystem::SampleRate());      AttackStepsLeft = (long) (AttackTime * ModulationSystem::SampleRate());
188      if (AttackStepsLeft) {      if (AttackStepsLeft) {
189          Level       = PreAttack;          Level       = (float) PreAttack / 1000.0;
190          AttackCoeff = (1.0 - PreAttack) / AttackStepsLeft;          AttackCoeff = (1.0 - Level) / AttackStepsLeft;
191      }      }
192      else {      else {
193          Level       = 1.0;          Level       = 1.0;
194          AttackCoeff = 0.0;          AttackCoeff = 0.0;
195      }      }
196    
197      // calcuate release stage parameters      // calculate decay1 stage parameters (lin. curve)
198        Decay1StepsLeft = (long) (Decay1Time * ModulationSystem::SampleRate());
199        Decay1Coeff     = (Decay1StepsLeft) ? (this->SustainLevel - 1.0) / Decay1StepsLeft : 0.0;
200    
201        // calculate decay2 stage parameters (exp. curve)
202        if (!InfiniteSustain) {
203            if (Decay2Time < EG_MIN_RELEASE_TIME) Decay2Time = EG_MIN_RELEASE_TIME;
204            long Decay2Steps = (long) (Decay2Time * ModulationSystem::SampleRate());
205            Decay2Coeff      = (Decay2Steps) ? exp((log(EG_ENVELOPE_LIMIT) - log(this->SustainLevel)) / Decay2Steps + log(this->SustainLevel)) - this->SustainLevel
206                                             : 0.0;
207        }
208    
209        // calcuate release stage parameters (exp. curve)
210      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
211      ReleaseStepsLeft = (long) (ReleaseTime * ModulationSystem::SampleRate());      ReleaseStepsLeft = (long) (ReleaseTime * ModulationSystem::SampleRate());
212      ReleaseCoeff     = 1.0 - exp(log(EG_ENVELOPE_LIMIT) / (double) ReleaseStepsLeft);      //ReleaseCoeff     = exp(log(EG_ENVELOPE_LIMIT) / (double) ReleaseStepsLeft) - 1.0; // <- this is only accurate for a curve start level of exactly 1.0, otherwise we have to use the following calculation for the coefficient...
213        ReleaseCoeff     = exp((log(EG_ENVELOPE_LIMIT) - log(this->SustainLevel)) / ReleaseStepsLeft + log(this->SustainLevel)) - this->SustainLevel;
214    
215      dmsg(4,("AttackLength=%d, ReleaseLength=%d",AttackStepsLeft,ReleaseStepsLeft));      dmsg(4,("PreAttack=%d, AttackLength=%d, AttackCoeff=%f, Decay1Coeff=%f, Decay2Coeff=%f, ReleaseLength=%d, ReleaseCoeff=%f\n",
216  }              PreAttack, AttackStepsLeft, AttackCoeff, Decay1Coeff, Decay2Coeff, ReleaseStepsLeft, ReleaseCoeff));
   
 /**  
  * Will be called by the voice when the key / voice was released.  
  *  
  * @param Delay - number of sample points the release stage should be delayed  
  */  
 void EG_VCA::Release(uint Delay) {  
     ReleaseSignalReceived = true;  
     ReleaseDelay          = Delay;  
217  }  }

Legend:
Removed from v.32  
changed lines
  Added in v.33

  ViewVC Help
Powered by ViewVC