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

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

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

revision 287 by schoenebeck, Sat Oct 16 17:38:03 2004 UTC revision 554 by schoenebeck, Thu May 19 19:25:14 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    
# 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 itNoteOnEvent       - 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       *  @param VoiceStealing       - wether the voice is allowed to steal voices for further subvoices       *  @param ReleaseTriggerVoice  - if this new voice is a release trigger voice (optional, default = false)
126       *  @returns 0 on success, a value < 0 if something failed       *  @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(Pool<Event>::Iterator& itNoteOnEvent, int PitchBend, ::gig::Instrument* pInstrument, int iLayer, bool ReleaseTriggerVoice, bool VoiceStealing) {      int Voice::Trigger(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent, int PitchBend, ::gig::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 (itNoteOnEvent->FragmentPos() > pEngine->MaxSamplesPerCycle) { // FIXME: should be removed before the final release (purpose: just a sanity check for debugging)
138                dmsg(1,("Voice::Trigger(): ERROR, TriggerDelay > Totalsamples\n"));
139            }
140    
141          Type            = type_normal;          Type            = type_normal;
142          MIDIKey         = itNoteOnEvent->Param.Note.Key;          MIDIKey         = itNoteOnEvent->Param.Note.Key;
# Line 124  namespace LinuxSampler { namespace gig { Line 145  namespace LinuxSampler { namespace gig {
145          Delay           = itNoteOnEvent->FragmentPos();          Delay           = itNoteOnEvent->FragmentPos();
146          itTriggerEvent  = itNoteOnEvent;          itTriggerEvent  = itNoteOnEvent;
147          itKillEvent     = Pool<Event>::Iterator();          itKillEvent     = Pool<Event>::Iterator();
         itChildVoice    = Pool<Voice>::Iterator();  
148    
149          if (!pRegion) {          if (!pRegion) {
150              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();  
151              return -1;              return -1;
152          }          }
153    
154          KeyGroup = pRegion->KeyGroup;          // only mark the first voice of a layered voice (group) to be in a
155            // key group, so the layered voices won't kill each other
156            KeyGroup = (iLayer == 0 && !ReleaseTriggerVoice) ? pRegion->KeyGroup : 0;
157    
158          // get current dimension values to select the right dimension region          // get current dimension values to select the right dimension region
159          //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
160          uint DimValues[5] = {0,0,0,0,0};          uint DimValues[8] = { 0 };
161          for (int i = pRegion->Dimensions - 1; i >= 0; i--) {          for (int i = pRegion->Dimensions - 1; i >= 0; i--) {
162              switch (pRegion->pDimensionDefinitions[i].dimension) {              switch (pRegion->pDimensionDefinitions[i].dimension) {
163                  case ::gig::dimension_samplechannel:                  case ::gig::dimension_samplechannel:
# Line 144  namespace LinuxSampler { namespace gig { Line 165  namespace LinuxSampler { namespace gig {
165                      break;                      break;
166                  case ::gig::dimension_layer:                  case ::gig::dimension_layer:
167                      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++)  
                             itChildVoice = pEngine->LaunchVoice(itNoteOnEvent, iNewLayer, ReleaseTriggerVoice, VoiceStealing);  
168                      break;                      break;
169                  case ::gig::dimension_velocity:                  case ::gig::dimension_velocity:
170                      DimValues[i] = itNoteOnEvent->Param.Note.Velocity;                      DimValues[i] = itNoteOnEvent->Param.Note.Velocity;
# Line 160  namespace LinuxSampler { namespace gig { Line 177  namespace LinuxSampler { namespace gig {
177                      DimValues[i] = (uint) ReleaseTriggerVoice;                      DimValues[i] = (uint) ReleaseTriggerVoice;
178                      break;                      break;
179                  case ::gig::dimension_keyboard:                  case ::gig::dimension_keyboard:
180                      DimValues[i] = (uint) itNoteOnEvent->Param.Note.Key;                      DimValues[i] = (uint) pEngineChannel->CurrentKeyDimension;
181                        break;
182                    case ::gig::dimension_roundrobin:
183                        DimValues[i] = (uint) pEngineChannel->pMIDIKeyInfo[MIDIKey].RoundRobinIndex; // incremented for each note on
184                        break;
185                    case ::gig::dimension_random:
186                        pEngine->RandomSeed = pEngine->RandomSeed * 1103515245 + 12345; // classic pseudo random number generator
187                        DimValues[i] = (uint) pEngine->RandomSeed >> (32 - pRegion->pDimensionDefinitions[i].bits); // highest bits are most random
188                      break;                      break;
189                  case ::gig::dimension_modwheel:                  case ::gig::dimension_modwheel:
190                      DimValues[i] = pEngine->ControllerTable[1];                      DimValues[i] = pEngineChannel->ControllerTable[1];
191                      break;                      break;
192                  case ::gig::dimension_breath:                  case ::gig::dimension_breath:
193                      DimValues[i] = pEngine->ControllerTable[2];                      DimValues[i] = pEngineChannel->ControllerTable[2];
194                      break;                      break;
195                  case ::gig::dimension_foot:                  case ::gig::dimension_foot:
196                      DimValues[i] = pEngine->ControllerTable[4];                      DimValues[i] = pEngineChannel->ControllerTable[4];
197                      break;                      break;
198                  case ::gig::dimension_portamentotime:                  case ::gig::dimension_portamentotime:
199                      DimValues[i] = pEngine->ControllerTable[5];                      DimValues[i] = pEngineChannel->ControllerTable[5];
200                      break;                      break;
201                  case ::gig::dimension_effect1:                  case ::gig::dimension_effect1:
202                      DimValues[i] = pEngine->ControllerTable[12];                      DimValues[i] = pEngineChannel->ControllerTable[12];
203                      break;                      break;
204                  case ::gig::dimension_effect2:                  case ::gig::dimension_effect2:
205                      DimValues[i] = pEngine->ControllerTable[13];                      DimValues[i] = pEngineChannel->ControllerTable[13];
206                      break;                      break;
207                  case ::gig::dimension_genpurpose1:                  case ::gig::dimension_genpurpose1:
208                      DimValues[i] = pEngine->ControllerTable[16];                      DimValues[i] = pEngineChannel->ControllerTable[16];
209                      break;                      break;
210                  case ::gig::dimension_genpurpose2:                  case ::gig::dimension_genpurpose2:
211                      DimValues[i] = pEngine->ControllerTable[17];                      DimValues[i] = pEngineChannel->ControllerTable[17];
212                      break;                      break;
213                  case ::gig::dimension_genpurpose3:                  case ::gig::dimension_genpurpose3:
214                      DimValues[i] = pEngine->ControllerTable[18];                      DimValues[i] = pEngineChannel->ControllerTable[18];
215                      break;                      break;
216                  case ::gig::dimension_genpurpose4:                  case ::gig::dimension_genpurpose4:
217                      DimValues[i] = pEngine->ControllerTable[19];                      DimValues[i] = pEngineChannel->ControllerTable[19];
218                      break;                      break;
219                  case ::gig::dimension_sustainpedal:                  case ::gig::dimension_sustainpedal:
220                      DimValues[i] = pEngine->ControllerTable[64];                      DimValues[i] = pEngineChannel->ControllerTable[64];
221                      break;                      break;
222                  case ::gig::dimension_portamento:                  case ::gig::dimension_portamento:
223                      DimValues[i] = pEngine->ControllerTable[65];                      DimValues[i] = pEngineChannel->ControllerTable[65];
224                      break;                      break;
225                  case ::gig::dimension_sostenutopedal:                  case ::gig::dimension_sostenutopedal:
226                      DimValues[i] = pEngine->ControllerTable[66];                      DimValues[i] = pEngineChannel->ControllerTable[66];
227                      break;                      break;
228                  case ::gig::dimension_softpedal:                  case ::gig::dimension_softpedal:
229                      DimValues[i] = pEngine->ControllerTable[67];                      DimValues[i] = pEngineChannel->ControllerTable[67];
230                      break;                      break;
231                  case ::gig::dimension_genpurpose5:                  case ::gig::dimension_genpurpose5:
232                      DimValues[i] = pEngine->ControllerTable[80];                      DimValues[i] = pEngineChannel->ControllerTable[80];
233                      break;                      break;
234                  case ::gig::dimension_genpurpose6:                  case ::gig::dimension_genpurpose6:
235                      DimValues[i] = pEngine->ControllerTable[81];                      DimValues[i] = pEngineChannel->ControllerTable[81];
236                      break;                      break;
237                  case ::gig::dimension_genpurpose7:                  case ::gig::dimension_genpurpose7:
238                      DimValues[i] = pEngine->ControllerTable[82];                      DimValues[i] = pEngineChannel->ControllerTable[82];
239                      break;                      break;
240                  case ::gig::dimension_genpurpose8:                  case ::gig::dimension_genpurpose8:
241                      DimValues[i] = pEngine->ControllerTable[83];                      DimValues[i] = pEngineChannel->ControllerTable[83];
242                      break;                      break;
243                  case ::gig::dimension_effect1depth:                  case ::gig::dimension_effect1depth:
244                      DimValues[i] = pEngine->ControllerTable[91];                      DimValues[i] = pEngineChannel->ControllerTable[91];
245                      break;                      break;
246                  case ::gig::dimension_effect2depth:                  case ::gig::dimension_effect2depth:
247                      DimValues[i] = pEngine->ControllerTable[92];                      DimValues[i] = pEngineChannel->ControllerTable[92];
248                      break;                      break;
249                  case ::gig::dimension_effect3depth:                  case ::gig::dimension_effect3depth:
250                      DimValues[i] = pEngine->ControllerTable[93];                      DimValues[i] = pEngineChannel->ControllerTable[93];
251                      break;                      break;
252                  case ::gig::dimension_effect4depth:                  case ::gig::dimension_effect4depth:
253                      DimValues[i] = pEngine->ControllerTable[94];                      DimValues[i] = pEngineChannel->ControllerTable[94];
254                      break;                      break;
255                  case ::gig::dimension_effect5depth:                  case ::gig::dimension_effect5depth:
256                      DimValues[i] = pEngine->ControllerTable[95];                      DimValues[i] = pEngineChannel->ControllerTable[95];
257                      break;                      break;
258                  case ::gig::dimension_none:                  case ::gig::dimension_none:
259                      std::cerr << "gig::Voice::Trigger() Error: dimension=none\n" << std::flush;                      std::cerr << "gig::Voice::Trigger() Error: dimension=none\n" << std::flush;
# Line 238  namespace LinuxSampler { namespace gig { Line 262  namespace LinuxSampler { namespace gig {
262                      std::cerr << "gig::Voice::Trigger() Error: Unknown dimension\n" << std::flush;                      std::cerr << "gig::Voice::Trigger() Error: Unknown dimension\n" << std::flush;
263              }              }
264          }          }
265          pDimRgn = pRegion->GetDimensionRegionByValue(DimValues[4],DimValues[3],DimValues[2],DimValues[1],DimValues[0]);          pDimRgn = pRegion->GetDimensionRegionByValue(DimValues);
266    
267            pSample = pDimRgn->pSample; // sample won't change until the voice is finished
268            if (!pSample || !pSample->SamplesTotal) return -1; // no need to continue if sample is silent
269    
270            // select channel mode (mono or stereo)
271            SYNTHESIS_MODE_SET_CHANNELS(SynthesisMode, pSample->Channels == 2);
272    
273          // get starting crossfade volume level          // get starting crossfade volume level
274          switch (pDimRgn->AttenuationController.type) {          switch (pDimRgn->AttenuationController.type) {
# Line 249  namespace LinuxSampler { namespace gig { Line 279  namespace LinuxSampler { namespace gig {
279                  CrossfadeVolume = CrossfadeAttenuation(itNoteOnEvent->Param.Note.Velocity);                  CrossfadeVolume = CrossfadeAttenuation(itNoteOnEvent->Param.Note.Velocity);
280                  break;                  break;
281              case ::gig::attenuation_ctrl_t::type_controlchange: //FIXME: currently not sample accurate              case ::gig::attenuation_ctrl_t::type_controlchange: //FIXME: currently not sample accurate
282                  CrossfadeVolume = CrossfadeAttenuation(pEngine->ControllerTable[pDimRgn->AttenuationController.controller_number]);                  CrossfadeVolume = CrossfadeAttenuation(pEngineChannel->ControllerTable[pDimRgn->AttenuationController.controller_number]);
283                  break;                  break;
284              case ::gig::attenuation_ctrl_t::type_none: // no crossfade defined              case ::gig::attenuation_ctrl_t::type_none: // no crossfade defined
285              default:              default:
# Line 259  namespace LinuxSampler { namespace gig { Line 289  namespace LinuxSampler { namespace gig {
289          PanLeft  = 1.0f - float(RTMath::Max(pDimRgn->Pan, 0)) /  63.0f;          PanLeft  = 1.0f - float(RTMath::Max(pDimRgn->Pan, 0)) /  63.0f;
290          PanRight = 1.0f - float(RTMath::Min(pDimRgn->Pan, 0)) / -64.0f;          PanRight = 1.0f - float(RTMath::Min(pDimRgn->Pan, 0)) / -64.0f;
291    
         pSample = pDimRgn->pSample; // sample won't change until the voice is finished  
   
292          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)
293    
294          // Check if the sample needs disk streaming or is too short for that          // Check if the sample needs disk streaming or is too short for that
# Line 268  namespace LinuxSampler { namespace gig { Line 296  namespace LinuxSampler { namespace gig {
296          DiskVoice          = cachedsamples < pSample->SamplesTotal;          DiskVoice          = cachedsamples < pSample->SamplesTotal;
297    
298          if (DiskVoice) { // voice to be streamed from disk          if (DiskVoice) { // voice to be streamed from disk
299              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)
300    
301              // 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
302              if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) {              if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) {
# Line 297  namespace LinuxSampler { namespace gig { Line 325  namespace LinuxSampler { namespace gig {
325    
326          // calculate initial pitch value          // calculate initial pitch value
327          {          {
328              double pitchbasecents = pDimRgn->FineTune * 10 + (int) pEngine->ScaleTuning[MIDIKey % 12];              double pitchbasecents = pDimRgn->FineTune + (int) pEngine->ScaleTuning[MIDIKey % 12];
329              if (pDimRgn->PitchTrack) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;              if (pDimRgn->PitchTrack) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;
330              this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents) * (double(pSample->SamplesPerSecond) / double(pEngine->pAudioOutputDevice->SampleRate()));              this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents) * (double(pSample->SamplesPerSecond) / double(pEngine->pAudioOutputDevice->SampleRate()));
331              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
332          }          }
333    
   
