/[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 239 by schoenebeck, Sun Sep 12 14:48:19 2004 UTC revision 630 by persson, Sat Jun 11 14:51:49 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    
31  namespace LinuxSampler { namespace gig {  namespace LinuxSampler { namespace gig {
32    
     // TODO: no support for crossfades yet  
   
33      const float Voice::FILTER_CUTOFF_COEFF(CalculateFilterCutoffCoeff());      const float Voice::FILTER_CUTOFF_COEFF(CalculateFilterCutoffCoeff());
34    
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 58  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 CONFIG_ASM && 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 105  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       *  @returns            0 on success, a value < 0 if something failed       *  @param iLayer               - layer number this voice refers to (only if this is a layered sound of course)
125         *  @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) {      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          Active          = true;          Type            = type_normal;
144          MIDIKey         = pNoteOnEvent->Key;          MIDIKey         = itNoteOnEvent->Param.Note.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);  
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
176                      break;                      break;
177                  case ::gig::dimension_releasetrigger:                  case ::gig::dimension_releasetrigger:
178                      DimValues[i] = 0; //TODO: we currently ignore this dimension                      Type = (ReleaseTriggerVoice) ? type_release_trigger : (!iLayer) ? type_release_trigger_required : type_normal;
179                        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 236  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            // calculate volume
273            const double velocityAttenuation = pDimRgn->GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity);
274    
275            Volume = velocityAttenuation / 32768.0f; // we downscale by 32768 to convert from int16 value range to DSP value range (which is -1.0..1.0)
276    
277            Volume *= pDimRgn->SampleAttenuation;
278    
279            // the volume of release triggered samples depends on note length
280            if (ReleaseTriggerVoice) {
281                float noteLength = float(pEngine->FrameTime + Delay -
282                                         pEngineChannel->pMIDIKeyInfo[MIDIKey].NoteOnTime) / pEngine->SampleRate;
283                float attenuation = 1 - 0.01053 * (256 >> pDimRgn->ReleaseTriggerDecay) * noteLength;
284                if (attenuation <= 0) return -1;
285                Volume *= attenuation;
286            }
287    
288            // select channel mode (mono or stereo)
289            SYNTHESIS_MODE_SET_CHANNELS(SynthesisMode, pSample->Channels == 2);
290    
291          // get starting crossfade volume level          // get starting crossfade volume level
292          switch (pDimRgn->AttenuationController.type) {          switch (pDimRgn->AttenuationController.type) {
# Line 244  namespace LinuxSampler { namespace gig { Line 294  namespace LinuxSampler { namespace gig {
294                  CrossfadeVolume = 1.0f; //TODO: aftertouch not supported yet                  CrossfadeVolume = 1.0f; //TODO: aftertouch not supported yet
295                  break;                  break;
296              case ::gig::attenuation_ctrl_t::type_velocity:              case ::gig::attenuation_ctrl_t::type_velocity:
297                  CrossfadeVolume = CrossfadeAttenuation(pNoteOnEvent->Velocity);                  CrossfadeVolume = CrossfadeAttenuation(itNoteOnEvent->Param.Note.Velocity);
298                  break;                  break;
299              case ::gig::attenuation_ctrl_t::type_controlchange: //FIXME: currently not sample accurate              case ::gig::attenuation_ctrl_t::type_controlchange: //FIXME: currently not sample accurate
300                  CrossfadeVolume = CrossfadeAttenuation(pEngine->ControllerTable[pDimRgn->AttenuationController.controller_number]);                  CrossfadeVolume = CrossfadeAttenuation(pEngineChannel->ControllerTable[pDimRgn->AttenuationController.controller_number]);
301                  break;                  break;
302              case ::gig::attenuation_ctrl_t::type_none: // no crossfade defined              case ::gig::attenuation_ctrl_t::type_none: // no crossfade defined
303              default:              default:
304                  CrossfadeVolume = 1.0f;                  CrossfadeVolume = 1.0f;
305          }          }
306    
307          pSample = pDimRgn->pSample; // sample won't change until the voice is finished          PanLeft  = 1.0f - float(RTMath::Max(pDimRgn->Pan, 0)) /  63.0f;
308            PanRight = 1.0f - float(RTMath::Min(pDimRgn->Pan, 0)) / -64.0f;
309    
310          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)
311    
# Line 263  namespace LinuxSampler { namespace gig { Line 314  namespace LinuxSampler { namespace gig {
314          DiskVoice          = cachedsamples < pSample->SamplesTotal;          DiskVoice          = cachedsamples < pSample->SamplesTotal;
315    
316          if (DiskVoice) { // voice to be streamed from disk          if (DiskVoice) { // voice to be streamed from disk
317              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)
318    
319              // 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
320              if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) {              if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) {
# Line 292  namespace LinuxSampler { namespace gig { Line 343  namespace LinuxSampler { namespace gig {
343    
344          // calculate initial pitch value          // calculate initial pitch value
345          {          {
346              double pitchbasecents = pDimRgn->FineTune * 10;              double pitchbasecents = pDimRgn->FineTune + (int) pEngine->ScaleTuning[MIDIKey % 12];
347              if (pDimRgn->PitchTrack) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;              if (pDimRgn->PitchTrack) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;
348              this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents) * (double(pSample->SamplesPerSecond) / double(pEngine->pAudioOutputDevice->SampleRate()));              this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents) * (double(pSample->SamplesPerSecond) / double(pEngine->pAudioOutputDevice->SampleRate()));
349              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
350          }          }
351    
352            // the length of the decay and release curves are dependent on the velocity
353          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)          const double velrelease = 1 / pDimRgn->GetVelocityRelease(itNoteOnEvent->Param.Note.Velocity);
   
