/[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 669 by schoenebeck, Tue Jun 21 13:33:19 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 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 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 pDimRgn        - points to the dimension region which provides sample wave(s) and articulation data
124       *  @param ReleaseTriggerVoice - if this new voice is a release trigger voice (optional, default = false)       *  @param VoiceType      - type of this voice
125       *  @param VoiceStealing       - wether the voice is allowed to steal voices for further subvoices       *  @param iKeyGroup      - a value > 0 defines a key group in which this voice is member of
126       *  @returns 0 on success, a value < 0 if something failed       *  @returns 0 on success, a value < 0 if the voice wasn't triggered
127         *           (either due to an error or e.g. because no region is
128         *           defined for the given key)
129       */       */
130      int Voice::Trigger(Pool<Event>::Iterator& itNoteOnEvent, int PitchBend, ::gig::Instrument* pInstrument, int iLayer, bool ReleaseTriggerVoice, bool VoiceStealing) {      int Voice::Trigger(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent, int PitchBend, ::gig::DimensionRegion* pDimRgn, type_t VoiceType, int iKeyGroup) {
131          if (!pInstrument) {          this->pEngineChannel = pEngineChannel;
132             dmsg(1,("voice::trigger: !pInstrument\n"));          this->pDimRgn        = pDimRgn;
133             exit(EXIT_FAILURE);  
134            #if CONFIG_DEVMODE
135            if (itNoteOnEvent->FragmentPos() > pEngine->MaxSamplesPerCycle) { // just a sanity check for debugging
136                dmsg(1,("Voice::Trigger(): ERROR, TriggerDelay > Totalsamples\n"));
137          }          }
138            #endif // CONFIG_DEVMODE
139    
140          Type            = type_normal;          Type            = VoiceType;
141          MIDIKey         = itNoteOnEvent->Param.Note.Key;          MIDIKey         = itNoteOnEvent->Param.Note.Key;
142          pRegion         = pInstrument->GetRegion(MIDIKey);          PlaybackState   = playback_state_init; // mark voice as triggered, but no audio rendered yet
         PlaybackState   = playback_state_ram; // we always start playback from RAM cache and switch then to disk if needed  
143          Delay           = itNoteOnEvent->FragmentPos();          Delay           = itNoteOnEvent->FragmentPos();
144          itTriggerEvent  = itNoteOnEvent;          itTriggerEvent  = itNoteOnEvent;
145          itKillEvent     = Pool<Event>::Iterator();          itKillEvent     = Pool<Event>::Iterator();
146          itChildVoice    = Pool<Voice>::Iterator();          KeyGroup        = iKeyGroup;
147            pSample         = pDimRgn->pSample; // sample won't change until the voice is finished
148    
149          if (!pRegion) {          // calculate volume
150              std::cerr << "gig::Voice: No Region defined for MIDI key " << MIDIKey << std::endl << std::flush;          const double velocityAttenuation = pDimRgn->GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity);
             KillImmediately();  
             return -1;  
         }  
151    
152          KeyGroup = pRegion->KeyGroup;          Volume = velocityAttenuation / 32768.0f; // we downscale by 32768 to convert from int16 value range to DSP value range (which is -1.0..1.0)
153    
154          // get current dimension values to select the right dimension region          Volume *= pDimRgn->SampleAttenuation;
155          //FIXME: controller values for selecting the dimension region here are currently not sample accurate  
156          uint DimValues[5] = {0,0,0,0,0};          // the volume of release triggered samples depends on note length
157          for (int i = pRegion->Dimensions - 1; i >= 0; i--) {          if (Type == type_release_trigger) {
158              switch (pRegion->pDimensionDefinitions[i].dimension) {              float noteLength = float(pEngine->FrameTime + Delay -
159                  case ::gig::dimension_samplechannel:                                       pEngineChannel->pMIDIKeyInfo[MIDIKey].NoteOnTime) / pEngine->SampleRate;
160                      DimValues[i] = 0; //TODO: we currently ignore this dimension              float attenuation = 1 - 0.01053 * (256 >> pDimRgn->ReleaseTriggerDecay) * noteLength;
161                      break;              if (attenuation <= 0) return -1;
162                  case ::gig::dimension_layer:              Volume *= attenuation;
                     DimValues[i] = iLayer;  
                     // if this is the 1st layer then spawn further voices for all the other layers  
                     if (iLayer == 0)  
                         for (int iNewLayer = 1; iNewLayer < pRegion->pDimensionDefinitions[i].zones; iNewLayer++)  
                             itChildVoice = pEngine->LaunchVoice(itNoteOnEvent, iNewLayer, ReleaseTriggerVoice, VoiceStealing);  
                     break;  
                 case ::gig::dimension_velocity:  
                     DimValues[i] = itNoteOnEvent->Param.Note.Velocity;  
                     break;  
                 case ::gig::dimension_channelaftertouch:  
                     DimValues[i] = 0; //TODO: we currently ignore this dimension  
                     break;  
                 case ::gig::dimension_releasetrigger:  
                     Type = (ReleaseTriggerVoice) ? type_release_trigger : (!iLayer) ? type_release_trigger_required : type_normal;  
                     DimValues[i] = (uint) ReleaseTriggerVoice;  
                     break;  
                 case ::gig::dimension_keyboard:  
                     DimValues[i] = (uint) itNoteOnEvent->Param.Note.Key;  
                     break;  
                 case ::gig::dimension_modwheel:  
                     DimValues[i] = pEngine->ControllerTable[1];  
                     break;  
                 case ::gig::dimension_breath:  
                     DimValues[i] = pEngine->ControllerTable[2];  
                     break;  
                 case ::gig::dimension_foot:  
                     DimValues[i] = pEngine->ControllerTable[4];  
                     break;  
                 case ::gig::dimension_portamentotime:  
                     DimValues[i] = pEngine->ControllerTable[5];  
                     break;  
                 case ::gig::dimension_effect1:  
                     DimValues[i] = pEngine->ControllerTable[12];  
                     break;  
                 case ::gig::dimension_effect2:  
                     DimValues[i] = pEngine->ControllerTable[13];  
                     break;  
                 case ::gig::dimension_genpurpose1:  
                     DimValues[i] = pEngine->ControllerTable[16];  
                     break;  
                 case ::gig::dimension_genpurpose2:  
                     DimValues[i] = pEngine->ControllerTable[17];  
                     break;  
                 case ::gig::dimension_genpurpose3:  
                     DimValues[i] = pEngine->ControllerTable[18];  
                     break;  
                 case ::gig::dimension_genpurpose4:  
                     DimValues[i] = pEngine->ControllerTable[19];  
                     break;  
                 case ::gig::dimension_sustainpedal:  
                     DimValues[i] = pEngine->ControllerTable[64];  
                     break;  
                 case ::gig::dimension_portamento:  
                     DimValues[i] = pEngine->ControllerTable[65];  
                     break;  
                 case ::gig::dimension_sostenutopedal:  
                     DimValues[i] = pEngine->ControllerTable[66];  
                     break;  
                 case ::gig::dimension_softpedal:  
                     DimValues[i] = pEngine->ControllerTable[67];  
                     break;  
                 case ::gig::dimension_genpurpose5:  
                     DimValues[i] = pEngine->ControllerTable[80];  
                     break;  
                 case ::gig::dimension_genpurpose6:  
                     DimValues[i] = pEngine->ControllerTable[81];  
                     break;  
                 case ::gig::dimension_genpurpose7:  
                     DimValues[i] = pEngine->ControllerTable[82];  
                     break;  
                 case ::gig::dimension_genpurpose8:  
                     DimValues[i] = pEngine->ControllerTable[83];  
                     break;  
                 case ::gig::dimension_effect1depth:  
                     DimValues[i] = pEngine->ControllerTable[91];  
                     break;  
                 case ::gig::dimension_effect2depth:  
                     DimValues[i] = pEngine->ControllerTable[92];  
                     break;  
                 case ::gig::dimension_effect3depth:  
                     DimValues[i] = pEngine->ControllerTable[93];  
                     break;  
                 case ::gig::dimension_effect4depth:  
                     DimValues[i] = pEngine->ControllerTable[94];  
                     break;  
                 case ::gig::dimension_effect5depth:  
                     DimValues[i] = pEngine->ControllerTable[95];  
                     break;  
                 case ::gig::dimension_none:  
                     std::cerr << "gig::Voice::Trigger() Error: dimension=none\n" << std::flush;  
                     break;  
                 default:  
                     std::cerr << "gig::Voice::Trigger() Error: Unknown dimension\n" << std::flush;  
             }  
163          }          }
164          pDimRgn = pRegion->GetDimensionRegionByValue(DimValues[4],DimValues[3],DimValues[2],DimValues[1],DimValues[0]);  
165            // select channel mode (mono or stereo)
166            SYNTHESIS_MODE_SET_CHANNELS(SynthesisMode, pSample->Channels == 2);
167    
168          // get starting crossfade volume level          // get starting crossfade volume level
169          switch (pDimRgn->AttenuationController.type) {          switch (pDimRgn->AttenuationController.type) {
# Line 249  namespace LinuxSampler { namespace gig { Line 174  namespace LinuxSampler { namespace gig {
174                  CrossfadeVolume = CrossfadeAttenuation(itNoteOnEvent->Param.Note.Velocity);                  CrossfadeVolume = CrossfadeAttenuation(itNoteOnEvent->Param.Note.Velocity);
175                  break;                  break;
176              case ::gig::attenuation_ctrl_t::type_controlchange: //FIXME: currently not sample accurate              case ::gig::attenuation_ctrl_t::type_controlchange: //FIXME: currently not sample accurate
177                  CrossfadeVolume = CrossfadeAttenuation(pEngine->ControllerTable[pDimRgn->AttenuationController.controller_number]);                  CrossfadeVolume = CrossfadeAttenuation(pEngineChannel->ControllerTable[pDimRgn->AttenuationController.controller_number]);
178                  break;                  break;
179              case ::gig::attenuation_ctrl_t::type_none: // no crossfade defined              case ::gig::attenuation_ctrl_t::type_none: // no crossfade defined
180              default:              default:
# Line 259  namespace LinuxSampler { namespace gig { Line 184  namespace LinuxSampler { namespace gig {
184          PanLeft  = 1.0f - float(RTMath::Max(pDimRgn->Pan, 0)) /  63.0f;          PanLeft  = 1.0f - float(RTMath::Max(pDimRgn->Pan, 0)) /  63.0f;
185          PanRight = 1.0f - float(RTMath::Min(pDimRgn->Pan, 0)) / -64.0f;          PanRight = 1.0f - float(RTMath::Min(pDimRgn->Pan, 0)) / -64.0f;
186    
         pSample = pDimRgn->pSample; // sample won't change until the voice is finished  
   
187          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)
188    
189          // 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 191  namespace LinuxSampler { namespace gig {
191          DiskVoice          = cachedsamples < pSample->SamplesTotal;          DiskVoice          = cachedsamples < pSample->SamplesTotal;
192    
193          if (DiskVoice) { // voice to be streamed from disk          if (DiskVoice) { // voice to be streamed from disk
194              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)
195    
196              // 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
197              if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) {              if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) {
# Line 297  namespace LinuxSampler { namespace gig { Line 220  namespace LinuxSampler { namespace gig {
220    
221          // calculate initial pitch value          // calculate initial pitch value
222          {          {
223              double pitchbasecents = pDimRgn->FineTune * 10 + (int) pEngine->ScaleTuning[MIDIKey % 12];              double pitchbasecents = pDimRgn->FineTune + (int) pEngine->ScaleTuning[MIDIKey % 12];
224              if (pDimRgn->PitchTrack) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;              if (pDimRgn->PitchTrack) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;
225              this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents) * (double(pSample->SamplesPerSecond) / double(pEngine->pAudioOutputDevice->SampleRate()));              this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents) * (double(pSample->SamplesPerSecond) / double(pEngine->pAudioOutputDevice->SampleRate()));
226              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
227          }          }
228    
229            // the length of the decay and release curves are dependent on the velocity
230          Volume = pDimRgn->GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity) / 32768.0f; // we downscale by 32768 to convert from int16 value range to DSP value range (which is -1.0..1.0)          const double velrelease = 1 / pDimRgn->GetVelocityRelease(itNoteOnEvent->Param.Note.Velocity);
   