334          Volume = pDimRgn->GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity) / 32768.0f; // we downscale by 32768 to convert from int16 value range to DSP value range (which is -1.0..1.0)          Volume = pDimRgn->GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity) / 32768.0f; // we downscale by 32768 to convert from int16 value range to DSP value range (which is -1.0..1.0)
335    
336            Volume *= pDimRgn->SampleAttenuation;
337    
338          // setup EG 1 (VCA EG)          // setup EG 1 (VCA EG)
339          {          {
# Line 322  namespace LinuxSampler { namespace gig { Line 350  namespace LinuxSampler { namespace gig {
350                      eg1controllervalue = itNoteOnEvent->Param.Note.Velocity;                      eg1controllervalue = itNoteOnEvent->Param.Note.Velocity;
351                      break;                      break;
352                  case ::gig::eg1_ctrl_t::type_controlchange: // MIDI control change controller                  case ::gig::eg1_ctrl_t::type_controlchange: // MIDI control change controller
353                      eg1controllervalue = pEngine->ControllerTable[pDimRgn->EG1Controller.controller_number];                      eg1controllervalue = pEngineChannel->ControllerTable[pDimRgn->EG1Controller.controller_number];
354                      break;                      break;
355              }              }
356              if (pDimRgn->EG1ControllerInvert) eg1controllervalue = 127 - eg1controllervalue;              if (pDimRgn->EG1ControllerInvert) eg1controllervalue = 127 - eg1controllervalue;
# Line 341  namespace LinuxSampler { namespace gig { Line 369  namespace LinuxSampler { namespace gig {
369                            pDimRgn->EG1InfiniteSustain,                            pDimRgn->EG1InfiniteSustain,
370                            pDimRgn->EG1Sustain,                            pDimRgn->EG1Sustain,
371                            pDimRgn->EG1Release + eg1release,                            pDimRgn->EG1Release + eg1release,
372                            Delay);                            // the SSE synthesis implementation requires
373                              // the vca start to be 16 byte aligned
374                              SYNTHESIS_MODE_GET_IMPLEMENTATION(SynthesisMode) ?
375                              Delay & 0xfffffffc : Delay);
376          }          }
377    
378    
     #if ENABLE_FILTER  
