/[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 244 by schoenebeck, Fri Sep 17 01:01:11 2004 UTC revision 614 by persson, Mon Jun 6 16:54:20 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 22  Line 23 
23    
24  #include "EGADSR.h"  #include "EGADSR.h"
25  #include "Manipulator.h"  #include "Manipulator.h"
26    #include "../../common/Features.h"
27    #include "Synthesizer.h"
28    
29  #include "Voice.h"  #include "Voice.h"
30    
# Line 32  namespace LinuxSampler { namespace gig { Line 35  namespace LinuxSampler { namespace gig {
35      const int Voice::FILTER_UPDATE_MASK(CalculateFilterUpdateMask());      const int Voice::FILTER_UPDATE_MASK(CalculateFilterUpdateMask());
36    
37      float Voice::CalculateFilterCutoffCoeff() {      float Voice::CalculateFilterCutoffCoeff() {
38          return log(FILTER_CUTOFF_MIN / FILTER_CUTOFF_MAX);          return log(CONFIG_FILTER_CUTOFF_MIN / CONFIG_FILTER_CUTOFF_MAX);
39      }      }
40    
41      int Voice::CalculateFilterUpdateMask() {      int Voice::CalculateFilterUpdateMask() {
42          if (FILTER_UPDATE_PERIOD <= 0) return 0;          if (CONFIG_FILTER_UPDATE_STEPS <= 0) return 0;
43          int power_of_two;          int power_of_two;
44          for (power_of_two = 0; 1<<power_of_two < FILTER_UPDATE_PERIOD; power_of_two++);          for (power_of_two = 0; 1<<power_of_two < CONFIG_FILTER_UPDATE_STEPS; power_of_two++);
45          return (1 << power_of_two) - 1;          return (1 << power_of_two) - 1;
46      }      }
47    
48      Voice::Voice() {      Voice::Voice() {
49          pEngine     = NULL;          pEngine     = NULL;
50          pDiskThread = NULL;          pDiskThread = NULL;
51          Active = false;          PlaybackState = playback_state_end;
52          pEG1   = NULL;          pEG1   = NULL;
53          pEG2   = NULL;          pEG2   = NULL;
54          pEG3   = NULL;          pEG3   = NULL;
# Line 56  namespace LinuxSampler { namespace gig { Line 59  namespace LinuxSampler { namespace gig {
59          pLFO2  = NULL;          pLFO2  = NULL;
60          pLFO3  = NULL;          pLFO3  = NULL;
61          KeyGroup = 0;          KeyGroup = 0;
62            SynthesisMode = 0; // set all mode bits to 0 first
63            // select synthesis implementation (currently either pure C++ or MMX+SSE(1))
64            #if ARCH_X86
65            SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, Features::supportsMMX() && Features::supportsSSE());
66            #else
67            SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, false);
68            #endif
69            SYNTHESIS_MODE_SET_PROFILING(SynthesisMode, true);
70    
71            FilterLeft.Reset();
72            FilterRight.Reset();
73      }      }
74    
75      Voice::~Voice() {      Voice::~Voice() {
# Line 103  namespace LinuxSampler { namespace gig { Line 117  namespace LinuxSampler { namespace gig {
117       *  Initializes and triggers the voice, a disk stream will be launched if       *  Initializes and triggers the voice, a disk stream will be launched if
118       *  needed.       *  needed.
119       *       *
120       *  @param pNoteOnEvent        - event that caused triggering of this voice       *  @param pEngineChannel       - engine channel on which this voice was ordered
121       *  @param PitchBend           - MIDI detune factor (-8192 ... +8191)       *  @param itNoteOnEvent        - event that caused triggering of this voice
122       *  @param pInstrument         - points to the loaded instrument which provides sample wave(s) and articulation data       *  @param PitchBend            - MIDI detune factor (-8192 ... +8191)
123       *  @param iLayer              - layer number this voice refers to (only if this is a layered sound of course)       *  @param pInstrument          - points to the loaded instrument which provides sample wave(s) and articulation data
124       *  @param ReleaseTriggerVoice - if this new voice is a release trigger voice (optional, default = false)       *  @param iLayer               - layer number this voice refers to (only if this is a layered sound of course)
125       *  @returns 0 on success, a value < 0 if something failed       *  @param ReleaseTriggerVoice  - if this new voice is a release trigger voice (optional, default = false)
126         *  @param VoiceStealingAllowed - wether the voice is allowed to steal voices for further subvoices
127         *  @returns 0 on success, a value < 0 if the voice wasn't triggered
128         *           (either due to an error or e.g. because no region is
129         *           defined for the given key)
130       */       */
131      int Voice::Trigger(Event* pNoteOnEvent, int PitchBend, ::gig::Instrument* pInstrument, int iLayer, bool ReleaseTriggerVoice) {      int Voice::Trigger(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent, int PitchBend, ::gig::Instrument* pInstrument, int iLayer, bool ReleaseTriggerVoice, bool VoiceStealingAllowed) {
132            this->pEngineChannel = pEngineChannel;
133          if (!pInstrument) {          if (!pInstrument) {
134             dmsg(1,("voice::trigger: !pInstrument\n"));             dmsg(1,("voice::trigger: !pInstrument\n"));
135             exit(EXIT_FAILURE);             exit(EXIT_FAILURE);
136          }          }
137            #if CONFIG_DEVMODE
138            if (itNoteOnEvent->FragmentPos() > pEngine->MaxSamplesPerCycle) { // just a sanity check for debugging
139                dmsg(1,("Voice::Trigger(): ERROR, TriggerDelay > Totalsamples\n"));
140            }
141            #endif // CONFIG_DEVMODE
142    
143          Type            = type_normal;          Type            = type_normal;
144          Active          = true;          MIDIKey         = itNoteOnEvent->Param.Note.Key;
         MIDIKey         = pNoteOnEvent->Key;  
145          pRegion         = pInstrument->GetRegion(MIDIKey);          pRegion         = pInstrument->GetRegion(MIDIKey);
146          PlaybackState   = playback_state_ram; // we always start playback from RAM cache and switch then to disk if needed          PlaybackState   = playback_state_init; // mark voice as triggered, but no audio rendered yet
147          Delay           = pNoteOnEvent->FragmentPos();          Delay           = itNoteOnEvent->FragmentPos();
148          pTriggerEvent   = pNoteOnEvent;          itTriggerEvent  = itNoteOnEvent;
149          pKillEvent      = NULL;          itKillEvent     = Pool<Event>::Iterator();
150    
151          if (!pRegion) {          if (!pRegion) {
152              std::cerr << "gig::Voice: No Region defined for MIDI key " << MIDIKey << std::endl << std::flush;              dmsg(4, ("gig::Voice: No Region defined for MIDI key %d\n", MIDIKey));
             KillImmediately();  
153              return -1;              return -1;
154          }          }
155    
156          KeyGroup = pRegion->KeyGroup;          // only mark the first voice of a layered voice (group) to be in a
157            // key group, so the layered voices won't kill each other
158            KeyGroup = (iLayer == 0 && !ReleaseTriggerVoice) ? pRegion->KeyGroup : 0;
159    
160          // get current dimension values to select the right dimension region          // get current dimension values to select the right dimension region
161          //FIXME: controller values for selecting the dimension region here are currently not sample accurate          //FIXME: controller values for selecting the dimension region here are currently not sample accurate
162          uint DimValues[5] = {0,0,0,0,0};          uint DimValues[8] = { 0 };
163          for (int i = pRegion->Dimensions - 1; i >= 0; i--) {          for (int i = pRegion->Dimensions - 1; i >= 0; i--) {
164              switch (pRegion->pDimensionDefinitions[i].dimension) {              switch (pRegion->pDimensionDefinitions[i].dimension) {
165                  case ::gig::dimension_samplechannel:                  case ::gig::dimension_samplechannel:
# Line 143  namespace LinuxSampler { namespace gig { Line 167  namespace LinuxSampler { namespace gig {
167                      break;                      break;
168                  case ::gig::dimension_layer:                  case ::gig::dimension_layer:
169                      DimValues[i] = iLayer;                      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++)  
                             pEngine->LaunchVoice(pNoteOnEvent, iNewLayer, ReleaseTriggerVoice);  
170                      break;                      break;
171                  case ::gig::dimension_velocity:                  case ::gig::dimension_velocity:
172                      DimValues[i] = pNoteOnEvent->Velocity;                      DimValues[i] = itNoteOnEvent->Param.Note.Velocity;
173                      break;                      break;
174                  case ::gig::dimension_channelaftertouch:                  case ::gig::dimension_channelaftertouch:
175                      DimValues[i] = 0; //TODO: we currently ignore this dimension                      DimValues[i] = 0; //TODO: we currently ignore this dimension
# Line 159  namespace LinuxSampler { namespace gig { Line 179  namespace LinuxSampler { namespace gig {
179                      DimValues[i] = (uint) ReleaseTriggerVoice;                      DimValues[i] = (uint) ReleaseTriggerVoice;
180                      break;                      break;
181                  case ::gig::dimension_keyboard:                  case ::gig::dimension_keyboard:
182                      DimValues[i] = (uint) pNoteOnEvent->Key;                      DimValues[i] = (uint) pEngineChannel->CurrentKeyDimension;
183                        break;
184                    case ::gig::dimension_roundrobin:
185                        DimValues[i] = (uint) pEngineChannel->pMIDIKeyInfo[MIDIKey].RoundRobinIndex; // incremented for each note on
186                        break;
187                    case ::gig::dimension_random:
188                        pEngine->RandomSeed = pEngine->RandomSeed * 1103515245 + 12345; // classic pseudo random number generator
189                        DimValues[i] = (uint) pEngine->RandomSeed >> (32 - pRegion->pDimensionDefinitions[i].bits); // highest bits are most random
190                      break;                      break;
191                  case ::gig::dimension_modwheel:                  case ::gig::dimension_modwheel:
192                      DimValues[i] = pEngine->ControllerTable[1];                      DimValues[i] = pEngineChannel->ControllerTable[1];
193                      break;                      break;
194                  case ::gig::dimension_breath:                  case ::gig::dimension_breath:
195                      DimValues[i] = pEngine->ControllerTable[2];                      DimValues[i] = pEngineChannel->ControllerTable[2];
196                      break;                      break;
197                  case ::gig::dimension_foot:                  case ::gig::dimension_foot:
198                      DimValues[i] = pEngine->ControllerTable[4];                      DimValues[i] = pEngineChannel->ControllerTable[4];
199                      break;                      break;
200                  case ::gig::dimension_portamentotime:                  case ::gig::dimension_portamentotime:
201                      DimValues[i] = pEngine->ControllerTable[5];                      DimValues[i] = pEngineChannel->ControllerTable[5];
202                      break;                      break;
203                  case ::gig::dimension_effect1:                  case ::gig::dimension_effect1:
204                      DimValues[i] = pEngine->ControllerTable[12];                      DimValues[i] = pEngineChannel->ControllerTable[12];
205                      break;                      break;
206                  case ::gig::dimension_effect2:                  case ::gig::dimension_effect2:
207                      DimValues[i] = pEngine->ControllerTable[13];                      DimValues[i] = pEngineChannel->ControllerTable[13];
208                      break;                      break;
209                  case ::gig::dimension_genpurpose1:                  case ::gig::dimension_genpurpose1:
210                      DimValues[i] = pEngine->ControllerTable[16];                      DimValues[i] = pEngineChannel->ControllerTable[16];
211                      break;                      break;
212                  case ::gig::dimension_genpurpose2:                  case ::gig::dimension_genpurpose2:
213                      DimValues[i] = pEngine->ControllerTable[17];                      DimValues[i] = pEngineChannel->ControllerTable[17];
214                      break;                      break;
215                  case ::gig::dimension_genpurpose3:                  case ::gig::dimension_genpurpose3:
216                      DimValues[i] = pEngine->ControllerTable[18];                      DimValues[i] = pEngineChannel->ControllerTable[18];
217                      break;                      break;
218                  case ::gig::dimension_genpurpose4:                  case ::gig::dimension_genpurpose4:
219                      DimValues[i] = pEngine->ControllerTable[19];                      DimValues[i] = pEngineChannel->ControllerTable[19];
220                      break;                      break;
221                  case ::gig::dimension_sustainpedal:                  case ::gig::dimension_sustainpedal:
222                      DimValues[i] = pEngine->ControllerTable[64];                      DimValues[i] = pEngineChannel->ControllerTable[64];
223                      break;                      break;
224                  case ::gig::dimension_portamento:                  case ::gig::dimension_portamento:
225                      DimValues[i] = pEngine->ControllerTable[65];                      DimValues[i] = pEngineChannel->ControllerTable[65];
226                      break;                      break;
227                  case ::gig::dimension_sostenutopedal:                  case ::gig::dimension_sostenutopedal:
228                      DimValues[i] = pEngine->ControllerTable[66];                      DimValues[i] = pEngineChannel->ControllerTable[66];
229                      break;                      break;
230                  case ::gig::dimension_softpedal:                  case ::gig::dimension_softpedal:
231                      DimValues[i] = pEngine->ControllerTable[67];                      DimValues[i] = pEngineChannel->ControllerTable[67];
232                      break;                      break;
233                  case ::gig::dimension_genpurpose5:                  case ::gig::dimension_genpurpose5:
234                      DimValues[i] = pEngine->ControllerTable[80];                      DimValues[i] = pEngineChannel->ControllerTable[80];
235                      break;                      break;
236                  case ::gig::dimension_genpurpose6:                  case ::gig::dimension_genpurpose6:
237                      DimValues[i] = pEngine->ControllerTable[81];                      DimValues[i] = pEngineChannel->ControllerTable[81];
238                      break;                      break;
239                  case ::gig::dimension_genpurpose7:                  case ::gig::dimension_genpurpose7:
240                      DimValues[i] = pEngine->ControllerTable[82];                      DimValues[i] = pEngineChannel->ControllerTable[82];
241                      break;                      break;
242                  case ::gig::dimension_genpurpose8:                  case ::gig::dimension_genpurpose8:
243                      DimValues[i] = pEngine->ControllerTable[83];                      DimValues[i] = pEngineChannel->ControllerTable[83];
244                      break;                      break;
245                  case ::gig::dimension_effect1depth:                  case ::gig::dimension_effect1depth:
246                      DimValues[i] = pEngine->ControllerTable[91];                      DimValues[i] = pEngineChannel->ControllerTable[91];
247                      break;                      break;
248                  case ::gig::dimension_effect2depth:                  case ::gig::dimension_effect2depth:
249                      DimValues[i] = pEngine->ControllerTable[92];                      DimValues[i] = pEngineChannel->ControllerTable[92];
250                      break;                      break;
251                  case ::gig::dimension_effect3depth:                  case ::gig::dimension_effect3depth:
252                      DimValues[i] = pEngine->ControllerTable[93];                      DimValues[i] = pEngineChannel->ControllerTable[93];
253                      break;                      break;
254                  case ::gig::dimension_effect4depth:                  case ::gig::dimension_effect4depth:
255                      DimValues[i] = pEngine->ControllerTable[94];                      DimValues[i] = pEngineChannel->ControllerTable[94];
256                      break;                      break;
257                  case ::gig::dimension_effect5depth:                  case ::gig::dimension_effect5depth:
258                      DimValues[i] = pEngine->ControllerTable[95];                      DimValues[i] = pEngineChannel->ControllerTable[95];
259                      break;                      break;
260                  case ::gig::dimension_none:                  case ::gig::dimension_none:
261                      std::cerr << "gig::Voice::Trigger() Error: dimension=none\n" << std::flush;                      std::cerr << "gig::Voice::Trigger() Error: dimension=none\n" << std::flush;
# Line 237  namespace LinuxSampler { namespace gig { Line 264  namespace LinuxSampler { namespace gig {
264                      std::cerr << "gig::Voice::Trigger() Error: Unknown dimension\n" << std::flush;                      std::cerr << "gig::Voice::Trigger() Error: Unknown dimension\n" << std::flush;
265              }              }
266          }          }
267          pDimRgn = pRegion->GetDimensionRegionByValue(DimValues[4],DimValues[3],DimValues[2],DimValues[1],DimValues[0]);          pDimRgn = pRegion->GetDimensionRegionByValue(DimValues);
268    
269            pSample = pDimRgn->pSample; // sample won't change until the voice is finished
270            if (!pSample || !pSample->SamplesTotal) return -1; // no need to continue if sample is silent
271    
272            // select channel mode (mono or stereo)
273            SYNTHESIS_MODE_SET_CHANNELS(SynthesisMode, pSample->Channels == 2);
274    
275          // get starting crossfade volume level          // get starting crossfade volume level
276          switch (pDimRgn->AttenuationController.type) {          switch (pDimRgn->AttenuationController.type) {
# Line 245  namespace LinuxSampler { namespace gig { Line 278  namespace LinuxSampler { namespace gig {
278                  CrossfadeVolume = 1.0f; //TODO: aftertouch not supported yet                  CrossfadeVolume = 1.0f; //TODO: aftertouch not supported yet
279                  break;                  break;
280              case ::gig::attenuation_ctrl_t::type_velocity:              case ::gig::attenuation_ctrl_t::type_velocity:
281                  CrossfadeVolume = CrossfadeAttenuation(pNoteOnEvent->Velocity);                  CrossfadeVolume = CrossfadeAttenuation(itNoteOnEvent->Param.Note.Velocity);
282                  break;                  break;
283              case ::gig::attenuation_ctrl_t::type_controlchange: //FIXME: currently not sample accurate              case ::gig::attenuation_ctrl_t::type_controlchange: //FIXME: currently not sample accurate
284                  CrossfadeVolume = CrossfadeAttenuation(pEngine->ControllerTable[pDimRgn->AttenuationController.controller_number]);                  CrossfadeVolume = CrossfadeAttenuation(pEngineChannel->ControllerTable[pDimRgn->AttenuationController.controller_number]);
285                  break;                  break;
286              case ::gig::attenuation_ctrl_t::type_none: // no crossfade defined              case ::gig::attenuation_ctrl_t::type_none: // no crossfade defined
287              default:              default:
288                  CrossfadeVolume = 1.0f;                  CrossfadeVolume = 1.0f;
289          }          }
290    
291          pSample = pDimRgn->pSample; // sample won't change until the voice is finished          PanLeft  = 1.0f - float(RTMath::Max(pDimRgn->Pan, 0)) /  63.0f;
292            PanRight = 1.0f - float(RTMath::Min(pDimRgn->Pan, 0)) / -64.0f;
293    
294          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)
295    
# Line 264  namespace LinuxSampler { namespace gig { Line 298  namespace LinuxSampler { namespace gig {
298          DiskVoice          = cachedsamples < pSample->SamplesTotal;          DiskVoice          = cachedsamples < pSample->SamplesTotal;
299    
300          if (DiskVoice) { // voice to be streamed from disk          if (DiskVoice) { // voice to be streamed from disk
301              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)
302    
303              // 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
304              if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) {              if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) {
# Line 293  namespace LinuxSampler { namespace gig { Line 327  namespace LinuxSampler { namespace gig {
327    
328          // calculate initial pitch value          // calculate initial pitch value
329          {          {
330              double pitchbasecents = pDimRgn->FineTune * 10 + (int) pEngine->ScaleTuning[MIDIKey % 12];              double pitchbasecents = pDimRgn->FineTune + (int) pEngine->ScaleTuning[MIDIKey % 12];
331              if (pDimRgn->PitchTrack) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;              if (pDimRgn->PitchTrack) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;
332              this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents) * (double(pSample->SamplesPerSecond) / double(pEngine->pAudioOutputDevice->SampleRate()));              this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents) * (double(pSample->SamplesPerSecond) / double(pEngine->pAudioOutputDevice->SampleRate()));
333              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
334          }          }
335    
336            const double velocityAttenuation = pDimRgn->GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity);
337    
338            Volume = velocityAttenuation / 32768.0f; // we downscale by 32768 to convert from int16 value range to DSP value range (which is -1.0..1.0)
339    
340          Volume = pDimRgn->GetVelocityAttenuation(pNoteOnEvent->Velocity) / 32768.0f; // we downscale by 32768 to convert from int16 value range to DSP value range (which is -1.0..1.0)          Volume *= pDimRgn->SampleAttenuation;
341    
342            // the length of the decay and release curves are dependent on the velocity
343            const double velrelease = 1 / pDimRgn->GetVelocityRelease(itNoteOnEvent->Param.Note.Velocity);
344    
345          // setup EG 1 (VCA EG)          // setup EG 1 (VCA EG)
346          {          {
# Line 315  namespace LinuxSampler { namespace gig { Line 354  namespace LinuxSampler { namespace gig {
354                      eg1controllervalue = 0; // TODO: aftertouch not yet supported                      eg1controllervalue = 0; // TODO: aftertouch not yet supported
355                      break;                      break;
356                  case ::gig::eg1_ctrl_t::type_velocity:                  case ::gig::eg1_ctrl_t::type_velocity:
357                      eg1controllervalue = pNoteOnEvent->Velocity;                      eg1controllervalue = itNoteOnEvent->Param.Note.Velocity;
358                      break;                      break;
359                  case ::gig::eg1_ctrl_t::type_controlchange: // MIDI control change controller                  case ::gig::eg1_ctrl_t::type_controlchange: // MIDI control change controller
360                      eg1controllervalue = pEngine->ControllerTable[pDimRgn->EG1Controller.controller_number];                      eg1controllervalue = pEngineChannel->ControllerTable[pDimRgn->EG1Controller.controller_number];
361                      break;                      break;
362              }              }
363              if (pDimRgn->EG1ControllerInvert) eg1controllervalue = 127 - eg1controllervalue;              if (pDimRgn->EG1ControllerInvert) eg1controllervalue = 127 - eg1controllervalue;
# Line 332  namespace LinuxSampler { namespace gig { Line 371  namespace LinuxSampler { namespace gig {
371                            pDimRgn->EG1Attack + eg1attack,                            pDimRgn->EG1Attack + eg1attack,
372                            pDimRgn->EG1Hold,                            pDimRgn->EG1Hold,
373                            pSample->LoopStart,                            pSample->LoopStart,
374                            pDimRgn->EG1Decay1 + eg1decay,                            (pDimRgn->EG1Decay1 + eg1decay) * velrelease,
375                            pDimRgn->EG1Decay2 + eg1decay,                            (pDimRgn->EG1Decay2 + eg1decay) * velrelease,
376                            pDimRgn->EG1InfiniteSustain,                            pDimRgn->EG1InfiniteSustain,
377                            pDimRgn->EG1Sustain,                            pDimRgn->EG1Sustain,
378                            pDimRgn->EG1Release + eg1release,                            (pDimRgn->EG1Release + eg1release) * velrelease,
379                            Delay);                            // the SSE synthesis implementation requires
380                              // the vca start to be 16 byte aligned
381                              SYNTHESIS_MODE_GET_IMPLEMENTATION(SynthesisMode) ?
382                              Delay & 0xfffffffc : Delay,
383                              velocityAttenuation);
384          }          }
385    
386    
     #if ENABLE_FILTER  