231    
232          // setup EG 1 (VCA EG)          // setup EG 1 (VCA EG)
233          {          {
# Line 322  namespace LinuxSampler { namespace gig { Line 244  namespace LinuxSampler { namespace gig {
244                      eg1controllervalue = itNoteOnEvent->Param.Note.Velocity;                      eg1controllervalue = itNoteOnEvent->Param.Note.Velocity;
245                      break;                      break;
246                  case ::gig::eg1_ctrl_t::type_controlchange: // MIDI control change controller                  case ::gig::eg1_ctrl_t::type_controlchange: // MIDI control change controller
247                      eg1controllervalue = pEngine->ControllerTable[pDimRgn->EG1Controller.controller_number];                      eg1controllervalue = pEngineChannel->ControllerTable[pDimRgn->EG1Controller.controller_number];
248                      break;                      break;
249              }              }
250              if (pDimRgn->EG1ControllerInvert) eg1controllervalue = 127 - eg1controllervalue;              if (pDimRgn->EG1ControllerInvert) eg1controllervalue = 127 - eg1controllervalue;
# Line 336  namespace LinuxSampler { namespace gig { Line 258  namespace LinuxSampler { namespace gig {
258                            pDimRgn->EG1Attack + eg1attack,                            pDimRgn->EG1Attack + eg1attack,
259                            pDimRgn->EG1Hold,                            pDimRgn->EG1Hold,
260                            pSample->LoopStart,                            pSample->LoopStart,
261                            pDimRgn->EG1Decay1 + eg1decay,                            (pDimRgn->EG1Decay1 + eg1decay) * velrelease,
262                            pDimRgn->EG1Decay2 + eg1decay,                            (pDimRgn->EG1Decay2 + eg1decay) * velrelease,
263                            pDimRgn->EG1InfiniteSustain,                            pDimRgn->EG1InfiniteSustain,
264                            pDimRgn->EG1Sustain,                            pDimRgn->EG1Sustain,
265                            pDimRgn->EG1Release + eg1release,                            (pDimRgn->EG1Release + eg1release) * velrelease,
266                            Delay);                            // the SSE synthesis implementation requires
267                              // the vca start to be 16 byte aligned
268                              SYNTHESIS_MODE_GET_IMPLEMENTATION(SynthesisMode) ?
269                              Delay & 0xfffffffc : Delay,
270                              velocityAttenuation);
271          }          }
272    
273    
     #if ENABLE_FILTER  