379          // setup EG 2 (VCF Cutoff EG)          // setup EG 2 (VCF Cutoff EG)
380          {          {
381              // get current value of EG2 controller              // get current value of EG2 controller
# Line 361  namespace LinuxSampler { namespace gig { Line 391  namespace LinuxSampler { namespace gig {
391                      eg2controllervalue = itNoteOnEvent->Param.Note.Velocity;                      eg2controllervalue = itNoteOnEvent->Param.Note.Velocity;
392                      break;                      break;
393                  case ::gig::eg2_ctrl_t::type_controlchange: // MIDI control change controller                  case ::gig::eg2_ctrl_t::type_controlchange: // MIDI control change controller
394                      eg2controllervalue = pEngine->ControllerTable[pDimRgn->EG2Controller.controller_number];                      eg2controllervalue = pEngineChannel->ControllerTable[pDimRgn->EG2Controller.controller_number];
395                      break;                      break;
396              }              }
397              if (pDimRgn->EG2ControllerInvert) eg2controllervalue = 127 - eg2controllervalue;              if (pDimRgn->EG2ControllerInvert) eg2controllervalue = 127 - eg2controllervalue;
# Line 382  namespace LinuxSampler { namespace gig { Line 412  namespace LinuxSampler { namespace gig {
412                            pDimRgn->EG2Release + eg2release,                            pDimRgn->EG2Release + eg2release,
413                            Delay);                            Delay);
414          }          }
     #endif // ENABLE_FILTER  