354    
355          // setup EG 1 (VCA EG)          // setup EG 1 (VCA EG)
356          {          {
# Line 314  namespace LinuxSampler { namespace gig { Line 364  namespace LinuxSampler { namespace gig {
364                      eg1controllervalue = 0; // TODO: aftertouch not yet supported                      eg1controllervalue = 0; // TODO: aftertouch not yet supported
365                      break;                      break;
366                  case ::gig::eg1_ctrl_t::type_velocity:                  case ::gig::eg1_ctrl_t::type_velocity:
367                      eg1controllervalue = pNoteOnEvent->Velocity;                      eg1controllervalue = itNoteOnEvent->Param.Note.Velocity;
368                      break;                      break;
369                  case ::gig::eg1_ctrl_t::type_controlchange: // MIDI control change controller                  case ::gig::eg1_ctrl_t::type_controlchange: // MIDI control change controller
370                      eg1controllervalue = pEngine->ControllerTable[pDimRgn->EG1Controller.controller_number];                      eg1controllervalue = pEngineChannel->ControllerTable[pDimRgn->EG1Controller.controller_number];
371                      break;                      break;
372              }              }
373              if (pDimRgn->EG1ControllerInvert) eg1controllervalue = 127 - eg1controllervalue;              if (pDimRgn->EG1ControllerInvert) eg1controllervalue = 127 - eg1controllervalue;
# Line 331  namespace LinuxSampler { namespace gig { Line 381  namespace LinuxSampler { namespace gig {
381                            pDimRgn->EG1Attack + eg1attack,                            pDimRgn->EG1Attack + eg1attack,
382                            pDimRgn->EG1Hold,                            pDimRgn->EG1Hold,
383                            pSample->LoopStart,                            pSample->LoopStart,
384                            pDimRgn->EG1Decay1 + eg1decay,                            (pDimRgn->EG1Decay1 + eg1decay) * velrelease,
385                            pDimRgn->EG1Decay2 + eg1decay,                            (pDimRgn->EG1Decay2 + eg1decay) * velrelease,
386                            pDimRgn->EG1InfiniteSustain,                            pDimRgn->EG1InfiniteSustain,
387                            pDimRgn->EG1Sustain,                            pDimRgn->EG1Sustain,
388                            pDimRgn->EG1Release + eg1release,                            (pDimRgn->EG1Release + eg1release) * velrelease,
389                            Delay);                            // the SSE synthesis implementation requires
390                              // the vca start to be 16 byte aligned
391                              SYNTHESIS_MODE_GET_IMPLEMENTATION(SynthesisMode) ?
392                              Delay & 0xfffffffc : Delay,
393                              velocityAttenuation);
394          }          }
395    
396    
     #if ENABLE_FILTER  
397          // setup EG 2 (VCF Cutoff EG)          // setup EG 2 (VCF Cutoff EG)
398          {          {
399              // get current value of EG2 controller              // get current value of EG2 controller
# Line 353  namespace LinuxSampler { namespace gig { Line 406  namespace LinuxSampler { namespace gig {
406                      eg2controllervalue = 0; // TODO: aftertouch not yet supported                      eg2controllervalue = 0; // TODO: aftertouch not yet supported
407                      break;                      break;
408                  case ::gig::eg2_ctrl_t::type_velocity:                  case ::gig::eg2_ctrl_t::type_velocity:
409                      eg2controllervalue = pNoteOnEvent->Velocity;                      eg2controllervalue = itNoteOnEvent->Param.Note.Velocity;
410                      break;                      break;
411                  case ::gig::eg2_ctrl_t::type_controlchange: // MIDI control change controller                  case ::gig::eg2_ctrl_t::type_controlchange: // MIDI control change controller
412                      eg2controllervalue = pEngine->ControllerTable[pDimRgn->EG2Controller.controller_number];                      eg2controllervalue = pEngineChannel->ControllerTable[pDimRgn->EG2Controller.controller_number];
413                      break;                      break;
414              }              }
415              if (pDimRgn->EG2ControllerInvert) eg2controllervalue = 127 - eg2controllervalue;              if (pDimRgn->EG2ControllerInvert) eg2controllervalue = 127 - eg2controllervalue;
# Line 370  namespace LinuxSampler { namespace gig { Line 423  namespace LinuxSampler { namespace gig {
423                            pDimRgn->EG2Attack + eg2attack,                            pDimRgn->EG2Attack + eg2attack,
424                            false,                            false,
425                            pSample->LoopStart,                            pSample->LoopStart,
426                            pDimRgn->EG2Decay1 + eg2decay,                            (pDimRgn->EG2Decay1 + eg2decay) * velrelease,
427                            pDimRgn->EG2Decay2 + eg2decay,                            (pDimRgn->EG2Decay2 + eg2decay) * velrelease,
428                            pDimRgn->EG2InfiniteSustain,                            pDimRgn->EG2InfiniteSustain,
429                            pDimRgn->EG2Sustain,                            pDimRgn->EG2Sustain,
430                            pDimRgn->EG2Release + eg2release,                            (pDimRgn->EG2Release + eg2release) * velrelease,
431                            Delay);                            Delay,
432                              velocityAttenuation);
433          }          }
     #endif // ENABLE_FILTER  