274          // setup EG 2 (VCF Cutoff EG)          // setup EG 2 (VCF Cutoff EG)
275          {          {
276              // get current value of EG2 controller              // get current value of EG2 controller
# Line 361  namespace LinuxSampler { namespace gig { Line 286  namespace LinuxSampler { namespace gig {
286                      eg2controllervalue = itNoteOnEvent->Param.Note.Velocity;                      eg2controllervalue = itNoteOnEvent->Param.Note.Velocity;
287                      break;                      break;
288                  case ::gig::eg2_ctrl_t::type_controlchange: // MIDI control change controller                  case ::gig::eg2_ctrl_t::type_controlchange: // MIDI control change controller
289                      eg2controllervalue = pEngine->ControllerTable[pDimRgn->EG2Controller.controller_number];                      eg2controllervalue = pEngineChannel->ControllerTable[pDimRgn->EG2Controller.controller_number];
290                      break;                      break;
291              }              }
292              if (pDimRgn->EG2ControllerInvert) eg2controllervalue = 127 - eg2controllervalue;              if (pDimRgn->EG2ControllerInvert) eg2controllervalue = 127 - eg2controllervalue;
# Line 375  namespace LinuxSampler { namespace gig { Line 300  namespace LinuxSampler { namespace gig {
300                            pDimRgn->EG2Attack + eg2attack,                            pDimRgn->EG2Attack + eg2attack,
301                            false,                            false,
302                            pSample->LoopStart,                            pSample->LoopStart,
303                            pDimRgn->EG2Decay1 + eg2decay,                            (pDimRgn->EG2Decay1 + eg2decay) * velrelease,
304                            pDimRgn->EG2Decay2 + eg2decay,                            (pDimRgn->EG2Decay2 + eg2decay) * velrelease,
305                            pDimRgn->EG2InfiniteSustain,                            pDimRgn->EG2InfiniteSustain,
306                            pDimRgn->EG2Sustain,                            pDimRgn->EG2Sustain,
307                            pDimRgn->EG2Release + eg2release,                            (pDimRgn->EG2Release + eg2release) * velrelease,
308                            Delay);                            Delay,
309                              velocityAttenuation);
310          }          }
     #endif // ENABLE_FILTER  
