/[svn]/linuxsampler/trunk/src/engines/gig/Voice.cpp
ViewVC logotype

Diff of /linuxsampler/trunk/src/engines/gig/Voice.cpp

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

revision 729 by persson, Tue Jul 26 11:18:46 2005 UTC revision 738 by schoenebeck, Tue Aug 16 17:14:25 2005 UTC
# Line 21  Line 21 
21   *   MA  02111-1307  USA                                                   *   *   MA  02111-1307  USA                                                   *
22   ***************************************************************************/   ***************************************************************************/
23    
 #include "EGADSR.h"  
 #include "Manipulator.h"  
24  #include "../../common/Features.h"  #include "../../common/Features.h"
25  #include "Synthesizer.h"  #include "Synthesizer.h"
26    
# Line 32  namespace LinuxSampler { namespace gig { Line 30  namespace LinuxSampler { namespace gig {
30    
31      const float Voice::FILTER_CUTOFF_COEFF(CalculateFilterCutoffCoeff());      const float Voice::FILTER_CUTOFF_COEFF(CalculateFilterCutoffCoeff());
32    
     const int Voice::FILTER_UPDATE_MASK(CalculateFilterUpdateMask());  
   
33      float Voice::CalculateFilterCutoffCoeff() {      float Voice::CalculateFilterCutoffCoeff() {
34          return log(CONFIG_FILTER_CUTOFF_MAX / CONFIG_FILTER_CUTOFF_MIN);          return log(CONFIG_FILTER_CUTOFF_MAX / CONFIG_FILTER_CUTOFF_MIN);
35      }      }
36    
     int Voice::CalculateFilterUpdateMask() {  
         if (CONFIG_FILTER_UPDATE_STEPS <= 0) return 0;  
         int power_of_two;  
         for (power_of_two = 0; 1<<power_of_two < CONFIG_FILTER_UPDATE_STEPS; power_of_two++);  
         return (1 << power_of_two) - 1;  
     }  
   
