/[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 287 by schoenebeck, Sat Oct 16 17:38:03 2004 UTC revision 738 by schoenebeck, Tue Aug 16 17:14:25 2005 UTC
# Line 3  Line 3 
3   *   LinuxSampler - modular, streaming capable sampler                     *   *   LinuxSampler - modular, streaming capable sampler                     *
4   *                                                                         *   *                                                                         *
5   *   Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck   *   *   Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck   *
6     *   Copyright (C) 2005 Christian Schoenebeck                              *
7   *                                                                         *   *                                                                         *
8   *   This program is free software; you can redistribute it and/or modify  *   *   This program is free software; you can redistribute it and/or modify  *
9   *   it under the terms of the GNU General Public License as published by  *   *   it under the terms of the GNU General Public License as published by  *
# Line 20  Line 21 
21   *   MA  02111-1307  USA                                                   *   *   MA  02111-1307  USA                                                   *
22   ***************************************************************************/   ***************************************************************************/
23    
24  #include "EGADSR.h"  #include "../../common/Features.h"
25  #include "Manipulator.h"  #include "Synthesizer.h"
26    
27  #include "Voice.h"  #include "Voice.h"
28    
# Line 29  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(FILTER_CUTOFF_MIN / FILTER_CUTOFF_MAX);          return log(CONFIG_FILTER_CUTOFF_MAX / CONFIG_FILTER_CUTOFF_MIN);
     }  
   
     int Voice::CalculateFilterUpdateMask() {  
         if (FILTER_UPDATE_PERIOD <= 0) return 0;  
         int power_of_two;  
         for (power_of_two = 0; 1<<power_of_two < FILTER_UPDATE_PERIOD; power_of_two++);  
         return (1 << power_of_two) - 1;  
35      }      }
36    
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
46            // select synthesis implementation (currently either pure C++ or MMX+SSE(1))
47            #if CONFIG_ASM && ARCH_X86
48            SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, Features::supportsMMX() && Features::supportsSSE());
49            #else
50            SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, false);
51            #endif
52            SYNTHESIS_MODE_SET_PROFILING(SynthesisMode, true);
53    
54            FilterLeft.Reset();
55            FilterRight.Reset();
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 103  namespace LinuxSampler { namespace gig { Line 71  namespace LinuxSampler { namespace gig {
71       *  Initializes and triggers the voice, a disk stream will be launched if       *  Initializes and triggers the voice, a disk stream will be launched if
72       *  needed.       *  needed.
73       *       *
74       *  @param itNoteOnEvent       - event that caused triggering of this voice       *  @param pEngineChannel - engine channel on which this voice was ordered
75       *  @param PitchBend           - MIDI detune factor (-8192 ... +8191)       *  @param itNoteOnEvent  - event that caused triggering of this voice
76       *  @param pInstrument         - points to the loaded instrument which provides sample wave(s) and articulation data       *  @param PitchBend      - MIDI detune factor (-8192 ... +8191)
77       *  @param iLayer              - layer number this voice refers to (only if this is a layered sound of course)       *  @param pDimRgn        - points to the dimension region which provides sample wave(s) and articulation data
78       *  @param ReleaseTriggerVoice - if this new voice is a release trigger voice (optional, default = false)       *  @param VoiceType      - type of this voice
79       *  @param VoiceStealing       - wether the voice is allowed to steal voices for further subvoices       *  @param iKeyGroup      - a value > 0 defines a key group in which this voice is member of
80       *  @returns 0 on success, a value < 0 if something failed       *  @returns 0 on success, a value < 0 if the voice wasn't triggered
81         *           (either due to an error or e.g. because no region is
82         *           defined for the given key)
83       */       */
84      int Voice::Trigger(Pool<Event>::Iterator& itNoteOnEvent, int PitchBend, ::gig::Instrument* pInstrument, int iLayer, bool ReleaseTriggerVoice, bool VoiceStealing) {      int Voice::Trigger(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent, int PitchBend, ::gig::DimensionRegion* pDimRgn, type_t VoiceType, int iKeyGroup) {
85          if (!pInstrument) {          this->pEngineChannel = pEngineChannel;
86             dmsg(1,("voice::trigger: !pInstrument\n"));          this->pDimRgn        = pDimRgn;
87             exit(EXIT_FAILURE);  
88            #if CONFIG_DEVMODE
89            if (itNoteOnEvent->FragmentPos() > pEngine->MaxSamplesPerCycle) { // just a sanity check for debugging
90                dmsg(1,("Voice::Trigger(): ERROR, TriggerDelay > Totalsamples\n"));
91          }          }
92            #endif // CONFIG_DEVMODE
93    
94          Type            = type_normal;          Type            = VoiceType;
95          MIDIKey         = itNoteOnEvent->Param.Note.Key;          MIDIKey         = itNoteOnEvent->Param.Note.Key;
96          pRegion         = pInstrument->GetRegion(MIDIKey);          PlaybackState   = playback_state_init; // mark voice as triggered, but no audio rendered yet
         PlaybackState   = playback_state_ram; // we always start playback from RAM cache and switch then to disk if needed  
97          Delay           = itNoteOnEvent->FragmentPos();          Delay           = itNoteOnEvent->FragmentPos();
98          itTriggerEvent  = itNoteOnEvent;          itTriggerEvent  = itNoteOnEvent;
99          itKillEvent     = Pool<Event>::Iterator();          itKillEvent     = Pool<Event>::Iterator();
100          itChildVoice    = Pool<Voice>::Iterator();          KeyGroup        = iKeyGroup;
101            pSample         = pDimRgn->pSample; // sample won't change until the voice is finished
102    
103          if (!pRegion) {          // calculate volume
104              std::cerr << "gig::Voice: No Region defined for MIDI key " << MIDIKey << std::endl << std::flush;          const double velocityAttenuation = pDimRgn->GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity);
             KillImmediately();  
             return -1;  
         }  
105    
106          KeyGroup = pRegion->KeyGroup;          Volume = velocityAttenuation / 32768.0f; // we downscale by 32768 to convert from int16 value range to DSP value range (which is -1.0..1.0)
107    
108          // get current dimension values to select the right dimension region          Volume *= pDimRgn->SampleAttenuation;
109          //FIXME: controller values for selecting the dimension region here are currently not sample accurate  
110          uint DimValues[5] = {0,0,0,0,0};          // the volume of release triggered samples depends on note length
111          for (int i = pRegion->Dimensions - 1; i >= 0; i--) {          if (Type == type_release_trigger) {
112              switch (pRegion->pDimensionDefinitions[i].dimension) {              float noteLength = float(pEngine->FrameTime + Delay -
113                  case ::gig::dimension_samplechannel:                                       pEngineChannel->pMIDIKeyInfo[MIDIKey].NoteOnTime) / pEngine->SampleRate;
114                      DimValues[i] = 0; //TODO: we currently ignore this dimension              float attenuation = 1 - 0.01053 * (256 >> pDimRgn->ReleaseTriggerDecay) * noteLength;
115                      break;              if (attenuation <= 0) return -1;
116                  case ::gig::dimension_layer:              Volume *= attenuation;
                     DimValues[i] = iLayer;  
                     // if this is the 1st layer then spawn further voices for all the other layers  
                     if (iLayer == 0)  
                         for (int iNewLayer = 1; iNewLayer < pRegion->pDimensionDefinitions[i].zones; iNewLayer++)  
                             itChildVoice = pEngine->LaunchVoice(itNoteOnEvent, iNewLayer, ReleaseTriggerVoice, VoiceStealing);  
                     break;  
                 case ::gig::dimension_velocity:  
                     DimValues[i] = itNoteOnEvent->Param.Note.Velocity;  
                     break;  
                 case ::gig::dimension_channelaftertouch:  
                     DimValues[i] = 0; //TODO: we currently ignore this dimension  
                     break;  
                 case ::gig::dimension_releasetrigger:  
                     Type = (ReleaseTriggerVoice) ? type_release_trigger : (!iLayer) ? type_release_trigger_required : type_normal;  
                     DimValues[i] = (uint) ReleaseTriggerVoice;  
                     break;  
                 case ::gig::dimension_keyboard:  
                     DimValues[i] = (uint) itNoteOnEvent->Param.Note.Key;  
                     break;  
                 case ::gig::dimension_modwheel:  
                     DimValues[i] = pEngine->ControllerTable[1];  
                     break;  
                 case ::gig::dimension_breath:  
                     DimValues[i] = pEngine->ControllerTable[2];  
                     break;  
                 case ::gig::dimension_foot:  
                     DimValues[i] = pEngine->ControllerTable[4];  
                     break;  
                 case ::gig::dimension_portamentotime:  
                     DimValues[i] = pEngine->ControllerTable[5];  
                     break;  
                 case ::gig::dimension_effect1:  
                     DimValues[i] = pEngine->ControllerTable[12];  
                     break;  
                 case ::gig::dimension_effect2:  
                     DimValues[i] = pEngine->ControllerTable[13];  
                     break;  
                 case ::gig::dimension_genpurpose1:  
                     DimValues[i] = pEngine->ControllerTable[16];  
                     break;  
                 case ::gig::dimension_genpurpose2:  
                     DimValues[i] = pEngine->ControllerTable[17];  
                     break;  
                 case ::gig::dimension_genpurpose3:  
                     DimValues[i] = pEngine->ControllerTable[18];  
                     break;  
                 case ::gig::dimension_genpurpose4:  
                     DimValues[i] = pEngine->ControllerTable[19];  
                     break;  
                 case ::gig::dimension_sustainpedal:  
                     DimValues[i] = pEngine->ControllerTable[64];  
                     break;  
                 case ::gig::dimension_portamento:  
                     DimValues[i] = pEngine->ControllerTable[65];  
                     break;  
                 case ::gig::dimension_sostenutopedal:  
                     DimValues[i] = pEngine->ControllerTable[66];  
                     break;  
                 case ::gig::dimension_softpedal:  
                     DimValues[i] = pEngine->ControllerTable[67];  
                     break;  
                 case ::gig::dimension_genpurpose5:  
                     DimValues[i] = pEngine->ControllerTable[80];  
                     break;  
                 case ::gig::dimension_genpurpose6:  
                     DimValues[i] = pEngine->ControllerTable[81];  
                     break;  
                 case ::gig::dimension_genpurpose7:  
                     DimValues[i] = pEngine->ControllerTable[82];  
                     break;  
                 case ::gig::dimension_genpurpose8:  
                     DimValues[i] = pEngine->ControllerTable[83];  
                     break;  
                 case ::gig::dimension_effect1depth:  
                     DimValues[i] = pEngine->ControllerTable[91];  
                     break;  
                 case ::gig::dimension_effect2depth:  
                     DimValues[i] = pEngine->ControllerTable[92];  
                     break;  
                 case ::gig::dimension_effect3depth:  
                     DimValues[i] = pEngine->ControllerTable[93];  
                     break;  
                 case ::gig::dimension_effect4depth:  
                     DimValues[i] = pEngine->ControllerTable[94];  
                     break;  
                 case ::gig::dimension_effect5depth:  
                     DimValues[i] = pEngine->ControllerTable[95];  
                     break;  
                 case ::gig::dimension_none:  
                     std::cerr << "gig::Voice::Trigger() Error: dimension=none\n" << std::flush;  
                     break;  
                 default:  
                     std::cerr << "gig::Voice::Trigger() Error: Unknown dimension\n" << std::flush;  
             }  
117          }          }
118          pDimRgn = pRegion->GetDimensionRegionByValue(DimValues[4],DimValues[3],DimValues[2],DimValues[1],DimValues[0]);  
119            // select channel mode (mono or stereo)
120            SYNTHESIS_MODE_SET_CHANNELS(SynthesisMode, pSample->Channels == 2);
121    
122          // get starting crossfade volume level          // get starting crossfade volume level
123          switch (pDimRgn->AttenuationController.type) {          switch (pDimRgn->AttenuationController.type) {
# Line 249  namespace LinuxSampler { namespace gig { Line 128  namespace LinuxSampler { namespace gig {
128                  CrossfadeVolume = CrossfadeAttenuation(itNoteOnEvent->Param.Note.Velocity);                  CrossfadeVolume = CrossfadeAttenuation(itNoteOnEvent->Param.Note.Velocity);
129                  break;                  break;
130              case ::gig::attenuation_ctrl_t::type_controlchange: //FIXME: currently not sample accurate              case ::gig::attenuation_ctrl_t::type_controlchange: //FIXME: currently not sample accurate
131                  CrossfadeVolume = CrossfadeAttenuation(pEngine->ControllerTable[pDimRgn->AttenuationController.controller_number]);                  CrossfadeVolume = CrossfadeAttenuation(pEngineChannel->ControllerTable[pDimRgn->AttenuationController.controller_number]);
132                  break;                  break;
133              case ::gig::attenuation_ctrl_t::type_none: // no crossfade defined              case ::gig::attenuation_ctrl_t::type_none: // no crossfade defined
134              default:              default:
# Line 259  namespace LinuxSampler { namespace gig { Line 138  namespace LinuxSampler { namespace gig {
138          PanLeft  = 1.0f - float(RTMath::Max(pDimRgn->Pan, 0)) /  63.0f;          PanLeft  = 1.0f - float(RTMath::Max(pDimRgn->Pan, 0)) /  63.0f;
139          PanRight = 1.0f - float(RTMath::Min(pDimRgn->Pan, 0)) / -64.0f;          PanRight = 1.0f - float(RTMath::Min(pDimRgn->Pan, 0)) / -64.0f;
140    
         pSample = pDimRgn->pSample; // sample won't change until the voice is finished  
   
141          Pos = pDimRgn->SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)          Pos = pDimRgn->SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)
142    
143          // Check if the sample needs disk streaming or is too short for that          // Check if the sample needs disk streaming or is too short for that
# Line 268  namespace LinuxSampler { namespace gig { Line 145  namespace LinuxSampler { namespace gig {
145          DiskVoice          = cachedsamples < pSample->SamplesTotal;          DiskVoice          = cachedsamples < pSample->SamplesTotal;
146    
147          if (DiskVoice) { // voice to be streamed from disk          if (DiskVoice) { // voice to be streamed from disk
148              MaxRAMPos = cachedsamples - (pEngine->MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels; //TODO: this calculation is too pessimistic and may better be moved to Render() method, so it calculates MaxRAMPos dependent to the current demand of sample points to be rendered (e.g. in case of JACK)              MaxRAMPos = cachedsamples - (pEngine->MaxSamplesPerCycle << CONFIG_MAX_PITCH) / pSample->Channels; //TODO: this calculation is too pessimistic and may better be moved to Render() method, so it calculates MaxRAMPos dependent to the current demand of sample points to be rendered (e.g. in case of JACK)
149    
150              // check if there's a loop defined which completely fits into the cached (RAM) part of the sample              // check if there's a loop defined which completely fits into the cached (RAM) part of the sample
151              if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) {              if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) {
# Line 297  namespace LinuxSampler { namespace gig { Line 174  namespace LinuxSampler { namespace gig {
174    
175          // calculate initial pitch value          // calculate initial pitch value
176          {          {
177              double pitchbasecents = pDimRgn->FineTune * 10 + (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    
183            // the length of the decay and release curves are dependent on the velocity
184          Volume = pDimRgn->GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity) / 32768.0f; // we downscale by 32768 to convert from int16 value range to DSP value range (which is -1.0..1.0)          const double velrelease = 1 / pDimRgn->GetVelocityRelease(itNoteOnEvent->Param.Note.Velocity);
   
185    
186          // setup EG 1 (VCA EG)          // setup EG 1 (VCA EG)
187          {          {
# Line 322  namespace LinuxSampler { namespace gig { Line 198  namespace LinuxSampler { namespace gig {
198                      eg1controllervalue = itNoteOnEvent->Param.Note.Velocity;                      eg1controllervalue = itNoteOnEvent->Param.Note.Velocity;
199                      break;                      break;
200                  case ::gig::eg1_ctrl_t::type_controlchange: // MIDI control change controller                  case ::gig::eg1_ctrl_t::type_controlchange: // MIDI control change controller
201                      eg1controllervalue = pEngine->ControllerTable[pDimRgn->EG1Controller.controller_number];                      eg1controllervalue = pEngineChannel->ControllerTable[pDimRgn->EG1Controller.controller_number];
202                      break;                      break;
203              }              }
204              if (pDimRgn->EG1ControllerInvert) eg1controllervalue = 127 - eg1controllervalue;              if (pDimRgn->EG1ControllerInvert) eg1controllervalue = 127 - eg1controllervalue;
205    
206              // calculate influence of EG1 controller on EG1's parameters (TODO: needs to be fine tuned)              // calculate influence of EG1 controller on EG1's parameters
207              double eg1attack  = (pDimRgn->EG1ControllerAttackInfluence)  ? 0.0001 * (double) (1 << pDimRgn->EG1ControllerAttackInfluence)  * eg1controllervalue : 0.0;              // (eg1attack is different from the others)
208              double eg1decay   = (pDimRgn->EG1ControllerDecayInfluence)   ? 0.0001 * (double) (1 << pDimRgn->EG1ControllerDecayInfluence)   * eg1controllervalue : 0.0;              double eg1attack  = (pDimRgn->EG1ControllerAttackInfluence)  ?
209              double eg1release = (pDimRgn->EG1ControllerReleaseInfluence) ? 0.0001 * (double) (1 << pDimRgn->EG1ControllerReleaseInfluence) * eg1controllervalue : 0.0;                  1 + 0.031 * (double) (pDimRgn->EG1ControllerAttackInfluence == 1 ?
210                                          1 : 1 << pDimRgn->EG1ControllerAttackInfluence) * eg1controllervalue : 1.0;
211              pEG1->Trigger(pDimRgn->EG1PreAttack,              double eg1decay   = (pDimRgn->EG1ControllerDecayInfluence)   ? 1 + 0.00775 * (double) (1 << pDimRgn->EG1ControllerDecayInfluence)   * eg1controllervalue : 1.0;
212                            pDimRgn->EG1Attack + eg1attack,              double eg1release = (pDimRgn->EG1ControllerReleaseInfluence) ? 1 + 0.00775 * (double) (1 << pDimRgn->EG1ControllerReleaseInfluence) * eg1controllervalue : 1.0;
213                            pDimRgn->EG1Hold,  
214                            pSample->LoopStart,              EG1.trigger(pDimRgn->EG1PreAttack,
215                            pDimRgn->EG1Decay1 + eg1decay,                          pDimRgn->EG1Attack * eg1attack,
216                            pDimRgn->EG1Decay2 + eg1decay,                          pDimRgn->EG1Hold,
217                            pDimRgn->EG1InfiniteSustain,                          pSample->LoopStart,
218                            pDimRgn->EG1Sustain,                          pDimRgn->EG1Decay1 * eg1decay * velrelease,
219                            pDimRgn->EG1Release + eg1release,                          pDimRgn->EG1Decay2 * eg1decay * velrelease,
220                            Delay);                          pDimRgn->EG1InfiniteSustain,
221                            pDimRgn->EG1Sustain,
222                            pDimRgn->EG1Release * eg1release * velrelease,
223                            velocityAttenuation,
224                            pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
225          }          }
226    
227    
     #if ENABLE_FILTER  
228          // setup EG 2 (VCF Cutoff EG)          // setup EG 2 (VCF Cutoff EG)
229          {          {
230              // get current value of EG2 controller              // get current value of EG2 controller
# Line 361  namespace LinuxSampler { namespace gig { Line 240  namespace LinuxSampler { namespace gig {
240                      eg2controllervalue = itNoteOnEvent->Param.Note.Velocity;                      eg2controllervalue = itNoteOnEvent->Param.Note.Velocity;
241                      break;                      break;
242                  case ::gig::eg2_ctrl_t::type_controlchange: // MIDI control change controller                  case ::gig::eg2_ctrl_t::type_controlchange: // MIDI control change controller
243                      eg2controllervalue = pEngine->ControllerTable[pDimRgn->EG2Controller.controller_number];                      eg2controllervalue = pEngineChannel->ControllerTable[pDimRgn->EG2Controller.controller_number];
244                      break;                      break;
245              }              }
246              if (pDimRgn->EG2ControllerInvert) eg2controllervalue = 127 - eg2controllervalue;              if (pDimRgn->EG2ControllerInvert) eg2controllervalue = 127 - eg2controllervalue;
247    
248              // calculate influence of EG2 controller on EG2's parameters (TODO: needs to be fine tuned)              // calculate influence of EG2 controller on EG2's parameters
249              double eg2attack  = (pDimRgn->EG2ControllerAttackInfluence)  ? 0.0001 * (double) (1 << pDimRgn->EG2ControllerAttackInfluence)  * eg2controllervalue : 0.0;              double eg2attack  = (pDimRgn->EG2ControllerAttackInfluence)  ? 1 + 0.00775 * (double) (1 << pDimRgn->EG2ControllerAttackInfluence)  * eg2controllervalue : 1.0;
250              double eg2decay   = (pDimRgn->EG2ControllerDecayInfluence)   ? 0.0001 * (double) (1 << pDimRgn->EG2ControllerDecayInfluence)   * eg2controllervalue : 0.0;              double eg2decay   = (pDimRgn->EG2ControllerDecayInfluence)   ? 1 + 0.00775 * (double) (1 << pDimRgn->EG2ControllerDecayInfluence)   * eg2controllervalue : 1.0;
251              double eg2release = (pDimRgn->EG2ControllerReleaseInfluence) ? 0.0001 * (double) (1 << pDimRgn->EG2ControllerReleaseInfluence) * eg2controllervalue : 0.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,                          pDimRgn->EG2Decay1 * eg2decay * velrelease,
258                            pDimRgn->EG2Decay2 + eg2decay,                          pDimRgn->EG2Decay2 * eg2decay * velrelease,
259                            pDimRgn->EG2InfiniteSustain,                          pDimRgn->EG2InfiniteSustain,
260                            pDimRgn->EG2Sustain,                          pDimRgn->EG2Sustain,
261                            pDimRgn->EG2Release + eg2release,                          pDimRgn->EG2Release * eg2release * velrelease,
262                            Delay);                          velocityAttenuation,
263                            pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
264          }          }
     #endif // ENABLE_FILTER  
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 399  namespace LinuxSampler { namespace gig { Line 278  namespace LinuxSampler { namespace gig {
278                  case ::gig::lfo1_ctrl_internal:                  case ::gig::lfo1_ctrl_internal:
279                      lfo1_internal_depth  = pDimRgn->LFO1InternalDepth;                      lfo1_internal_depth  = pDimRgn->LFO1InternalDepth;
280                      pLFO1->ExtController = 0; // no external controller                      pLFO1->ExtController = 0; // no external controller
281                        bLFO1Enabled         = (lfo1_internal_depth > 0);
282                      break;                      break;
283                  case ::gig::lfo1_ctrl_modwheel:                  case ::gig::lfo1_ctrl_modwheel:
284                      lfo1_internal_depth  = 0;                      lfo1_internal_depth  = 0;
285                      pLFO1->ExtController = 1; // MIDI controller 1                      pLFO1->ExtController = 1; // MIDI controller 1
286                        bLFO1Enabled         = (pDimRgn->LFO1ControlDepth > 0);
287                      break;                      break;
288                  case ::gig::lfo1_ctrl_breath:                  case ::gig::lfo1_ctrl_breath:
289                      lfo1_internal_depth  = 0;                      lfo1_internal_depth  = 0;
290                      pLFO1->ExtController = 2; // MIDI controller 2                      pLFO1->ExtController = 2; // MIDI controller 2
291                        bLFO1Enabled         = (pDimRgn->LFO1ControlDepth > 0);
292                      break;                      break;
293                  case ::gig::lfo1_ctrl_internal_modwheel:                  case ::gig::lfo1_ctrl_internal_modwheel:
294                      lfo1_internal_depth  = pDimRgn->LFO1InternalDepth;                      lfo1_internal_depth  = pDimRgn->LFO1InternalDepth;
295                      pLFO1->ExtController = 1; // MIDI controller 1                      pLFO1->ExtController = 1; // MIDI controller 1
296                        bLFO1Enabled         = (lfo1_internal_depth > 0 || pDimRgn->LFO1ControlDepth > 0);
297                      break;                      break;
298                  case ::gig::lfo1_ctrl_internal_breath:                  case ::gig::lfo1_ctrl_internal_breath:
299                      lfo1_internal_depth  = pDimRgn->LFO1InternalDepth;                      lfo1_internal_depth  = pDimRgn->LFO1InternalDepth;
300                      pLFO1->ExtController = 2; // MIDI controller 2                      pLFO1->ExtController = 2; // MIDI controller 2
301                        bLFO1Enabled         = (lfo1_internal_depth > 0 || pDimRgn->LFO1ControlDepth > 0);
302                      break;                      break;
303                  default:                  default:
304                      lfo1_internal_depth  = 0;                      lfo1_internal_depth  = 0;
305                      pLFO1->ExtController = 0; // no external controller                      pLFO1->ExtController = 0; // no external controller
306                        bLFO1Enabled         = false;
307              }              }
308              pLFO1->Trigger(pDimRgn->LFO1Frequency,              if (bLFO1Enabled) pLFO1->trigger(pDimRgn->LFO1Frequency,
309                            lfo1_internal_depth,                                               start_level_max,
310                            pDimRgn->LFO1ControlDepth,                                               lfo1_internal_depth,
311                            pEngine->ControllerTable[pLFO1->ExtController],                                               pDimRgn->LFO1ControlDepth,
312                            pDimRgn->LFO1FlipPhase,                                               pDimRgn->LFO1FlipPhase,
313                            pEngine->SampleRate,                                               pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
                           Delay);  
314          }          }
315    
316      #if ENABLE_FILTER  
317          // setup LFO 2 (VCF Cutoff LFO)          // setup LFO 2 (VCF Cutoff LFO)
318          {          {
319              uint16_t lfo2_internal_depth;              uint16_t lfo2_internal_depth;
# Line 437  namespace LinuxSampler { namespace gig { Line 321  namespace LinuxSampler { namespace gig {
321                  case ::gig::lfo2_ctrl_internal:                  case ::gig::lfo2_ctrl_internal:
322                      lfo2_internal_depth  = pDimRgn->LFO2InternalDepth;                      lfo2_internal_depth  = pDimRgn->LFO2InternalDepth;
323                      pLFO2->ExtController = 0; // no external controller                      pLFO2->ExtController = 0; // no external controller
324                        bLFO2Enabled         = (lfo2_internal_depth > 0);
325                      break;                      break;
326                  case ::gig::lfo2_ctrl_modwheel:                  case ::gig::lfo2_ctrl_modwheel:
327                      lfo2_internal_depth  = 0;                      lfo2_internal_depth  = 0;
328                      pLFO2->ExtController = 1; // MIDI controller 1                      pLFO2->ExtController = 1; // MIDI controller 1
329                        bLFO2Enabled         = (pDimRgn->LFO2ControlDepth > 0);
330                      break;                      break;
331                  case ::gig::lfo2_ctrl_foot:                  case ::gig::lfo2_ctrl_foot:
332                      lfo2_internal_depth  = 0;                      lfo2_internal_depth  = 0;
333                      pLFO2->ExtController = 4; // MIDI controller 4                      pLFO2->ExtController = 4; // MIDI controller 4
334                        bLFO2Enabled         = (pDimRgn->LFO2ControlDepth > 0);
335                      break;                      break;
336                  case ::gig::lfo2_ctrl_internal_modwheel:                  case ::gig::lfo2_ctrl_internal_modwheel:
337                      lfo2_internal_depth  = pDimRgn->LFO2InternalDepth;                      lfo2_internal_depth  = pDimRgn->LFO2InternalDepth;
338                      pLFO2->ExtController = 1; // MIDI controller 1                      pLFO2->ExtController = 1; // MIDI controller 1
339                        bLFO2Enabled         = (lfo2_internal_depth > 0 || pDimRgn->LFO2ControlDepth > 0);
340                      break;                      break;
341                  case ::gig::lfo2_ctrl_internal_foot:                  case ::gig::lfo2_ctrl_internal_foot:
342                      lfo2_internal_depth  = pDimRgn->LFO2InternalDepth;                      lfo2_internal_depth  = pDimRgn->LFO2InternalDepth;
343                      pLFO2->ExtController = 4; // MIDI controller 4                      pLFO2->ExtController = 4; // MIDI controller 4
344                        bLFO2Enabled         = (lfo2_internal_depth > 0 || pDimRgn->LFO2ControlDepth > 0);
345                      break;                      break;
346                  default:                  default:
347                      lfo2_internal_depth  = 0;                      lfo2_internal_depth  = 0;
348                      pLFO2->ExtController = 0; // no external controller                      pLFO2->ExtController = 0; // no external controller
349                        bLFO2Enabled         = false;
350              }              }
351              pLFO2->Trigger(pDimRgn->LFO2Frequency,              if (bLFO2Enabled) pLFO2->trigger(pDimRgn->LFO2Frequency,
352                            lfo2_internal_depth,                                               start_level_max,
353                            pDimRgn->LFO2ControlDepth,                                               lfo2_internal_depth,
354                            pEngine->ControllerTable[pLFO2->ExtController],                                               pDimRgn->LFO2ControlDepth,
355                            pDimRgn->LFO2FlipPhase,                                               pDimRgn->LFO2FlipPhase,
356                            pEngine->SampleRate,                                               pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
                           Delay);  
357          }          }
358      #endif // ENABLE_FILTER  
359    
360          // setup LFO 3 (VCO LFO)          // setup LFO 3 (VCO LFO)
361          {          {
# Line 475  namespace LinuxSampler { namespace gig { Line 364  namespace LinuxSampler { namespace gig {
364                  case ::gig::lfo3_ctrl_internal:                  case ::gig::lfo3_ctrl_internal:
365                      lfo3_internal_depth  = pDimRgn->LFO3InternalDepth;                      lfo3_internal_depth  = pDimRgn->LFO3InternalDepth;
366                      pLFO3->ExtController = 0; // no external controller                      pLFO3->ExtController = 0; // no external controller
367                        bLFO3Enabled         = (lfo3_internal_depth > 0);
368                      break;                      break;
369                  case ::gig::lfo3_ctrl_modwheel:                  case ::gig::lfo3_ctrl_modwheel:
370                      lfo3_internal_depth  = 0;                      lfo3_internal_depth  = 0;
371                      pLFO3->ExtController = 1; // MIDI controller 1                      pLFO3->ExtController = 1; // MIDI controller 1
372                        bLFO3Enabled         = (pDimRgn->LFO3ControlDepth > 0);
373                      break;                      break;
374                  case ::gig::lfo3_ctrl_aftertouch:                  case ::gig::lfo3_ctrl_aftertouch:
375                      lfo3_internal_depth  = 0;                      lfo3_internal_depth  = 0;
376                      pLFO3->ExtController = 0; // TODO: aftertouch not implemented yet                      pLFO3->ExtController = 0; // TODO: aftertouch not implemented yet
377                        bLFO3Enabled         = false; // see TODO comment in line above
378                      break;                      break;
379                  case ::gig::lfo3_ctrl_internal_modwheel:                  case ::gig::lfo3_ctrl_internal_modwheel:
380                      lfo3_internal_depth  = pDimRgn->LFO3InternalDepth;                      lfo3_internal_depth  = pDimRgn->LFO3InternalDepth;
381                      pLFO3->ExtController = 1; // MIDI controller 1                      pLFO3->ExtController = 1; // MIDI controller 1
382                        bLFO3Enabled         = (lfo3_internal_depth > 0 || pDimRgn->LFO3ControlDepth > 0);
383                      break;                      break;
384                  case ::gig::lfo3_ctrl_internal_aftertouch:                  case ::gig::lfo3_ctrl_internal_aftertouch:
385                      lfo3_internal_depth  = pDimRgn->LFO3InternalDepth;                      lfo3_internal_depth  = pDimRgn->LFO3InternalDepth;
386                      pLFO1->ExtController = 0; // TODO: aftertouch not implemented yet                      pLFO1->ExtController = 0; // TODO: aftertouch not implemented yet
387                        bLFO3Enabled         = (lfo3_internal_depth > 0 /*|| pDimRgn->LFO3ControlDepth > 0*/); // see TODO comment in line above
388                      break;                      break;
389                  default:                  default:
390                      lfo3_internal_depth  = 0;                      lfo3_internal_depth  = 0;
391                      pLFO3->ExtController = 0; // no external controller                      pLFO3->ExtController = 0; // no external controller
392                        bLFO3Enabled         = false;
393              }              }
394              pLFO3->Trigger(pDimRgn->LFO3Frequency,              if (bLFO3Enabled) pLFO3->trigger(pDimRgn->LFO3Frequency,
395                            lfo3_internal_depth,                                               start_level_mid,
396                            pDimRgn->LFO3ControlDepth,                                               lfo3_internal_depth,
397                            pEngine->ControllerTable[pLFO3->ExtController],                                               pDimRgn->LFO3ControlDepth,
398                            false,                                               false,
399                            pEngine->SampleRate,                                               pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
                           Delay);  
400          }          }
401    
402      #if ENABLE_FILTER  
403          #if FORCE_FILTER_USAGE          #if CONFIG_FORCE_FILTER
404          FilterLeft.Enabled = FilterRight.Enabled = true;          const bool bUseFilter = true;
405          #else // use filter only if instrument file told so          #else // use filter only if instrument file told so
406          FilterLeft.Enabled = FilterRight.Enabled = pDimRgn->VCFEnabled;          const bool bUseFilter = pDimRgn->VCFEnabled;
407          #endif // FORCE_FILTER_USAGE          #endif // CONFIG_FORCE_FILTER
408          if (pDimRgn->VCFEnabled) {          SYNTHESIS_MODE_SET_FILTER(SynthesisMode, bUseFilter);
409              #ifdef OVERRIDE_FILTER_CUTOFF_CTRL          if (bUseFilter) {
410              VCFCutoffCtrl.controller = OVERRIDE_FILTER_CUTOFF_CTRL;              #ifdef CONFIG_OVERRIDE_CUTOFF_CTRL
411                VCFCutoffCtrl.controller = CONFIG_OVERRIDE_CUTOFF_CTRL;
412              #else // use the one defined in the instrument file              #else // use the one defined in the instrument file
413              switch (pDimRgn->VCFCutoffController) {              switch (pDimRgn->VCFCutoffController) {
414                  case ::gig::vcf_cutoff_ctrl_modwheel:                  case ::gig::vcf_cutoff_ctrl_modwheel:
# Line 549  namespace LinuxSampler { namespace gig { Line 444  namespace LinuxSampler { namespace gig {
444                      VCFCutoffCtrl.controller = 0;                      VCFCutoffCtrl.controller = 0;
445                      break;                      break;
446              }              }
447              #endif // OVERRIDE_FILTER_CUTOFF_CTRL              #endif // CONFIG_OVERRIDE_CUTOFF_CTRL
448    
449              #ifdef OVERRIDE_FILTER_RES_CTRL              #ifdef CONFIG_OVERRIDE_RESONANCE_CTRL
450              VCFResonanceCtrl.controller = OVERRIDE_FILTER_RES_CTRL;              VCFResonanceCtrl.controller = CONFIG_OVERRIDE_RESONANCE_CTRL;
451              #else // use the one defined in the instrument file              #else // use the one defined in the instrument file
452              switch (pDimRgn->VCFResonanceController) {              switch (pDimRgn->VCFResonanceController) {
453                  case ::gig::vcf_res_ctrl_genpurpose3:                  case ::gig::vcf_res_ctrl_genpurpose3:
# Line 571  namespace LinuxSampler { namespace gig { Line 466  namespace LinuxSampler { namespace gig {
466                  default:                  default:
467                      VCFResonanceCtrl.controller = 0;                      VCFResonanceCtrl.controller = 0;
468              }              }
469              #endif // OVERRIDE_FILTER_RES_CTRL              #endif // CONFIG_OVERRIDE_RESONANCE_CTRL
470    
471              #ifndef OVERRIDE_FILTER_TYPE              #ifndef CONFIG_OVERRIDE_FILTER_TYPE
472              FilterLeft.SetType(pDimRgn->VCFType);              FilterLeft.SetType(pDimRgn->VCFType);
473              FilterRight.SetType(pDimRgn->VCFType);              FilterRight.SetType(pDimRgn->VCFType);
474              #else // override filter type              #else // override filter type
475              FilterLeft.SetType(OVERRIDE_FILTER_TYPE);              FilterLeft.SetType(CONFIG_OVERRIDE_FILTER_TYPE);
476              FilterRight.SetType(OVERRIDE_FILTER_TYPE);              FilterRight.SetType(CONFIG_OVERRIDE_FILTER_TYPE);
477              #endif // OVERRIDE_FILTER_TYPE              #endif // CONFIG_OVERRIDE_FILTER_TYPE
478    
479              VCFCutoffCtrl.value    = pEngine->ControllerTable[VCFCutoffCtrl.controller];              VCFCutoffCtrl.value    = pEngineChannel->ControllerTable[VCFCutoffCtrl.controller];
480              VCFResonanceCtrl.value = pEngine->ControllerTable[VCFResonanceCtrl.controller];              VCFResonanceCtrl.value = pEngineChannel->ControllerTable[VCFResonanceCtrl.controller];
481    
482              // calculate cutoff frequency              // calculate cutoff frequency
483              float cutoff = (!VCFCutoffCtrl.controller)              float cutoff = pDimRgn->GetVelocityCutoff(itNoteOnEvent->Param.Note.Velocity);
484                  ? exp((float) (127 - itNoteOnEvent->Param.Note.Velocity) * (float) pDimRgn->VCFVelocityScale * 6.2E-5f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX              if (pDimRgn->VCFKeyboardTracking) {
485                  : exp((float) VCFCutoffCtrl.value * 0.00787402f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX;                  cutoff *= exp((itNoteOnEvent->Param.Note.Key - pDimRgn->VCFKeyboardTrackingBreakpoint) * 0.057762265f); // (ln(2) / 12)
486                }
487                CutoffBase = cutoff;
488    
489                int cvalue;
490                if (VCFCutoffCtrl.controller) {
491                    cvalue = pEngineChannel->ControllerTable[VCFCutoffCtrl.controller];
492                    if (pDimRgn->VCFCutoffControllerInvert) cvalue = 127 - cvalue;
493                    if (cvalue < pDimRgn->VCFVelocityScale) cvalue = pDimRgn->VCFVelocityScale;
494                }
495                else {
496                    cvalue = pDimRgn->VCFCutoff;
497                }
498                cutoff *= float(cvalue) * 0.00787402f; // (1 / 127)
499                if (cutoff > 1.0) cutoff = 1.0;
500                cutoff = exp(cutoff * FILTER_CUTOFF_COEFF) * CONFIG_FILTER_CUTOFF_MIN;
501    
502              // calculate resonance              // calculate resonance
503              float resonance = (float) VCFResonanceCtrl.value * 0.00787f;   // 0.0..1.0              float resonance = (float) VCFResonanceCtrl.value * 0.00787f;   // 0.0..1.0
# Line 596  namespace LinuxSampler { namespace gig { Line 506  namespace LinuxSampler { namespace gig {
506              }              }
507              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)
508    
509              VCFCutoffCtrl.fvalue    = cutoff - FILTER_CUTOFF_MIN;              VCFCutoffCtrl.fvalue    = cutoff - CONFIG_FILTER_CUTOFF_MIN;
510              VCFResonanceCtrl.fvalue = resonance;              VCFResonanceCtrl.fvalue = resonance;
   
             FilterLeft.SetParameters(cutoff,  resonance, pEngine->SampleRate);  
             FilterRight.SetParameters(cutoff, resonance, pEngine->SampleRate);  
   
             FilterUpdateCounter = -1;  
511          }          }
512          else {          else {
513              VCFCutoffCtrl.controller    = 0;              VCFCutoffCtrl.controller    = 0;
514              VCFResonanceCtrl.controller = 0;              VCFResonanceCtrl.controller = 0;
515          }          }
     #endif // ENABLE_FILTER  
516    
517          return 0; // success          return 0; // success
518      }      }
# Line 626  namespace LinuxSampler { namespace gig { Line 530  namespace LinuxSampler { namespace gig {
530       */       */
531      void Voice::Render(uint Samples) {      void Voice::Render(uint Samples) {
532    
533          // Reset the synthesis parameter matrix          // select default values for synthesis mode bits
534          pEngine->ResetSynthesisParameters(Event::destination_vca, this->Volume * this->CrossfadeVolume * pEngine->GlobalVolume);          SYNTHESIS_MODE_SET_LOOP(SynthesisMode, false);
         pEngine->ResetSynthesisParameters(Event::destination_vco, this->PitchBase);  
     #if ENABLE_FILTER  
         pEngine->ResetSynthesisParameters(Event::destination_vcfc, VCFCutoffCtrl.fvalue);  
         pEngine->ResetSynthesisParameters(Event::destination_vcfr, VCFResonanceCtrl.fvalue);  
     #endif // ENABLE_FILTER  
   
   
         // 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, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, itTriggerEvent, this->Pos, this->PitchBase * this->PitchBend, itKillEvent);  
     #if ENABLE_FILTER  
         pEG2->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, itTriggerEvent, this->Pos, this->PitchBase * this->PitchBend);  
     #endif // ENABLE_FILTER  
         pEG3->Process(Samples);  
         pLFO1->Process(Samples);  
     #if ENABLE_FILTER  
         pLFO2->Process(Samples);  
     #endif // ENABLE_FILTER  
         pLFO3->Process(Samples);  
   
   
     #if ENABLE_FILTER  
         CalculateBiquadParameters(Samples); // calculate the final biquad filter parameters  
     #endif // ENABLE_FILTER  
   
535    
536          switch (this->PlaybackState) {          switch (this->PlaybackState) {
537    
538                case playback_state_init:
539                    this->PlaybackState = playback_state_ram; // we always start playback from RAM cache and switch then to disk if needed
540                    // no break - continue with playback_state_ram
541    
542              case playback_state_ram: {              case playback_state_ram: {
543                      if (RAMLoop) InterpolateAndLoop(Samples, (sample_t*) pSample->GetCache().pStart, Delay);                      if (RAMLoop) SYNTHESIS_MODE_SET_LOOP(SynthesisMode, true); // enable looping
544                      else         InterpolateNoLoop(Samples, (sample_t*) pSample->GetCache().pStart, Delay);  
545                        // render current fragment
546                        Synthesize(Samples, (sample_t*) pSample->GetCache().pStart, Delay);
547    
548                      if (DiskVoice) {                      if (DiskVoice) {
549                          // check if we reached the allowed limit of the sample RAM cache                          // check if we reached the allowed limit of the sample RAM cache
550                          if (Pos > MaxRAMPos) {                          if (Pos > MaxRAMPos) {
# Line 684  namespace LinuxSampler { namespace gig { Line 567  namespace LinuxSampler { namespace gig {
567                              KillImmediately();                              KillImmediately();
568                              return;                              return;
569                          }                          }
570                          DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (RTMath::DoubleToInt(Pos) - MaxRAMPos));                          DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (int(Pos) - MaxRAMPos));
571                          Pos -= RTMath::DoubleToInt(Pos);                          Pos -= int(Pos);
572                            RealSampleWordsLeftToRead = -1; // -1 means no silence has been added yet
573                      }                      }
574    
575                        const int sampleWordsLeftToRead = DiskStreamRef.pStream->GetReadSpace();
576    
577                      // 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)
578                      if (DiskStreamRef.State == Stream::state_end && DiskStreamRef.pStream->GetReadSpace() < (pEngine->MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels) {                      if (DiskStreamRef.State == Stream::state_end) {
579                          DiskStreamRef.pStream->WriteSilence((pEngine->MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels);                          const int maxSampleWordsPerCycle = (pEngine->MaxSamplesPerCycle << CONFIG_MAX_PITCH) * pSample->Channels + 6; // +6 for the interpolator algorithm
580                          this->PlaybackState = playback_state_end;                          if (sampleWordsLeftToRead <= maxSampleWordsPerCycle) {
581                                // remember how many sample words there are before any silence has been added
582                                if (RealSampleWordsLeftToRead < 0) RealSampleWordsLeftToRead = sampleWordsLeftToRead;
583                                DiskStreamRef.pStream->WriteSilence(maxSampleWordsPerCycle - sampleWordsLeftToRead);
584                            }
585                      }                      }
586    
587                      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
588                      InterpolateNoLoop(Samples, ptr, Delay);  
589                      DiskStreamRef.pStream->IncrementReadPos(RTMath::DoubleToInt(Pos) * pSample->Channels);                      // render current audio fragment
590                      Pos -= RTMath::DoubleToInt(Pos);                      Synthesize(Samples, ptr, Delay);
591    
592                        const int iPos = (int) Pos;
593                        const int readSampleWords = iPos * pSample->Channels; // amount of sample words actually been read
594                        DiskStreamRef.pStream->IncrementReadPos(readSampleWords);
595                        Pos -= iPos; // just keep fractional part of Pos
596    
597                        // change state of voice to 'end' if we really reached the end of the sample data
598                        if (RealSampleWordsLeftToRead >= 0) {
599                            RealSampleWordsLeftToRead -= readSampleWords;
600                            if (RealSampleWordsLeftToRead <= 0) this->PlaybackState = playback_state_end;
601                        }
602                  }                  }
603                  break;                  break;
604    
# Line 706  namespace LinuxSampler { namespace gig { Line 607  namespace LinuxSampler { namespace gig {
607                  break;                  break;
608          }          }
609    
610            // Reset synthesis event lists
611          // Reset synthesis event lists (except VCO, as VCO events apply channel wide currently)          pEngineChannel->pEvents->clear();
         pEngine->pSynthesisEvents[Event::destination_vca]->clear();  
     #if ENABLE_FILTER  
         pEngine->pSynthesisEvents[Event::destination_vcfc]->clear();  
         pEngine->pSynthesisEvents[Event::destination_vcfr]->clear();  
     #endif // ENABLE_FILTER  
612    
613          // Reset delay          // Reset delay
614          Delay = 0;          Delay = 0;
# Line 720  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 728  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() {
627          pLFO1->Reset();          FilterLeft.Reset();
628          pLFO2->Reset();          FilterRight.Reset();
         pLFO3->Reset();  
629          DiskStreamRef.pStream = NULL;          DiskStreamRef.pStream = NULL;
630          DiskStreamRef.hStream = 0;          DiskStreamRef.hStream = 0;
631          DiskStreamRef.State   = Stream::state_unused;          DiskStreamRef.State   = Stream::state_unused;
# Line 741  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 = pEngine->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 ENABLE_FILTER  
                 if (itCCEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {  
                     *pEngine->pSynthesisEvents[Event::destination_vcfc]->allocAppend() = *itCCEvent;  
                 }  
                 if (itCCEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {  
                     *pEngine->pSynthesisEvents[Event::destination_vcfr]->allocAppend() = *itCCEvent;  
                 }  
                 #endif // ENABLE_FILTER  
                 if (itCCEvent->Param.CC.Controller == pLFO1->ExtController) {  
                     pLFO1->SendEvent(itCCEvent);  
                 }  
                 #if ENABLE_FILTER  
                 if (itCCEvent->Param.CC.Controller == pLFO2->ExtController) {  
                     pLFO2->SendEvent(itCCEvent);  
                 }  
                 #endif // ENABLE_FILTER  
                 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  
                     *pEngine->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 = pEngine->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;  
         }  
   
         // process volume / attenuation events (TODO: we only handle and _expect_ crossfade events here ATM !)  
         {  
             RTList<Event>* pVCAEventList = pEngine->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);  
   
                 float effective_volume = crossfadevolume * this->Volume * pEngine->GlobalVolume;  
   
                 // 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;  
         }  
   
     #if ENABLE_FILTER  
         // process filter cutoff events  
         {  
             RTList<Event>* pCutoffEventList = pEngine->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;  
   
                 cutoff = exp((float) itCutoffEvent->Param.CC.Value * 0.00787402f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX - 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 = pEngine->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          }          }
     #endif // ENABLE_FILTER  
691      }      }
692    
693      #if ENABLE_FILTER      void Voice::processPitchEvent(RTList<Event>::Iterator& itEvent) {
694      /**          const float pitch = RTMath::CentsToFreqRatio(((double) itEvent->Param.Pitch.Pitch / 8192.0) * 200.0); // +-two semitones = +-200 cents
695       * Calculate all necessary, final biquad filter parameters.          fFinalPitch *= pitch;
696       *      }
697       * @param Samples - number of samples to be rendered in this audio fragment cycle  
698       */      void Voice::processCrossFadeEvent(RTList<Event>::Iterator& itEvent) {
699      void Voice::CalculateBiquadParameters(uint Samples) {          CrossfadeVolume = CrossfadeAttenuation(itEvent->Param.CC.Value);
700          if (!FilterLeft.Enabled) return;          #if CONFIG_PROCESS_MUTED_CHANNELS
701            const float effectiveVolume = CrossfadeVolume * Volume * (pEngineChannel->GetMute() ? 0 : pEngineChannel->GlobalVolume);
702          biquad_param_t bqbase;          #else
703          biquad_param_t bqmain;          const float effectiveVolume = CrossfadeVolume * Volume * pEngineChannel->GlobalVolume;
704          float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0];          #endif
705          float prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][0];          fFinalVolume = effectiveVolume;
706          FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);      }
707          pEngine->pBasicFilterParameters[0] = bqbase;  
708          pEngine->pMainFilterParameters[0]  = bqmain;      void Voice::processCutoffEvent(RTList<Event>::Iterator& itEvent) {
709            int ccvalue = itEvent->Param.CC.Value;
710          float* bq;          if (VCFCutoffCtrl.value == ccvalue) return;
711          for (int i = 1; i < Samples; i++) {          VCFCutoffCtrl.value == ccvalue;
712              // recalculate biquad parameters if cutoff or resonance differ from previous sample point          if (pDimRgn->VCFCutoffControllerInvert)  ccvalue = 127 - ccvalue;
713              if (!(i & FILTER_UPDATE_MASK)) if (pEngine->pSynthesisParameters[Event::destination_vcfr][i] != prev_res ||          if (ccvalue < pDimRgn->VCFVelocityScale) ccvalue = pDimRgn->VCFVelocityScale;
714                                                 pEngine->pSynthesisParameters[Event::destination_vcfc][i] != prev_cutoff) {          float cutoff = CutoffBase * float(ccvalue) * 0.00787402f; // (1 / 127)
715                  prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][i];          if (cutoff > 1.0) cutoff = 1.0;
716                  prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][i];          cutoff = exp(cutoff * FILTER_CUTOFF_COEFF) * CONFIG_FILTER_CUTOFF_MIN - CONFIG_FILTER_CUTOFF_MIN;
717                  FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);          VCFCutoffCtrl.fvalue = cutoff; // needed for initialization of fFinalCutoff next time
718              }          fFinalCutoff = cutoff;
719        }
720              //same as 'pEngine->pBasicFilterParameters[i] = bqbase;'  
721              bq    = (float*) &pEngine->pBasicFilterParameters[i];      void Voice::processResonanceEvent(RTList<Event>::Iterator& itEvent) {
722              bq[0] = bqbase.a1;          // convert absolute controller value to differential
723              bq[1] = bqbase.a2;          const int ctrldelta = itEvent->Param.CC.Value - VCFResonanceCtrl.value;
724              bq[2] = bqbase.b0;          VCFResonanceCtrl.value = itEvent->Param.CC.Value;
725              bq[3] = bqbase.b1;          const float resonancedelta = (float) ctrldelta * 0.00787f; // 0.0..1.0
726              bq[4] = bqbase.b2;          fFinalResonance += resonancedelta;
727            // needed for initialization of parameter
728              // same as 'pEngine->pMainFilterParameters[i] = bqmain;'          VCFResonanceCtrl.fvalue = itEvent->Param.CC.Value * 0.00787f;
             bq    = (float*) &pEngine->pMainFilterParameters[i];  
             bq[0] = bqmain.a1;  
             bq[1] = bqmain.a2;  
             bq[2] = bqmain.b0;  
             bq[3] = bqmain.b1;  
             bq[4] = bqmain.b2;  
         }  