311    
312    
313          // setup EG 3 (VCO EG)          // setup EG 3 (VCO EG)
# Line 423  namespace LinuxSampler { namespace gig { Line 348  namespace LinuxSampler { namespace gig {
348              pLFO1->Trigger(pDimRgn->LFO1Frequency,              pLFO1->Trigger(pDimRgn->LFO1Frequency,
349                            lfo1_internal_depth,                            lfo1_internal_depth,
350                            pDimRgn->LFO1ControlDepth,                            pDimRgn->LFO1ControlDepth,
351                            pEngine->ControllerTable[pLFO1->ExtController],                            pEngineChannel->ControllerTable[pLFO1->ExtController],
352                            pDimRgn->LFO1FlipPhase,                            pDimRgn->LFO1FlipPhase,
353                            pEngine->SampleRate,                            pEngine->SampleRate,
354                            Delay);                            Delay);
355          }          }
356    
357      #if ENABLE_FILTER  
358          // setup LFO 2 (VCF Cutoff LFO)          // setup LFO 2 (VCF Cutoff LFO)
359          {          {
360              uint16_t lfo2_internal_depth;              uint16_t lfo2_internal_depth;
# Line 461  namespace LinuxSampler { namespace gig { Line 386  namespace LinuxSampler { namespace gig {
386              pLFO2->Trigger(pDimRgn->LFO2Frequency,              pLFO2->Trigger(pDimRgn->LFO2Frequency,
387                            lfo2_internal_depth,                            lfo2_internal_depth,
388                            pDimRgn->LFO2ControlDepth,                            pDimRgn->LFO2ControlDepth,
389                            pEngine->ControllerTable[pLFO2->ExtController],                            pEngineChannel->ControllerTable[pLFO2->ExtController],
390                            pDimRgn->LFO2FlipPhase,                            pDimRgn->LFO2FlipPhase,
391                            pEngine->SampleRate,                            pEngine->SampleRate,
392                            Delay);                            Delay);
393          }          }
394      #endif // ENABLE_FILTER  
395    
396          // setup LFO 3 (VCO LFO)          // setup LFO 3 (VCO LFO)
397          {          {
# Line 499  namespace LinuxSampler { namespace gig { Line 424  namespace LinuxSampler { namespace gig {
424              pLFO3->Trigger(pDimRgn->LFO3Frequency,              pLFO3->Trigger(pDimRgn->LFO3Frequency,
425                            lfo3_internal_depth,                            lfo3_internal_depth,
426                            pDimRgn->LFO3ControlDepth,                            pDimRgn->LFO3ControlDepth,
427                            pEngine->ControllerTable[pLFO3->ExtController],                            pEngineChannel->ControllerTable[pLFO3->ExtController],
428                            false,                            false,
429                            pEngine->SampleRate,                            pEngine->SampleRate,
430                            Delay);                            Delay);
431          }          }
432    
433      #if ENABLE_FILTER  
434          #if FORCE_FILTER_USAGE          #if CONFIG_FORCE_FILTER
435          FilterLeft.Enabled = FilterRight.Enabled = true;          const bool bUseFilter = true;
436          #else // use filter only if instrument file told so          #else // use filter only if instrument file told so
437          FilterLeft.Enabled = FilterRight.Enabled = pDimRgn->VCFEnabled;          const bool bUseFilter = pDimRgn->VCFEnabled;
438          #endif // FORCE_FILTER_USAGE          #endif // CONFIG_FORCE_FILTER
439          if (pDimRgn->VCFEnabled) {          SYNTHESIS_MODE_SET_FILTER(SynthesisMode, bUseFilter);
440              #ifdef OVERRIDE_FILTER_CUTOFF_CTRL          if (bUseFilter) {
441              VCFCutoffCtrl.controller = OVERRIDE_FILTER_CUTOFF_CTRL;              #ifdef CONFIG_OVERRIDE_CUTOFF_CTRL
442                VCFCutoffCtrl.controller = CONFIG_OVERRIDE_CUTOFF_CTRL;
443              #else // use the one defined in the instrument file              #else // use the one defined in the instrument file
444              switch (pDimRgn->VCFCutoffController) {              switch (pDimRgn->VCFCutoffController) {
445                  case ::gig::vcf_cutoff_ctrl_modwheel:                  case ::gig::vcf_cutoff_ctrl_modwheel:
# Line 549  namespace LinuxSampler { namespace gig { Line 475  namespace LinuxSampler { namespace gig {
475                      VCFCutoffCtrl.controller = 0;                      VCFCutoffCtrl.controller = 0;
476                      break;                      break;
477              }              }
478              #endif // OVERRIDE_FILTER_CUTOFF_CTRL              #endif // CONFIG_OVERRIDE_CUTOFF_CTRL
479    
480              #ifdef OVERRIDE_FILTER_RES_CTRL              #ifdef CONFIG_OVERRIDE_RESONANCE_CTRL
481              VCFResonanceCtrl.controller = OVERRIDE_FILTER_RES_CTRL;              VCFResonanceCtrl.controller = CONFIG_OVERRIDE_RESONANCE_CTRL;
482              #else // use the one defined in the instrument file              #else // use the one defined in the instrument file
483              switch (pDimRgn->VCFResonanceController) {              switch (pDimRgn->VCFResonanceController) {
484                  case ::gig::vcf_res_ctrl_genpurpose3:                  case ::gig::vcf_res_ctrl_genpurpose3:
# Line 571  namespace LinuxSampler { namespace gig { Line 497  namespace LinuxSampler { namespace gig {
497                  default:                  default:
498                      VCFResonanceCtrl.controller = 0;                      VCFResonanceCtrl.controller = 0;
499              }              }
500              #endif // OVERRIDE_FILTER_RES_CTRL              #endif // CONFIG_OVERRIDE_RESONANCE_CTRL
501    
502              #ifndef OVERRIDE_FILTER_TYPE              #ifndef CONFIG_OVERRIDE_FILTER_TYPE
503              FilterLeft.SetType(pDimRgn->VCFType);              FilterLeft.SetType(pDimRgn->VCFType);
504              FilterRight.SetType(pDimRgn->VCFType);              FilterRight.SetType(pDimRgn->VCFType);
505              #else // override filter type              #else // override filter type
506              FilterLeft.SetType(OVERRIDE_FILTER_TYPE);              FilterLeft.SetType(CONFIG_OVERRIDE_FILTER_TYPE);
507              FilterRight.SetType(OVERRIDE_FILTER_TYPE);              FilterRight.SetType(CONFIG_OVERRIDE_FILTER_TYPE);
508              #endif // OVERRIDE_FILTER_TYPE              #endif // CONFIG_OVERRIDE_FILTER_TYPE
509    
510              VCFCutoffCtrl.value    = pEngine->ControllerTable[VCFCutoffCtrl.controller];              VCFCutoffCtrl.value    = pEngineChannel->ControllerTable[VCFCutoffCtrl.controller];
511              VCFResonanceCtrl.value = pEngine->ControllerTable[VCFResonanceCtrl.controller];              VCFResonanceCtrl.value = pEngineChannel->ControllerTable[VCFResonanceCtrl.controller];
512    
513              // calculate cutoff frequency              // calculate cutoff frequency
514              float cutoff = (!VCFCutoffCtrl.controller)              float cutoff = (!VCFCutoffCtrl.controller)
515                  ? 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
516                  : 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;
517    
518              // calculate resonance              // calculate resonance
519              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 522  namespace LinuxSampler { namespace gig {
522              }              }
523              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)
524    
525              VCFCutoffCtrl.fvalue    = cutoff - FILTER_CUTOFF_MIN;              VCFCutoffCtrl.fvalue    = cutoff - CONFIG_FILTER_CUTOFF_MIN;
526              VCFResonanceCtrl.fvalue = resonance;              VCFResonanceCtrl.fvalue = resonance;
527    
             FilterLeft.SetParameters(cutoff,  resonance, pEngine->SampleRate);  
             FilterRight.SetParameters(cutoff, resonance, pEngine->SampleRate);  
   