434    
435    
436          // setup EG 3 (VCO EG)          // setup EG 3 (VCO EG)
# Line 418  namespace LinuxSampler { namespace gig { Line 471  namespace LinuxSampler { namespace gig {
471              pLFO1->Trigger(pDimRgn->LFO1Frequency,              pLFO1->Trigger(pDimRgn->LFO1Frequency,
472                            lfo1_internal_depth,                            lfo1_internal_depth,
473                            pDimRgn->LFO1ControlDepth,                            pDimRgn->LFO1ControlDepth,
474                            pEngine->ControllerTable[pLFO1->ExtController],                            pEngineChannel->ControllerTable[pLFO1->ExtController],
475                            pDimRgn->LFO1FlipPhase,                            pDimRgn->LFO1FlipPhase,
476                            pEngine->SampleRate,                            pEngine->SampleRate,
477                            Delay);                            Delay);
478          }          }
479    
480      #if ENABLE_FILTER  
481          // setup LFO 2 (VCF Cutoff LFO)          // setup LFO 2 (VCF Cutoff LFO)
482          {          {
483              uint16_t lfo2_internal_depth;              uint16_t lfo2_internal_depth;
# Line 456  namespace LinuxSampler { namespace gig { Line 509  namespace LinuxSampler { namespace gig {
509              pLFO2->Trigger(pDimRgn->LFO2Frequency,              pLFO2->Trigger(pDimRgn->LFO2Frequency,
510                            lfo2_internal_depth,                            lfo2_internal_depth,
511                            pDimRgn->LFO2ControlDepth,                            pDimRgn->LFO2ControlDepth,
512                            pEngine->ControllerTable[pLFO2->ExtController],                            pEngineChannel->ControllerTable[pLFO2->ExtController],
513                            pDimRgn->LFO2FlipPhase,                            pDimRgn->LFO2FlipPhase,
514                            pEngine->SampleRate,                            pEngine->SampleRate,
515                            Delay);                            Delay);
516          }          }
517      #endif // ENABLE_FILTER  
518    
519          // setup LFO 3 (VCO LFO)          // setup LFO 3 (VCO LFO)
520          {          {
# Line 494  namespace LinuxSampler { namespace gig { Line 547  namespace LinuxSampler { namespace gig {
547              pLFO3->Trigger(pDimRgn->LFO3Frequency,              pLFO3->Trigger(pDimRgn->LFO3Frequency,
548                            lfo3_internal_depth,                            lfo3_internal_depth,
549                            pDimRgn->LFO3ControlDepth,                            pDimRgn->LFO3ControlDepth,
550                            pEngine->ControllerTable[pLFO3->ExtController],                            pEngineChannel->ControllerTable[pLFO3->ExtController],
551                            false,                            false,
552                            pEngine->SampleRate,                            pEngine->SampleRate,
553                            Delay);                            Delay);
554          }          }
555    
556      #if ENABLE_FILTER  
557          #if FORCE_FILTER_USAGE          #if CONFIG_FORCE_FILTER
558          FilterLeft.Enabled = FilterRight.Enabled = true;          const bool bUseFilter = true;
559          #else // use filter only if instrument file told so          #else // use filter only if instrument file told so
560          FilterLeft.Enabled = FilterRight.Enabled = pDimRgn->VCFEnabled;          const bool bUseFilter = pDimRgn->VCFEnabled;
561          #endif // FORCE_FILTER_USAGE          #endif // CONFIG_FORCE_FILTER
562          if (pDimRgn->VCFEnabled) {          SYNTHESIS_MODE_SET_FILTER(SynthesisMode, bUseFilter);
563              #ifdef OVERRIDE_FILTER_CUTOFF_CTRL          if (bUseFilter) {
564              VCFCutoffCtrl.controller = OVERRIDE_FILTER_CUTOFF_CTRL;              #ifdef CONFIG_OVERRIDE_CUTOFF_CTRL
565                VCFCutoffCtrl.controller = CONFIG_OVERRIDE_CUTOFF_CTRL;
566              #else // use the one defined in the instrument file              #else // use the one defined in the instrument file
567              switch (pDimRgn->VCFCutoffController) {              switch (pDimRgn->VCFCutoffController) {
568                  case ::gig::vcf_cutoff_ctrl_modwheel:                  case ::gig::vcf_cutoff_ctrl_modwheel:
# Line 544  namespace LinuxSampler { namespace gig { Line 598  namespace LinuxSampler { namespace gig {
598                      VCFCutoffCtrl.controller = 0;                      VCFCutoffCtrl.controller = 0;
599                      break;                      break;
600              }              }
601              #endif // OVERRIDE_FILTER_CUTOFF_CTRL              #endif // CONFIG_OVERRIDE_CUTOFF_CTRL
602    
603              #ifdef OVERRIDE_FILTER_RES_CTRL              #ifdef CONFIG_OVERRIDE_RESONANCE_CTRL
604              VCFResonanceCtrl.controller = OVERRIDE_FILTER_RES_CTRL;              VCFResonanceCtrl.controller = CONFIG_OVERRIDE_RESONANCE_CTRL;
605              #else // use the one defined in the instrument file              #else // use the one defined in the instrument file
606              switch (pDimRgn->VCFResonanceController) {              switch (pDimRgn->VCFResonanceController) {
607                  case ::gig::vcf_res_ctrl_genpurpose3:                  case ::gig::vcf_res_ctrl_genpurpose3:
# Line 566  namespace LinuxSampler { namespace gig { Line 620  namespace LinuxSampler { namespace gig {
620                  default:                  default:
621                      VCFResonanceCtrl.controller = 0;                      VCFResonanceCtrl.controller = 0;
622              }              }
623              #endif // OVERRIDE_FILTER_RES_CTRL              #endif // CONFIG_OVERRIDE_RESONANCE_CTRL
624    
625              #ifndef OVERRIDE_FILTER_TYPE              #ifndef CONFIG_OVERRIDE_FILTER_TYPE
626              FilterLeft.SetType(pDimRgn->VCFType);              FilterLeft.SetType(pDimRgn->VCFType);
627              FilterRight.SetType(pDimRgn->VCFType);              FilterRight.SetType(pDimRgn->VCFType);
628              #else // override filter type              #else // override filter type
629              FilterLeft.SetType(OVERRIDE_FILTER_TYPE);              FilterLeft.SetType(CONFIG_OVERRIDE_FILTER_TYPE);
630              FilterRight.SetType(OVERRIDE_FILTER_TYPE);              FilterRight.SetType(CONFIG_OVERRIDE_FILTER_TYPE);
631              #endif // OVERRIDE_FILTER_TYPE              #endif // CONFIG_OVERRIDE_FILTER_TYPE
632    
633              VCFCutoffCtrl.value    = pEngine->ControllerTable[VCFCutoffCtrl.controller];              VCFCutoffCtrl.value    = pEngineChannel->ControllerTable[VCFCutoffCtrl.controller];
634              VCFResonanceCtrl.value = pEngine->ControllerTable[VCFResonanceCtrl.controller];              VCFResonanceCtrl.value = pEngineChannel->ControllerTable[VCFResonanceCtrl.controller];
635    
636              // calculate cutoff frequency              // calculate cutoff frequency
637              float cutoff = (!VCFCutoffCtrl.controller)              float cutoff = (!VCFCutoffCtrl.controller)
638                  ? 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
639                  : 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;
640    
641              // calculate resonance              // calculate resonance
642              float resonance = (float) VCFResonanceCtrl.value * 0.00787f;   // 0.0..1.0              float resonance = (float) VCFResonanceCtrl.value * 0.00787f;   // 0.0..1.0
643              if (pDimRgn->VCFKeyboardTracking) {              if (pDimRgn->VCFKeyboardTracking) {
644                  resonance += (float) (pNoteOnEvent->Key - pDimRgn->VCFKeyboardTrackingBreakpoint) * 0.00787f;                  resonance += (float) (itNoteOnEvent->Param.Note.Key - pDimRgn->VCFKeyboardTrackingBreakpoint) * 0.00787f;
645              }              }
646              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)
647    
648              VCFCutoffCtrl.fvalue    = cutoff - FILTER_CUTOFF_MIN;              VCFCutoffCtrl.fvalue    = cutoff - CONFIG_FILTER_CUTOFF_MIN;
649              VCFResonanceCtrl.fvalue = resonance;              VCFResonanceCtrl.fvalue = resonance;
650    
             FilterLeft.SetParameters(cutoff,  resonance, pEngine->SampleRate);  
             FilterRight.SetParameters(cutoff, resonance, pEngine->SampleRate);  
   