37      Voice::Voice() {      Voice::Voice() {
38          pEngine     = NULL;          pEngine     = NULL;
39          pDiskThread = NULL;          pDiskThread = NULL;
40          PlaybackState = playback_state_end;          PlaybackState = playback_state_end;
41          pEG1   = NULL;          pLFO1 = new LFOUnsigned(1.0f);  // amplitude EG (0..1 range)
42          pEG2   = NULL;          pLFO2 = new LFOUnsigned(1.0f);  // filter EG (0..1 range)
43          pEG3   = NULL;          pLFO3 = new LFOSigned(1200.0f); // pitch EG (-1200..+1200 range)
         pVCAManipulator  = NULL;  
         pVCFCManipulator = NULL;  
         pVCOManipulator  = NULL;  
         pLFO1  = NULL;  
         pLFO2  = NULL;  
         pLFO3  = NULL;  
44          KeyGroup = 0;          KeyGroup = 0;
45          SynthesisMode = 0; // set all mode bits to 0 first          SynthesisMode = 0; // set all mode bits to 0 first
46          // select synthesis implementation (currently either pure C++ or MMX+SSE(1))          // select synthesis implementation (currently either pure C++ or MMX+SSE(1))
# Line 73  namespace LinuxSampler { namespace gig { Line 56  namespace LinuxSampler { namespace gig {
56      }      }
57    
58      Voice::~Voice() {      Voice::~Voice() {
         if (pEG1)  delete pEG1;  
         if (pEG2)  delete pEG2;  
         if (pEG3)  delete pEG3;  
59          if (pLFO1) delete pLFO1;          if (pLFO1) delete pLFO1;
60          if (pLFO2) delete pLFO2;          if (pLFO2) delete pLFO2;
61          if (pLFO3) delete pLFO3;          if (pLFO3) delete pLFO3;
         if (pVCAManipulator)  delete pVCAManipulator;  
         if (pVCFCManipulator) delete pVCFCManipulator;  
         if (pVCOManipulator)  delete pVCOManipulator;  
62      }      }
63    
64      void Voice::SetEngine(Engine* pEngine) {      void Voice::SetEngine(Engine* pEngine) {
65          this->pEngine = pEngine;          this->pEngine     = pEngine;
   
         // delete old objects  
         if (pEG1) delete pEG1;  
         if (pEG2) delete pEG2;  
         if (pEG3) delete pEG3;  
         if (pVCAManipulator)  delete pVCAManipulator;  
         if (pVCFCManipulator) delete pVCFCManipulator;  
         if (pVCOManipulator)  delete pVCOManipulator;  
         if (pLFO1) delete pLFO1;  
         if (pLFO2) delete pLFO2;  
         if (pLFO3) delete pLFO3;  
   
         // create new ones  
         pEG1   = new EGADSR(pEngine, Event::destination_vca);  
         pEG2   = new EGADSR(pEngine, Event::destination_vcfc);  
         pEG3   = new EGDecay(pEngine, Event::destination_vco);  
         pVCAManipulator  = new VCAManipulator(pEngine);  
         pVCFCManipulator = new VCFCManipulator(pEngine);  
         pVCOManipulator  = new VCOManipulator(pEngine);  
         pLFO1  = new LFO<gig::VCAManipulator>(0.0f, 1.0f, LFO<VCAManipulator>::propagation_top_down, pVCAManipulator, pEngine->pEventPool);  
         pLFO2  = new LFO<gig::VCFCManipulator>(0.0f, 1.0f, LFO<VCFCManipulator>::propagation_top_down, pVCFCManipulator, pEngine->pEventPool);  
         pLFO3  = new LFO<gig::VCOManipulator>(-1200.0f, 1200.0f, LFO<VCOManipulator>::propagation_middle_balanced, pVCOManipulator, pEngine->pEventPool); // +-1 octave (+-1200 cents) max.  
   
66          this->pDiskThread = pEngine->pDiskThread;          this->pDiskThread = pEngine->pDiskThread;
67          dmsg(6,("Voice::SetEngine()\n"));          dmsg(6,("Voice::SetEngine()\n"));
68      }      }
# Line 222  namespace LinuxSampler { namespace gig { Line 176  namespace LinuxSampler { namespace gig {
176          {          {
177              double pitchbasecents = pDimRgn->FineTune + (int) pEngine->ScaleTuning[MIDIKey % 12];              double pitchbasecents = pDimRgn->FineTune + (int) pEngine->ScaleTuning[MIDIKey % 12];
178              if (pDimRgn->PitchTrack) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;              if (pDimRgn->PitchTrack) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;
179              this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents) * (double(pSample->SamplesPerSecond) / double(pEngine->pAudioOutputDevice->SampleRate()));              this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents) * (double(pSample->SamplesPerSecond) / double(pEngine->SampleRate));
180              this->PitchBend = RTMath::CentsToFreqRatio(((double) PitchBend / 8192.0) * 200.0); // pitchbend wheel +-2 semitones = 200 cents              this->PitchBend = RTMath::CentsToFreqRatio(((double) PitchBend / 8192.0) * 200.0); // pitchbend wheel +-2 semitones = 200 cents
181          }          }
182    
# Line 257  namespace LinuxSampler { namespace gig { Line 211  namespace LinuxSampler { namespace gig {
211              double eg1decay   = (pDimRgn->EG1ControllerDecayInfluence)   ? 1 + 0.00775 * (double) (1 << pDimRgn->EG1ControllerDecayInfluence)   * eg1controllervalue : 1.0;              double eg1decay   = (pDimRgn->EG1ControllerDecayInfluence)   ? 1 + 0.00775 * (double) (1 << pDimRgn->EG1ControllerDecayInfluence)   * eg1controllervalue : 1.0;
212              double eg1release = (pDimRgn->EG1ControllerReleaseInfluence) ? 1 + 0.00775 * (double) (1 << pDimRgn->EG1ControllerReleaseInfluence) * eg1controllervalue : 1.0;              double eg1release = (pDimRgn->EG1ControllerReleaseInfluence) ? 1 + 0.00775 * (double) (1 << pDimRgn->EG1ControllerReleaseInfluence) * eg1controllervalue : 1.0;
213    
214              pEG1->Trigger(pDimRgn->EG1PreAttack,              EG1.trigger(pDimRgn->EG1PreAttack,
215                            pDimRgn->EG1Attack * eg1attack,                          pDimRgn->EG1Attack * eg1attack,
216                            pDimRgn->EG1Hold,                          pDimRgn->EG1Hold,
217                            pSample->LoopStart,                          pSample->LoopStart,
218                            pDimRgn->EG1Decay1 * eg1decay * velrelease,                          pDimRgn->EG1Decay1 * eg1decay * velrelease,
219                            pDimRgn->EG1Decay2 * eg1decay * velrelease,                          pDimRgn->EG1Decay2 * eg1decay * velrelease,
220                            pDimRgn->EG1InfiniteSustain,                          pDimRgn->EG1InfiniteSustain,
221                            pDimRgn->EG1Sustain,                          pDimRgn->EG1Sustain,
222                            pDimRgn->EG1Release * eg1release * velrelease,                          pDimRgn->EG1Release * eg1release * velrelease,
223                            // the SSE synthesis implementation requires                          velocityAttenuation,
224                            // the vca start to be 16 byte aligned                          pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
                           SYNTHESIS_MODE_GET_IMPLEMENTATION(SynthesisMode) ?  
                           Delay & 0xfffffffc : Delay,  
                           velocityAttenuation);  
225          }          }
226    
227    
# Line 299  namespace LinuxSampler { namespace gig { Line 250  namespace LinuxSampler { namespace gig {
250              double eg2decay   = (pDimRgn->EG2ControllerDecayInfluence)   ? 1 + 0.00775 * (double) (1 << pDimRgn->EG2ControllerDecayInfluence)   * eg2controllervalue : 1.0;              double eg2decay   = (pDimRgn->EG2ControllerDecayInfluence)   ? 1 + 0.00775 * (double) (1 << pDimRgn->EG2ControllerDecayInfluence)   * eg2controllervalue : 1.0;
251              double eg2release = (pDimRgn->EG2ControllerReleaseInfluence) ? 1 + 0.00775 * (double) (1 << pDimRgn->EG2ControllerReleaseInfluence) * eg2controllervalue : 1.0;              double eg2release = (pDimRgn->EG2ControllerReleaseInfluence) ? 1 + 0.00775 * (double) (1 << pDimRgn->EG2ControllerReleaseInfluence) * eg2controllervalue : 1.0;
252    
253              pEG2->Trigger(pDimRgn->EG2PreAttack,              EG2.trigger(pDimRgn->EG2PreAttack,
254                            pDimRgn->EG2Attack * eg2attack,                          pDimRgn->EG2Attack * eg2attack,
255                            false,                          false,
256                            pSample->LoopStart,                          pSample->LoopStart,
257                            pDimRgn->EG2Decay1 * eg2decay * velrelease,                          pDimRgn->EG2Decay1 * eg2decay * velrelease,
258                            pDimRgn->EG2Decay2 * eg2decay * velrelease,                          pDimRgn->EG2Decay2 * eg2decay * velrelease,
259                            pDimRgn->EG2InfiniteSustain,                          pDimRgn->EG2InfiniteSustain,
260                            pDimRgn->EG2Sustain,                          pDimRgn->EG2Sustain,
261                            pDimRgn->EG2Release * eg2release * velrelease,                          pDimRgn->EG2Release * eg2release * velrelease,
262                            Delay,                          velocityAttenuation,
263                            velocityAttenuation);                          pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
264          }          }
265    
266    
267          // setup EG 3 (VCO EG)          // setup EG 3 (VCO EG)
268          {          {
269            double eg3depth = RTMath::CentsToFreqRatio(pDimRgn->EG3Depth);            double eg3depth = RTMath::CentsToFreqRatio(pDimRgn->EG3Depth);
270            pEG3->Trigger(eg3depth, pDimRgn->EG3Attack, Delay);            EG3.trigger(eg3depth, pDimRgn->EG3Attack, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
271          }          }
272    
273    
# Line 354  namespace LinuxSampler { namespace gig { Line 305  namespace LinuxSampler { namespace gig {
305                      pLFO1->ExtController = 0; // no external controller                      pLFO1->ExtController = 0; // no external controller
306                      bLFO1Enabled         = false;                      bLFO1Enabled         = false;
307              }              }
308              if (bLFO1Enabled) pLFO1->Trigger(pDimRgn->LFO1Frequency,              if (bLFO1Enabled) pLFO1->trigger(pDimRgn->LFO1Frequency,
309                                                 start_level_max,
310                                               lfo1_internal_depth,                                               lfo1_internal_depth,
311                                               pDimRgn->LFO1ControlDepth,                                               pDimRgn->LFO1ControlDepth,
                                              pEngineChannel->ControllerTable[pLFO1->ExtController],  
312                                               pDimRgn->LFO1FlipPhase,                                               pDimRgn->LFO1FlipPhase,
313                                               pEngine->SampleRate,                                               pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
                                              Delay);  
314          }          }
315    
316    
# Line 398  namespace LinuxSampler { namespace gig { Line 348  namespace LinuxSampler { namespace gig {
348                      pLFO2->ExtController = 0; // no external controller                      pLFO2->ExtController = 0; // no external controller
349                      bLFO2Enabled         = false;                      bLFO2Enabled         = false;
350              }              }
351              if (bLFO2Enabled) pLFO2->Trigger(pDimRgn->LFO2Frequency,              if (bLFO2Enabled) pLFO2->trigger(pDimRgn->LFO2Frequency,
352                                                 start_level_max,
353                                               lfo2_internal_depth,                                               lfo2_internal_depth,
354                                               pDimRgn->LFO2ControlDepth,                                               pDimRgn->LFO2ControlDepth,
                                              pEngineChannel->ControllerTable[pLFO2->ExtController],  
355                                               pDimRgn->LFO2FlipPhase,                                               pDimRgn->LFO2FlipPhase,
356                                               pEngine->SampleRate,                                               pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
                                              Delay);  
357          }          }
358    
359    
# Line 442  namespace LinuxSampler { namespace gig { Line 391  namespace LinuxSampler { namespace gig {
391                      pLFO3->ExtController = 0; // no external controller                      pLFO3->ExtController = 0; // no external controller
392                      bLFO3Enabled         = false;                      bLFO3Enabled         = false;
393              }              }
394              if (bLFO3Enabled) pLFO3->Trigger(pDimRgn->LFO3Frequency,              if (bLFO3Enabled) pLFO3->trigger(pDimRgn->LFO3Frequency,
395                                                 start_level_mid,
396                                               lfo3_internal_depth,                                               lfo3_internal_depth,
397                                               pDimRgn->LFO3ControlDepth,                                               pDimRgn->LFO3ControlDepth,
                                              pEngineChannel->ControllerTable[pLFO3->ExtController],  
398                                               false,                                               false,
399                                               pEngine->SampleRate,                                               pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
                                              Delay);  
400          }          }
401    
402    
# Line 560  namespace LinuxSampler { namespace gig { Line 508  namespace LinuxSampler { namespace gig {
508    
509              VCFCutoffCtrl.fvalue    = cutoff - CONFIG_FILTER_CUTOFF_MIN;              VCFCutoffCtrl.fvalue    = cutoff - CONFIG_FILTER_CUTOFF_MIN;
510              VCFResonanceCtrl.fvalue = resonance;              VCFResonanceCtrl.fvalue = resonance;
   
             FilterUpdateCounter = -1;  