528              FilterUpdateCounter = -1;              FilterUpdateCounter = -1;
529          }          }
530          else {          else {
531              VCFCutoffCtrl.controller    = 0;              VCFCutoffCtrl.controller    = 0;
532              VCFResonanceCtrl.controller = 0;              VCFResonanceCtrl.controller = 0;
533          }          }
     #endif // ENABLE_FILTER  
534    
535          return 0; // success          return 0; // success
536      }      }
# Line 626  namespace LinuxSampler { namespace gig { Line 548  namespace LinuxSampler { namespace gig {
548       */       */
549      void Voice::Render(uint Samples) {      void Voice::Render(uint Samples) {
550    
551            // select default values for synthesis mode bits
552            SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, (PitchBase * PitchBend) != 1.0f);
553            SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, true);
554            SYNTHESIS_MODE_SET_LOOP(SynthesisMode, false);
555    
556          // Reset the synthesis parameter matrix          // Reset the synthesis parameter matrix
557          pEngine->ResetSynthesisParameters(Event::destination_vca, this->Volume * this->CrossfadeVolume * pEngine->GlobalVolume);  
558            pEngine->ResetSynthesisParameters(Event::destination_vca, this->Volume * this->CrossfadeVolume * pEngineChannel->GlobalVolume);
559          pEngine->ResetSynthesisParameters(Event::destination_vco, this->PitchBase);          pEngine->ResetSynthesisParameters(Event::destination_vco, this->PitchBase);
     #if ENABLE_FILTER  
560          pEngine->ResetSynthesisParameters(Event::destination_vcfc, VCFCutoffCtrl.fvalue);          pEngine->ResetSynthesisParameters(Event::destination_vcfc, VCFCutoffCtrl.fvalue);
561          pEngine->ResetSynthesisParameters(Event::destination_vcfr, VCFResonanceCtrl.fvalue);          pEngine->ResetSynthesisParameters(Event::destination_vcfr, VCFResonanceCtrl.fvalue);
     #endif // ENABLE_FILTER  
   
562    
563          // Apply events to the synthesis parameter matrix          // Apply events to the synthesis parameter matrix
564          ProcessEvents(Samples);          ProcessEvents(Samples);
565    
   
566          // 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
567          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);
568      #if ENABLE_FILTER          pEG2->Process(Samples, pEngineChannel->pMIDIKeyInfo[MIDIKey].pEvents, itTriggerEvent, this->Pos, this->PitchBase * this->PitchBend);
569          pEG2->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, itTriggerEvent, this->Pos, this->PitchBase * this->PitchBend);          if (pEG3->Process(Samples)) { // if pitch EG is active
570      #endif // ENABLE_FILTER              SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, true);
571          pEG3->Process(Samples);              SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, false);
572            }
573          pLFO1->Process(Samples);          pLFO1->Process(Samples);
     #if ENABLE_FILTER  
574          pLFO2->Process(Samples);          pLFO2->Process(Samples);
575      #endif // ENABLE_FILTER          if (pLFO3->Process(Samples)) { // if pitch LFO modulation is active
576          pLFO3->Process(Samples);              SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, true);
577                SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, false);
578            }
     #if ENABLE_FILTER  
         CalculateBiquadParameters(Samples); // calculate the final biquad filter parameters  
     #endif // ENABLE_FILTER  
579    
580            if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode))
581                CalculateBiquadParameters(Samples); // calculate the final biquad filter parameters
582    
583          switch (this->PlaybackState) {          switch (this->PlaybackState) {
584    
585                case playback_state_init:
586                    this->PlaybackState = playback_state_ram; // we always start playback from RAM cache and switch then to disk if needed
587                    // no break - continue with playback_state_ram
588    
589              case playback_state_ram: {              case playback_state_ram: {
590                      if (RAMLoop) InterpolateAndLoop(Samples, (sample_t*) pSample->GetCache().pStart, Delay);                      if (RAMLoop) SYNTHESIS_MODE_SET_LOOP(SynthesisMode, true); // enable looping
591                      else         InterpolateNoLoop(Samples, (sample_t*) pSample->GetCache().pStart, Delay);  
592                        // render current fragment
593                        Synthesize(Samples, (sample_t*) pSample->GetCache().pStart, Delay);
594    
595                      if (DiskVoice) {                      if (DiskVoice) {
596                          // check if we reached the allowed limit of the sample RAM cache                          // check if we reached the allowed limit of the sample RAM cache
597                          if (Pos > MaxRAMPos) {                          if (Pos > MaxRAMPos) {
# Line 684  namespace LinuxSampler { namespace gig { Line 614  namespace LinuxSampler { namespace gig {
614                              KillImmediately();                              KillImmediately();
615                              return;                              return;
616                          }                          }
617                          DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (RTMath::DoubleToInt(Pos) - MaxRAMPos));                          DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (int(Pos) - MaxRAMPos));
618                          Pos -= RTMath::DoubleToInt(Pos);                          Pos -= int(Pos);
619                            RealSampleWordsLeftToRead = -1; // -1 means no silence has been added yet
620                      }                      }
621    
622                        const int sampleWordsLeftToRead = DiskStreamRef.pStream->GetReadSpace();
623    
624                      // 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)
625                      if (DiskStreamRef.State == Stream::state_end && DiskStreamRef.pStream->GetReadSpace() < (pEngine->MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels) {                      if (DiskStreamRef.State == Stream::state_end) {
626                          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
627                          this->PlaybackState = playback_state_end;                          if (sampleWordsLeftToRead <= maxSampleWordsPerCycle) {
628                                // remember how many sample words there are before any silence has been added
629                                if (RealSampleWordsLeftToRead < 0) RealSampleWordsLeftToRead = sampleWordsLeftToRead;
630                                DiskStreamRef.pStream->WriteSilence(maxSampleWordsPerCycle - sampleWordsLeftToRead);
631                            }
632                      }                      }
633    
634                      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
635                      InterpolateNoLoop(Samples, ptr, Delay);  
636                      DiskStreamRef.pStream->IncrementReadPos(RTMath::DoubleToInt(Pos) * pSample->Channels);                      // render current audio fragment
637                      Pos -= RTMath::DoubleToInt(Pos);                      Synthesize(Samples, ptr, Delay);
638    
639                        const int iPos = (int) Pos;
640                        const int readSampleWords = iPos * pSample->Channels; // amount of sample words actually been read
641                        DiskStreamRef.pStream->IncrementReadPos(readSampleWords);
642                        Pos -= iPos; // just keep fractional part of Pos
643    
644                        // change state of voice to 'end' if we really reached the end of the sample data
645                        if (RealSampleWordsLeftToRead >= 0) {
646                            RealSampleWordsLeftToRead -= readSampleWords;
647                            if (RealSampleWordsLeftToRead <= 0) this->PlaybackState = playback_state_end;
648                        }
649                  }                  }
650                  break;                  break;
651    
# Line 706  namespace LinuxSampler { namespace gig { Line 654  namespace LinuxSampler { namespace gig {
654                  break;                  break;
655          }          }
656    
   