651              FilterUpdateCounter = -1;              FilterUpdateCounter = -1;
652          }          }
653          else {          else {
654              VCFCutoffCtrl.controller    = 0;              VCFCutoffCtrl.controller    = 0;
655              VCFResonanceCtrl.controller = 0;              VCFResonanceCtrl.controller = 0;
656          }          }
     #endif // ENABLE_FILTER  
657    
658          return 0; // success          return 0; // success
659      }      }
# Line 621  namespace LinuxSampler { namespace gig { Line 671  namespace LinuxSampler { namespace gig {
671       */       */
672      void Voice::Render(uint Samples) {      void Voice::Render(uint Samples) {
673    
674            // select default values for synthesis mode bits
675            SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, (PitchBase * PitchBend) != 1.0f);
676            SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, true);
677            SYNTHESIS_MODE_SET_LOOP(SynthesisMode, false);
678    
679          // Reset the synthesis parameter matrix          // Reset the synthesis parameter matrix
680          pEngine->ResetSynthesisParameters(Event::destination_vca, this->Volume * this->CrossfadeVolume * pEngine->GlobalVolume);  
681            pEngine->ResetSynthesisParameters(Event::destination_vca, this->Volume * this->CrossfadeVolume * pEngineChannel->GlobalVolume);
682          pEngine->ResetSynthesisParameters(Event::destination_vco, this->PitchBase);          pEngine->ResetSynthesisParameters(Event::destination_vco, this->PitchBase);
     #if ENABLE_FILTER  
683          pEngine->ResetSynthesisParameters(Event::destination_vcfc, VCFCutoffCtrl.fvalue);          pEngine->ResetSynthesisParameters(Event::destination_vcfc, VCFCutoffCtrl.fvalue);
684          pEngine->ResetSynthesisParameters(Event::destination_vcfr, VCFResonanceCtrl.fvalue);          pEngine->ResetSynthesisParameters(Event::destination_vcfr, VCFResonanceCtrl.fvalue);
     #endif // ENABLE_FILTER  
   
685    
686          // Apply events to the synthesis parameter matrix          // Apply events to the synthesis parameter matrix
687          ProcessEvents(Samples);          ProcessEvents(Samples);
688    
   
689          // 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
690          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);
691      #if ENABLE_FILTER          pEG2->Process(Samples, pEngineChannel->pMIDIKeyInfo[MIDIKey].pEvents, itTriggerEvent, this->Pos, this->PitchBase * this->PitchBend);
692          pEG2->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, pTriggerEvent, this->Pos, this->PitchBase * this->PitchBend);          if (pEG3->Process(Samples)) { // if pitch EG is active
693      #endif // ENABLE_FILTER              SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, true);
694          pEG3->Process(Samples);              SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, false);
695            }
696          pLFO1->Process(Samples);          pLFO1->Process(Samples);
     #if ENABLE_FILTER  
697          pLFO2->Process(Samples);          pLFO2->Process(Samples);
698      #endif // ENABLE_FILTER          if (pLFO3->Process(Samples)) { // if pitch LFO modulation is active
699          pLFO3->Process(Samples);              SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, true);
700                SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, false);
701            }
     #if ENABLE_FILTER  
         CalculateBiquadParameters(Samples); // calculate the final biquad filter parameters  
     #endif // ENABLE_FILTER  