387          // setup EG 2 (VCF Cutoff EG)          // setup EG 2 (VCF Cutoff EG)
388          {          {
389              // get current value of EG2 controller              // get current value of EG2 controller
# Line 354  namespace LinuxSampler { namespace gig { Line 396  namespace LinuxSampler { namespace gig {
396                      eg2controllervalue = 0; // TODO: aftertouch not yet supported                      eg2controllervalue = 0; // TODO: aftertouch not yet supported
397                      break;                      break;
398                  case ::gig::eg2_ctrl_t::type_velocity:                  case ::gig::eg2_ctrl_t::type_velocity:
399                      eg2controllervalue = pNoteOnEvent->Velocity;                      eg2controllervalue = itNoteOnEvent->Param.Note.Velocity;
400                      break;                      break;
401                  case ::gig::eg2_ctrl_t::type_controlchange: // MIDI control change controller                  case ::gig::eg2_ctrl_t::type_controlchange: // MIDI control change controller
402                      eg2controllervalue = pEngine->ControllerTable[pDimRgn->EG2Controller.controller_number];                      eg2controllervalue = pEngineChannel->ControllerTable[pDimRgn->EG2Controller.controller_number];
403                      break;                      break;
404              }              }
405              if (pDimRgn->EG2ControllerInvert) eg2controllervalue = 127 - eg2controllervalue;              if (pDimRgn->EG2ControllerInvert) eg2controllervalue = 127 - eg2controllervalue;
# Line 371  namespace LinuxSampler { namespace gig { Line 413  namespace LinuxSampler { namespace gig {
413                            pDimRgn->EG2Attack + eg2attack,                            pDimRgn->EG2Attack + eg2attack,
414                            false,                            false,
415                            pSample->LoopStart,                            pSample->LoopStart,
416                            pDimRgn->EG2Decay1 + eg2decay,                            (pDimRgn->EG2Decay1 + eg2decay) * velrelease,
417                            pDimRgn->EG2Decay2 + eg2decay,                            (pDimRgn->EG2Decay2 + eg2decay) * velrelease,
418                            pDimRgn->EG2InfiniteSustain,                            pDimRgn->EG2InfiniteSustain,
419                            pDimRgn->EG2Sustain,                            pDimRgn->EG2Sustain,
420                            pDimRgn->EG2Release + eg2release,                            (pDimRgn->EG2Release + eg2release) * velrelease,
421                            Delay);                            Delay,
422                              velocityAttenuation);
423          }          }
     #endif // ENABLE_FILTER  