729      }      }
     #endif // ENABLE_FILTER  
730    
731      /**      /**
732       *  Interpolates the input audio data (without looping).       *  Synthesizes the current audio fragment for this voice.
733       *       *
734       *  @param Samples - number of sample points to be rendered in this audio       *  @param Samples - number of sample points to be rendered in this audio
735       *                   fragment cycle       *                   fragment cycle
736       *  @param pSrc    - pointer to input sample data       *  @param pSrc    - pointer to input sample data
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::InterpolateNoLoop(uint Samples, sample_t* pSrc, uint Skip) {      void Voice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {
740          int i = Skip;          RTList<Event>::Iterator itCCEvent = pEngineChannel->pEvents->first();
741            RTList<Event>::Iterator itNoteEvent = pEngineChannel->pMIDIKeyInfo[MIDIKey].pEvents->first();
742          // FIXME: assuming either mono or stereo                  
743          if (this->pSample->Channels == 2) { // Stereo Sample          if (Skip) { // skip events that happened before this voice was triggered
744              while (i < Samples) InterpolateStereo(pSrc, i);              while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;
745          }              while (itNoteEvent && itNoteEvent->FragmentPos() <= Skip) ++itNoteEvent;
746          else { // Mono Sample          }
747              while (i < Samples) InterpolateMono(pSrc, i);          
748          }          uint i = Skip;
749      }          while (i < Samples) {
750                int iSubFragmentEnd = RTMath::Min(i + CONFIG_DEFAULT_SUBFRAGMENT_SIZE, Samples);
751      /**              
752       *  Interpolates the input audio data, this method honors looping.              // initialize all final synthesis parameters
753       *              fFinalPitch = PitchBase * PitchBend;
754       *  @param Samples - number of sample points to be rendered in this audio              #if CONFIG_PROCESS_MUTED_CHANNELS
755       *                   fragment cycle              fFinalVolume = this->Volume * this->CrossfadeVolume * (pEngineChannel->GetMute() ? 0 : pEngineChannel->GlobalVolume));
756       *  @param pSrc    - pointer to input sample data              #else
757       *  @param Skip    - number of sample points to skip in output buffer              fFinalVolume = this->Volume * this->CrossfadeVolume * pEngineChannel->GlobalVolume;
758       */              #endif
759      void Voice::InterpolateAndLoop(uint Samples, sample_t* pSrc, uint Skip) {              fFinalCutoff    = VCFCutoffCtrl.fvalue;
760          int i = Skip;              fFinalResonance = VCFResonanceCtrl.fvalue;
761                
762          // FIXME: assuming either mono or stereo              // process MIDI control change and pitchbend events for this subfragment
763          if (pSample->Channels == 2) { // Stereo Sample              processCCEvents(itCCEvent, iSubFragmentEnd);
764              if (pSample->LoopPlayCount) {  
765                  // render loop (loop count limited)              // process transition events (note on, note off & sustain pedal)
766                  while (i < Samples && LoopCyclesLeft) {              processTransitionEvents(itNoteEvent, iSubFragmentEnd);
767                      InterpolateStereo(pSrc, i);              
768                      if (Pos > pSample->LoopEnd) {              // process envelope generators
769                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;              switch (EG1.getSegmentType()) {
770                          LoopCyclesLeft--;                  case EGADSR::segment_lin:
771                      }                      fFinalVolume *= EG1.processLin();
772                  }                      break;
773                  // render on without loop                  case EGADSR::segment_exp:
774                  while (i < Samples) InterpolateStereo(pSrc, i);                      fFinalVolume *= EG1.processExp();
775              }                      break;
776              else { // render loop (endless loop)                  case EGADSR::segment_end:
777                  while (i < Samples) {                      fFinalVolume *= EG1.getLevel();
778                      InterpolateStereo(pSrc, i);                      break; // noop
779                      if (Pos > pSample->LoopEnd) {              }
780                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);              switch (EG2.getSegmentType()) {
781                      }                  case EGADSR::segment_lin:
782                  }                      fFinalCutoff *= EG2.processLin();
783              }                      break;
784          }                  case EGADSR::segment_exp:
785          else { // Mono Sample                      fFinalCutoff *= EG2.processExp();
786              if (pSample->LoopPlayCount) {                      break;
787                  // render loop (loop count limited)                  case EGADSR::segment_end:
788                  while (i < Samples && LoopCyclesLeft) {                      fFinalCutoff *= EG2.getLevel();
789                      InterpolateMono(pSrc, i);                      break; // noop
790                      if (Pos > pSample->LoopEnd) {              }
791                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;              fFinalPitch *= RTMath::CentsToFreqRatio(EG3.render());
792                          LoopCyclesLeft--;              
793                      }              // process low frequency oscillators
794                  }              if (bLFO1Enabled) fFinalVolume *= pLFO1->render();
795                  // render on without loop              if (bLFO2Enabled) fFinalCutoff *= pLFO2->render();
796                  while (i < Samples) InterpolateMono(pSrc, i);              if (bLFO3Enabled) fFinalPitch  *= RTMath::CentsToFreqRatio(pLFO3->render());
797              }  
798              else { // render loop (endless loop)              // if filter enabled then update filter coefficients
799                  while (i < Samples) {              if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode)) {
800                      InterpolateMono(pSrc, i);                  FilterLeft.SetParameters(fFinalCutoff, fFinalResonance, pEngine->SampleRate);
801                      if (Pos > pSample->LoopEnd) {                  FilterRight.SetParameters(fFinalCutoff, fFinalResonance, pEngine->SampleRate);
802                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;              }
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    
# Line 1057  namespace LinuxSampler { namespace gig { Line 849  namespace LinuxSampler { namespace gig {
849       *  @param itKillEvent - event which caused the voice to be killed       *  @param itKillEvent - event which caused the voice to be killed
850       */       */
851      void Voice::Kill(Pool<Event>::Iterator& itKillEvent) {      void Voice::Kill(Pool<Event>::Iterator& itKillEvent) {
852          //FIXME: just two sanity checks for debugging, can be removed          #if CONFIG_DEVMODE
853          if (!itKillEvent) dmsg(1,("gig::Voice::Kill(): ERROR, !itKillEvent !!!\n"));          if (!itKillEvent) dmsg(1,("gig::Voice::Kill(): ERROR, !itKillEvent !!!\n"));
854          if (itKillEvent && !itKillEvent.isValid()) dmsg(1,("gig::Voice::Kill(): ERROR, itKillEvent invalid !!!\n"));          if (itKillEvent && !itKillEvent.isValid()) dmsg(1,("gig::Voice::Kill(): ERROR, itKillEvent invalid !!!\n"));
855            #endif // CONFIG_DEVMODE
856    
857          if (itTriggerEvent && itKillEvent->FragmentPos() <= itTriggerEvent->FragmentPos()) return;          if (itTriggerEvent && itKillEvent->FragmentPos() <= itTriggerEvent->FragmentPos()) return;
858          this->itKillEvent = itKillEvent;          this->itKillEvent = itKillEvent;

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

  ViewVC Help
Powered by ViewVC