657          // 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)
658          pEngine->pSynthesisEvents[Event::destination_vca]->clear();          pEngineChannel->pSynthesisEvents[Event::destination_vca]->clear();
659      #if ENABLE_FILTER          pEngineChannel->pSynthesisEvents[Event::destination_vcfc]->clear();
660          pEngine->pSynthesisEvents[Event::destination_vcfc]->clear();          pEngineChannel->pSynthesisEvents[Event::destination_vcfr]->clear();
         pEngine->pSynthesisEvents[Event::destination_vcfr]->clear();  
     #endif // ENABLE_FILTER  
661    
662          // Reset delay          // Reset delay
663          Delay = 0;          Delay = 0;
# Line 731  namespace LinuxSampler { namespace gig { Line 676  namespace LinuxSampler { namespace gig {
676          pLFO1->Reset();          pLFO1->Reset();
677          pLFO2->Reset();          pLFO2->Reset();
678          pLFO3->Reset();          pLFO3->Reset();
679            FilterLeft.Reset();
680            FilterRight.Reset();
681          DiskStreamRef.pStream = NULL;          DiskStreamRef.pStream = NULL;
682          DiskStreamRef.hStream = 0;          DiskStreamRef.hStream = 0;
683          DiskStreamRef.State   = Stream::state_unused;          DiskStreamRef.State   = Stream::state_unused;
# Line 750  namespace LinuxSampler { namespace gig { Line 697  namespace LinuxSampler { namespace gig {
697      void Voice::ProcessEvents(uint Samples) {      void Voice::ProcessEvents(uint Samples) {
698    
699          // dispatch control change events          // dispatch control change events
700          RTList<Event>::Iterator itCCEvent = pEngine->pCCEvents->first();          RTList<Event>::Iterator itCCEvent = pEngineChannel->pCCEvents->first();
701          if (Delay) { // skip events that happened before this voice was triggered          if (Delay) { // skip events that happened before this voice was triggered
702              while (itCCEvent && itCCEvent->FragmentPos() <= Delay) ++itCCEvent;              while (itCCEvent && itCCEvent->FragmentPos() <= Delay) ++itCCEvent;
703          }          }
704          while (itCCEvent) {          while (itCCEvent) {
705              if (itCCEvent->Param.CC.Controller) { // if valid MIDI controller              if (itCCEvent->Param.CC.Controller) { // if valid MIDI controller
                 #if ENABLE_FILTER  
706                  if (itCCEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {                  if (itCCEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {
707                      *pEngine->pSynthesisEvents[Event::destination_vcfc]->allocAppend() = *itCCEvent;                      *pEngineChannel->pSynthesisEvents[Event::destination_vcfc]->allocAppend() = *itCCEvent;
708                  }                  }
709                  if (itCCEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {                  if (itCCEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {
710                      *pEngine->pSynthesisEvents[Event::destination_vcfr]->allocAppend() = *itCCEvent;                      *pEngineChannel->pSynthesisEvents[Event::destination_vcfr]->allocAppend() = *itCCEvent;
711                  }                  }
                 #endif // ENABLE_FILTER  
712                  if (itCCEvent->Param.CC.Controller == pLFO1->ExtController) {                  if (itCCEvent->Param.CC.Controller == pLFO1->ExtController) {
713                      pLFO1->SendEvent(itCCEvent);                      pLFO1->SendEvent(itCCEvent);
714                  }                  }
                 #if ENABLE_FILTER  
715                  if (itCCEvent->Param.CC.Controller == pLFO2->ExtController) {                  if (itCCEvent->Param.CC.Controller == pLFO2->ExtController) {
716                      pLFO2->SendEvent(itCCEvent);                      pLFO2->SendEvent(itCCEvent);
717                  }                  }
                 #endif // ENABLE_FILTER  
718                  if (itCCEvent->Param.CC.Controller == pLFO3->ExtController) {                  if (itCCEvent->Param.CC.Controller == pLFO3->ExtController) {
719                      pLFO3->SendEvent(itCCEvent);                      pLFO3->SendEvent(itCCEvent);
720                  }                  }
721                  if (pDimRgn->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange &&                  if (pDimRgn->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange &&
722                      itCCEvent->Param.CC.Controller == pDimRgn->AttenuationController.controller_number) { // if crossfade event                      itCCEvent->Param.CC.Controller == pDimRgn->AttenuationController.controller_number) { // if crossfade event
723                      *pEngine->pSynthesisEvents[Event::destination_vca]->allocAppend() = *itCCEvent;                      *pEngineChannel->pSynthesisEvents[Event::destination_vca]->allocAppend() = *itCCEvent;
724                  }                  }
725              }              }
726    
# Line 787  namespace LinuxSampler { namespace gig { Line 730  namespace LinuxSampler { namespace gig {
730    
731          // process pitch events          // process pitch events
732          {          {
733              RTList<Event>* pVCOEventList = pEngine->pSynthesisEvents[Event::destination_vco];              RTList<Event>* pVCOEventList = pEngineChannel->pSynthesisEvents[Event::destination_vco];
734              RTList<Event>::Iterator itVCOEvent = pVCOEventList->first();              RTList<Event>::Iterator itVCOEvent = pVCOEventList->first();
735              if (Delay) { // skip events that happened before this voice was triggered              if (Delay) { // skip events that happened before this voice was triggered
736                  while (itVCOEvent && itVCOEvent->FragmentPos() <= Delay) ++itVCOEvent;                  while (itVCOEvent && itVCOEvent->FragmentPos() <= Delay) ++itVCOEvent;
# Line 816  namespace LinuxSampler { namespace gig { Line 759  namespace LinuxSampler { namespace gig {
759    
760                  itVCOEvent = itNextVCOEvent;                  itVCOEvent = itNextVCOEvent;
761              }              }
762              if (!pVCOEventList->isEmpty()) this->PitchBend = pitch;              if (!pVCOEventList->isEmpty()) {
763                    this->PitchBend = pitch;
764                    SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, true);
765                    SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, false);
766                }
767          }          }
768    
769          // 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 !)
770          {          {
771              RTList<Event>* pVCAEventList = pEngine->pSynthesisEvents[Event::destination_vca];              RTList<Event>* pVCAEventList = pEngineChannel->pSynthesisEvents[Event::destination_vca];
772              RTList<Event>::Iterator itVCAEvent = pVCAEventList->first();              RTList<Event>::Iterator itVCAEvent = pVCAEventList->first();
773              if (Delay) { // skip events that happened before this voice was triggered              if (Delay) { // skip events that happened before this voice was triggered
774                  while (itVCAEvent && itVCAEvent->FragmentPos() <= Delay) ++itVCAEvent;                  while (itVCAEvent && itVCAEvent->FragmentPos() <= Delay) ++itVCAEvent;
# Line 836  namespace LinuxSampler { namespace gig { Line 783  namespace LinuxSampler { namespace gig {
783    
784                  crossfadevolume = CrossfadeAttenuation(itVCAEvent->Param.CC.Value);                  crossfadevolume = CrossfadeAttenuation(itVCAEvent->Param.CC.Value);
785    
786                  float effective_volume = crossfadevolume * this->Volume * pEngine->GlobalVolume;                  float effective_volume = crossfadevolume * this->Volume * pEngineChannel->GlobalVolume;
787    
788                  // apply volume value to the volume parameter sequence                  // apply volume value to the volume parameter sequence
789                  for (uint i = itVCAEvent->FragmentPos(); i < end; i++) {                  for (uint i = itVCAEvent->FragmentPos(); i < end; i++) {
# Line 848  namespace LinuxSampler { namespace gig { Line 795  namespace LinuxSampler { namespace gig {
795              if (!pVCAEventList->isEmpty()) this->CrossfadeVolume = crossfadevolume;              if (!pVCAEventList->isEmpty()) this->CrossfadeVolume = crossfadevolume;
796          }          }
797    
     #if ENABLE_FILTER  
798          // process filter cutoff events          // process filter cutoff events
799          {          {
800              RTList<Event>* pCutoffEventList = pEngine->pSynthesisEvents[Event::destination_vcfc];              RTList<Event>* pCutoffEventList = pEngineChannel->pSynthesisEvents[Event::destination_vcfc];
801              RTList<Event>::Iterator itCutoffEvent = pCutoffEventList->first();              RTList<Event>::Iterator itCutoffEvent = pCutoffEventList->first();
802              if (Delay) { // skip events that happened before this voice was triggered              if (Delay) { // skip events that happened before this voice was triggered
803                  while (itCutoffEvent && itCutoffEvent->FragmentPos() <= Delay) ++itCutoffEvent;                  while (itCutoffEvent && itCutoffEvent->FragmentPos() <= Delay) ++itCutoffEvent;
# Line 864  namespace LinuxSampler { namespace gig { Line 810  namespace LinuxSampler { namespace gig {
810                  // calculate the influence length of this event (in sample points)                  // calculate the influence length of this event (in sample points)
811                  uint end = (itNextCutoffEvent) ? itNextCutoffEvent->FragmentPos() : Samples;                  uint end = (itNextCutoffEvent) ? itNextCutoffEvent->FragmentPos() : Samples;
812    
813                  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;
814    
815                  // apply cutoff frequency to the cutoff parameter sequence                  // apply cutoff frequency to the cutoff parameter sequence
816                  for (uint i = itCutoffEvent->FragmentPos(); i < end; i++) {                  for (uint i = itCutoffEvent->FragmentPos(); i < end; i++) {
# Line 878  namespace LinuxSampler { namespace gig { Line 824  namespace LinuxSampler { namespace gig {
824    
825          // process filter resonance events          // process filter resonance events
826          {          {
827              RTList<Event>* pResonanceEventList = pEngine->pSynthesisEvents[Event::destination_vcfr];              RTList<Event>* pResonanceEventList = pEngineChannel->pSynthesisEvents[Event::destination_vcfr];
828              RTList<Event>::Iterator itResonanceEvent = pResonanceEventList->first();              RTList<Event>::Iterator itResonanceEvent = pResonanceEventList->first();
829              if (Delay) { // skip events that happened before this voice was triggered              if (Delay) { // skip events that happened before this voice was triggered
830                  while (itResonanceEvent && itResonanceEvent->FragmentPos() <= Delay) ++itResonanceEvent;                  while (itResonanceEvent && itResonanceEvent->FragmentPos() <= Delay) ++itResonanceEvent;
# Line 905  namespace LinuxSampler { namespace gig { Line 851  namespace LinuxSampler { namespace gig {
851              }              }
852              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
853          }          }
     #endif // ENABLE_FILTER  
854      }      }
855    
     #if ENABLE_FILTER  
856      /**      /**
857       * Calculate all necessary, final biquad filter parameters.       * Calculate all necessary, final biquad filter parameters.
858       *       *
859       * @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
860       */       */
861      void Voice::CalculateBiquadParameters(uint Samples) {      void Voice::CalculateBiquadParameters(uint Samples) {
         if (!FilterLeft.Enabled) return;  
   
862          biquad_param_t bqbase;          biquad_param_t bqbase;
863          biquad_param_t bqmain;          biquad_param_t bqmain;
864          float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0];          float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0];
865          float prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][0];          float prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][0];
866          FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);          FilterLeft.SetParameters( &bqbase, &bqmain, prev_cutoff + CONFIG_FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate);
867            FilterRight.SetParameters(&bqbase, &bqmain, prev_cutoff + CONFIG_FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate);
868          pEngine->pBasicFilterParameters[0] = bqbase;          pEngine->pBasicFilterParameters[0] = bqbase;
869          pEngine->pMainFilterParameters[0]  = bqmain;          pEngine->pMainFilterParameters[0]  = bqmain;
870    
871          float* bq;          float* bq;
872          for (int i = 1; i < Samples; i++) {          for (int i = 1; i < Samples; i++) {
873              // recalculate biquad parameters if cutoff or resonance differ from previous sample point              // recalculate biquad parameters if cutoff or resonance differ from previous sample point
874              if (!(i & FILTER_UPDATE_MASK)) if (pEngine->pSynthesisParameters[Event::destination_vcfr][i] != prev_res ||              if (!(i & FILTER_UPDATE_MASK)) {
875                                                 pEngine->pSynthesisParameters[Event::destination_vcfc][i] != prev_cutoff) {                  if (pEngine->pSynthesisParameters[Event::destination_vcfr][i] != prev_res ||
876                  prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][i];                      pEngine->pSynthesisParameters[Event::destination_vcfc][i] != prev_cutoff)
877                  prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][i];                  {
878                  FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);                      prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][i];
879                        prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][i];
880                        FilterLeft.SetParameters( &bqbase, &bqmain, prev_cutoff + CONFIG_FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate);
881                        FilterRight.SetParameters(&bqbase, &bqmain, prev_cutoff + CONFIG_FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate);
882                    }
883              }              }
884    
885              //same as 'pEngine->pBasicFilterParameters[i] = bqbase;'              //same as 'pEngine->pBasicFilterParameters[i] = bqbase;'
886              bq    = (float*) &pEngine->pBasicFilterParameters[i];              bq    = (float*) &pEngine->pBasicFilterParameters[i];
887              bq[0] = bqbase.a1;              bq[0] = bqbase.b0;
888              bq[1] = bqbase.a2;              bq[1] = bqbase.b1;
889              bq[2] = bqbase.b0;              bq[2] = bqbase.b2;
890              bq[3] = bqbase.b1;              bq[3] = bqbase.a1;
891              bq[4] = bqbase.b2;              bq[4] = bqbase.a2;
892    
893              // same as 'pEngine->pMainFilterParameters[i] = bqmain;'              // same as 'pEngine->pMainFilterParameters[i] = bqmain;'
894              bq    = (float*) &pEngine->pMainFilterParameters[i];              bq    = (float*) &pEngine->pMainFilterParameters[i];
895              bq[0] = bqmain.a1;              bq[0] = bqmain.b0;
896              bq[1] = bqmain.a2;              bq[1] = bqmain.b1;
897              bq[2] = bqmain.b0;              bq[2] = bqmain.b2;
898              bq[3] = bqmain.b1;              bq[3] = bqmain.a1;
899              bq[4] = bqmain.b2;              bq[4] = bqmain.a2;
900          }          }
901      }      }
     #endif // ENABLE_FILTER  