424    
425    
426          // setup EG 3 (VCO EG)          // setup EG 3 (VCO EG)
# Line 419  namespace LinuxSampler { namespace gig { Line 461  namespace LinuxSampler { namespace gig {
461              pLFO1->Trigger(pDimRgn->LFO1Frequency,              pLFO1->Trigger(pDimRgn->LFO1Frequency,
462                            lfo1_internal_depth,                            lfo1_internal_depth,
463                            pDimRgn->LFO1ControlDepth,                            pDimRgn->LFO1ControlDepth,
464                            pEngine->ControllerTable[pLFO1->ExtController],                            pEngineChannel->ControllerTable[pLFO1->ExtController],
465                            pDimRgn->LFO1FlipPhase,                            pDimRgn->LFO1FlipPhase,
466                            pEngine->SampleRate,                            pEngine->SampleRate,
467                            Delay);                            Delay);
468          }          }
469    
470      #if ENABLE_FILTER  
471          // setup LFO 2 (VCF Cutoff LFO)          // setup LFO 2 (VCF Cutoff LFO)
472          {          {
473              uint16_t lfo2_internal_depth;              uint16_t lfo2_internal_depth;
# Line 457  namespace LinuxSampler { namespace gig { Line 499  namespace LinuxSampler { namespace gig {
499              pLFO2->Trigger(pDimRgn->LFO2Frequency,              pLFO2->Trigger(pDimRgn->LFO2Frequency,
500                            lfo2_internal_depth,                            lfo2_internal_depth,
501                            pDimRgn->LFO2ControlDepth,                            pDimRgn->LFO2ControlDepth,
502                            pEngine->ControllerTable[pLFO2->ExtController],                            pEngineChannel->ControllerTable[pLFO2->ExtController],
503                            pDimRgn->LFO2FlipPhase,                            pDimRgn->LFO2FlipPhase,
504                            pEngine->SampleRate,                            pEngine->SampleRate,
505                            Delay);                            Delay);
506          }          }
507      #endif // ENABLE_FILTER  
508    
509          // setup LFO 3 (VCO LFO)          // setup LFO 3 (VCO LFO)
510          {          {
# Line 495  namespace LinuxSampler { namespace gig { Line 537  namespace LinuxSampler { namespace gig {
537              pLFO3->Trigger(pDimRgn->LFO3Frequency,              pLFO3->Trigger(pDimRgn->LFO3Frequency,
538                            lfo3_internal_depth,                            lfo3_internal_depth,
539                            pDimRgn->LFO3ControlDepth,                            pDimRgn->LFO3ControlDepth,
540                            pEngine->ControllerTable[pLFO3->ExtController],                            pEngineChannel->ControllerTable[pLFO3->ExtController],
541                            false,                            false,
542                            pEngine->SampleRate,                            pEngine->SampleRate,
543                            Delay);                            Delay);
544          }          }
545    
546      #if ENABLE_FILTER  
547          #if FORCE_FILTER_USAGE          #if CONFIG_FORCE_FILTER
548          FilterLeft.Enabled = FilterRight.Enabled = true;          const bool bUseFilter = true;
549          #else // use filter only if instrument file told so          #else // use filter only if instrument file told so
550          FilterLeft.Enabled = FilterRight.Enabled = pDimRgn->VCFEnabled;          const bool bUseFilter = pDimRgn->VCFEnabled;
551          #endif // FORCE_FILTER_USAGE          #endif // CONFIG_FORCE_FILTER
552          if (pDimRgn->VCFEnabled) {          SYNTHESIS_MODE_SET_FILTER(SynthesisMode, bUseFilter);
553              #ifdef OVERRIDE_FILTER_CUTOFF_CTRL          if (bUseFilter) {
554              VCFCutoffCtrl.controller = OVERRIDE_FILTER_CUTOFF_CTRL;              #ifdef CONFIG_OVERRIDE_CUTOFF_CTRL
555                VCFCutoffCtrl.controller = CONFIG_OVERRIDE_CUTOFF_CTRL;
556              #else // use the one defined in the instrument file              #else // use the one defined in the instrument file
557              switch (pDimRgn->VCFCutoffController) {              switch (pDimRgn->VCFCutoffController) {
558                  case ::gig::vcf_cutoff_ctrl_modwheel:                  case ::gig::vcf_cutoff_ctrl_modwheel:
# Line 545  namespace LinuxSampler { namespace gig { Line 588  namespace LinuxSampler { namespace gig {
588                      VCFCutoffCtrl.controller = 0;                      VCFCutoffCtrl.controller = 0;
589                      break;                      break;
590              }              }
591              #endif // OVERRIDE_FILTER_CUTOFF_CTRL              #endif // CONFIG_OVERRIDE_CUTOFF_CTRL
592    
593              #ifdef OVERRIDE_FILTER_RES_CTRL              #ifdef CONFIG_OVERRIDE_RESONANCE_CTRL
594              VCFResonanceCtrl.controller = OVERRIDE_FILTER_RES_CTRL;              VCFResonanceCtrl.controller = CONFIG_OVERRIDE_RESONANCE_CTRL;
595              #else // use the one defined in the instrument file              #else // use the one defined in the instrument file
596              switch (pDimRgn->VCFResonanceController) {              switch (pDimRgn->VCFResonanceController) {
597                  case ::gig::vcf_res_ctrl_genpurpose3:                  case ::gig::vcf_res_ctrl_genpurpose3:
# Line 567  namespace LinuxSampler { namespace gig { Line 610  namespace LinuxSampler { namespace gig {
610                  default:                  default:
611                      VCFResonanceCtrl.controller = 0;                      VCFResonanceCtrl.controller = 0;
612              }              }
613              #endif // OVERRIDE_FILTER_RES_CTRL              #endif // CONFIG_OVERRIDE_RESONANCE_CTRL
614    
615              #ifndef OVERRIDE_FILTER_TYPE              #ifndef CONFIG_OVERRIDE_FILTER_TYPE
616              FilterLeft.SetType(pDimRgn->VCFType);              FilterLeft.SetType(pDimRgn->VCFType);
617              FilterRight.SetType(pDimRgn->VCFType);              FilterRight.SetType(pDimRgn->VCFType);
618              #else // override filter type              #else // override filter type
619              FilterLeft.SetType(OVERRIDE_FILTER_TYPE);              FilterLeft.SetType(CONFIG_OVERRIDE_FILTER_TYPE);
620              FilterRight.SetType(OVERRIDE_FILTER_TYPE);              FilterRight.SetType(CONFIG_OVERRIDE_FILTER_TYPE);
621              #endif // OVERRIDE_FILTER_TYPE              #endif // CONFIG_OVERRIDE_FILTER_TYPE
622    
623              VCFCutoffCtrl.value    = pEngine->ControllerTable[VCFCutoffCtrl.controller];              VCFCutoffCtrl.value    = pEngineChannel->ControllerTable[VCFCutoffCtrl.controller];
624              VCFResonanceCtrl.value = pEngine->ControllerTable[VCFResonanceCtrl.controller];              VCFResonanceCtrl.value = pEngineChannel->ControllerTable[VCFResonanceCtrl.controller];
625    
626              // calculate cutoff frequency              // calculate cutoff frequency
627              float cutoff = (!VCFCutoffCtrl.controller)              float cutoff = (!VCFCutoffCtrl.controller)
628                  ? exp((float) (127 - pNoteOnEvent->Velocity) * (float) pDimRgn->VCFVelocityScale * 6.2E-5f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX                  ? exp((float) (127 - itNoteOnEvent->Param.Note.Velocity) * (float) pDimRgn->VCFVelocityScale * 6.2E-5f * FILTER_CUTOFF_COEFF) * CONFIG_FILTER_CUTOFF_MAX
629                  : exp((float) VCFCutoffCtrl.value * 0.00787402f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX;                  : exp((float) VCFCutoffCtrl.value * 0.00787402f * FILTER_CUTOFF_COEFF) * CONFIG_FILTER_CUTOFF_MAX;
630    
631              // calculate resonance              // calculate resonance
632              float resonance = (float) VCFResonanceCtrl.value * 0.00787f;   // 0.0..1.0              float resonance = (float) VCFResonanceCtrl.value * 0.00787f;   // 0.0..1.0
633              if (pDimRgn->VCFKeyboardTracking) {              if (pDimRgn->VCFKeyboardTracking) {
634                  resonance += (float) (pNoteOnEvent->Key - pDimRgn->VCFKeyboardTrackingBreakpoint) * 0.00787f;                  resonance += (float) (itNoteOnEvent->Param.Note.Key - pDimRgn->VCFKeyboardTrackingBreakpoint) * 0.00787f;
635              }              }
636              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)
637    
638              VCFCutoffCtrl.fvalue    = cutoff - FILTER_CUTOFF_MIN;              VCFCutoffCtrl.fvalue    = cutoff - CONFIG_FILTER_CUTOFF_MIN;
639              VCFResonanceCtrl.fvalue = resonance;              VCFResonanceCtrl.fvalue = resonance;
640    
             FilterLeft.SetParameters(cutoff,  resonance, pEngine->SampleRate);  
             FilterRight.SetParameters(cutoff, resonance, pEngine->SampleRate);  
   
641              FilterUpdateCounter = -1;              FilterUpdateCounter = -1;
642          }          }
643          else {          else {
644              VCFCutoffCtrl.controller    = 0;              VCFCutoffCtrl.controller    = 0;
645              VCFResonanceCtrl.controller = 0;              VCFResonanceCtrl.controller = 0;
646          }          }
     #endif // ENABLE_FILTER  