702    
703            if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode))
704                CalculateBiquadParameters(Samples); // calculate the final biquad filter parameters
705    
706          switch (this->PlaybackState) {          switch (this->PlaybackState) {
707    
708                case playback_state_init:
709                    this->PlaybackState = playback_state_ram; // we always start playback from RAM cache and switch then to disk if needed
710                    // no break - continue with playback_state_ram
711    
712              case playback_state_ram: {              case playback_state_ram: {
713                      if (RAMLoop) InterpolateAndLoop(Samples, (sample_t*) pSample->GetCache().pStart, Delay);                      if (RAMLoop) SYNTHESIS_MODE_SET_LOOP(SynthesisMode, true); // enable looping
714                      else         Interpolate(Samples, (sample_t*) pSample->GetCache().pStart, Delay);  
715                        // render current fragment
716                        Synthesize(Samples, (sample_t*) pSample->GetCache().pStart, Delay);
717    
718                      if (DiskVoice) {                      if (DiskVoice) {
719                          // check if we reached the allowed limit of the sample RAM cache                          // check if we reached the allowed limit of the sample RAM cache
720                          if (Pos > MaxRAMPos) {                          if (Pos > MaxRAMPos) {
# Line 679  namespace LinuxSampler { namespace gig { Line 737  namespace LinuxSampler { namespace gig {
737                              KillImmediately();                              KillImmediately();
738                              return;                              return;
739                          }                          }
740                          DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (RTMath::DoubleToInt(Pos) - MaxRAMPos));                          DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (int(Pos) - MaxRAMPos));
741                          Pos -= RTMath::DoubleToInt(Pos);                          Pos -= int(Pos);
742                            RealSampleWordsLeftToRead = -1; // -1 means no silence has been added yet
743                      }                      }
744    
745                        const int sampleWordsLeftToRead = DiskStreamRef.pStream->GetReadSpace();
746    
747                      // 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)
748                      if (DiskStreamRef.State == Stream::state_end && DiskStreamRef.pStream->GetReadSpace() < (pEngine->MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels) {                      if (DiskStreamRef.State == Stream::state_end) {
749                          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
750                          this->PlaybackState = playback_state_end;                          if (sampleWordsLeftToRead <= maxSampleWordsPerCycle) {
751                                // remember how many sample words there are before any silence has been added
752                                if (RealSampleWordsLeftToRead < 0) RealSampleWordsLeftToRead = sampleWordsLeftToRead;
753                                DiskStreamRef.pStream->WriteSilence(maxSampleWordsPerCycle - sampleWordsLeftToRead);
754                            }
755                      }                      }
756    
757                      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
758                      Interpolate(Samples, ptr, Delay);  
759                      DiskStreamRef.pStream->IncrementReadPos(RTMath::DoubleToInt(Pos) * pSample->Channels);                      // render current audio fragment
760                      Pos -= RTMath::DoubleToInt(Pos);                      Synthesize(Samples, ptr, Delay);
761    
762                        const int iPos = (int) Pos;
763                        const int readSampleWords = iPos * pSample->Channels; // amount of sample words actually been read
764                        DiskStreamRef.pStream->IncrementReadPos(readSampleWords);
765                        Pos -= iPos; // just keep fractional part of Pos
766    
767                        // change state of voice to 'end' if we really reached the end of the sample data
768                        if (RealSampleWordsLeftToRead >= 0) {
769                            RealSampleWordsLeftToRead -= readSampleWords;
770                            if (RealSampleWordsLeftToRead <= 0) this->PlaybackState = playback_state_end;
771                        }
772                  }                  }
773                  break;                  break;
774    
775              case playback_state_end:              case playback_state_end:
776                  KillImmediately(); // free voice                  std::cerr << "gig::Voice::Render(): entered with playback_state_end, this is a bug!\n" << std::flush;
777                  break;                  break;
778          }          }
779    
   
780          // 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)
781          pEngine->pSynthesisEvents[Event::destination_vca]->clear();          pEngineChannel->pSynthesisEvents[Event::destination_vca]->clear();
782      #if ENABLE_FILTER          pEngineChannel->pSynthesisEvents[Event::destination_vcfc]->clear();
783          pEngine->pSynthesisEvents[Event::destination_vcfc]->clear();          pEngineChannel->pSynthesisEvents[Event::destination_vcfr]->clear();
         pEngine->pSynthesisEvents[Event::destination_vcfr]->clear();  
     #endif // ENABLE_FILTER  