902    
903      /**      /**
904       *  Interpolates the input audio data (without looping).       *  Synthesizes the current audio fragment for this voice.
905       *       *
906       *  @param Samples - number of sample points to be rendered in this audio       *  @param Samples - number of sample points to be rendered in this audio
907       *                   fragment cycle       *                   fragment cycle
908       *  @param pSrc    - pointer to input sample data       *  @param pSrc    - pointer to input sample data
909       *  @param Skip    - number of sample points to skip in output buffer       *  @param Skip    - number of sample points to skip in output buffer
910       */       */
911      void Voice::InterpolateNoLoop(uint Samples, sample_t* pSrc, uint Skip) {      void Voice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {
912          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) InterpolateStereo(pSrc, i);  
         }  
         else { // Mono Sample  
             while (i < Samples) InterpolateMono(pSrc, 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) {  
                     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);;  
                     }  
                 }  
             }  
         }  
913      }      }
914    
915      /**      /**
# Line 1057  namespace LinuxSampler { namespace gig { Line 937  namespace LinuxSampler { namespace gig {
937       *  @param itKillEvent - event which caused the voice to be killed       *  @param itKillEvent - event which caused the voice to be killed
938       */       */
939      void Voice::Kill(Pool<Event>::Iterator& itKillEvent) {      void Voice::Kill(Pool<Event>::Iterator& itKillEvent) {
940          //FIXME: just two sanity checks for debugging, can be removed          #if CONFIG_DEVMODE
941          if (!itKillEvent) dmsg(1,("gig::Voice::Kill(): ERROR, !itKillEvent !!!\n"));          if (!itKillEvent) dmsg(1,("gig::Voice::Kill(): ERROR, !itKillEvent !!!\n"));
942          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"));
943            #endif // CONFIG_DEVMODE
944    
945          if (itTriggerEvent && itKillEvent->FragmentPos() <= itTriggerEvent->FragmentPos()) return;          if (itTriggerEvent && itKillEvent->FragmentPos() <= itTriggerEvent->FragmentPos()) return;
946          this->itKillEvent = itKillEvent;          this->itKillEvent = itKillEvent;

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

  ViewVC Help
Powered by ViewVC