647    
648          return 0; // success          return 0; // success
649      }      }
# Line 622  namespace LinuxSampler { namespace gig { Line 661  namespace LinuxSampler { namespace gig {
661       */       */
662      void Voice::Render(uint Samples) {      void Voice::Render(uint Samples) {
663    
664            // select default values for synthesis mode bits
665            SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, (PitchBase * PitchBend) != 1.0f);
666            SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, true);
667            SYNTHESIS_MODE_SET_LOOP(SynthesisMode, false);
668    
669          // Reset the synthesis parameter matrix          // Reset the synthesis parameter matrix
670          pEngine->ResetSynthesisParameters(Event::destination_vca, this->Volume * this->CrossfadeVolume * pEngine->GlobalVolume);  
671            pEngine->ResetSynthesisParameters(Event::destination_vca, this->Volume * this->CrossfadeVolume * pEngineChannel->GlobalVolume);
672          pEngine->ResetSynthesisParameters(Event::destination_vco, this->PitchBase);          pEngine->ResetSynthesisParameters(Event::destination_vco, this->PitchBase);
     #if ENABLE_FILTER  
673          pEngine->ResetSynthesisParameters(Event::destination_vcfc, VCFCutoffCtrl.fvalue);          pEngine->ResetSynthesisParameters(Event::destination_vcfc, VCFCutoffCtrl.fvalue);
674          pEngine->ResetSynthesisParameters(Event::destination_vcfr, VCFResonanceCtrl.fvalue);          pEngine->ResetSynthesisParameters(Event::destination_vcfr, VCFResonanceCtrl.fvalue);
     #endif // ENABLE_FILTER  
   