784    
785          // Reset delay          // Reset delay
786          Delay = 0;          Delay = 0;
787    
788          pTriggerEvent = NULL;          itTriggerEvent = Pool<Event>::Iterator();
789    
790          // If release stage finished, let the voice be killed          // If sample stream or release stage finished, kill the voice
791          if (pEG1->GetStage() == EGADSR::stage_end) this->PlaybackState = playback_state_end;          if (PlaybackState == playback_state_end || pEG1->GetStage() == EGADSR::stage_end) KillImmediately();
792      }      }
793    
794      /**      /**
# Line 726  namespace LinuxSampler { namespace gig { Line 799  namespace LinuxSampler { namespace gig {
799          pLFO1->Reset();          pLFO1->Reset();
800          pLFO2->Reset();          pLFO2->Reset();
801          pLFO3->Reset();          pLFO3->Reset();
802            FilterLeft.Reset();
803            FilterRight.Reset();
804          DiskStreamRef.pStream = NULL;          DiskStreamRef.pStream = NULL;
805          DiskStreamRef.hStream = 0;          DiskStreamRef.hStream = 0;
806          DiskStreamRef.State   = Stream::state_unused;          DiskStreamRef.State   = Stream::state_unused;
807          DiskStreamRef.OrderID = 0;          DiskStreamRef.OrderID = 0;
808          Active = false;          PlaybackState = playback_state_end;
809            itTriggerEvent = Pool<Event>::Iterator();
810            itKillEvent    = Pool<Event>::Iterator();
811      }      }
812    
813      /**      /**
# Line 743  namespace LinuxSampler { namespace gig { Line 820  namespace LinuxSampler { namespace gig {
820      void Voice::ProcessEvents(uint Samples) {      void Voice::ProcessEvents(uint Samples) {
821    
822          // dispatch control change events          // dispatch control change events
823          Event* pCCEvent = pEngine->pCCEvents->first();          RTList<Event>::Iterator itCCEvent = pEngineChannel->pCCEvents->first();
824          if (Delay) { // skip events that happened before this voice was triggered          if (Delay) { // skip events that happened before this voice was triggered
825              while (pCCEvent && pCCEvent->FragmentPos() <= Delay) pCCEvent = pEngine->pCCEvents->next();              while (itCCEvent && itCCEvent->FragmentPos() <= Delay) ++itCCEvent;
826          }          }
827          while (pCCEvent) {          while (itCCEvent) {
828              if (pCCEvent->Controller) { // if valid MIDI controller              if (itCCEvent->Param.CC.Controller) { // if valid MIDI controller
829                  #if ENABLE_FILTER                  if (itCCEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {
830                  if (pCCEvent->Controller == VCFCutoffCtrl.controller) {                      *pEngineChannel->pSynthesisEvents[Event::destination_vcfc]->allocAppend() = *itCCEvent;
                     pEngine->pSynthesisEvents[Event::destination_vcfc]->alloc_assign(*pCCEvent);  
831                  }                  }
832                  if (pCCEvent->Controller == VCFResonanceCtrl.controller) {                  if (itCCEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {
833                      pEngine->pSynthesisEvents[Event::destination_vcfr]->alloc_assign(*pCCEvent);                      *pEngineChannel->pSynthesisEvents[Event::destination_vcfr]->allocAppend() = *itCCEvent;
834                  }                  }
835                  #endif // ENABLE_FILTER                  if (itCCEvent->Param.CC.Controller == pLFO1->ExtController) {
836                  if (pCCEvent->Controller == pLFO1->ExtController) {                      pLFO1->SendEvent(itCCEvent);
                     pLFO1->SendEvent(pCCEvent);  
837                  }                  }
838                  #if ENABLE_FILTER                  if (itCCEvent->Param.CC.Controller == pLFO2->ExtController) {
839                  if (pCCEvent->Controller == pLFO2->ExtController) {                      pLFO2->SendEvent(itCCEvent);
                     pLFO2->SendEvent(pCCEvent);  
840                  }                  }
841                  #endif // ENABLE_FILTER                  if (itCCEvent->Param.CC.Controller == pLFO3->ExtController) {
842                  if (pCCEvent->Controller == pLFO3->ExtController) {                      pLFO3->SendEvent(itCCEvent);
                     pLFO3->SendEvent(pCCEvent);  
843                  }                  }
844                  if (pDimRgn->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange &&                  if (pDimRgn->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange &&
845                      pCCEvent->Controller == pDimRgn->AttenuationController.controller_number) { // if crossfade event                      itCCEvent->Param.CC.Controller == pDimRgn->AttenuationController.controller_number) { // if crossfade event
846                      pEngine->pSynthesisEvents[Event::destination_vca]->alloc_assign(*pCCEvent);                      *pEngineChannel->pSynthesisEvents[Event::destination_vca]->allocAppend() = *itCCEvent;
847                  }                  }
848              }              }
849    
850              pCCEvent = pEngine->pCCEvents->next();              ++itCCEvent;
851          }          }
852    
853    
854          // process pitch events          // process pitch events
855          {          {
856              RTEList<Event>* pVCOEventList = pEngine->pSynthesisEvents[Event::destination_vco];              RTList<Event>* pVCOEventList = pEngineChannel->pSynthesisEvents[Event::destination_vco];
857              Event* pVCOEvent = pVCOEventList->first();              RTList<Event>::Iterator itVCOEvent = pVCOEventList->first();
858              if (Delay) { // skip events that happened before this voice was triggered              if (Delay) { // skip events that happened before this voice was triggered
859                  while (pVCOEvent && pVCOEvent->FragmentPos() <= Delay) pVCOEvent = pVCOEventList->next();                  while (itVCOEvent && itVCOEvent->FragmentPos() <= Delay) ++itVCOEvent;
860              }              }
861              // apply old pitchbend value until first pitch event occurs              // apply old pitchbend value until first pitch event occurs
862              if (this->PitchBend != 1.0) {              if (this->PitchBend != 1.0) {
863                  uint end = (pVCOEvent) ? pVCOEvent->FragmentPos() : Samples;                  uint end = (itVCOEvent) ? itVCOEvent->FragmentPos() : Samples;
864                  for (uint i = Delay; i < end; i++) {                  for (uint i = Delay; i < end; i++) {
865                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= this->PitchBend;                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= this->PitchBend;
866                  }                  }
867              }              }
868              float pitch;              float pitch;
869              while (pVCOEvent) {              while (itVCOEvent) {
870                  Event* pNextVCOEvent = pVCOEventList->next();                  RTList<Event>::Iterator itNextVCOEvent = itVCOEvent;
871                    ++itNextVCOEvent;
872    
873                  // calculate the influence length of this event (in sample points)                  // calculate the influence length of this event (in sample points)
874                  uint end = (pNextVCOEvent) ? pNextVCOEvent->FragmentPos() : Samples;                  uint end = (itNextVCOEvent) ? itNextVCOEvent->FragmentPos() : Samples;
875    
876                  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
877    
878                  // apply pitch value to the pitch parameter sequence                  // apply pitch value to the pitch parameter sequence
879                  for (uint i = pVCOEvent->FragmentPos(); i < end; i++) {                  for (uint i = itVCOEvent->FragmentPos(); i < end; i++) {
880                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= pitch;                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= pitch;
881                  }                  }
882    
883                  pVCOEvent = pNextVCOEvent;                  itVCOEvent = itNextVCOEvent;
884                }
885                if (!pVCOEventList->isEmpty()) {
886                    this->PitchBend = pitch;
887                    SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, true);
888                    SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, false);
889              }              }
             if (pVCOEventList->last()) this->PitchBend = pitch;  
890          }          }
891    
892          // 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 !)
893          {          {
894              RTEList<Event>* pVCAEventList = pEngine->pSynthesisEvents[Event::destination_vca];              RTList<Event>* pVCAEventList = pEngineChannel->pSynthesisEvents[Event::destination_vca];
895              Event* pVCAEvent = pVCAEventList->first();              RTList<Event>::Iterator itVCAEvent = pVCAEventList->first();
896              if (Delay) { // skip events that happened before this voice was triggered              if (Delay) { // skip events that happened before this voice was triggered
897                  while (pVCAEvent && pVCAEvent->FragmentPos() <= Delay) pVCAEvent = pVCAEventList->next();                  while (itVCAEvent && itVCAEvent->FragmentPos() <= Delay) ++itVCAEvent;
898              }              }
899              float crossfadevolume;              float crossfadevolume;
900              while (pVCAEvent) {              while (itVCAEvent) {
901                  Event* pNextVCAEvent = pVCAEventList->next();                  RTList<Event>::Iterator itNextVCAEvent = itVCAEvent;
902                    ++itNextVCAEvent;
903    
904                  // calculate the influence length of this event (in sample points)                  // calculate the influence length of this event (in sample points)
905                  uint end = (pNextVCAEvent) ? pNextVCAEvent->FragmentPos() : Samples;                  uint end = (itNextVCAEvent) ? itNextVCAEvent->FragmentPos() : Samples;
906    
907                  crossfadevolume = CrossfadeAttenuation(pVCAEvent->Value);                  crossfadevolume = CrossfadeAttenuation(itVCAEvent->Param.CC.Value);
908    
909                  float effective_volume = crossfadevolume * this->Volume * pEngine->GlobalVolume;                  float effective_volume = crossfadevolume * this->Volume * pEngineChannel->GlobalVolume;
910    
911                  // apply volume value to the volume parameter sequence                  // apply volume value to the volume parameter sequence
912                  for (uint i = pVCAEvent->FragmentPos(); i < end; i++) {                  for (uint i = itVCAEvent->FragmentPos(); i < end; i++) {
913                      pEngine->pSynthesisParameters[Event::destination_vca][i] = effective_volume;                      pEngine->pSynthesisParameters[Event::destination_vca][i] = effective_volume;
914                  }                  }
915    
916                  pVCAEvent = pNextVCAEvent;                  itVCAEvent = itNextVCAEvent;
917              }              }
918              if (pVCAEventList->last()) this->CrossfadeVolume = crossfadevolume;              if (!pVCAEventList->isEmpty()) this->CrossfadeVolume = crossfadevolume;
919          }          }
920    
     #if ENABLE_FILTER  
921          // process filter cutoff events          // process filter cutoff events
922          {          {
923              RTEList<Event>* pCutoffEventList = pEngine->pSynthesisEvents[Event::destination_vcfc];              RTList<Event>* pCutoffEventList = pEngineChannel->pSynthesisEvents[Event::destination_vcfc];
924              Event* pCutoffEvent = pCutoffEventList->first();              RTList<Event>::Iterator itCutoffEvent = pCutoffEventList->first();
925              if (Delay) { // skip events that happened before this voice was triggered              if (Delay) { // skip events that happened before this voice was triggered
926                  while (pCutoffEvent && pCutoffEvent->FragmentPos() <= Delay) pCutoffEvent = pCutoffEventList->next();                  while (itCutoffEvent && itCutoffEvent->FragmentPos() <= Delay) ++itCutoffEvent;
927              }              }
928              float cutoff;              float cutoff;
929              while (pCutoffEvent) {              while (itCutoffEvent) {
930                  Event* pNextCutoffEvent = pCutoffEventList->next();                  RTList<Event>::Iterator itNextCutoffEvent = itCutoffEvent;
931                    ++itNextCutoffEvent;
932    
933                  // calculate the influence length of this event (in sample points)                  // calculate the influence length of this event (in sample points)
934                  uint end = (pNextCutoffEvent) ? pNextCutoffEvent->FragmentPos() : Samples;                  uint end = (itNextCutoffEvent) ? itNextCutoffEvent->FragmentPos() : Samples;
935    
936                  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;
937    
938                  // apply cutoff frequency to the cutoff parameter sequence                  // apply cutoff frequency to the cutoff parameter sequence
939                  for (uint i = pCutoffEvent->FragmentPos(); i < end; i++) {                  for (uint i = itCutoffEvent->FragmentPos(); i < end; i++) {
940                      pEngine->pSynthesisParameters[Event::destination_vcfc][i] = cutoff;                      pEngine->pSynthesisParameters[Event::destination_vcfc][i] = cutoff;
941                  }                  }
942    
943                  pCutoffEvent = pNextCutoffEvent;                  itCutoffEvent = itNextCutoffEvent;
944              }              }
945              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
946          }          }
947    
948          // process filter resonance events          // process filter resonance events
949          {          {
950              RTEList<Event>* pResonanceEventList = pEngine->pSynthesisEvents[Event::destination_vcfr];              RTList<Event>* pResonanceEventList = pEngineChannel->pSynthesisEvents[Event::destination_vcfr];
951              Event* pResonanceEvent = pResonanceEventList->first();              RTList<Event>::Iterator itResonanceEvent = pResonanceEventList->first();
952              if (Delay) { // skip events that happened before this voice was triggered              if (Delay) { // skip events that happened before this voice was triggered
953                  while (pResonanceEvent && pResonanceEvent->FragmentPos() <= Delay) pResonanceEvent = pResonanceEventList->next();                  while (itResonanceEvent && itResonanceEvent->FragmentPos() <= Delay) ++itResonanceEvent;
954              }              }
955              while (pResonanceEvent) {              while (itResonanceEvent) {
956                  Event* pNextResonanceEvent = pResonanceEventList->next();                  RTList<Event>::Iterator itNextResonanceEvent = itResonanceEvent;
957                    ++itNextResonanceEvent;
958    
959                  // calculate the influence length of this event (in sample points)                  // calculate the influence length of this event (in sample points)
960                  uint end = (pNextResonanceEvent) ? pNextResonanceEvent->FragmentPos() : Samples;                  uint end = (itNextResonanceEvent) ? itNextResonanceEvent->FragmentPos() : Samples;
961    
962                  // convert absolute controller value to differential                  // convert absolute controller value to differential
963                  int ctrldelta = pResonanceEvent->Value - VCFResonanceCtrl.value;                  int ctrldelta = itResonanceEvent->Param.CC.Value - VCFResonanceCtrl.value;
964                  VCFResonanceCtrl.value = pResonanceEvent->Value;                  VCFResonanceCtrl.value = itResonanceEvent->Param.CC.Value;
965    
966                  float resonancedelta = (float) ctrldelta * 0.00787f; // 0.0..1.0                  float resonancedelta = (float) ctrldelta * 0.00787f; // 0.0..1.0
967    
968                  // apply cutoff frequency to the cutoff parameter sequence                  // apply cutoff frequency to the cutoff parameter sequence
969                  for (uint i = pResonanceEvent->FragmentPos(); i < end; i++) {                  for (uint i = itResonanceEvent->FragmentPos(); i < end; i++) {
970                      pEngine->pSynthesisParameters[Event::destination_vcfr][i] += resonancedelta;                      pEngine->pSynthesisParameters[Event::destination_vcfr][i] += resonancedelta;
971                  }                  }
972    
973                  pResonanceEvent = pNextResonanceEvent;                  itResonanceEvent = itNextResonanceEvent;
974              }              }
975              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
976          }          }
     #endif // ENABLE_FILTER  
977      }      }
978    
     #if ENABLE_FILTER  
979      /**      /**
980       * Calculate all necessary, final biquad filter parameters.       * Calculate all necessary, final biquad filter parameters.
981       *       *
982       * @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
983       */       */
984      void Voice::CalculateBiquadParameters(uint Samples) {      void Voice::CalculateBiquadParameters(uint Samples) {
         if (!FilterLeft.Enabled) return;  
   
985          biquad_param_t bqbase;          biquad_param_t bqbase;
986          biquad_param_t bqmain;          biquad_param_t bqmain;
987          float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0];          float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0];
988          float prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][0];          float prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][0];
989          FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);          FilterLeft.SetParameters( &bqbase, &bqmain, prev_cutoff + CONFIG_FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate);
990            FilterRight.SetParameters(&bqbase, &bqmain, prev_cutoff + CONFIG_FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate);
991          pEngine->pBasicFilterParameters[0] = bqbase;          pEngine->pBasicFilterParameters[0] = bqbase;
992          pEngine->pMainFilterParameters[0]  = bqmain;          pEngine->pMainFilterParameters[0]  = bqmain;
993    
994          float* bq;          float* bq;
995          for (int i = 1; i < Samples; i++) {          for (int i = 1; i < Samples; i++) {
996              // recalculate biquad parameters if cutoff or resonance differ from previous sample point              // recalculate biquad parameters if cutoff or resonance differ from previous sample point
997              if (!(i & FILTER_UPDATE_MASK)) if (pEngine->pSynthesisParameters[Event::destination_vcfr][i] != prev_res ||              if (!(i & FILTER_UPDATE_MASK)) {
998                                                 pEngine->pSynthesisParameters[Event::destination_vcfc][i] != prev_cutoff) {                  if (pEngine->pSynthesisParameters[Event::destination_vcfr][i] != prev_res ||
999                  prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][i];                      pEngine->pSynthesisParameters[Event::destination_vcfc][i] != prev_cutoff)
1000                  prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][i];                  {
1001                  FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);                      prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][i];
1002                        prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][i];
1003                        FilterLeft.SetParameters( &bqbase, &bqmain, prev_cutoff + CONFIG_FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate);
1004                        FilterRight.SetParameters(&bqbase, &bqmain, prev_cutoff + CONFIG_FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate);
1005                    }
1006              }              }
1007    
1008              //same as 'pEngine->pBasicFilterParameters[i] = bqbase;'              //same as 'pEngine->pBasicFilterParameters[i] = bqbase;'
1009              bq    = (float*) &pEngine->pBasicFilterParameters[i];              bq    = (float*) &pEngine->pBasicFilterParameters[i];
1010              bq[0] = bqbase.a1;              bq[0] = bqbase.b0;
1011              bq[1] = bqbase.a2;              bq[1] = bqbase.b1;
1012              bq[2] = bqbase.b0;              bq[2] = bqbase.b2;
1013              bq[3] = bqbase.b1;              bq[3] = bqbase.a1;
1014              bq[4] = bqbase.b2;              bq[4] = bqbase.a2;
1015    
1016              // same as 'pEngine->pMainFilterParameters[i] = bqmain;'              // same as 'pEngine->pMainFilterParameters[i] = bqmain;'
1017              bq    = (float*) &pEngine->pMainFilterParameters[i];              bq    = (float*) &pEngine->pMainFilterParameters[i];
1018              bq[0] = bqmain.a1;              bq[0] = bqmain.b0;
1019              bq[1] = bqmain.a2;              bq[1] = bqmain.b1;
1020              bq[2] = bqmain.b0;              bq[2] = bqmain.b2;
1021              bq[3] = bqmain.b1;              bq[3] = bqmain.a1;
1022              bq[4] = bqmain.b2;              bq[4] = bqmain.a2;
1023          }          }
1024      }      }
     #endif // ENABLE_FILTER  
