/[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 332 by senkov, Sat Jan 1 03:06:06 2005 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    
 #include "EGADSR.h"  
 #include "Manipulator.h"  
24  #include "../../common/Features.h"  #include "../../common/Features.h"
25  #include "Synthesizer.h"  #include "Synthesizer.h"
26    
# Line 31  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          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))
47            #if CONFIG_ASM && ARCH_X86
48          SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, Features::supportsMMX() && Features::supportsSSE());          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);          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 110  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) { // FIXME: should be removed before the final release (purpose: just a sanity check for debugging)          if (itNoteOnEvent->FragmentPos() > pEngine->MaxSamplesPerCycle) { // just a sanity check for debugging
90              dmsg(1,("Voice::Trigger(): ERROR, TriggerDelay > Totalsamples\n"));              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          }          }
         pDimRgn = pRegion->GetDimensionRegionByValue(DimValues[4],DimValues[3],DimValues[2],DimValues[1],DimValues[0]);  
   
         pSample = pDimRgn->pSample; // sample won't change until the voice is finished  
118    
119          // select channel mode (mono or stereo)          // select channel mode (mono or stereo)
120          SYNTHESIS_MODE_SET_CHANNELS(SynthesisMode, pSample->Channels == 2);          SYNTHESIS_MODE_SET_CHANNELS(SynthesisMode, pSample->Channels == 2);
# Line 264  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 281  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 310  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          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)          // the length of the decay and release curves are dependent on the velocity
184            const double velrelease = 1 / pDimRgn->GetVelocityRelease(itNoteOnEvent->Param.Note.Velocity);
185    
186          // setup EG 1 (VCA EG)          // setup EG 1 (VCA EG)
187          {          {
# Line 333  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    
# Line 371  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          }          }
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 408  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    
# Line 446  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    
359    
# Line 484  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    
403          #if FORCE_FILTER_USAGE          #if CONFIG_FORCE_FILTER
404          SYNTHESIS_MODE_SET_FILTER(SynthesisMode, 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          SYNTHESIS_MODE_SET_FILTER(SynthesisMode, 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 558  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 580  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 605  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;
   
             FilterUpdateCounter = -1;  
511          }          }
512          else {          else {
513              VCFCutoffCtrl.controller    = 0;              VCFCutoffCtrl.controller    = 0;
# Line 632  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  
   
         pEngine->ResetSynthesisParameters(Event::destination_vca, this->Volume * this->CrossfadeVolume * pEngine->GlobalVolume);  
         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, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, itTriggerEvent, this->Pos, this->PitchBase * this->PitchBend, itKillEvent);  
         pEG2->Process(Samples, pEngine->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);  
         }  
         pLFO1->Process(Samples);  
         pLFO2->Process(Samples);  
         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:
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) SYNTHESIS_MODE_SET_LOOP(SynthesisMode, true); // enable looping                      if (RAMLoop) SYNTHESIS_MODE_SET_LOOP(SynthesisMode, true); // enable looping
544    
# Line 702  namespace LinuxSampler { namespace gig { Line 576  namespace LinuxSampler { namespace gig {
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) {                      if (DiskStreamRef.State == Stream::state_end) {
579                          const int maxSampleWordsPerCycle = (pEngine->MaxSamplesPerCycle << MAX_PITCH) * pSample->Channels + 6; // +6 for the interpolator algorithm                          const int maxSampleWordsPerCycle = (pEngine->MaxSamplesPerCycle << CONFIG_MAX_PITCH) * pSample->Channels + 6; // +6 for the interpolator algorithm
580                          if (sampleWordsLeftToRead <= maxSampleWordsPerCycle) {                          if (sampleWordsLeftToRead <= maxSampleWordsPerCycle) {
581                              // remember how many sample words there are before any silence has been added                              // remember how many sample words there are before any silence has been added
582                              if (RealSampleWordsLeftToRead < 0) RealSampleWordsLeftToRead = sampleWordsLeftToRead;                              if (RealSampleWordsLeftToRead < 0) RealSampleWordsLeftToRead = sampleWordsLeftToRead;
# Line 733  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          pEngine->pSynthesisEvents[Event::destination_vca]->clear();          pEngineChannel->pEvents->clear();
         pEngine->pSynthesisEvents[Event::destination_vcfc]->clear();  
         pEngine->pSynthesisEvents[Event::destination_vcfr]->clear();  
612    
613          // Reset delay          // Reset delay
614          Delay = 0;          Delay = 0;
# Line 744  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 752  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 767  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 (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;  
                 }  
                 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  
                     *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;  
                 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 = 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;  
         }  
   
         // 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          }          }
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      }
697       */  
698      void Voice::CalculateBiquadParameters(uint Samples) {      void Voice::processCrossFadeEvent(RTList<Event>::Iterator& itEvent) {
699          biquad_param_t bqbase;          CrossfadeVolume = CrossfadeAttenuation(itEvent->Param.CC.Value);
700          biquad_param_t bqmain;          #if CONFIG_PROCESS_MUTED_CHANNELS
701          float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0];          const float effectiveVolume = CrossfadeVolume * Volume * (pEngineChannel->GetMute() ? 0 : pEngineChannel->GlobalVolume);
702          float prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][0];          #else
703          FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);          const float effectiveVolume = CrossfadeVolume * Volume * pEngineChannel->GlobalVolume;
704          FilterRight.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);          #endif
705          pEngine->pBasicFilterParameters[0] = bqbase;          fFinalVolume = effectiveVolume;
706          pEngine->pMainFilterParameters[0]  = bqmain;      }
707    
708          float* bq;      void Voice::processCutoffEvent(RTList<Event>::Iterator& itEvent) {
709          for (int i = 1; i < Samples; i++) {          int ccvalue = itEvent->Param.CC.Value;
710              // recalculate biquad parameters if cutoff or resonance differ from previous sample point          if (VCFCutoffCtrl.value == ccvalue) return;
711              if (!(i & FILTER_UPDATE_MASK)) {          VCFCutoffCtrl.value == ccvalue;
712                  if (pEngine->pSynthesisParameters[Event::destination_vcfr][i] != prev_res ||          if (pDimRgn->VCFCutoffControllerInvert)  ccvalue = 127 - ccvalue;
713                      pEngine->pSynthesisParameters[Event::destination_vcfc][i] != prev_cutoff)          if (ccvalue < pDimRgn->VCFVelocityScale) ccvalue = pDimRgn->VCFVelocityScale;
714                  {          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                      FilterRight.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);          fFinalCutoff = cutoff;
719                  }      }
720              }  
721        void Voice::processResonanceEvent(RTList<Event>::Iterator& itEvent) {
722              //same as 'pEngine->pBasicFilterParameters[i] = bqbase;'          // convert absolute controller value to differential
723              bq    = (float*) &pEngine->pBasicFilterParameters[i];          const int ctrldelta = itEvent->Param.CC.Value - VCFResonanceCtrl.value;
724              bq[0] = bqbase.b0;          VCFResonanceCtrl.value = itEvent->Param.CC.Value;
725              bq[1] = bqbase.b1;          const float resonancedelta = (float) ctrldelta * 0.00787f; // 0.0..1.0
726              bq[2] = bqbase.b2;          fFinalResonance += resonancedelta;
727              bq[3] = bqbase.a1;          // needed for initialization of parameter
728              bq[4] = bqbase.a2;          VCFResonanceCtrl.fvalue = itEvent->Param.CC.Value * 0.00787f;
   
             // same as 'pEngine->pMainFilterParameters[i] = bqmain;'  
             bq    = (float*) &pEngine->pMainFilterParameters[i];  
             bq[0] = bqmain.b0;  
             bq[1] = bqmain.b1;  
             bq[2] = bqmain.b2;  
             bq[3] = bqmain.a1;  
             bq[4] = bqmain.a2;  
         }  
729      }      }
730    
731      /**      /**
# Line 988  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      /**      /**
# Line 1016  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.332  
changed lines
  Added in v.738

  ViewVC Help
Powered by ViewVC