415    
416    
417          // setup EG 3 (VCO EG)          // setup EG 3 (VCO EG)
# Line 423  namespace LinuxSampler { namespace gig { Line 452  namespace LinuxSampler { namespace gig {
452              pLFO1->Trigger(pDimRgn->LFO1Frequency,              pLFO1->Trigger(pDimRgn->LFO1Frequency,
453                            lfo1_internal_depth,                            lfo1_internal_depth,
454                            pDimRgn->LFO1ControlDepth,                            pDimRgn->LFO1ControlDepth,
455                            pEngine->ControllerTable[pLFO1->ExtController],                            pEngineChannel->ControllerTable[pLFO1->ExtController],
456                            pDimRgn->LFO1FlipPhase,                            pDimRgn->LFO1FlipPhase,
457                            pEngine->SampleRate,                            pEngine->SampleRate,
458                            Delay);                            Delay);
459          }          }
460    
461      #if ENABLE_FILTER  
462          // setup LFO 2 (VCF Cutoff LFO)          // setup LFO 2 (VCF Cutoff LFO)
463          {          {
464              uint16_t lfo2_internal_depth;              uint16_t lfo2_internal_depth;
# Line 461  namespace LinuxSampler { namespace gig { Line 490  namespace LinuxSampler { namespace gig {
490              pLFO2->Trigger(pDimRgn->LFO2Frequency,              pLFO2->Trigger(pDimRgn->LFO2Frequency,
491                            lfo2_internal_depth,                            lfo2_internal_depth,
492                            pDimRgn->LFO2ControlDepth,                            pDimRgn->LFO2ControlDepth,
493                            pEngine->ControllerTable[pLFO2->ExtController],                            pEngineChannel->ControllerTable[pLFO2->ExtController],
494                            pDimRgn->LFO2FlipPhase,                            pDimRgn->LFO2FlipPhase,
495                            pEngine->SampleRate,                            pEngine->SampleRate,
496                            Delay);                            Delay);
497          }          }
498      #endif // ENABLE_FILTER  
499    
500          // setup LFO 3 (VCO LFO)          // setup LFO 3 (VCO LFO)
501          {          {
# Line 499  namespace LinuxSampler { namespace gig { Line 528  namespace LinuxSampler { namespace gig {
528              pLFO3->Trigger(pDimRgn->LFO3Frequency,              pLFO3->Trigger(pDimRgn->LFO3Frequency,
529                            lfo3_internal_depth,                            lfo3_internal_depth,
530                            pDimRgn->LFO3ControlDepth,                            pDimRgn->LFO3ControlDepth,
531                            pEngine->ControllerTable[pLFO3->ExtController],                            pEngineChannel->ControllerTable[pLFO3->ExtController],
532                            false,                            false,
533                            pEngine->SampleRate,                            pEngine->SampleRate,
534                            Delay);                            Delay);
535          }          }
536    
537      #if ENABLE_FILTER  
538          #if FORCE_FILTER_USAGE          #if CONFIG_FORCE_FILTER
539          FilterLeft.Enabled = FilterRight.Enabled = true;          const bool bUseFilter = true;
540          #else // use filter only if instrument file told so          #else // use filter only if instrument file told so
541          FilterLeft.Enabled = FilterRight.Enabled = pDimRgn->VCFEnabled;          const bool bUseFilter = pDimRgn->VCFEnabled;
542          #endif // FORCE_FILTER_USAGE          #endif // CONFIG_FORCE_FILTER
543          if (pDimRgn->VCFEnabled) {          SYNTHESIS_MODE_SET_FILTER(SynthesisMode, bUseFilter);
544              #ifdef OVERRIDE_FILTER_CUTOFF_CTRL          if (bUseFilter) {
545              VCFCutoffCtrl.controller = OVERRIDE_FILTER_CUTOFF_CTRL;              #ifdef CONFIG_OVERRIDE_CUTOFF_CTRL
546                VCFCutoffCtrl.controller = CONFIG_OVERRIDE_CUTOFF_CTRL;
547              #else // use the one defined in the instrument file              #else // use the one defined in the instrument file
548              switch (pDimRgn->VCFCutoffController) {              switch (pDimRgn->VCFCutoffController) {
549                  case ::gig::vcf_cutoff_ctrl_modwheel:                  case ::gig::vcf_cutoff_ctrl_modwheel:
# Line 549  namespace LinuxSampler { namespace gig { Line 579  namespace LinuxSampler { namespace gig {
579                      VCFCutoffCtrl.controller = 0;                      VCFCutoffCtrl.controller = 0;
580                      break;                      break;
581              }              }
582              #endif // OVERRIDE_FILTER_CUTOFF_CTRL              #endif // CONFIG_OVERRIDE_CUTOFF_CTRL
583    
584              #ifdef OVERRIDE_FILTER_RES_CTRL              #ifdef CONFIG_OVERRIDE_RESONANCE_CTRL
585              VCFResonanceCtrl.controller = OVERRIDE_FILTER_RES_CTRL;              VCFResonanceCtrl.controller = CONFIG_OVERRIDE_RESONANCE_CTRL;
586              #else // use the one defined in the instrument file              #else // use the one defined in the instrument file
587              switch (pDimRgn->VCFResonanceController) {              switch (pDimRgn->VCFResonanceController) {
588                  case ::gig::vcf_res_ctrl_genpurpose3:                  case ::gig::vcf_res_ctrl_genpurpose3:
# Line 571  namespace LinuxSampler { namespace gig { Line 601  namespace LinuxSampler { namespace gig {
601                  default:                  default:
602                      VCFResonanceCtrl.controller = 0;                      VCFResonanceCtrl.controller = 0;
603              }              }
604              #endif // OVERRIDE_FILTER_RES_CTRL              #endif // CONFIG_OVERRIDE_RESONANCE_CTRL
605    
606              #ifndef OVERRIDE_FILTER_TYPE              #ifndef CONFIG_OVERRIDE_FILTER_TYPE
607              FilterLeft.SetType(pDimRgn->VCFType);              FilterLeft.SetType(pDimRgn->VCFType);
608              FilterRight.SetType(pDimRgn->VCFType);              FilterRight.SetType(pDimRgn->VCFType);
609              #else // override filter type              #else // override filter type
610              FilterLeft.SetType(OVERRIDE_FILTER_TYPE);              FilterLeft.SetType(CONFIG_OVERRIDE_FILTER_TYPE);
611              FilterRight.SetType(OVERRIDE_FILTER_TYPE);              FilterRight.SetType(CONFIG_OVERRIDE_FILTER_TYPE);
612              #endif // OVERRIDE_FILTER_TYPE              #endif // CONFIG_OVERRIDE_FILTER_TYPE
613    
614              VCFCutoffCtrl.value    = pEngine->ControllerTable[VCFCutoffCtrl.controller];              VCFCutoffCtrl.value    = pEngineChannel->ControllerTable[VCFCutoffCtrl.controller];
615              VCFResonanceCtrl.value = pEngine->ControllerTable[VCFResonanceCtrl.controller];              VCFResonanceCtrl.value = pEngineChannel->ControllerTable[VCFResonanceCtrl.controller];
616    
617              // calculate cutoff frequency              // calculate cutoff frequency
618              float cutoff = (!VCFCutoffCtrl.controller)              float cutoff = (!VCFCutoffCtrl.controller)
619                  ? exp((float) (127 - itNoteOnEvent->Param.Note.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
620                  : 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;
621    
622              // calculate resonance              // calculate resonance
623              float resonance = (float) VCFResonanceCtrl.value * 0.00787f;   // 0.0..1.0              float resonance = (float) VCFResonanceCtrl.value * 0.00787f;   // 0.0..1.0
# Line 596  namespace LinuxSampler { namespace gig { Line 626  namespace LinuxSampler { namespace gig {
626              }              }
627              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)
628    
629              VCFCutoffCtrl.fvalue    = cutoff - FILTER_CUTOFF_MIN;              VCFCutoffCtrl.fvalue    = cutoff - CONFIG_FILTER_CUTOFF_MIN;
630              VCFResonanceCtrl.fvalue = resonance;              VCFResonanceCtrl.fvalue = resonance;
631    
             FilterLeft.SetParameters(cutoff,  resonance, pEngine->SampleRate);  
             FilterRight.SetParameters(cutoff, resonance, pEngine->SampleRate);  
   