1025    
1026      /**      /**
1027       *  Interpolates the input audio data (no loop).       *  Synthesizes the current audio fragment for this voice.
1028       *       *
1029       *  @param Samples - number of sample points to be rendered in this audio       *  @param Samples - number of sample points to be rendered in this audio
1030       *                   fragment cycle       *                   fragment cycle
1031       *  @param pSrc    - pointer to input sample data       *  @param pSrc    - pointer to input sample data
1032       *  @param Skip    - number of sample points to skip in output buffer       *  @param Skip    - number of sample points to skip in output buffer
1033       */       */
1034      void Voice::Interpolate(uint Samples, sample_t* pSrc, uint Skip) {      void Voice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {
1035          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);;  
                     }  
                 }  
             }  
         }  
1036      }      }
1037    
1038      /**      /**
# Line 1083  namespace LinuxSampler { namespace gig { Line 1057  namespace LinuxSampler { namespace gig {
1057       *  of a voice, a kill process cannot be cancalled and is therefore       *  of a voice, a kill process cannot be cancalled and is therefore
1058       *  usually used for voice stealing and key group conflicts.       *  usually used for voice stealing and key group conflicts.
1059       *       *
1060       *  @param pKillEvent - event which caused the voice to be killed       *  @param itKillEvent - event which caused the voice to be killed
1061       */       */
1062      void Voice::Kill(Event* pKillEvent) {      void Voice::Kill(Pool<Event>::Iterator& itKillEvent) {
1063          this->pKillEvent = pKillEvent;          #if CONFIG_DEVMODE
1064            if (!itKillEvent) dmsg(1,("gig::Voice::Kill(): ERROR, !itKillEvent !!!\n"));
1065            if (itKillEvent && !itKillEvent.isValid()) dmsg(1,("gig::Voice::Kill(): ERROR, itKillEvent invalid !!!\n"));
1066            #endif // CONFIG_DEVMODE
1067    
1068            if (itTriggerEvent && itKillEvent->FragmentPos() <= itTriggerEvent->FragmentPos()) return;
1069            this->itKillEvent = itKillEvent;
1070      }      }
1071    
1072  }} // namespace LinuxSampler::gig  }} // namespace LinuxSampler::gig

Legend:
Removed from v.239  
changed lines
  Added in v.630

  ViewVC Help
Powered by ViewVC