675    
676          // Apply events to the synthesis parameter matrix          // Apply events to the synthesis parameter matrix
677          ProcessEvents(Samples);          ProcessEvents(Samples);
678    
   
679          // Let all modulators write their parameter changes to the synthesis parameter matrix for the current audio fragment          // Let all modulators write their parameter changes to the synthesis parameter matrix for the current audio fragment
680          pEG1->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, pTriggerEvent, this->Pos, this->PitchBase * this->PitchBend, pKillEvent);          pEG1->Process(Samples, pEngineChannel->pMIDIKeyInfo[MIDIKey].pEvents, itTriggerEvent, this->Pos, this->PitchBase * this->PitchBend, itKillEvent);
681      #if ENABLE_FILTER          pEG2->Process(Samples, pEngineChannel->pMIDIKeyInfo[MIDIKey].pEvents, itTriggerEvent, this->Pos, this->PitchBase * this->PitchBend);
682          pEG2->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, pTriggerEvent, this->Pos, this->PitchBase * this->PitchBend);          if (pEG3->Process(Samples)) { // if pitch EG is active
683      #endif // ENABLE_FILTER              SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, true);
684          pEG3->Process(Samples);              SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, false);
685            }
686          pLFO1->Process(Samples);          pLFO1->Process(Samples);
     #if ENABLE_FILTER  
687          pLFO2->Process(Samples);          pLFO2->Process(Samples);
688      #endif // ENABLE_FILTER          if (pLFO3->Process(Samples)) { // if pitch LFO modulation is active
689          pLFO3->Process(Samples);              SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, true);
690                SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, false);
691            }
     #if ENABLE_FILTER  
         CalculateBiquadParameters(Samples); // calculate the final biquad filter parameters  
     #endif // ENABLE_FILTER  
692    
693            if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode))
694                CalculateBiquadParameters(Samples); // calculate the final biquad filter parameters
695    
696          switch (this->PlaybackState) {          switch (this->PlaybackState) {
697    
698                case playback_state_init:
699                    this->PlaybackState = playback_state_ram; // we always start playback from RAM cache and switch then to disk if needed
700                    // no break - continue with playback_state_ram
701    
702              case playback_state_ram: {              case playback_state_ram: {
703                      if (RAMLoop) InterpolateAndLoop(Samples, (sample_t*) pSample->GetCache().pStart, Delay);                      if (RAMLoop) SYNTHESIS_MODE_SET_LOOP(SynthesisMode, true); // enable looping
704                      else         Interpolate(Samples, (sample_t*) pSample->GetCache().pStart, Delay);  
705                        // render current fragment
706                        Synthesize(Samples, (sample_t*) pSample->GetCache().pStart, Delay);
707    
708                      if (DiskVoice) {                      if (DiskVoice) {
709                          // check if we reached the allowed limit of the sample RAM cache                          // check if we reached the allowed limit of the sample RAM cache
710                          if (Pos > MaxRAMPos) {                          if (Pos > MaxRAMPos) {
# Line 680  namespace LinuxSampler { namespace gig { Line 727  namespace LinuxSampler { namespace gig {
727                              KillImmediately();                              KillImmediately();
728                              return;                              return;
729                          }                          }
730                          DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (RTMath::DoubleToInt(Pos) - MaxRAMPos));                          DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (int(Pos) - MaxRAMPos));
731                          Pos -= RTMath::DoubleToInt(Pos);                          Pos -= int(Pos);
732                            RealSampleWordsLeftToRead = -1; // -1 means no silence has been added yet
733                      }                      }
734    
735                        const int sampleWordsLeftToRead = DiskStreamRef.pStream->GetReadSpace();
736    
737                      // 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)
738                      if (DiskStreamRef.State == Stream::state_end && DiskStreamRef.pStream->GetReadSpace() < (pEngine->MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels) {                      if (DiskStreamRef.State == Stream::state_end) {
739                          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
740                          this->PlaybackState = playback_state_end;                          if (sampleWordsLeftToRead <= maxSampleWordsPerCycle) {
741                                // remember how many sample words there are before any silence has been added
742                                if (RealSampleWordsLeftToRead < 0) RealSampleWordsLeftToRead = sampleWordsLeftToRead;
743                                DiskStreamRef.pStream->WriteSilence(maxSampleWordsPerCycle - sampleWordsLeftToRead);
744                            }
745                      }                      }
746    
747                      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
748                      Interpolate(Samples, ptr, Delay);  
749                      DiskStreamRef.pStream->IncrementReadPos(RTMath::DoubleToInt(Pos) * pSample->Channels);                      // render current audio fragment
750                      Pos -= RTMath::DoubleToInt(Pos);                      Synthesize(Samples, ptr, Delay);
751    
752                        const int iPos = (int) Pos;
753                        const int readSampleWords = iPos * pSample->Channels; // amount of sample words actually been read
754                        DiskStreamRef.pStream->IncrementReadPos(readSampleWords);
755                        Pos -= iPos; // just keep fractional part of Pos
756    
757                        // change state of voice to 'end' if we really reached the end of the sample data
758                        if (RealSampleWordsLeftToRead >= 0) {
759                            RealSampleWordsLeftToRead -= readSampleWords;
760                            if (RealSampleWordsLeftToRead <= 0) this->PlaybackState = playback_state_end;
761                        }
762                  }                  }
763                  break;                  break;
764    
765              case playback_state_end:              case playback_state_end:
766                  KillImmediately(); // free voice                  std::cerr << "gig::Voice::Render(): entered with playback_state_end, this is a bug!\n" << std::flush;
767                  break;                  break;
768          }          }
769    
   
770          // Reset synthesis event lists (except VCO, as VCO events apply channel wide currently)          // Reset synthesis event lists (except VCO, as VCO events apply channel wide currently)
771          pEngine->pSynthesisEvents[Event::destination_vca]->clear();          pEngineChannel->pSynthesisEvents[Event::destination_vca]->clear();
772      #if ENABLE_FILTER          pEngineChannel->pSynthesisEvents[Event::destination_vcfc]->clear();
773          pEngine->pSynthesisEvents[Event::destination_vcfc]->clear();          pEngineChannel->pSynthesisEvents[Event::destination_vcfr]->clear();
         pEngine->pSynthesisEvents[Event::destination_vcfr]->clear();  
     #endif // ENABLE_FILTER  