632              FilterUpdateCounter = -1;              FilterUpdateCounter = -1;
633          }          }
634          else {          else {
635              VCFCutoffCtrl.controller    = 0;              VCFCutoffCtrl.controller    = 0;
636              VCFResonanceCtrl.controller = 0;              VCFResonanceCtrl.controller = 0;
637          }          }
     #endif // ENABLE_FILTER  
638    
639          return 0; // success          return 0; // success
640      }      }
# Line 626  namespace LinuxSampler { namespace gig { Line 652  namespace LinuxSampler { namespace gig {
652       */       */
653      void Voice::Render(uint Samples) {      void Voice::Render(uint Samples) {
654    
655            // select default values for synthesis mode bits
656            SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, (PitchBase * PitchBend) != 1.0f);
657            SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, true);
658            SYNTHESIS_MODE_SET_LOOP(SynthesisMode, false);
659    
660          // Reset the synthesis parameter matrix          // Reset the synthesis parameter matrix
661          pEngine->ResetSynthesisParameters(Event::destination_vca, this->Volume * this->CrossfadeVolume * pEngine->GlobalVolume);  
662            pEngine->ResetSynthesisParameters(Event::destination_vca, this->Volume * this->CrossfadeVolume * pEngineChannel->GlobalVolume);
663          pEngine->ResetSynthesisParameters(Event::destination_vco, this->PitchBase);          pEngine->ResetSynthesisParameters(Event::destination_vco, this->PitchBase);
     #if ENABLE_FILTER  
664          pEngine->ResetSynthesisParameters(Event::destination_vcfc, VCFCutoffCtrl.fvalue);          pEngine->ResetSynthesisParameters(Event::destination_vcfc, VCFCutoffCtrl.fvalue);
665          pEngine->ResetSynthesisParameters(Event::destination_vcfr, VCFResonanceCtrl.fvalue);          pEngine->ResetSynthesisParameters(Event::destination_vcfr, VCFResonanceCtrl.fvalue);
     #endif // ENABLE_FILTER  
   
666    
667          // Apply events to the synthesis parameter matrix          // Apply events to the synthesis parameter matrix
668          ProcessEvents(Samples);          ProcessEvents(Samples);
669    
   
670          // 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
671          pEG1->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, itTriggerEvent, this->Pos, this->PitchBase * this->PitchBend, itKillEvent);          pEG1->Process(Samples, pEngineChannel->pMIDIKeyInfo[MIDIKey].pEvents, itTriggerEvent, this->Pos, this->PitchBase * this->PitchBend, itKillEvent);
672      #if ENABLE_FILTER          pEG2->Process(Samples, pEngineChannel->pMIDIKeyInfo[MIDIKey].pEvents, itTriggerEvent, this->Pos, this->PitchBase * this->PitchBend);
673          pEG2->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, itTriggerEvent, this->Pos, this->PitchBase * this->PitchBend);          if (pEG3->Process(Samples)) { // if pitch EG is active
674      #endif // ENABLE_FILTER              SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, true);
675          pEG3->Process(Samples);              SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, false);
676            }
677          pLFO1->Process(Samples);          pLFO1->Process(Samples);
     #if ENABLE_FILTER  
678          pLFO2->Process(Samples);          pLFO2->Process(Samples);
679      #endif // ENABLE_FILTER          if (pLFO3->Process(Samples)) { // if pitch LFO modulation is active
680          pLFO3->Process(Samples);              SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, true);
681                SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, false);
682            }
     #if ENABLE_FILTER  
         CalculateBiquadParameters(Samples); // calculate the final biquad filter parameters  
     #endif // ENABLE_FILTER  
683    
684            if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode))
685                CalculateBiquadParameters(Samples); // calculate the final biquad filter parameters
686    
687          switch (this->PlaybackState) {          switch (this->PlaybackState) {
688    
689              case playback_state_ram: {              case playback_state_ram: {
690                      if (RAMLoop) InterpolateAndLoop(Samples, (sample_t*) pSample->GetCache().pStart, Delay);                      if (RAMLoop) SYNTHESIS_MODE_SET_LOOP(SynthesisMode, true); // enable looping
691                      else         InterpolateNoLoop(Samples, (sample_t*) pSample->GetCache().pStart, Delay);  
692                        // render current fragment
693                        Synthesize(Samples, (sample_t*) pSample->GetCache().pStart, Delay);
694    
695                      if (DiskVoice) {                      if (DiskVoice) {
696                          // check if we reached the allowed limit of the sample RAM cache                          // check if we reached the allowed limit of the sample RAM cache
697                          if (Pos > MaxRAMPos) {                          if (Pos > MaxRAMPos) {
# Line 684  namespace LinuxSampler { namespace gig { Line 714  namespace LinuxSampler { namespace gig {
714                              KillImmediately();                              KillImmediately();
715                              return;                              return;
716                          }                          }
717                          DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (RTMath::DoubleToInt(Pos) - MaxRAMPos));                          DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (int(Pos) - MaxRAMPos));
718                          Pos -= RTMath::DoubleToInt(Pos);                          Pos -= int(Pos);
719                            RealSampleWordsLeftToRead = -1; // -1 means no silence has been added yet
720                      }                      }
721    
722                        const int sampleWordsLeftToRead = DiskStreamRef.pStream->GetReadSpace();
723    
724                      // 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)
725                      if (DiskStreamRef.State == Stream::state_end && DiskStreamRef.pStream->GetReadSpace() < (pEngine->MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels) {                      if (DiskStreamRef.State == Stream::state_end) {
726                          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
727                          this->PlaybackState = playback_state_end;                          if (sampleWordsLeftToRead <= maxSampleWordsPerCycle) {
728                                // remember how many sample words there are before any silence has been added
729                                if (RealSampleWordsLeftToRead < 0) RealSampleWordsLeftToRead = sampleWordsLeftToRead;
730                                DiskStreamRef.pStream->WriteSilence(maxSampleWordsPerCycle - sampleWordsLeftToRead);
731                            }
732                      }                      }
733    
734                      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
735                      InterpolateNoLoop(Samples, ptr, Delay);  
736                      DiskStreamRef.pStream->IncrementReadPos(RTMath::DoubleToInt(Pos) * pSample->Channels);                      // render current audio fragment
737                      Pos -= RTMath::DoubleToInt(Pos);                      Synthesize(Samples, ptr, Delay);
738    
739                        const int iPos = (int) Pos;
740                        const int readSampleWords = iPos * pSample->Channels; // amount of sample words actually been read
741                        DiskStreamRef.pStream->IncrementReadPos(readSampleWords);
742                        Pos -= iPos; // just keep fractional part of Pos
743    
744                        // change state of voice to 'end' if we really reached the end of the sample data
745                        if (RealSampleWordsLeftToRead >= 0) {
746                            RealSampleWordsLeftToRead -= readSampleWords;
747                            if (RealSampleWordsLeftToRead <= 0) this->PlaybackState = playback_state_end;
748                        }
749                  }                  }
750                  break;                  break;
751    
# Line 706  namespace LinuxSampler { namespace gig { Line 754  namespace LinuxSampler { namespace gig {
754                  break;                  break;
755          }          }
756    
   
