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

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

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

revision 39 by schoenebeck, Sun Mar 21 16:09:43 2004 UTC revision 40 by schoenebeck, Tue Mar 30 13:14:58 2004 UTC
# Line 26  Line 26 
26    
27  DiskThread*  Voice::pDiskThread = NULL;  DiskThread*  Voice::pDiskThread = NULL;
28  AudioThread* Voice::pEngine     = NULL;  AudioThread* Voice::pEngine     = NULL;
29    const float  Voice::FILTER_CUTOFF_COEFF(CalculateFilterCutoffCoeff());
30    
31    float Voice::CalculateFilterCutoffCoeff() {
32        return log(FILTER_CUTOFF_MIN / FILTER_CUTOFF_MAX);
33    }
34    
35  Voice::Voice() {  Voice::Voice() {
36      Active = false;      Active = false;
37      pLFO1  = new LFO(ModulationSystem::destination_vca, LFO::manipulation_type_multiply, 0.0f, 1.0f, LFO::propagation_top_down, pEngine->pEventPool);      pEG1   = new EG_VCA(ModulationSystem::destination_vca);
38      pLFO2  = new LFO(ModulationSystem::destination_vcfc, LFO::manipulation_type_multiply, 0.0f, 1.0f, LFO::propagation_top_down, pEngine->pEventPool);      pEG2   = new EG_VCA(ModulationSystem::destination_vcfc);
39      pLFO3  = new LFO(ModulationSystem::destination_vco, LFO::manipulation_type_add, -1.0f, 1.0f, LFO::propagation_middle_balanced, pEngine->pEventPool);      pEG3   = new EG_D(ModulationSystem::destination_vco);
40        pLFO1  = new LFO<VCAManipulator>(0.0f, 1.0f, LFO<VCAManipulator>::propagation_top_down, pEngine->pEventPool);
41        pLFO2  = new LFO<VCFCManipulator>(0.0f, 1.0f, LFO<VCFCManipulator>::propagation_top_down, pEngine->pEventPool);
42        pLFO3  = new LFO<VCOManipulator>(-1200.0f, 1200.0f, LFO<VCOManipulator>::propagation_middle_balanced, pEngine->pEventPool); // +-1 octave (+-1200 cents) max.
43  }  }
44    
45  Voice::~Voice() {  Voice::~Voice() {
46        if (pEG1)  delete pEG1;
47        if (pEG2)  delete pEG2;
48        if (pEG3)  delete pEG3;
49      if (pLFO1) delete pLFO1;      if (pLFO1) delete pLFO1;
50      if (pLFO2) delete pLFO2;      if (pLFO2) delete pLFO2;
51      if (pLFO3) delete pLFO3;      if (pLFO3) delete pLFO3;
# Line 45  Voice::~Voice() { Line 56  Voice::~Voice() {
56   *  needed.   *  needed.
57   *   *
58   *  @param pNoteOnEvent - event that caused triggering of this voice   *  @param pNoteOnEvent - event that caused triggering of this voice
59   *  @param Pitch        - MIDI detune factor (-8192 ... +8191)   *  @param PitchBend    - MIDI detune factor (-8192 ... +8191)
60   *  @param pInstrument  - points to the loaded instrument which provides sample wave(s) and articulation data   *  @param pInstrument  - points to the loaded instrument which provides sample wave(s) and articulation data
61   *  @returns            0 on success, a value < 0 if something failed   *  @returns            0 on success, a value < 0 if something failed
62   */   */
63  int Voice::Trigger(ModulationSystem::Event* pNoteOnEvent, int Pitch, gig::Instrument* pInstrument) {  int Voice::Trigger(ModulationSystem::Event* pNoteOnEvent, int PitchBend, gig::Instrument* pInstrument) {
64      Active          = true;      Active          = true;
65      MIDIKey         = pNoteOnEvent->Key;      MIDIKey         = pNoteOnEvent->Key;
66      pRegion         = pInstrument->GetRegion(MIDIKey);      pRegion         = pInstrument->GetRegion(MIDIKey);
# Line 113  int Voice::Trigger(ModulationSystem::Eve Line 124  int Voice::Trigger(ModulationSystem::Eve
124      }      }
125    
126    
127      // Pitch according to keyboard position (if 'PitchTrack' is set) and given detune factor      // calculate initial pitch value
128      this->Pitch = ((double) Pitch / 8192.0) / 12.0 + ((pDimRgn->PitchTrack) ? pow(2, ((double) (MIDIKey - (int) pDimRgn->UnityNote) + (double) pDimRgn->FineTune / 100.0) / 12.0)      {
129                                                                              : pow(2, ((double) pDimRgn->FineTune / 100.0) / 12.0));          double pitchbasecents = pDimRgn->FineTune * 10;
130            if (pDimRgn->PitchTrack) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;
131            this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents);
132            this->PitchBend = RTMath::CentsToFreqRatio(((double) PitchBend / 8192.0) * 200.0); // pitchbend wheel +-2 semitones = 200 cents
133        }
134    
135    
136      Volume = pDimRgn->GetVelocityAttenuation(pNoteOnEvent->Velocity);      Volume = pDimRgn->GetVelocityAttenuation(pNoteOnEvent->Velocity);
137    
138      // get current value of EG1 controller  
139      double eg1controllervalue;      // setup EG 1 (VCA EG)
140      switch (pDimRgn->EG1Controller.type) {      {
141          case gig::eg1_ctrl_t::type_none: // no controller defined          // get current value of EG1 controller
142              eg1controllervalue = 0;          double eg1controllervalue;
143              break;          switch (pDimRgn->EG1Controller.type) {
144          case gig::eg1_ctrl_t::type_channelaftertouch:              case gig::eg1_ctrl_t::type_none: // no controller defined
145              eg1controllervalue = 0; // TODO: aftertouch not yet supported                  eg1controllervalue = 0;
146              break;                  break;
147          case gig::eg1_ctrl_t::type_velocity:              case gig::eg1_ctrl_t::type_channelaftertouch:
148              eg1controllervalue = pNoteOnEvent->Velocity;                  eg1controllervalue = 0; // TODO: aftertouch not yet supported
149              break;                  break;
150          case gig::eg1_ctrl_t::type_controlchange: // MIDI control change controller              case gig::eg1_ctrl_t::type_velocity:
151              eg1controllervalue = pEngine->ControllerTable[pDimRgn->EG1Controller.controller_number];                  eg1controllervalue = pNoteOnEvent->Velocity;
152              break;                  break;
153                case gig::eg1_ctrl_t::type_controlchange: // MIDI control change controller
154                    eg1controllervalue = pEngine->ControllerTable[pDimRgn->EG1Controller.controller_number];
155                    break;
156            }
157            if (pDimRgn->EG1ControllerInvert) eg1controllervalue = 127 - eg1controllervalue;
158    
159            // calculate influence of EG1 controller on EG1's parameters (TODO: needs to be fine tuned)
160            double eg1attack  = (pDimRgn->EG1ControllerAttackInfluence)  ? 0.0001 * (double) (1 << pDimRgn->EG1ControllerAttackInfluence)  * eg1controllervalue : 0.0;
161            double eg1decay   = (pDimRgn->EG1ControllerDecayInfluence)   ? 0.0001 * (double) (1 << pDimRgn->EG1ControllerDecayInfluence)   * eg1controllervalue : 0.0;
162            double eg1release = (pDimRgn->EG1ControllerReleaseInfluence) ? 0.0001 * (double) (1 << pDimRgn->EG1ControllerReleaseInfluence) * eg1controllervalue : 0.0;
163    
164            pEG1->Trigger(pDimRgn->EG1PreAttack,
165                          pDimRgn->EG1Attack + eg1attack,
166                          pDimRgn->EG1Hold,
167                          pSample->LoopStart,
168                          pDimRgn->EG1Decay1 + eg1decay,
169                          pDimRgn->EG1Decay2 + eg1decay,
170                          pDimRgn->EG1InfiniteSustain,
171                          pDimRgn->EG1Sustain,
172                          pDimRgn->EG1Release + eg1release,
173                          Delay);
174        }
175    
176    
177    #if ENABLE_FILTER
178        // setup EG 2 (VCF Cutoff EG)
179        {
180            // get current value of EG2 controller
181            double eg2controllervalue;
182            switch (pDimRgn->EG2Controller.type) {
183                case gig::eg2_ctrl_t::type_none: // no controller defined
184                    eg2controllervalue = 0;
185                    break;
186                case gig::eg2_ctrl_t::type_channelaftertouch:
187                    eg2controllervalue = 0; // TODO: aftertouch not yet supported
188                    break;
189                case gig::eg2_ctrl_t::type_velocity:
190                    eg2controllervalue = pNoteOnEvent->Velocity;
191                    break;
192                case gig::eg2_ctrl_t::type_controlchange: // MIDI control change controller
193                    eg2controllervalue = pEngine->ControllerTable[pDimRgn->EG2Controller.controller_number];
194                    break;
195            }
196            if (pDimRgn->EG2ControllerInvert) eg2controllervalue = 127 - eg2controllervalue;
197    
198            // calculate influence of EG2 controller on EG2's parameters (TODO: needs to be fine tuned)
199            double eg2attack  = (pDimRgn->EG2ControllerAttackInfluence)  ? 0.0001 * (double) (1 << pDimRgn->EG2ControllerAttackInfluence)  * eg2controllervalue : 0.0;
200            double eg2decay   = (pDimRgn->EG2ControllerDecayInfluence)   ? 0.0001 * (double) (1 << pDimRgn->EG2ControllerDecayInfluence)   * eg2controllervalue : 0.0;
201            double eg2release = (pDimRgn->EG2ControllerReleaseInfluence) ? 0.0001 * (double) (1 << pDimRgn->EG2ControllerReleaseInfluence) * eg2controllervalue : 0.0;
202    
203            pEG2->Trigger(pDimRgn->EG2PreAttack,
204                          pDimRgn->EG2Attack + eg2attack,
205                          false,
206                          pSample->LoopStart,
207                          pDimRgn->EG2Decay1 + eg2decay,
208                          pDimRgn->EG2Decay2 + eg2decay,
209                          pDimRgn->EG2InfiniteSustain,
210                          pDimRgn->EG2Sustain,
211                          pDimRgn->EG2Release + eg2release,
212                          Delay);
213        }
214    #endif // ENABLE_FILTER
215    
216    
217        // setup EG 3 (VCO EG)
218        {
219           double eg3depth = RTMath::CentsToFreqRatio(pDimRgn->EG3Depth);
220           pEG3->Trigger(eg3depth, pDimRgn->EG3Attack, Delay);
221      }      }
     if (pDimRgn->EG1ControllerInvert) eg1controllervalue = 127 - eg1controllervalue;  
222    
     // calculate influence of EG1 controller on EG1's parameters (TODO: needs to be fine tuned)  
     double eg1attack  = (pDimRgn->EG1ControllerAttackInfluence)  ? 0.0001 * (double) (1 << pDimRgn->EG1ControllerAttackInfluence)  * eg1controllervalue : 0.0;  
     double eg1decay   = (pDimRgn->EG1ControllerDecayInfluence)   ? 0.0001 * (double) (1 << pDimRgn->EG1ControllerDecayInfluence)   * eg1controllervalue : 0.0;  
     double eg1release = (pDimRgn->EG1ControllerReleaseInfluence) ? 0.0001 * (double) (1 << pDimRgn->EG1ControllerReleaseInfluence) * eg1controllervalue : 0.0;  
   
     EG1.Trigger(pDimRgn->EG1PreAttack,  
                 pDimRgn->EG1Attack + eg1attack,  
                 pDimRgn->EG1Hold,  
                 pSample->LoopStart,  
                 pDimRgn->EG1Decay1 + eg1decay,  
                 pDimRgn->EG1Decay2 + eg1decay,  
                 pDimRgn->EG1InfiniteSustain,  
                 pDimRgn->EG1Sustain,  
                 pDimRgn->EG1Release + eg1release,  
                 Delay);  
223    
224      // setup LFO 1 (VCA LFO)      // setup LFO 1 (VCA LFO)
225      {      {
# Line 343  int Voice::Trigger(ModulationSystem::Eve Line 411  int Voice::Trigger(ModulationSystem::Eve
411          VCFResonanceCtrl.value = pEngine->ControllerTable[VCFResonanceCtrl.controller];          VCFResonanceCtrl.value = pEngine->ControllerTable[VCFResonanceCtrl.controller];
412    
413          // calculate cutoff frequency          // calculate cutoff frequency
414          float cutoff = (!VCFCutoffCtrl.controller && pDimRgn->VCFVelocityScale)          float cutoff = (!VCFCutoffCtrl.controller)
415              ? (float) pNoteOnEvent->Velocity * pDimRgn->VCFVelocityScale * 0.31f // up to 5kHz              ? exp((float) (127 - pNoteOnEvent->Velocity) * (float) pDimRgn->VCFVelocityScale * 6.2E-5f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX
416              : (float) (127 - VCFCutoffCtrl.value) * 39.4f;                       // up to 5kHz (inverted)              : exp((float) VCFCutoffCtrl.value * 0.00787402f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX;
417    
418          // calculate resonance          // calculate resonance
419          float resonance = (float) VCFResonanceCtrl.value * 0.00787f;   // 0.0..1.0          float resonance = (float) VCFResonanceCtrl.value * 0.00787f;   // 0.0..1.0
# Line 354  int Voice::Trigger(ModulationSystem::Eve Line 422  int Voice::Trigger(ModulationSystem::Eve
422          }          }
423          Constrain(resonance, 0.0, 1.0); // correct resonance if outside allowed value range (0.0..1.0)          Constrain(resonance, 0.0, 1.0); // correct resonance if outside allowed value range (0.0..1.0)
424    
425          VCFCutoffCtrl.fvalue    = cutoff;          VCFCutoffCtrl.fvalue    = cutoff - FILTER_CUTOFF_MIN;
426          VCFResonanceCtrl.fvalue = resonance;          VCFResonanceCtrl.fvalue = resonance;
427    
428          FilterLeft.SetParameters(cutoff + 20.0f,  resonance, ModulationSystem::SampleRate()); // 20Hz min.          FilterLeft.SetParameters(cutoff,  resonance, ModulationSystem::SampleRate());
429          FilterRight.SetParameters(cutoff + 20.0f, resonance, ModulationSystem::SampleRate()); // 20Hz min.          FilterRight.SetParameters(cutoff, resonance, ModulationSystem::SampleRate());
430    
431            FilterUpdateCounter = -1;
432      }      }
433      else {      else {
434          VCFCutoffCtrl.controller    = 0;          VCFCutoffCtrl.controller    = 0;
# Line 388  void Voice::Render(uint Samples) { Line 458  void Voice::Render(uint Samples) {
458    
459      // Reset the synthesis parameter matrix      // Reset the synthesis parameter matrix
460      ModulationSystem::ResetDestinationParameter(ModulationSystem::destination_vca, this->Volume);      ModulationSystem::ResetDestinationParameter(ModulationSystem::destination_vca, this->Volume);
461      ModulationSystem::ResetDestinationParameter(ModulationSystem::destination_vco, this->Pitch);      ModulationSystem::ResetDestinationParameter(ModulationSystem::destination_vco, this->PitchBase);
462  #if ENABLE_FILTER  #if ENABLE_FILTER
463      ModulationSystem::ResetDestinationParameter(ModulationSystem::destination_vcfc, VCFCutoffCtrl.fvalue);      ModulationSystem::ResetDestinationParameter(ModulationSystem::destination_vcfc, VCFCutoffCtrl.fvalue);
464      ModulationSystem::ResetDestinationParameter(ModulationSystem::destination_vcfr, VCFResonanceCtrl.fvalue);      ModulationSystem::ResetDestinationParameter(ModulationSystem::destination_vcfr, VCFResonanceCtrl.fvalue);
# Line 400  void Voice::Render(uint Samples) { Line 470  void Voice::Render(uint Samples) {
470    
471    
472      // Let all modulators write their parameter changes to the synthesis parameter matrix for the current audio fragment      // Let all modulators write their parameter changes to the synthesis parameter matrix for the current audio fragment
473      EG1.Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, pTriggerEvent, this->Pos, this->Pitch);      pEG1->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, pTriggerEvent, this->Pos, this->PitchBase * this->PitchBend);
474    #if ENABLE_FILTER
475        pEG2->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, pTriggerEvent, this->Pos, this->PitchBase * this->PitchBend);
476    #endif // ENABLE_FILTER
477        pEG3->Process(Samples);
478      pLFO1->Process(Samples);      pLFO1->Process(Samples);
479  #if ENABLE_FILTER  #if ENABLE_FILTER
480      pLFO2->Process(Samples);      pLFO2->Process(Samples);
# Line 435  void Voice::Render(uint Samples) { Line 509  void Voice::Render(uint Samples) {
509                          Kill();                          Kill();
510                          return;                          return;
511                      }                      }
512                      DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (double_to_int(Pos) - MaxRAMPos));                      DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (RTMath::DoubleToInt(Pos) - MaxRAMPos));
513                      Pos -= double_to_int(Pos);                      Pos -= RTMath::DoubleToInt(Pos);
514                  }                  }
515    
516                  // add silence sample at the end if we reached the end of the stream (for the interpolator)                  // add silence sample at the end if we reached the end of the stream (for the interpolator)
# Line 447  void Voice::Render(uint Samples) { Line 521  void Voice::Render(uint Samples) {
521    
522                  sample_t* ptr = DiskStreamRef.pStream->GetReadPtr(); // get the current read_ptr within the ringbuffer where we read the samples from                  sample_t* ptr = DiskStreamRef.pStream->GetReadPtr(); // get the current read_ptr within the ringbuffer where we read the samples from
523                  Interpolate(Samples, ptr, Delay);                  Interpolate(Samples, ptr, Delay);
524                  DiskStreamRef.pStream->IncrementReadPos(double_to_int(Pos) * pSample->Channels);                  DiskStreamRef.pStream->IncrementReadPos(RTMath::DoubleToInt(Pos) * pSample->Channels);
525                  Pos -= double_to_int(Pos);                  Pos -= RTMath::DoubleToInt(Pos);
526              }              }
527              break;              break;
528    
# Line 470  void Voice::Render(uint Samples) { Line 544  void Voice::Render(uint Samples) {
544      pTriggerEvent = NULL;      pTriggerEvent = NULL;
545    
546      // If release stage finished, let the voice be killed      // If release stage finished, let the voice be killed
547      if (EG1.GetStage() == EG_VCA::stage_end) this->PlaybackState = playback_state_end;      if (pEG1->GetStage() == EG_VCA::stage_end) this->PlaybackState = playback_state_end;
548  }  }
549    
550  /**  /**
# Line 499  void Voice::ProcessEvents(uint Samples) Line 573  void Voice::ProcessEvents(uint Samples)
573    
574      // dispatch control change events      // dispatch control change events
575      ModulationSystem::Event* pCCEvent = pEngine->pCCEvents->first();      ModulationSystem::Event* pCCEvent = pEngine->pCCEvents->first();
576        if (Delay) { // skip events that happened before this voice was triggered
577            while (pCCEvent && pCCEvent->FragmentPos() <= Delay) pCCEvent = pEngine->pCCEvents->next();
578        }
579      while (pCCEvent) {      while (pCCEvent) {
580          if (pCCEvent->Controller) { // if valid MIDI controller          if (pCCEvent->Controller) { // if valid MIDI controller
581              #if ENABLE_FILTER              #if ENABLE_FILTER
# Line 525  void Voice::ProcessEvents(uint Samples) Line 602  void Voice::ProcessEvents(uint Samples)
602          pCCEvent = pEngine->pCCEvents->next();          pCCEvent = pEngine->pCCEvents->next();
603      }      }
604    
605    
606      // process pitch events      // process pitch events
607      RTEList<ModulationSystem::Event>* pVCOEventList = pEngine->pSynthesisEvents[ModulationSystem::destination_vco];      {
608      ModulationSystem::Event* pVCOEvent = pVCOEventList->first();          RTEList<ModulationSystem::Event>* pVCOEventList = pEngine->pSynthesisEvents[ModulationSystem::destination_vco];
609      while (pVCOEvent) {          ModulationSystem::Event* pVCOEvent = pVCOEventList->first();
610          ModulationSystem::Event* pNextVCOEvent = pVCOEventList->next();          if (Delay) { // skip events that happened before this voice was triggered
611                while (pVCOEvent && pVCOEvent->FragmentPos() <= Delay) pVCOEvent = pVCOEventList->next();
612            }
613            // apply old pitchbend value until first pitch event occurs
614            if (this->PitchBend != 1.0) {
615                uint end = (pVCOEvent) ? pVCOEvent->FragmentPos() : Samples;
616                for (uint i = Delay; i < end; i++) {
617                    ModulationSystem::pDestinationParameter[ModulationSystem::destination_vco][i] *= this->PitchBend;
618                }
619            }
620            float pitch;
621            while (pVCOEvent) {
622                ModulationSystem::Event* pNextVCOEvent = pVCOEventList->next();
623    
624          // calculate the influence length of this event (in sample points)              // calculate the influence length of this event (in sample points)
625          uint end = (pNextVCOEvent) ? pNextVCOEvent->FragmentPos() : Samples;              uint end = (pNextVCOEvent) ? pNextVCOEvent->FragmentPos() : Samples;
626    
627          this->Pitch += ((double) pVCOEvent->Pitch / 8192.0) / 12.0; // +- one semitone              pitch = RTMath::CentsToFreqRatio(((double) pVCOEvent->Pitch / 8192.0) * 200.0); // +-two semitones = +-200 cents
628    
629          // apply pitch value to the pitch parameter sequence              // apply pitch value to the pitch parameter sequence
630          for (uint i = pVCOEvent->FragmentPos(); i < end; i++) {              for (uint i = pVCOEvent->FragmentPos(); i < end; i++) {
631              ModulationSystem::pDestinationParameter[ModulationSystem::destination_vco][i] = this->Pitch;                  ModulationSystem::pDestinationParameter[ModulationSystem::destination_vco][i] *= pitch;
632          }              }
633    
634          pVCOEvent = pNextVCOEvent;              pVCOEvent = pNextVCOEvent;
635            }
636            if (pVCOEventList->last()) this->PitchBend = pitch;
637      }      }
638    
639    
640  #if ENABLE_FILTER  #if ENABLE_FILTER
641      // process filter cutoff events      // process filter cutoff events
642      RTEList<ModulationSystem::Event>* pCutoffEventList = pEngine->pSynthesisEvents[ModulationSystem::destination_vcfc];      {
643      ModulationSystem::Event* pCutoffEvent = pCutoffEventList->first();          RTEList<ModulationSystem::Event>* pCutoffEventList = pEngine->pSynthesisEvents[ModulationSystem::destination_vcfc];
644      while (pCutoffEvent) {          ModulationSystem::Event* pCutoffEvent = pCutoffEventList->first();
645          ModulationSystem::Event* pNextCutoffEvent = pCutoffEventList->next();          if (Delay) { // skip events that happened before this voice was triggered
646                while (pCutoffEvent && pCutoffEvent->FragmentPos() <= Delay) pCutoffEvent = pCutoffEventList->next();
647            }
648            float cutoff;
649            while (pCutoffEvent) {
650                ModulationSystem::Event* pNextCutoffEvent = pCutoffEventList->next();
651    
652          // calculate the influence length of this event (in sample points)              // calculate the influence length of this event (in sample points)
653          uint end = (pNextCutoffEvent) ? pNextCutoffEvent->FragmentPos() : Samples;              uint end = (pNextCutoffEvent) ? pNextCutoffEvent->FragmentPos() : Samples;
654    
655          // convert absolute controller value to differential              cutoff = exp((float) pCutoffEvent->Value * 0.00787402f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX - FILTER_CUTOFF_MIN;
         int ctrldelta = pCutoffEvent->Value - VCFCutoffCtrl.value;  
         VCFCutoffCtrl.value = pCutoffEvent->Value;  
656    
657          float cutoffdelta = (float) ctrldelta * -39.4f; // (20Hz)..5kHz (inverted)              // apply cutoff frequency to the cutoff parameter sequence
658                for (uint i = pCutoffEvent->FragmentPos(); i < end; i++) {
659                    ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfc][i] = cutoff;
660                }
661    
662          // apply cutoff frequency to the cutoff parameter sequence              pCutoffEvent = pNextCutoffEvent;
         for (uint i = pCutoffEvent->FragmentPos(); i < end; i++) {  
             ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfc][i] += cutoffdelta;  
663          }          }
664            if (pCutoffEventList->last()) VCFCutoffCtrl.fvalue = cutoff; // needed for initialization of parameter matrix next time
         pCutoffEvent = pNextCutoffEvent;  
665      }      }
     if (pCutoffEventList->last()) VCFCutoffCtrl.fvalue = (float) (127 - pCutoffEventList->last()->Value) * 39.4f; // needed for initialization of parameter matrix next time  
666    
667      // process filter resonance events      // process filter resonance events
668      RTEList<ModulationSystem::Event>* pResonanceEventList = pEngine->pSynthesisEvents[ModulationSystem::destination_vcfr];      {
669      ModulationSystem::Event* pResonanceEvent = pResonanceEventList->first();          RTEList<ModulationSystem::Event>* pResonanceEventList = pEngine->pSynthesisEvents[ModulationSystem::destination_vcfr];
670      while (pResonanceEvent) {          ModulationSystem::Event* pResonanceEvent = pResonanceEventList->first();
671          ModulationSystem::Event* pNextResonanceEvent = pResonanceEventList->next();          if (Delay) { // skip events that happened before this voice was triggered
672                while (pResonanceEvent && pResonanceEvent->FragmentPos() <= Delay) pResonanceEvent = pResonanceEventList->next();
673            }
674            while (pResonanceEvent) {
675                ModulationSystem::Event* pNextResonanceEvent = pResonanceEventList->next();
676    
677          // calculate the influence length of this event (in sample points)              // calculate the influence length of this event (in sample points)
678          uint end = (pNextResonanceEvent) ? pNextResonanceEvent->FragmentPos() : Samples;              uint end = (pNextResonanceEvent) ? pNextResonanceEvent->FragmentPos() : Samples;
679    
680          // convert absolute controller value to differential              // convert absolute controller value to differential
681          int ctrldelta = pResonanceEvent->Value - VCFResonanceCtrl.value;              int ctrldelta = pResonanceEvent->Value - VCFResonanceCtrl.value;
682          VCFResonanceCtrl.value = pResonanceEvent->Value;              VCFResonanceCtrl.value = pResonanceEvent->Value;
683    
684          float resonancedelta = (float) ctrldelta * 0.00787f; // 0.0..1.0              float resonancedelta = (float) ctrldelta * 0.00787f; // 0.0..1.0
685    
686          // apply cutoff frequency to the cutoff parameter sequence              // apply cutoff frequency to the cutoff parameter sequence
687          for (uint i = pResonanceEvent->FragmentPos(); i < end; i++) {              for (uint i = pResonanceEvent->FragmentPos(); i < end; i++) {
688              ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfr][i] += resonancedelta;                  ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfr][i] += resonancedelta;
689          }              }
690    
691          pResonanceEvent = pNextResonanceEvent;              pResonanceEvent = pNextResonanceEvent;
692            }
693            if (pResonanceEventList->last()) VCFResonanceCtrl.fvalue = pResonanceEventList->last()->Value * 0.00787f; // needed for initialization of parameter matrix next time
694      }      }
     if (pResonanceEventList->last()) VCFResonanceCtrl.fvalue = pResonanceEventList->last()->Value * 0.00787f; // needed for initialization of parameter matrix next time  
695  #endif // ENABLE_FILTER  #endif // ENABLE_FILTER
696  }  }
697    
# Line 615  void Voice::Interpolate(uint Samples, sa Line 715  void Voice::Interpolate(uint Samples, sa
715                                        ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfc][i],                                        ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfc][i],
716                                        ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfr][i]);                                        ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfr][i]);
717          }          }
   
 #if ENABLE_FILTER  
         // to save the last filter setting for the next render cycle (only needed when we update the filter not-sample-accurate)  
         ForceUpdateFilter_Stereo(ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfc][Samples - 1],  
                                  ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfr][Samples - 1]);  
 #endif // ENABLE_FILTER  
718      }      }
719      else { // Mono Sample      else { // Mono Sample
720          while (i < Samples) {          while (i < Samples) {
# Line 630  void Voice::Interpolate(uint Samples, sa Line 724  void Voice::Interpolate(uint Samples, sa
724                                      ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfc][i],                                      ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfc][i],
725                                      ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfr][i]);                                      ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfr][i]);
726          }          }
   
 #if ENABLE_FILTER  
         // to save the last filter setting for the next render cycle (only needed when we update the filter not-sample-accurate)  
         ForceUpdateFilter_Mono(ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfc][Samples - 1],  
                                ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfr][Samples - 1]);  
 #endif // ENABLE_FILTER  
727      }      }
728  }  }
729    
# Line 686  void Voice::InterpolateAndLoop(uint Samp Line 774  void Voice::InterpolateAndLoop(uint Samp
774                  }                  }
775              }              }
776          }          }
 #if ENABLE_FILTER  
         // to save the last filter setting for the next render cycle (only needed when we update the filter not-sample-accurate)  
         ForceUpdateFilter_Stereo(ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfc][Samples - 1],  
                                  ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfr][Samples - 1]);  
 #endif // ENABLE_FILTER  
777      }      }
778      else { // Mono Sample      else { // Mono Sample
779          if (pSample->LoopPlayCount) {          if (pSample->LoopPlayCount) {
# Line 727  void Voice::InterpolateAndLoop(uint Samp Line 810  void Voice::InterpolateAndLoop(uint Samp
810                  }                  }
811              }              }
812          }          }
 #if ENABLE_FILTER  
         // to save the last filter setting for the next render cycle (only needed when we update the filter not-sample-accurate)  
         ForceUpdateFilter_Mono(ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfc][Samples - 1],  
                                ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfr][Samples - 1]);  
 #endif // ENABLE_FILTER  
813      }      }
814  }  }
815    

Legend:
Removed from v.39  
changed lines
  Added in v.40

  ViewVC Help
Powered by ViewVC