511          }          }
512          else {          else {
513              VCFCutoffCtrl.controller    = 0;              VCFCutoffCtrl.controller    = 0;
# Line 585  namespace LinuxSampler { namespace gig { Line 531  namespace LinuxSampler { namespace gig {
531      void Voice::Render(uint Samples) {      void Voice::Render(uint Samples) {
532    
533          // select default values for synthesis mode bits          // select default values for synthesis mode bits
         SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, (PitchBase * PitchBend) != 1.0f);  
         SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, true);  
534          SYNTHESIS_MODE_SET_LOOP(SynthesisMode, false);          SYNTHESIS_MODE_SET_LOOP(SynthesisMode, false);
535    
         // Reset the synthesis parameter matrix  
   
         #if CONFIG_PROCESS_MUTED_CHANNELS  
         pEngine->ResetSynthesisParameters(Event::destination_vca, this->Volume * this->CrossfadeVolume * (pEngineChannel->GetMute() ? 0 : pEngineChannel->GlobalVolume));  
         #else  
         pEngine->ResetSynthesisParameters(Event::destination_vca, this->Volume * this->CrossfadeVolume * pEngineChannel->GlobalVolume);  
         #endif  
         pEngine->ResetSynthesisParameters(Event::destination_vco, this->PitchBase);  
         pEngine->ResetSynthesisParameters(Event::destination_vcfc, VCFCutoffCtrl.fvalue);  
         pEngine->ResetSynthesisParameters(Event::destination_vcfr, VCFResonanceCtrl.fvalue);  
   
         // Apply events to the synthesis parameter matrix  
         ProcessEvents(Samples);  
   
         // Let all modulators write their parameter changes to the synthesis parameter matrix for the current audio fragment  
         pEG1->Process(Samples, pEngineChannel->pMIDIKeyInfo[MIDIKey].pEvents, itTriggerEvent, this->Pos, this->PitchBase * this->PitchBend, itKillEvent);  
         pEG2->Process(Samples, pEngineChannel->pMIDIKeyInfo[MIDIKey].pEvents, itTriggerEvent, this->Pos, this->PitchBase * this->PitchBend);  
         if (pEG3->Process(Samples)) { // if pitch EG is active  
             SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, true);  
             SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, false);  
         }  
         if (bLFO1Enabled) pLFO1->Process(Samples);  
         if (bLFO2Enabled) pLFO2->Process(Samples);  
         if (bLFO3Enabled) {  
             if (pLFO3->Process(Samples)) { // if pitch LFO modulation is active  
                 SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, true);  
                 SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, false);  
             }  
         }  
   
         if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode))  
             CalculateBiquadParameters(Samples); // calculate the final biquad filter parameters  
   