757          // 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)
758          pEngine->pSynthesisEvents[Event::destination_vca]->clear();          pEngineChannel->pSynthesisEvents[Event::destination_vca]->clear();
759      #if ENABLE_FILTER          pEngineChannel->pSynthesisEvents[Event::destination_vcfc]->clear();
760          pEngine->pSynthesisEvents[Event::destination_vcfc]->clear();          pEngineChannel->pSynthesisEvents[Event::destination_vcfr]->clear();
         pEngine->pSynthesisEvents[Event::destination_vcfr]->clear();  
     #endif // ENABLE_FILTER  
761    
762          // Reset delay          // Reset delay
763          Delay = 0;          Delay = 0;
# Line 731  namespace LinuxSampler { namespace gig { Line 776  namespace LinuxSampler { namespace gig {
776          pLFO1->Reset();          pLFO1->Reset();
777          pLFO2->Reset();          pLFO2->Reset();
778          pLFO3->Reset();          pLFO3->Reset();
779            FilterLeft.Reset();
780            FilterRight.Reset();
781          DiskStreamRef.pStream = NULL;          DiskStreamRef.pStream = NULL;
782          DiskStreamRef.hStream = 0;          DiskStreamRef.hStream = 0;
783          DiskStreamRef.State   = Stream::state_unused;          DiskStreamRef.State   = Stream::state_unused;
# Line 750  namespace LinuxSampler { namespace gig { Line 797  namespace LinuxSampler { namespace gig {
797      void Voice::ProcessEvents(uint Samples) {      void Voice::ProcessEvents(uint Samples) {
798    
799          // dispatch control change events          // dispatch control change events
800          RTList<Event>::Iterator itCCEvent = pEngine->pCCEvents->first();          RTList<Event>::Iterator itCCEvent = pEngineChannel->pCCEvents->first();
801          if (Delay) { // skip events that happened before this voice was triggered          if (Delay) { // skip events that happened before this voice was triggered
802              while (itCCEvent && itCCEvent->FragmentPos() <= Delay) ++itCCEvent;              while (itCCEvent && itCCEvent->FragmentPos() <= Delay) ++itCCEvent;
803          }          }
804          while (itCCEvent) {          while (itCCEvent) {
805              if (itCCEvent->Param.CC.Controller) { // if valid MIDI controller              if (itCCEvent->Param.CC.Controller) { // if valid MIDI controller
                 #if ENABLE_FILTER  
806                  if (itCCEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {                  if (itCCEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {
807                      *pEngine->pSynthesisEvents[Event::destination_vcfc]->allocAppend() = *itCCEvent;                      *pEngineChannel->pSynthesisEvents[Event::destination_vcfc]->allocAppend() = *itCCEvent;
808                  }                  }
809                  if (itCCEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {                  if (itCCEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {
810                      *pEngine->pSynthesisEvents[Event::destination_vcfr]->allocAppend() = *itCCEvent;                      *pEngineChannel->pSynthesisEvents[Event::destination_vcfr]->allocAppend() = *itCCEvent;
811                  }                  }
                 #endif // ENABLE_FILTER  
812                  if (itCCEvent->Param.CC.Controller == pLFO1->ExtController) {                  if (itCCEvent->Param.CC.Controller == pLFO1->ExtController) {
813                      pLFO1->SendEvent(itCCEvent);                      pLFO1->SendEvent(itCCEvent);
814                  }                  }
                 #if ENABLE_FILTER  
815                  if (itCCEvent->Param.CC.Controller == pLFO2->ExtController) {                  if (itCCEvent->Param.CC.Controller == pLFO2->ExtController) {
816                      pLFO2->SendEvent(itCCEvent);                      pLFO2->SendEvent(itCCEvent);
817                  }                  }
                 #endif // ENABLE_FILTER  
818                  if (itCCEvent->Param.CC.Controller == pLFO3->ExtController) {                  if (itCCEvent->Param.CC.Controller == pLFO3->ExtController) {
819                      pLFO3->SendEvent(itCCEvent);                      pLFO3->SendEvent(itCCEvent);
820                  }                  }
821                  if (pDimRgn->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange &&                  if (pDimRgn->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange &&
822                      itCCEvent->Param.CC.Controller == pDimRgn->AttenuationController.controller_number) { // if crossfade event                      itCCEvent->Param.CC.Controller == pDimRgn->AttenuationController.controller_number) { // if crossfade event
823                      *pEngine->pSynthesisEvents[Event::destination_vca]->allocAppend() = *itCCEvent;                      *pEngineChannel->pSynthesisEvents[Event::destination_vca]->allocAppend() = *itCCEvent;
824                  }                  }
825              }              }
826    
# Line 787  namespace LinuxSampler { namespace gig { Line 830  namespace LinuxSampler { namespace gig {
830    
831          // process pitch events          // process pitch events
832          {          {
833              RTList<Event>* pVCOEventList = pEngine->pSynthesisEvents[Event::destination_vco];              RTList<Event>* pVCOEventList = pEngineChannel->pSynthesisEvents[Event::destination_vco];
834              RTList<Event>::Iterator itVCOEvent = pVCOEventList->first();              RTList<Event>::Iterator itVCOEvent = pVCOEventList->first();
835              if (Delay) { // skip events that happened before this voice was triggered              if (Delay) { // skip events that happened before this voice was triggered
836                  while (itVCOEvent && itVCOEvent->FragmentPos() <= Delay) ++itVCOEvent;                  while (itVCOEvent && itVCOEvent->FragmentPos() <= Delay) ++itVCOEvent;
# Line 816  namespace LinuxSampler { namespace gig { Line 859  namespace LinuxSampler { namespace gig {
859    
860                  itVCOEvent = itNextVCOEvent;                  itVCOEvent = itNextVCOEvent;
861              }              }
862              if (!pVCOEventList->isEmpty()) this->PitchBend = pitch;              if (!pVCOEventList->isEmpty()) {
863                    this->PitchBend = pitch;
864                    SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, true);
865                    SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, false);
866                }
867          }          }
868    
869          // 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 !)
870          {          {
871              RTList<Event>* pVCAEventList = pEngine->pSynthesisEvents[Event::destination_vca];              RTList<Event>* pVCAEventList = pEngineChannel->pSynthesisEvents[Event::destination_vca];
872              RTList<Event>::Iterator itVCAEvent = pVCAEventList->first();              RTList<Event>::Iterator itVCAEvent = pVCAEventList->first();
873              if (Delay) { // skip events that happened before this voice was triggered              if (Delay) { // skip events that happened before this voice was triggered
874                  while (itVCAEvent && itVCAEvent->FragmentPos() <= Delay) ++itVCAEvent;                  while (itVCAEvent && itVCAEvent->FragmentPos() <= Delay) ++itVCAEvent;
# Line 836  namespace LinuxSampler { namespace gig { Line 883  namespace LinuxSampler { namespace gig {
883    
884                  crossfadevolume = CrossfadeAttenuation(itVCAEvent->Param.CC.Value);                  crossfadevolume = CrossfadeAttenuation(itVCAEvent->Param.CC.Value);
885    
886                  float effective_volume = crossfadevolume * this->Volume * pEngine->GlobalVolume;                  float effective_volume = crossfadevolume * this->Volume * pEngineChannel->GlobalVolume;
887    
888                  // apply volume value to the volume parameter sequence                  // apply volume value to the volume parameter sequence
889                  for (uint i = itVCAEvent->FragmentPos(); i < end; i++) {                  for (uint i = itVCAEvent->FragmentPos(); i < end; i++) {
# Line 848  namespace LinuxSampler { namespace gig { Line 895  namespace LinuxSampler { namespace gig {
895              if (!pVCAEventList->isEmpty()) this->CrossfadeVolume = crossfadevolume;              if (!pVCAEventList->isEmpty()) this->CrossfadeVolume = crossfadevolume;
896          }          }
897    
     #if ENABLE_FILTER  
898          // process filter cutoff events          // process filter cutoff events
899          {          {
900              RTList<Event>* pCutoffEventList = pEngine->pSynthesisEvents[Event::destination_vcfc];              RTList<Event>* pCutoffEventList = pEngineChannel->pSynthesisEvents[Event::destination_vcfc];
901              RTList<Event>::Iterator itCutoffEvent = pCutoffEventList->first();              RTList<Event>::Iterator itCutoffEvent = pCutoffEventList->first();
902              if (Delay) { // skip events that happened before this voice was triggered              if (Delay) { // skip events that happened before this voice was triggered
903                  while (itCutoffEvent && itCutoffEvent->FragmentPos() <= Delay) ++itCutoffEvent;                  while (itCutoffEvent && itCutoffEvent->FragmentPos() <= Delay) ++itCutoffEvent;
# Line 864  namespace LinuxSampler { namespace gig { Line 910  namespace LinuxSampler { namespace gig {
910                  // calculate the influence length of this event (in sample points)                  // calculate the influence length of this event (in sample points)
911                  uint end = (itNextCutoffEvent) ? itNextCutoffEvent->FragmentPos() : Samples;                  uint end = (itNextCutoffEvent) ? itNextCutoffEvent->FragmentPos() : Samples;
912    
913                  cutoff = exp((float) itCutoffEvent->Param.CC.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;
914    
915                  // apply cutoff frequency to the cutoff parameter sequence                  // apply cutoff frequency to the cutoff parameter sequence
916                  for (uint i = itCutoffEvent->FragmentPos(); i < end; i++) {                  for (uint i = itCutoffEvent->FragmentPos(); i < end; i++) {
# Line 878  namespace LinuxSampler { namespace gig { Line 924  namespace LinuxSampler { namespace gig {
924    
925          // process filter resonance events          // process filter resonance events
926          {          {
927              RTList<Event>* pResonanceEventList = pEngine->pSynthesisEvents[Event::destination_vcfr];              RTList<Event>* pResonanceEventList = pEngineChannel->pSynthesisEvents[Event::destination_vcfr];
928              RTList<Event>::Iterator itResonanceEvent = pResonanceEventList->first();              RTList<Event>::Iterator itResonanceEvent = pResonanceEventList->first();
929              if (Delay) { // skip events that happened before this voice was triggered              if (Delay) { // skip events that happened before this voice was triggered
930                  while (itResonanceEvent && itResonanceEvent->FragmentPos() <= Delay) ++itResonanceEvent;                  while (itResonanceEvent && itResonanceEvent->FragmentPos() <= Delay) ++itResonanceEvent;
# Line 905  namespace LinuxSampler { namespace gig { Line 951  namespace LinuxSampler { namespace gig {
951              }              }
952              if (!pResonanceEventList->isEmpty()) VCFResonanceCtrl.fvalue = pResonanceEventList->last()->Param.CC.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
953          }          }
     #endif // ENABLE_FILTER  
954      }      }
955    
     #if ENABLE_FILTER  
956      /**      /**
957       * Calculate all necessary, final biquad filter parameters.       * Calculate all necessary, final biquad filter parameters.
958       *       *
959       * @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
960       */       */
961      void Voice::CalculateBiquadParameters(uint Samples) {      void Voice::CalculateBiquadParameters(uint Samples) {
         if (!FilterLeft.Enabled) return;  
   
962          biquad_param_t bqbase;          biquad_param_t bqbase;
963          biquad_param_t bqmain;          biquad_param_t bqmain;
964          float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0];          float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0];
965          float prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][0];          float prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][0];
966          FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);          FilterLeft.SetParameters( &bqbase, &bqmain, prev_cutoff + CONFIG_FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate);
967            FilterRight.SetParameters(&bqbase, &bqmain, prev_cutoff + CONFIG_FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate);
968          pEngine->pBasicFilterParameters[0] = bqbase;          pEngine->pBasicFilterParameters[0] = bqbase;
969          pEngine->pMainFilterParameters[0]  = bqmain;          pEngine->pMainFilterParameters[0]  = bqmain;
970    
971          float* bq;          float* bq;
972          for (int i = 1; i < Samples; i++) {          for (int i = 1; i < Samples; i++) {
973              // recalculate biquad parameters if cutoff or resonance differ from previous sample point              // recalculate biquad parameters if cutoff or resonance differ from previous sample point
974              if (!(i & FILTER_UPDATE_MASK)) if (pEngine->pSynthesisParameters[Event::destination_vcfr][i] != prev_res ||              if (!(i & FILTER_UPDATE_MASK)) {
975                                                 pEngine->pSynthesisParameters[Event::destination_vcfc][i] != prev_cutoff) {                  if (pEngine->pSynthesisParameters[Event::destination_vcfr][i] != prev_res ||
976                  prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][i];                      pEngine->pSynthesisParameters[Event::destination_vcfc][i] != prev_cutoff)
977                  prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][i];                  {
978                  FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);                      prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][i];
979                        prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][i];
980                        FilterLeft.SetParameters( &bqbase, &bqmain, prev_cutoff + CONFIG_FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate);
981                        FilterRight.SetParameters(&bqbase, &bqmain, prev_cutoff + CONFIG_FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate);
982                    }
983              }              }
984    
985              //same as 'pEngine->pBasicFilterParameters[i] = bqbase;'              //same as 'pEngine->pBasicFilterParameters[i] = bqbase;'
986              bq    = (float*) &pEngine->pBasicFilterParameters[i];              bq    = (float*) &pEngine->pBasicFilterParameters[i];
987              bq[0] = bqbase.a1;              bq[0] = bqbase.b0;
988              bq[1] = bqbase.a2;              bq[1] = bqbase.b1;
989              bq[2] = bqbase.b0;              bq[2] = bqbase.b2;
990              bq[3] = bqbase.b1;              bq[3] = bqbase.a1;
991              bq[4] = bqbase.b2;              bq[4] = bqbase.a2;
992    
993              // same as 'pEngine->pMainFilterParameters[i] = bqmain;'              // same as 'pEngine->pMainFilterParameters[i] = bqmain;'
994              bq    = (float*) &pEngine->pMainFilterParameters[i];              bq    = (float*) &pEngine->pMainFilterParameters[i];
995              bq[0] = bqmain.a1;              bq[0] = bqmain.b0;
996              bq[1] = bqmain.a2;              bq[1] = bqmain.b1;
997              bq[2] = bqmain.b0;              bq[2] = bqmain.b2;
998              bq[3] = bqmain.b1;              bq[3] = bqmain.a1;
999              bq[4] = bqmain.b2;              bq[4] = bqmain.a2;
         }  
     }  
     #endif // ENABLE_FILTER  
   
     /**  
      *  Interpolates the input audio data (without 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::InterpolateNoLoop(uint Samples, sample_t* pSrc, uint Skip) {  
         int i = Skip;  
   
         // FIXME: assuming either mono or stereo  
         if (this->pSample->Channels == 2) { // Stereo Sample  
             while (i < Samples) InterpolateStereo(pSrc, i);  
         }  
         else { // Mono Sample  
             while (i < Samples) InterpolateMono(pSrc, i);  
1000          }          }
1001      }      }
1002    
1003      /**      /**
1004       *  Interpolates the input audio data, this method honors looping.       *  Synthesizes the current audio fragment for this voice.
1005       *       *
1006       *  @param Samples - number of sample points to be rendered in this audio       *  @param Samples - number of sample points to be rendered in this audio
1007       *                   fragment cycle       *                   fragment cycle
1008       *  @param pSrc    - pointer to input sample data       *  @param pSrc    - pointer to input sample data
1009       *  @param Skip    - number of sample points to skip in output buffer       *  @param Skip    - number of sample points to skip in output buffer
1010       */       */
1011      void Voice::InterpolateAndLoop(uint Samples, sample_t* pSrc, uint Skip) {      void Voice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {
1012          int i = Skip;          RunSynthesisFunction(SynthesisMode, *this, Samples, pSrc, 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) {  
                     InterpolateStereo(pSrc, i);  
                     if (Pos > pSample->LoopEnd) {  
                         Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;  
                         LoopCyclesLeft--;  
                     }  
                 }  
                 // render on without loop  
                 while (i < Samples) InterpolateStereo(pSrc, i);  
             }  
             else { // render loop (endless loop)  
                 while (i < Samples) {  
                     InterpolateStereo(pSrc, 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) {  
                     InterpolateMono(pSrc, i);  
                     if (Pos > pSample->LoopEnd) {  
                         Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;  
                         LoopCyclesLeft--;  
                     }  
                 }  
                 // render on without loop  
                 while (i < Samples) InterpolateMono(pSrc, i);  
             }  
             else { // render loop (endless loop)  
                 while (i < Samples) {  
                     InterpolateMono(pSrc, i);  
                     if (Pos > pSample->LoopEnd) {  
                         Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;  
                     }  
                 }  
             }  
         }  
1013      }      }
1014    
1015      /**      /**
# Line 1057  namespace LinuxSampler { namespace gig { Line 1037  namespace LinuxSampler { namespace gig {
1037       *  @param itKillEvent - event which caused the voice to be killed       *  @param itKillEvent - event which caused the voice to be killed
1038       */       */
1039      void Voice::Kill(Pool<Event>::Iterator& itKillEvent) {      void Voice::Kill(Pool<Event>::Iterator& itKillEvent) {
1040          //FIXME: just two sanity checks for debugging, can be removed          #if CONFIG_DEVMODE
1041          if (!itKillEvent) dmsg(1,("gig::Voice::Kill(): ERROR, !itKillEvent !!!\n"));          if (!itKillEvent) dmsg(1,("gig::Voice::Kill(): ERROR, !itKillEvent !!!\n"));
1042          if (itKillEvent && !itKillEvent.isValid()) dmsg(1,("gig::Voice::Kill(): ERROR, itKillEvent invalid !!!\n"));          if (itKillEvent && !itKillEvent.isValid()) dmsg(1,("gig::Voice::Kill(): ERROR, itKillEvent invalid !!!\n"));
1043            #endif // CONFIG_DEVMODE
1044    
1045          if (itTriggerEvent && itKillEvent->FragmentPos() <= itTriggerEvent->FragmentPos()) return;          if (itTriggerEvent && itKillEvent->FragmentPos() <= itTriggerEvent->FragmentPos()) return;
1046          this->itKillEvent = itKillEvent;          this->itKillEvent = itKillEvent;

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

  ViewVC Help
Powered by ViewVC