774    
775          // Reset delay          // Reset delay
776          Delay = 0;          Delay = 0;
777    
778          pTriggerEvent = NULL;          itTriggerEvent = Pool<Event>::Iterator();
779    
780          // If release stage finished, let the voice be killed          // If sample stream or release stage finished, kill the voice
781          if (pEG1->GetStage() == EGADSR::stage_end) this->PlaybackState = playback_state_end;          if (PlaybackState == playback_state_end || pEG1->GetStage() == EGADSR::stage_end) KillImmediately();
782      }      }
783    
784      /**      /**
# Line 727  namespace LinuxSampler { namespace gig { Line 789  namespace LinuxSampler { namespace gig {
789          pLFO1->Reset();          pLFO1->Reset();
790          pLFO2->Reset();          pLFO2->Reset();
791          pLFO3->Reset();          pLFO3->Reset();
792            FilterLeft.Reset();
793            FilterRight.Reset();
794          DiskStreamRef.pStream = NULL;          DiskStreamRef.pStream = NULL;
795          DiskStreamRef.hStream = 0;          DiskStreamRef.hStream = 0;
796          DiskStreamRef.State   = Stream::state_unused;          DiskStreamRef.State   = Stream::state_unused;
797          DiskStreamRef.OrderID = 0;          DiskStreamRef.OrderID = 0;
798          Active = false;          PlaybackState = playback_state_end;
799            itTriggerEvent = Pool<Event>::Iterator();
800            itKillEvent    = Pool<Event>::Iterator();
801      }      }
802    
803      /**      /**
# Line 744  namespace LinuxSampler { namespace gig { Line 810  namespace LinuxSampler { namespace gig {
810      void Voice::ProcessEvents(uint Samples) {      void Voice::ProcessEvents(uint Samples) {
811    
812          // dispatch control change events          // dispatch control change events
813          Event* pCCEvent = pEngine->pCCEvents->first();          RTList<Event>::Iterator itCCEvent = pEngineChannel->pCCEvents->first();
814          if (Delay) { // skip events that happened before this voice was triggered          if (Delay) { // skip events that happened before this voice was triggered
815              while (pCCEvent && pCCEvent->FragmentPos() <= Delay) pCCEvent = pEngine->pCCEvents->next();              while (itCCEvent && itCCEvent->FragmentPos() <= Delay) ++itCCEvent;
816          }          }
817          while (pCCEvent) {          while (itCCEvent) {
818              if (pCCEvent->Controller) { // if valid MIDI controller              if (itCCEvent->Param.CC.Controller) { // if valid MIDI controller
819                  #if ENABLE_FILTER                  if (itCCEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {
820                  if (pCCEvent->Controller == VCFCutoffCtrl.controller) {                      *pEngineChannel->pSynthesisEvents[Event::destination_vcfc]->allocAppend() = *itCCEvent;
                     pEngine->pSynthesisEvents[Event::destination_vcfc]->alloc_assign(*pCCEvent);  
821                  }                  }
822                  if (pCCEvent->Controller == VCFResonanceCtrl.controller) {                  if (itCCEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {
823                      pEngine->pSynthesisEvents[Event::destination_vcfr]->alloc_assign(*pCCEvent);                      *pEngineChannel->pSynthesisEvents[Event::destination_vcfr]->allocAppend() = *itCCEvent;
824                  }                  }
825                  #endif // ENABLE_FILTER                  if (itCCEvent->Param.CC.Controller == pLFO1->ExtController) {
826                  if (pCCEvent->Controller == pLFO1->ExtController) {                      pLFO1->SendEvent(itCCEvent);
                     pLFO1->SendEvent(pCCEvent);  
827                  }                  }
828                  #if ENABLE_FILTER                  if (itCCEvent->Param.CC.Controller == pLFO2->ExtController) {
829                  if (pCCEvent->Controller == pLFO2->ExtController) {                      pLFO2->SendEvent(itCCEvent);
                     pLFO2->SendEvent(pCCEvent);  
830                  }                  }
831                  #endif // ENABLE_FILTER                  if (itCCEvent->Param.CC.Controller == pLFO3->ExtController) {
832                  if (pCCEvent->Controller == pLFO3->ExtController) {                      pLFO3->SendEvent(itCCEvent);
                     pLFO3->SendEvent(pCCEvent);  
833                  }                  }
834                  if (pDimRgn->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange &&                  if (pDimRgn->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange &&
835                      pCCEvent->Controller == pDimRgn->AttenuationController.controller_number) { // if crossfade event                      itCCEvent->Param.CC.Controller == pDimRgn->AttenuationController.controller_number) { // if crossfade event
836                      pEngine->pSynthesisEvents[Event::destination_vca]->alloc_assign(*pCCEvent);                      *pEngineChannel->pSynthesisEvents[Event::destination_vca]->allocAppend() = *itCCEvent;
837                  }                  }
838              }              }
839    
840              pCCEvent = pEngine->pCCEvents->next();              ++itCCEvent;
841          }          }
842    
843    
844          // process pitch events          // process pitch events
845          {          {
846              RTEList<Event>* pVCOEventList = pEngine->pSynthesisEvents[Event::destination_vco];              RTList<Event>* pVCOEventList = pEngineChannel->pSynthesisEvents[Event::destination_vco];
847              Event* pVCOEvent = pVCOEventList->first();              RTList<Event>::Iterator itVCOEvent = pVCOEventList->first();
848              if (Delay) { // skip events that happened before this voice was triggered              if (Delay) { // skip events that happened before this voice was triggered
849                  while (pVCOEvent && pVCOEvent->FragmentPos() <= Delay) pVCOEvent = pVCOEventList->next();                  while (itVCOEvent && itVCOEvent->FragmentPos() <= Delay) ++itVCOEvent;
850              }              }
851              // apply old pitchbend value until first pitch event occurs              // apply old pitchbend value until first pitch event occurs
852              if (this->PitchBend != 1.0) {              if (this->PitchBend != 1.0) {
853                  uint end = (pVCOEvent) ? pVCOEvent->FragmentPos() : Samples;                  uint end = (itVCOEvent) ? itVCOEvent->FragmentPos() : Samples;
854                  for (uint i = Delay; i < end; i++) {                  for (uint i = Delay; i < end; i++) {
855                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= this->PitchBend;                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= this->PitchBend;
856                  }                  }
857              }              }
858              float pitch;              float pitch;
859              while (pVCOEvent) {              while (itVCOEvent) {
860                  Event* pNextVCOEvent = pVCOEventList->next();                  RTList<Event>::Iterator itNextVCOEvent = itVCOEvent;
861                    ++itNextVCOEvent;
862    
863                  // calculate the influence length of this event (in sample points)                  // calculate the influence length of this event (in sample points)
864                  uint end = (pNextVCOEvent) ? pNextVCOEvent->FragmentPos() : Samples;                  uint end = (itNextVCOEvent) ? itNextVCOEvent->FragmentPos() : Samples;
865    
866                  pitch = RTMath::CentsToFreqRatio(((double) pVCOEvent->Pitch / 8192.0) * 200.0); // +-two semitones = +-200 cents                  pitch = RTMath::CentsToFreqRatio(((double) itVCOEvent->Param.Pitch.Pitch / 8192.0) * 200.0); // +-two semitones = +-200 cents
867    
868                  // apply pitch value to the pitch parameter sequence                  // apply pitch value to the pitch parameter sequence
869                  for (uint i = pVCOEvent->FragmentPos(); i < end; i++) {                  for (uint i = itVCOEvent->FragmentPos(); i < end; i++) {
870                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= pitch;                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= pitch;
871                  }                  }
872    
873                  pVCOEvent = pNextVCOEvent;                  itVCOEvent = itNextVCOEvent;
874                }
875                if (!pVCOEventList->isEmpty()) {
876                    this->PitchBend = pitch;
877                    SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, true);
878                    SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, false);
879              }              }
             if (pVCOEventList->last()) this->PitchBend = pitch;  
880          }          }
881    
882          // process volume / attenuation events (TODO: we only handle and _expect_ crossfade events here ATM !)          // process volume / attenuation events (TODO: we only handle and _expect_ crossfade events here ATM !)
883          {          {
884              RTEList<Event>* pVCAEventList = pEngine->pSynthesisEvents[Event::destination_vca];              RTList<Event>* pVCAEventList = pEngineChannel->pSynthesisEvents[Event::destination_vca];
885              Event* pVCAEvent = pVCAEventList->first();              RTList<Event>::Iterator itVCAEvent = pVCAEventList->first();
886              if (Delay) { // skip events that happened before this voice was triggered              if (Delay) { // skip events that happened before this voice was triggered
887                  while (pVCAEvent && pVCAEvent->FragmentPos() <= Delay) pVCAEvent = pVCAEventList->next();                  while (itVCAEvent && itVCAEvent->FragmentPos() <= Delay) ++itVCAEvent;
888              }              }
889              float crossfadevolume;              float crossfadevolume;
890              while (pVCAEvent) {              while (itVCAEvent) {
891                  Event* pNextVCAEvent = pVCAEventList->next();                  RTList<Event>::Iterator itNextVCAEvent = itVCAEvent;
892                    ++itNextVCAEvent;
893    
894                  // calculate the influence length of this event (in sample points)                  // calculate the influence length of this event (in sample points)
895                  uint end = (pNextVCAEvent) ? pNextVCAEvent->FragmentPos() : Samples;                  uint end = (itNextVCAEvent) ? itNextVCAEvent->FragmentPos() : Samples;
896    
897                  crossfadevolume = CrossfadeAttenuation(pVCAEvent->Value);                  crossfadevolume = CrossfadeAttenuation(itVCAEvent->Param.CC.Value);
898    
899                  float effective_volume = crossfadevolume * this->Volume * pEngine->GlobalVolume;                  float effective_volume = crossfadevolume * this->Volume * pEngineChannel->GlobalVolume;
900    
901                  // apply volume value to the volume parameter sequence                  // apply volume value to the volume parameter sequence
902                  for (uint i = pVCAEvent->FragmentPos(); i < end; i++) {                  for (uint i = itVCAEvent->FragmentPos(); i < end; i++) {
903                      pEngine->pSynthesisParameters[Event::destination_vca][i] = effective_volume;                      pEngine->pSynthesisParameters[Event::destination_vca][i] = effective_volume;
904                  }                  }
905    
906                  pVCAEvent = pNextVCAEvent;                  itVCAEvent = itNextVCAEvent;
907              }              }
908              if (pVCAEventList->last()) this->CrossfadeVolume = crossfadevolume;              if (!pVCAEventList->isEmpty()) this->CrossfadeVolume = crossfadevolume;
909          }          }
910    
     #if ENABLE_FILTER  
911          // process filter cutoff events          // process filter cutoff events
912          {          {
913              RTEList<Event>* pCutoffEventList = pEngine->pSynthesisEvents[Event::destination_vcfc];              RTList<Event>* pCutoffEventList = pEngineChannel->pSynthesisEvents[Event::destination_vcfc];
914              Event* pCutoffEvent = pCutoffEventList->first();              RTList<Event>::Iterator itCutoffEvent = pCutoffEventList->first();
915              if (Delay) { // skip events that happened before this voice was triggered              if (Delay) { // skip events that happened before this voice was triggered
916                  while (pCutoffEvent && pCutoffEvent->FragmentPos() <= Delay) pCutoffEvent = pCutoffEventList->next();                  while (itCutoffEvent && itCutoffEvent->FragmentPos() <= Delay) ++itCutoffEvent;
917              }              }
918              float cutoff;              float cutoff;
919              while (pCutoffEvent) {              while (itCutoffEvent) {
920                  Event* pNextCutoffEvent = pCutoffEventList->next();                  RTList<Event>::Iterator itNextCutoffEvent = itCutoffEvent;
921                    ++itNextCutoffEvent;
922    
923                  // calculate the influence length of this event (in sample points)                  // calculate the influence length of this event (in sample points)
924                  uint end = (pNextCutoffEvent) ? pNextCutoffEvent->FragmentPos() : Samples;                  uint end = (itNextCutoffEvent) ? itNextCutoffEvent->FragmentPos() : Samples;
925    
926                  cutoff = exp((float) pCutoffEvent->Value * 0.00787402f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX - FILTER_CUTOFF_MIN;                  cutoff = exp((float) itCutoffEvent->Param.CC.Value * 0.00787402f * FILTER_CUTOFF_COEFF) * CONFIG_FILTER_CUTOFF_MAX - CONFIG_FILTER_CUTOFF_MIN;
927    
928                  // apply cutoff frequency to the cutoff parameter sequence                  // apply cutoff frequency to the cutoff parameter sequence
929                  for (uint i = pCutoffEvent->FragmentPos(); i < end; i++) {                  for (uint i = itCutoffEvent->FragmentPos(); i < end; i++) {
930                      pEngine->pSynthesisParameters[Event::destination_vcfc][i] = cutoff;                      pEngine->pSynthesisParameters[Event::destination_vcfc][i] = cutoff;
931                  }                  }
932    
933                  pCutoffEvent = pNextCutoffEvent;                  itCutoffEvent = itNextCutoffEvent;
934              }              }
935              if (pCutoffEventList->last()) VCFCutoffCtrl.fvalue = cutoff; // needed for initialization of parameter matrix next time              if (!pCutoffEventList->isEmpty()) VCFCutoffCtrl.fvalue = cutoff; // needed for initialization of parameter matrix next time
936          }          }
937    
938          // process filter resonance events          // process filter resonance events
939          {          {
940              RTEList<Event>* pResonanceEventList = pEngine->pSynthesisEvents[Event::destination_vcfr];              RTList<Event>* pResonanceEventList = pEngineChannel->pSynthesisEvents[Event::destination_vcfr];
941              Event* pResonanceEvent = pResonanceEventList->first();              RTList<Event>::Iterator itResonanceEvent = pResonanceEventList->first();
942              if (Delay) { // skip events that happened before this voice was triggered              if (Delay) { // skip events that happened before this voice was triggered
943                  while (pResonanceEvent && pResonanceEvent->FragmentPos() <= Delay) pResonanceEvent = pResonanceEventList->next();                  while (itResonanceEvent && itResonanceEvent->FragmentPos() <= Delay) ++itResonanceEvent;
944              }              }
945              while (pResonanceEvent) {              while (itResonanceEvent) {
946                  Event* pNextResonanceEvent = pResonanceEventList->next();                  RTList<Event>::Iterator itNextResonanceEvent = itResonanceEvent;
947                    ++itNextResonanceEvent;
948    
949                  // calculate the influence length of this event (in sample points)                  // calculate the influence length of this event (in sample points)
950                  uint end = (pNextResonanceEvent) ? pNextResonanceEvent->FragmentPos() : Samples;                  uint end = (itNextResonanceEvent) ? itNextResonanceEvent->FragmentPos() : Samples;
951    
952                  // convert absolute controller value to differential                  // convert absolute controller value to differential
953                  int ctrldelta = pResonanceEvent->Value - VCFResonanceCtrl.value;                  int ctrldelta = itResonanceEvent->Param.CC.Value - VCFResonanceCtrl.value;
954                  VCFResonanceCtrl.value = pResonanceEvent->Value;                  VCFResonanceCtrl.value = itResonanceEvent->Param.CC.Value;
955    
956                  float resonancedelta = (float) ctrldelta * 0.00787f; // 0.0..1.0                  float resonancedelta = (float) ctrldelta * 0.00787f; // 0.0..1.0
957    
958                  // apply cutoff frequency to the cutoff parameter sequence                  // apply cutoff frequency to the cutoff parameter sequence
959                  for (uint i = pResonanceEvent->FragmentPos(); i < end; i++) {                  for (uint i = itResonanceEvent->FragmentPos(); i < end; i++) {
960                      pEngine->pSynthesisParameters[Event::destination_vcfr][i] += resonancedelta;                      pEngine->pSynthesisParameters[Event::destination_vcfr][i] += resonancedelta;
961                  }                  }
962    
963                  pResonanceEvent = pNextResonanceEvent;                  itResonanceEvent = itNextResonanceEvent;
964              }              }
965              if (pResonanceEventList->last()) VCFResonanceCtrl.fvalue = pResonanceEventList->last()->Value * 0.00787f; // needed for initialization of parameter matrix next time              if (!pResonanceEventList->isEmpty()) VCFResonanceCtrl.fvalue = pResonanceEventList->last()->Param.CC.Value * 0.00787f; // needed for initialization of parameter matrix next time
966          }          }
     #endif // ENABLE_FILTER  
967      }      }
968    
     #if ENABLE_FILTER  
969      /**      /**
970       * Calculate all necessary, final biquad filter parameters.       * Calculate all necessary, final biquad filter parameters.
971       *       *
972       * @param Samples - number of samples to be rendered in this audio fragment cycle       * @param Samples - number of samples to be rendered in this audio fragment cycle
973       */       */
974      void Voice::CalculateBiquadParameters(uint Samples) {      void Voice::CalculateBiquadParameters(uint Samples) {
         if (!FilterLeft.Enabled) return;  
   
975          biquad_param_t bqbase;          biquad_param_t bqbase;
976          biquad_param_t bqmain;          biquad_param_t bqmain;
977          float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0];          float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0];
978          float prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][0];          float prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][0];
979          FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);          FilterLeft.SetParameters( &bqbase, &bqmain, prev_cutoff + CONFIG_FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate);
980            FilterRight.SetParameters(&bqbase, &bqmain, prev_cutoff + CONFIG_FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate);
981          pEngine->pBasicFilterParameters[0] = bqbase;          pEngine->pBasicFilterParameters[0] = bqbase;
982          pEngine->pMainFilterParameters[0]  = bqmain;          pEngine->pMainFilterParameters[0]  = bqmain;
983    
984          float* bq;          float* bq;
985          for (int i = 1; i < Samples; i++) {          for (int i = 1; i < Samples; i++) {
986              // recalculate biquad parameters if cutoff or resonance differ from previous sample point              // recalculate biquad parameters if cutoff or resonance differ from previous sample point
987              if (!(i & FILTER_UPDATE_MASK)) if (pEngine->pSynthesisParameters[Event::destination_vcfr][i] != prev_res ||              if (!(i & FILTER_UPDATE_MASK)) {
988                                                 pEngine->pSynthesisParameters[Event::destination_vcfc][i] != prev_cutoff) {                  if (pEngine->pSynthesisParameters[Event::destination_vcfr][i] != prev_res ||
989                  prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][i];                      pEngine->pSynthesisParameters[Event::destination_vcfc][i] != prev_cutoff)
990                  prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][i];                  {
991                  FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);                      prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][i];
992                        prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][i];
993                        FilterLeft.SetParameters( &bqbase, &bqmain, prev_cutoff + CONFIG_FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate);
994                        FilterRight.SetParameters(&bqbase, &bqmain, prev_cutoff + CONFIG_FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate);
995                    }
996              }              }
997    
998              //same as 'pEngine->pBasicFilterParameters[i] = bqbase;'              //same as 'pEngine->pBasicFilterParameters[i] = bqbase;'
999              bq    = (float*) &pEngine->pBasicFilterParameters[i];              bq    = (float*) &pEngine->pBasicFilterParameters[i];
1000              bq[0] = bqbase.a1;              bq[0] = bqbase.b0;
1001              bq[1] = bqbase.a2;              bq[1] = bqbase.b1;
1002              bq[2] = bqbase.b0;              bq[2] = bqbase.b2;
1003              bq[3] = bqbase.b1;              bq[3] = bqbase.a1;
1004              bq[4] = bqbase.b2;              bq[4] = bqbase.a2;
1005    
1006              // same as 'pEngine->pMainFilterParameters[i] = bqmain;'              // same as 'pEngine->pMainFilterParameters[i] = bqmain;'
1007              bq    = (float*) &pEngine->pMainFilterParameters[i];              bq    = (float*) &pEngine->pMainFilterParameters[i];
1008              bq[0] = bqmain.a1;              bq[0] = bqmain.b0;
1009              bq[1] = bqmain.a2;              bq[1] = bqmain.b1;
1010              bq[2] = bqmain.b0;              bq[2] = bqmain.b2;
1011              bq[3] = bqmain.b1;              bq[3] = bqmain.a1;
1012              bq[4] = bqmain.b2;              bq[4] = bqmain.a2;
1013          }          }
1014      }      }
     #endif // ENABLE_FILTER  