536          switch (this->PlaybackState) {          switch (this->PlaybackState) {
537    
538              case playback_state_init:              case playback_state_init:
# Line 696  namespace LinuxSampler { namespace gig { Line 607  namespace LinuxSampler { namespace gig {
607                  break;                  break;
608          }          }
609    
610          // Reset synthesis event lists (except VCO, as VCO events apply channel wide currently)          // Reset synthesis event lists
611          pEngineChannel->pSynthesisEvents[Event::destination_vca]->clear();          pEngineChannel->pEvents->clear();
         pEngineChannel->pSynthesisEvents[Event::destination_vcfc]->clear();  
         pEngineChannel->pSynthesisEvents[Event::destination_vcfr]->clear();  
612    
613          // Reset delay          // Reset delay
614          Delay = 0;          Delay = 0;
# Line 707  namespace LinuxSampler { namespace gig { Line 616  namespace LinuxSampler { namespace gig {
616          itTriggerEvent = Pool<Event>::Iterator();          itTriggerEvent = Pool<Event>::Iterator();
617    
618          // If sample stream or release stage finished, kill the voice          // If sample stream or release stage finished, kill the voice
619          if (PlaybackState == playback_state_end || pEG1->GetStage() == EGADSR::stage_end) KillImmediately();          if (PlaybackState == playback_state_end || EG1.getSegmentType() == EGADSR::segment_end) KillImmediately();
620      }      }
621    
622      /**      /**
# Line 715  namespace LinuxSampler { namespace gig { Line 624  namespace LinuxSampler { namespace gig {
624       *  suspended / not running.       *  suspended / not running.
625       */       */
626      void Voice::Reset() {      void Voice::Reset() {
         pLFO1->Reset();  
         pLFO2->Reset();  
         pLFO3->Reset();  
627          FilterLeft.Reset();          FilterLeft.Reset();
628          FilterRight.Reset();          FilterRight.Reset();
629          DiskStreamRef.pStream = NULL;          DiskStreamRef.pStream = NULL;
# Line 730  namespace LinuxSampler { namespace gig { Line 636  namespace LinuxSampler { namespace gig {
636      }      }
637    
638      /**      /**
639       *  Process the control change event lists of the engine for the current       * Process given list of MIDI note on, note off and sustain pedal events
640       *  audio fragment. Event values will be applied to the synthesis parameter       * for the given time.
      *  matrix.  
641       *       *
642       *  @param Samples - number of samples to be rendered in this audio fragment cycle       * @param itEvent - iterator pointing to the next event to be processed
643         * @param End     - youngest time stamp where processing should be stopped
644       */       */
645      void Voice::ProcessEvents(uint Samples) {      void Voice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) {
646            for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
647          // dispatch control change events              if (itEvent->Type == Event::type_release) {
648          RTList<Event>::Iterator itCCEvent = pEngineChannel->pCCEvents->first();                  EG1.update(EGADSR::event_release, this->Pos, fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
649          if (Delay) { // skip events that happened before this voice was triggered                  EG2.update(EGADSR::event_release, this->Pos, fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
650              while (itCCEvent && itCCEvent->FragmentPos() <= Delay) ++itCCEvent;              } else if (itEvent->Type == Event::type_cancel_release) {
651          }                  EG1.update(EGADSR::event_cancel_release, this->Pos, fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
652          while (itCCEvent) {                  EG2.update(EGADSR::event_cancel_release, this->Pos, fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
             if (itCCEvent->Param.CC.Controller) { // if valid MIDI controller  
                 if (itCCEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {  
                     *pEngineChannel->pSynthesisEvents[Event::destination_vcfc]->allocAppend() = *itCCEvent;  
                 }  
                 if (itCCEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {  
                     *pEngineChannel->pSynthesisEvents[Event::destination_vcfr]->allocAppend() = *itCCEvent;  
                 }  
                 if (itCCEvent->Param.CC.Controller == pLFO1->ExtController) {  
                     pLFO1->SendEvent(itCCEvent);  
                 }  
                 if (itCCEvent->Param.CC.Controller == pLFO2->ExtController) {  
                     pLFO2->SendEvent(itCCEvent);  
                 }  
                 if (itCCEvent->Param.CC.Controller == pLFO3->ExtController) {  
                     pLFO3->SendEvent(itCCEvent);  
                 }  
                 if (pDimRgn->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange &&  
                     itCCEvent->Param.CC.Controller == pDimRgn->AttenuationController.controller_number) { // if crossfade event  
                     *pEngineChannel->pSynthesisEvents[Event::destination_vca]->allocAppend() = *itCCEvent;  
                 }  
653              }              }
   
             ++itCCEvent;  
654          }          }
655        }
656    
657        /**
658          // process pitch events       * Process given list of MIDI control change and pitch bend events for
659          {       * the given time.
660              RTList<Event>* pVCOEventList = pEngineChannel->pSynthesisEvents[Event::destination_vco];       *
661              RTList<Event>::Iterator itVCOEvent = pVCOEventList->first();       * @param itEvent - iterator pointing to the next event to be processed
662              if (Delay) { // skip events that happened before this voice was triggered       * @param End     - youngest time stamp where processing should be stopped
663                  while (itVCOEvent && itVCOEvent->FragmentPos() <= Delay) ++itVCOEvent;       */
664              }      void Voice::processCCEvents(RTList<Event>::Iterator& itEvent, uint End) {
665              // apply old pitchbend value until first pitch event occurs          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
666              if (this->PitchBend != 1.0) {              if (itEvent->Type == Event::type_control_change &&
667                  uint end = (itVCOEvent) ? itVCOEvent->FragmentPos() : Samples;                  itEvent->Param.CC.Controller) { // if (valid) MIDI control change event
668                  for (uint i = Delay; i < end; i++) {                  if (itEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {
669                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= this->PitchBend;                      processCutoffEvent(itEvent);
670                    }
671                    if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {
672                        processResonanceEvent(itEvent);
673                  }                  }
674              }                  if (itEvent->Param.CC.Controller == pLFO1->ExtController) {
675              float pitch;                      pLFO1->update(itEvent->Param.CC.Value);
             while (itVCOEvent) {  
                 RTList<Event>::Iterator itNextVCOEvent = itVCOEvent;  
                 ++itNextVCOEvent;  
   
                 // calculate the influence length of this event (in sample points)  
                 uint end = (itNextVCOEvent) ? itNextVCOEvent->FragmentPos() : Samples;  
   
                 pitch = RTMath::CentsToFreqRatio(((double) itVCOEvent->Param.Pitch.Pitch / 8192.0) * 200.0); // +-two semitones = +-200 cents  
   
                 // apply pitch value to the pitch parameter sequence  
                 for (uint i = itVCOEvent->FragmentPos(); i < end; i++) {  
                     pEngine->pSynthesisParameters[Event::destination_vco][i] *= pitch;  
676                  }                  }
677                    if (itEvent->Param.CC.Controller == pLFO2->ExtController) {
678                  itVCOEvent = itNextVCOEvent;                      pLFO2->update(itEvent->Param.CC.Value);
             }  
             if (!pVCOEventList->isEmpty()) {  
                 this->PitchBend = pitch;  
                 SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, true);  
                 SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, false);  
             }  
         }  
   
         // process volume / attenuation events (TODO: we only handle and _expect_ crossfade events here ATM !)  
         {  
             RTList<Event>* pVCAEventList = pEngineChannel->pSynthesisEvents[Event::destination_vca];  
             RTList<Event>::Iterator itVCAEvent = pVCAEventList->first();  
             if (Delay) { // skip events that happened before this voice was triggered  
                 while (itVCAEvent && itVCAEvent->FragmentPos() <= Delay) ++itVCAEvent;  
             }  
             float crossfadevolume;  
             while (itVCAEvent) {  
                 RTList<Event>::Iterator itNextVCAEvent = itVCAEvent;  
                 ++itNextVCAEvent;  
   
                 // calculate the influence length of this event (in sample points)  
                 uint end = (itNextVCAEvent) ? itNextVCAEvent->FragmentPos() : Samples;  
   
                 crossfadevolume = CrossfadeAttenuation(itVCAEvent->Param.CC.Value);  
   
                 #if CONFIG_PROCESS_MUTED_CHANNELS  
                 float effective_volume = crossfadevolume * this->Volume * (pEngineChannel->GetMute() ? 0 : pEngineChannel->GlobalVolume);  
                 #else  
                 float effective_volume = crossfadevolume * this->Volume * pEngineChannel->GlobalVolume;  
                 #endif  
   
                 // apply volume value to the volume parameter sequence  
                 for (uint i = itVCAEvent->FragmentPos(); i < end; i++) {  
                     pEngine->pSynthesisParameters[Event::destination_vca][i] = effective_volume;  
679                  }                  }
680                    if (itEvent->Param.CC.Controller == pLFO3->ExtController) {
681                  itVCAEvent = itNextVCAEvent;                      pLFO3->update(itEvent->Param.CC.Value);
             }  
             if (!pVCAEventList->isEmpty()) this->CrossfadeVolume = crossfadevolume;  
         }  
   
         // process filter cutoff events  
         {  
             RTList<Event>* pCutoffEventList = pEngineChannel->pSynthesisEvents[Event::destination_vcfc];  
             RTList<Event>::Iterator itCutoffEvent = pCutoffEventList->first();  
             if (Delay) { // skip events that happened before this voice was triggered  
                 while (itCutoffEvent && itCutoffEvent->FragmentPos() <= Delay) ++itCutoffEvent;  
             }  
             float cutoff;  
             while (itCutoffEvent) {  
                 RTList<Event>::Iterator itNextCutoffEvent = itCutoffEvent;  
                 ++itNextCutoffEvent;  
   
                 // calculate the influence length of this event (in sample points)  
                 uint end = (itNextCutoffEvent) ? itNextCutoffEvent->FragmentPos() : Samples;  
   
                 int cvalue = pEngineChannel->ControllerTable[VCFCutoffCtrl.controller];  
                 if (pDimRgn->VCFCutoffControllerInvert) cvalue = 127 - cvalue;  
                 if (cvalue < pDimRgn->VCFVelocityScale) cvalue = pDimRgn->VCFVelocityScale;  
                 cutoff = CutoffBase * float(cvalue) * 0.00787402f; // (1 / 127)  
                 if (cutoff > 1.0) cutoff = 1.0;  
                 cutoff = exp(cutoff * FILTER_CUTOFF_COEFF) * CONFIG_FILTER_CUTOFF_MIN - CONFIG_FILTER_CUTOFF_MIN;  
   
                 // apply cutoff frequency to the cutoff parameter sequence  
                 for (uint i = itCutoffEvent->FragmentPos(); i < end; i++) {  
                     pEngine->pSynthesisParameters[Event::destination_vcfc][i] = cutoff;  
682                  }                  }
683                    if (pDimRgn->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange &&
684                  itCutoffEvent = itNextCutoffEvent;                      itEvent->Param.CC.Controller == pDimRgn->AttenuationController.controller_number) {
685              }                      processCrossFadeEvent(itEvent);
             if (!pCutoffEventList->isEmpty()) VCFCutoffCtrl.fvalue = cutoff; // needed for initialization of parameter matrix next time  
         }  
   
         // process filter resonance events  
         {  
             RTList<Event>* pResonanceEventList = pEngineChannel->pSynthesisEvents[Event::destination_vcfr];  
             RTList<Event>::Iterator itResonanceEvent = pResonanceEventList->first();  
             if (Delay) { // skip events that happened before this voice was triggered  
                 while (itResonanceEvent && itResonanceEvent->FragmentPos() <= Delay) ++itResonanceEvent;  
             }  
             while (itResonanceEvent) {  
                 RTList<Event>::Iterator itNextResonanceEvent = itResonanceEvent;  
                 ++itNextResonanceEvent;  
   
                 // calculate the influence length of this event (in sample points)  
                 uint end = (itNextResonanceEvent) ? itNextResonanceEvent->FragmentPos() : Samples;  
   
                 // convert absolute controller value to differential  
                 int ctrldelta = itResonanceEvent->Param.CC.Value - VCFResonanceCtrl.value;  
                 VCFResonanceCtrl.value = itResonanceEvent->Param.CC.Value;  
   
                 float resonancedelta = (float) ctrldelta * 0.00787f; // 0.0..1.0  
   
                 // apply cutoff frequency to the cutoff parameter sequence  
                 for (uint i = itResonanceEvent->FragmentPos(); i < end; i++) {  
                     pEngine->pSynthesisParameters[Event::destination_vcfr][i] += resonancedelta;  
686                  }                  }
687                } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event
688                  itResonanceEvent = itNextResonanceEvent;                  processPitchEvent(itEvent);
689              }              }
             if (!pResonanceEventList->isEmpty()) VCFResonanceCtrl.fvalue = pResonanceEventList->last()->Param.CC.Value * 0.00787f; // needed for initialization of parameter matrix next time  
690          }          }
691      }      }
692    
693      /**      void Voice::processPitchEvent(RTList<Event>::Iterator& itEvent) {
694       * Calculate all necessary, final biquad filter parameters.          const float pitch = RTMath::CentsToFreqRatio(((double) itEvent->Param.Pitch.Pitch / 8192.0) * 200.0); // +-two semitones = +-200 cents
695       *          fFinalPitch *= pitch;
696       * @param Samples - number of samples to be rendered in this audio fragment cycle      }
      */  
     void Voice::CalculateBiquadParameters(uint Samples) {  
         biquad_param_t bqbase;  
         biquad_param_t bqmain;  
         float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0];  
         float prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][0];  
         FilterLeft.SetParameters( &bqbase, &bqmain, prev_cutoff + CONFIG_FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate);  
         FilterRight.SetParameters(&bqbase, &bqmain, prev_cutoff + CONFIG_FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate);  
         pEngine->pBasicFilterParameters[0] = bqbase;  
         pEngine->pMainFilterParameters[0]  = bqmain;  
   
         float* bq;  
         for (int i = 1; i < Samples; i++) {  
             // recalculate biquad parameters if cutoff or resonance differ from previous sample point  
             if (!(i & FILTER_UPDATE_MASK)) {  
                 if (pEngine->pSynthesisParameters[Event::destination_vcfr][i] != prev_res ||  
                     pEngine->pSynthesisParameters[Event::destination_vcfc][i] != prev_cutoff)  
                 {  
                     prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][i];  
                     prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][i];  
                     FilterLeft.SetParameters( &bqbase, &bqmain, prev_cutoff + CONFIG_FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate);  
                     FilterRight.SetParameters(&bqbase, &bqmain, prev_cutoff + CONFIG_FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate);  
                 }  
             }  