1015    
1016      /**      /**
1017       *  Interpolates the input audio data (no loop).       *  Synthesizes the current audio fragment for this voice.
1018       *       *
1019       *  @param Samples - number of sample points to be rendered in this audio       *  @param Samples - number of sample points to be rendered in this audio
1020       *                   fragment cycle       *                   fragment cycle
1021       *  @param pSrc    - pointer to input sample data       *  @param pSrc    - pointer to input sample data
1022       *  @param Skip    - number of sample points to skip in output buffer       *  @param Skip    - number of sample points to skip in output buffer
1023       */       */
1024      void Voice::Interpolate(uint Samples, sample_t* pSrc, uint Skip) {      void Voice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {
1025          int i = Skip;          RunSynthesisFunction(SynthesisMode, *this, Samples, pSrc, Skip);
   
         // FIXME: assuming either mono or stereo  
         if (this->pSample->Channels == 2) { // Stereo Sample  
             while (i < Samples) {  
                 InterpolateOneStep_Stereo(pSrc, i,  
                                           pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                           pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                           pEngine->pBasicFilterParameters[i],  
                                           pEngine->pMainFilterParameters[i]);  
             }  
         }  
         else { // Mono Sample  
             while (i < Samples) {  
                 InterpolateOneStep_Mono(pSrc, i,  
                                         pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                         pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                         pEngine->pBasicFilterParameters[i],  
                                         pEngine->pMainFilterParameters[i]);  
             }  
         }  
     }  
   
     /**  
      *  Interpolates the input audio data, this method honors looping.  
      *  
      *  @param Samples - number of sample points to be rendered in this audio  
      *                   fragment cycle  
      *  @param pSrc    - pointer to input sample data  
      *  @param Skip    - number of sample points to skip in output buffer  
      */  
     void Voice::InterpolateAndLoop(uint Samples, sample_t* pSrc, uint Skip) {  
         int i = Skip;  
   
         // FIXME: assuming either mono or stereo  
         if (pSample->Channels == 2) { // Stereo Sample  
             if (pSample->LoopPlayCount) {  
                 // render loop (loop count limited)  
                 while (i < Samples && LoopCyclesLeft) {  
                     InterpolateOneStep_Stereo(pSrc, i,  
                                               pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                               pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                               pEngine->pBasicFilterParameters[i],  
                                               pEngine->pMainFilterParameters[i]);  
                     if (Pos > pSample->LoopEnd) {  
                         Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;  
                         LoopCyclesLeft--;  
                     }  
                 }  
                 // render on without loop  
                 while (i < Samples) {  
                     InterpolateOneStep_Stereo(pSrc, i,  
                                               pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                               pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                               pEngine->pBasicFilterParameters[i],  
                                               pEngine->pMainFilterParameters[i]);  
                 }  
             }  
             else { // render loop (endless loop)  
                 while (i < Samples) {  
                     InterpolateOneStep_Stereo(pSrc, i,  
                                               pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                               pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                               pEngine->pBasicFilterParameters[i],  
                                               pEngine->pMainFilterParameters[i]);  
                     if (Pos > pSample->LoopEnd) {  
                         Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);  
                     }  
                 }  
             }  
         }  
         else { // Mono Sample  
             if (pSample->LoopPlayCount) {  
                 // render loop (loop count limited)  
                 while (i < Samples && LoopCyclesLeft) {  
                     InterpolateOneStep_Mono(pSrc, i,  
                                             pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                             pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                             pEngine->pBasicFilterParameters[i],  
                                             pEngine->pMainFilterParameters[i]);  
                     if (Pos > pSample->LoopEnd) {  
                         Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;  
                         LoopCyclesLeft--;  
                     }  
                 }  
                 // render on without loop  
                 while (i < Samples) {  
                     InterpolateOneStep_Mono(pSrc, i,  
                                             pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                             pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                             pEngine->pBasicFilterParameters[i],  
                                             pEngine->pMainFilterParameters[i]);  
                 }  
             }  
             else { // render loop (endless loop)  
                 while (i < Samples) {  
                     InterpolateOneStep_Mono(pSrc, i,  
                                             pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                             pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                             pEngine->pBasicFilterParameters[i],  
                                             pEngine->pMainFilterParameters[i]);  
                     if (Pos > pSample->LoopEnd) {  
                         Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;  
                     }  
                 }  
             }  
         }  
1026      }      }
1027    
1028      /**      /**
# Line 1084  namespace LinuxSampler { namespace gig { Line 1047  namespace LinuxSampler { namespace gig {
1047       *  of a voice, a kill process cannot be cancalled and is therefore       *  of a voice, a kill process cannot be cancalled and is therefore
1048       *  usually used for voice stealing and key group conflicts.       *  usually used for voice stealing and key group conflicts.
1049       *       *
1050       *  @param pKillEvent - event which caused the voice to be killed       *  @param itKillEvent - event which caused the voice to be killed
1051       */       */
1052      void Voice::Kill(Event* pKillEvent) {      void Voice::Kill(Pool<Event>::Iterator& itKillEvent) {
1053          if (pTriggerEvent && pKillEvent->FragmentPos() <= pTriggerEvent->FragmentPos()) return;          #if CONFIG_DEVMODE
1054          this->pKillEvent = pKillEvent;          if (!itKillEvent) dmsg(1,("gig::Voice::Kill(): ERROR, !itKillEvent !!!\n"));
1055            if (itKillEvent && !itKillEvent.isValid()) dmsg(1,("gig::Voice::Kill(): ERROR, itKillEvent invalid !!!\n"));
1056            #endif // CONFIG_DEVMODE
1057    
1058            if (itTriggerEvent && itKillEvent->FragmentPos() <= itTriggerEvent->FragmentPos()) return;
1059            this->itKillEvent = itKillEvent;
1060      }      }
1061    
1062  }} // namespace LinuxSampler::gig  }} // namespace LinuxSampler::gig

Legend:
Removed from v.244  
changed lines
  Added in v.614

  ViewVC Help
Powered by ViewVC