697    
698              //same as 'pEngine->pBasicFilterParameters[i] = bqbase;'      void Voice::processCrossFadeEvent(RTList<Event>::Iterator& itEvent) {
699              bq    = (float*) &pEngine->pBasicFilterParameters[i];          CrossfadeVolume = CrossfadeAttenuation(itEvent->Param.CC.Value);
700              bq[0] = bqbase.b0;          #if CONFIG_PROCESS_MUTED_CHANNELS
701              bq[1] = bqbase.b1;          const float effectiveVolume = CrossfadeVolume * Volume * (pEngineChannel->GetMute() ? 0 : pEngineChannel->GlobalVolume);
702              bq[2] = bqbase.b2;          #else
703              bq[3] = bqbase.a1;          const float effectiveVolume = CrossfadeVolume * Volume * pEngineChannel->GlobalVolume;
704              bq[4] = bqbase.a2;          #endif
705            fFinalVolume = effectiveVolume;
706              // same as 'pEngine->pMainFilterParameters[i] = bqmain;'      }
707              bq    = (float*) &pEngine->pMainFilterParameters[i];  
708              bq[0] = bqmain.b0;      void Voice::processCutoffEvent(RTList<Event>::Iterator& itEvent) {
709              bq[1] = bqmain.b1;          int ccvalue = itEvent->Param.CC.Value;
710              bq[2] = bqmain.b2;          if (VCFCutoffCtrl.value == ccvalue) return;
711              bq[3] = bqmain.a1;          VCFCutoffCtrl.value == ccvalue;
712              bq[4] = bqmain.a2;          if (pDimRgn->VCFCutoffControllerInvert)  ccvalue = 127 - ccvalue;
713          }          if (ccvalue < pDimRgn->VCFVelocityScale) ccvalue = pDimRgn->VCFVelocityScale;
714            float cutoff = CutoffBase * float(ccvalue) * 0.00787402f; // (1 / 127)
715            if (cutoff > 1.0) cutoff = 1.0;
716            cutoff = exp(cutoff * FILTER_CUTOFF_COEFF) * CONFIG_FILTER_CUTOFF_MIN - CONFIG_FILTER_CUTOFF_MIN;
717            VCFCutoffCtrl.fvalue = cutoff; // needed for initialization of fFinalCutoff next time
718            fFinalCutoff = cutoff;
719        }
720    
721        void Voice::processResonanceEvent(RTList<Event>::Iterator& itEvent) {
722            // convert absolute controller value to differential
723            const int ctrldelta = itEvent->Param.CC.Value - VCFResonanceCtrl.value;
724            VCFResonanceCtrl.value = itEvent->Param.CC.Value;
725            const float resonancedelta = (float) ctrldelta * 0.00787f; // 0.0..1.0
726            fFinalResonance += resonancedelta;
727            // needed for initialization of parameter
728            VCFResonanceCtrl.fvalue = itEvent->Param.CC.Value * 0.00787f;
729      }      }
730    
731      /**      /**
# Line 960  namespace LinuxSampler { namespace gig { Line 737  namespace LinuxSampler { namespace gig {
737       *  @param Skip    - number of sample points to skip in output buffer       *  @param Skip    - number of sample points to skip in output buffer
738       */       */
739      void Voice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {      void Voice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {
740          RunSynthesisFunction(SynthesisMode, *this, Samples, pSrc, Skip);          RTList<Event>::Iterator itCCEvent = pEngineChannel->pEvents->first();
741            RTList<Event>::Iterator itNoteEvent = pEngineChannel->pMIDIKeyInfo[MIDIKey].pEvents->first();
742                    
743            if (Skip) { // skip events that happened before this voice was triggered
744                while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;
745                while (itNoteEvent && itNoteEvent->FragmentPos() <= Skip) ++itNoteEvent;
746            }
747            
748            uint i = Skip;
749            while (i < Samples) {
750                int iSubFragmentEnd = RTMath::Min(i + CONFIG_DEFAULT_SUBFRAGMENT_SIZE, Samples);
751                
752                // initialize all final synthesis parameters
753                fFinalPitch = PitchBase * PitchBend;
754                #if CONFIG_PROCESS_MUTED_CHANNELS
755                fFinalVolume = this->Volume * this->CrossfadeVolume * (pEngineChannel->GetMute() ? 0 : pEngineChannel->GlobalVolume));
756                #else
757                fFinalVolume = this->Volume * this->CrossfadeVolume * pEngineChannel->GlobalVolume;
758                #endif
759                fFinalCutoff    = VCFCutoffCtrl.fvalue;
760                fFinalResonance = VCFResonanceCtrl.fvalue;
761                
762                // process MIDI control change and pitchbend events for this subfragment
763                processCCEvents(itCCEvent, iSubFragmentEnd);
764    
765                // process transition events (note on, note off & sustain pedal)
766                processTransitionEvents(itNoteEvent, iSubFragmentEnd);
767                
768                // process envelope generators
769                switch (EG1.getSegmentType()) {
770                    case EGADSR::segment_lin:
771                        fFinalVolume *= EG1.processLin();
772                        break;
773                    case EGADSR::segment_exp:
774                        fFinalVolume *= EG1.processExp();
775                        break;
776                    case EGADSR::segment_end:
777                        fFinalVolume *= EG1.getLevel();
778                        break; // noop
779                }
780                switch (EG2.getSegmentType()) {
781                    case EGADSR::segment_lin:
782                        fFinalCutoff *= EG2.processLin();
783                        break;
784                    case EGADSR::segment_exp:
785                        fFinalCutoff *= EG2.processExp();
786                        break;
787                    case EGADSR::segment_end:
788                        fFinalCutoff *= EG2.getLevel();
789                        break; // noop
790                }
791                fFinalPitch *= RTMath::CentsToFreqRatio(EG3.render());
792                
793                // process low frequency oscillators
794                if (bLFO1Enabled) fFinalVolume *= pLFO1->render();
795                if (bLFO2Enabled) fFinalCutoff *= pLFO2->render();
796                if (bLFO3Enabled) fFinalPitch  *= RTMath::CentsToFreqRatio(pLFO3->render());
797    
798                // if filter enabled then update filter coefficients
799                if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode)) {
800                    FilterLeft.SetParameters(fFinalCutoff, fFinalResonance, pEngine->SampleRate);
801                    FilterRight.SetParameters(fFinalCutoff, fFinalResonance, pEngine->SampleRate);
802                }
803    
804                // how many steps do we calculate for this next subfragment
805                const int steps = iSubFragmentEnd - i;
806                
807                // select the appropriate synthesis mode
808                SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, fFinalPitch != 1.0f);
809                
810                // render audio for one subfragment
811                RunSynthesisFunction(SynthesisMode, *this, iSubFragmentEnd, pSrc, i);
812    
813                // increment envelopes' positions            
814                if (EG1.active()) {
815                    EG1.increment(steps);
816                    if (!EG1.toStageEndLeft()) EG1.update(EGADSR::event_stage_end, this->Pos, fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
817                }
818                if (EG2.active()) {
819                    EG2.increment(steps);
820                    if (!EG2.toStageEndLeft()) EG2.update(EGADSR::event_stage_end, this->Pos, fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
821                }
822                EG3.increment(steps);
823                if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached
824            }
825      }      }
826    
827      /**      /**

Legend:
Removed from v.729  
changed lines
  Added in v.738

  ViewVC Help
Powered by ViewVC