/[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 245 by schoenebeck, Sat Sep 18 14:12:36 2004 UTC revision 3721 by schoenebeck, Mon Jan 20 15:10:05 2020 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 - 2008 Christian Schoenebeck                       *
7     *   Copyright (C) 2009 Christian Schoenebeck and Grigor Iliev             *
8     *   Copyright (C) 2010 - 2017 Christian Schoenebeck and Andreas Persson   *
9   *                                                                         *   *                                                                         *
10   *   This program is free software; you can redistribute it and/or modify  *   *   This program is free software; you can redistribute it and/or modify  *
11   *   it under the terms of the GNU General Public License as published by  *   *   it under the terms of the GNU General Public License as published by  *
# Line 20  Line 23 
23   *   MA  02111-1307  USA                                                   *   *   MA  02111-1307  USA                                                   *
24   ***************************************************************************/   ***************************************************************************/
25    
26  #include "EGADSR.h"  #include "../../common/Features.h"
27  #include "Manipulator.h"  #include "Synthesizer.h"
28    #include "Profiler.h"
29    #include "Engine.h"
30    #include "EngineChannel.h"
31    
32  #include "Voice.h"  #include "Voice.h"
33    
34  namespace LinuxSampler { namespace gig {  namespace LinuxSampler { namespace gig {
35    
36      const float Voice::FILTER_CUTOFF_COEFF(CalculateFilterCutoffCoeff());      // sanity checks: fromGigLfoWave() assumes equally mapped enums
37        static_assert(int64_t(::gig::lfo_wave_sine) == int64_t(LFO::wave_sine),
38      const int Voice::FILTER_UPDATE_MASK(CalculateFilterUpdateMask());                    "enum LFO::wave_t not equally value mapped to libgig's enum ::gig::lfo_wave_t");
39        static_assert(int64_t(::gig::lfo_wave_triangle) == int64_t(LFO::wave_triangle),
40      float Voice::CalculateFilterCutoffCoeff() {                    "enum LFO::wave_t not equally value mapped to libgig's enum ::gig::lfo_wave_t");
41          return log(FILTER_CUTOFF_MIN / FILTER_CUTOFF_MAX);      static_assert(int64_t(::gig::lfo_wave_saw) == int64_t(LFO::wave_saw),
42      }                    "enum LFO::wave_t not equally value mapped to libgig's enum ::gig::lfo_wave_t");
43        static_assert(int64_t(::gig::lfo_wave_square) == int64_t(LFO::wave_square),
44      int Voice::CalculateFilterUpdateMask() {                    "enum LFO::wave_t not equally value mapped to libgig's enum ::gig::lfo_wave_t");
45          if (FILTER_UPDATE_PERIOD <= 0) return 0;  
46          int power_of_two;      // converts ::gig::lfo_wave_t (libgig) -> LFO::wave_t (LinuxSampler)
47          for (power_of_two = 0; 1<<power_of_two < FILTER_UPDATE_PERIOD; power_of_two++);      inline LFO::wave_t fromGigLfoWave(::gig::lfo_wave_t wave) {
48          return (1 << power_of_two) - 1;          // simply assuming equally mapped enums on both sides
49            return static_cast<LFO::wave_t>(wave);
50        }
51    
52        // Returns true for GigaStudio's original filter types (which are resembled
53        // by LS very accurately with same frequency response and patch settings
54        // behaviour), false for our own LS specific filter implementation types.
55        constexpr bool isGStFilterType(::gig::vcf_type_t type) {
56            return type == ::gig::vcf_type_lowpass ||
57                   type == ::gig::vcf_type_lowpassturbo ||
58                   type == ::gig::vcf_type_bandpass ||
59                   type == ::gig::vcf_type_highpass ||
60                   type == ::gig::vcf_type_bandreject;
61      }      }
62    
63      Voice::Voice() {      Voice::Voice() {
64          pEngine     = NULL;          pEngine = NULL;
65          pDiskThread = NULL;          pEG1 = &EG1;
66          Active = false;          pEG2 = &EG2;
         pEG1   = NULL;  
         pEG2   = NULL;  
         pEG3   = NULL;  
         pVCAManipulator  = NULL;  
         pVCFCManipulator = NULL;  
         pVCOManipulator  = NULL;  
         pLFO1  = NULL;  
         pLFO2  = NULL;  
         pLFO3  = NULL;  
         KeyGroup = 0;  
67      }      }
68    
69      Voice::~Voice() {      Voice::~Voice() {
         if (pEG1)  delete pEG1;  
         if (pEG2)  delete pEG2;  
         if (pEG3)  delete pEG3;  
         if (pLFO1) delete pLFO1;  
         if (pLFO2) delete pLFO2;  
         if (pLFO3) delete pLFO3;  
         if (pVCAManipulator)  delete pVCAManipulator;  
         if (pVCFCManipulator) delete pVCFCManipulator;  
         if (pVCOManipulator)  delete pVCOManipulator;  
     }  
   
     void Voice::SetEngine(Engine* pEngine) {  
         this->pEngine = pEngine;  
   
         // delete old objects  
         if (pEG1) delete pEG1;  
         if (pEG2) delete pEG2;  
         if (pEG3) delete pEG3;  
         if (pVCAManipulator)  delete pVCAManipulator;  
         if (pVCFCManipulator) delete pVCFCManipulator;  
         if (pVCOManipulator)  delete pVCOManipulator;  
         if (pLFO1) delete pLFO1;  
         if (pLFO2) delete pLFO2;  
         if (pLFO3) delete pLFO3;  
   
         // create new ones  
         pEG1   = new EGADSR(pEngine, Event::destination_vca);  
         pEG2   = new EGADSR(pEngine, Event::destination_vcfc);  
         pEG3   = new EGDecay(pEngine, Event::destination_vco);  
         pVCAManipulator  = new VCAManipulator(pEngine);  
         pVCFCManipulator = new VCFCManipulator(pEngine);  
         pVCOManipulator  = new VCOManipulator(pEngine);  
         pLFO1  = new LFO<gig::VCAManipulator>(0.0f, 1.0f, LFO<VCAManipulator>::propagation_top_down, pVCAManipulator, pEngine->pEventPool);  
         pLFO2  = new LFO<gig::VCFCManipulator>(0.0f, 1.0f, LFO<VCFCManipulator>::propagation_top_down, pVCFCManipulator, pEngine->pEventPool);  
         pLFO3  = new LFO<gig::VCOManipulator>(-1200.0f, 1200.0f, LFO<VCOManipulator>::propagation_middle_balanced, pVCOManipulator, pEngine->pEventPool); // +-1 octave (+-1200 cents) max.  
   
         this->pDiskThread = pEngine->pDiskThread;  
         dmsg(6,("Voice::SetEngine()\n"));  
70      }      }
71    
72      /**      EngineChannel* Voice::GetGigEngineChannel() {
73       *  Initializes and triggers the voice, a disk stream will be launched if          return static_cast<EngineChannel*>(pEngineChannel);
74       *  needed.      }
      *  
      *  @param pNoteOnEvent        - event that caused triggering of this voice  
      *  @param PitchBend           - MIDI detune factor (-8192 ... +8191)  
      *  @param pInstrument         - points to the loaded instrument which provides sample wave(s) and articulation data  
      *  @param iLayer              - layer number this voice refers to (only if this is a layered sound of course)  
      *  @param ReleaseTriggerVoice - if this new voice is a release trigger voice (optional, default = false)  
      *  @returns 0 on success, a value < 0 if something failed  
      */  
     int Voice::Trigger(Event* pNoteOnEvent, int PitchBend, ::gig::Instrument* pInstrument, int iLayer, bool ReleaseTriggerVoice) {  
         if (!pInstrument) {  
            dmsg(1,("voice::trigger: !pInstrument\n"));  
            exit(EXIT_FAILURE);  
         }  
   
         Type            = type_normal;  
         Active          = true;  
         MIDIKey         = pNoteOnEvent->Key;  
         pRegion         = pInstrument->GetRegion(MIDIKey);  
         PlaybackState   = playback_state_ram; // we always start playback from RAM cache and switch then to disk if needed  
         Delay           = pNoteOnEvent->FragmentPos();  
         pTriggerEvent   = pNoteOnEvent;  
         pKillEvent      = NULL;  
   
         if (!pRegion) {  
             std::cerr << "gig::Voice: No Region defined for MIDI key " << MIDIKey << std::endl << std::flush;  
             KillImmediately();  
             return -1;  
         }  
   
         KeyGroup = pRegion->KeyGroup;  
   
         // get current dimension values to select the right dimension region  
         //FIXME: controller values for selecting the dimension region here are currently not sample accurate  
         uint DimValues[5] = {0,0,0,0,0};  
         for (int i = pRegion->Dimensions - 1; i >= 0; i--) {  
             switch (pRegion->pDimensionDefinitions[i].dimension) {  
                 case ::gig::dimension_samplechannel:  
                     DimValues[i] = 0; //TODO: we currently ignore this dimension  
                     break;  
                 case ::gig::dimension_layer:  
                     DimValues[i] = iLayer;  
                     // if this is the 1st layer then spawn further voices for all the other layers  
                     if (iLayer == 0)  
                         for (int iNewLayer = 1; iNewLayer < pRegion->pDimensionDefinitions[i].zones; iNewLayer++)  
                             pEngine->LaunchVoice(pNoteOnEvent, iNewLayer, ReleaseTriggerVoice);  
                     break;  
                 case ::gig::dimension_velocity:  
                     DimValues[i] = pNoteOnEvent->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) pNoteOnEvent->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;  
             }  
         }  
         pDimRgn = pRegion->GetDimensionRegionByValue(DimValues[4],DimValues[3],DimValues[2],DimValues[1],DimValues[0]);  
   
         // get starting crossfade volume level  
         switch (pDimRgn->AttenuationController.type) {  
             case ::gig::attenuation_ctrl_t::type_channelaftertouch:  
                 CrossfadeVolume = 1.0f; //TODO: aftertouch not supported yet  
                 break;  
             case ::gig::attenuation_ctrl_t::type_velocity:  
                 CrossfadeVolume = CrossfadeAttenuation(pNoteOnEvent->Velocity);  
                 break;  
             case ::gig::attenuation_ctrl_t::type_controlchange: //FIXME: currently not sample accurate  
                 CrossfadeVolume = CrossfadeAttenuation(pEngine->ControllerTable[pDimRgn->AttenuationController.controller_number]);  
                 break;  
             case ::gig::attenuation_ctrl_t::type_none: // no crossfade defined  
             default:  
                 CrossfadeVolume = 1.0f;  
         }  
   
         PanLeft  = float(RTMath::Max(pDimRgn->Pan, 0)) / -64.0f;  
         PanRight = float(RTMath::Min(pDimRgn->Pan, 0)) /  63.0f;  
   
         pSample = pDimRgn->pSample; // sample won't change until the voice is finished  
   
         Pos = pDimRgn->SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)  
   
         // Check if the sample needs disk streaming or is too short for that  
         long cachedsamples = pSample->GetCache().Size / pSample->FrameSize;  
         DiskVoice          = cachedsamples < pSample->SamplesTotal;  
   
         if (DiskVoice) { // voice to be streamed from disk  
             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)  
   
             // check if there's a loop defined which completely fits into the cached (RAM) part of the sample  
             if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) {  
                 RAMLoop        = true;  
                 LoopCyclesLeft = pSample->LoopPlayCount;  
             }  
             else RAMLoop = false;  
75    
76              if (pDiskThread->OrderNewStream(&DiskStreamRef, pSample, MaxRAMPos, !RAMLoop) < 0) {      void Voice::SetEngine(LinuxSampler::Engine* pEngine) {
77                  dmsg(1,("Disk stream order failed!\n"));          Engine* engine = static_cast<Engine*>(pEngine);
78                  KillImmediately();          this->pEngine     = engine;
79                  return -1;          this->pDiskThread = engine->pDiskThread;
80              }          dmsg(6,("Voice::SetEngine()\n"));
81              dmsg(4,("Disk voice launched (cached samples: %d, total Samples: %d, MaxRAMPos: %d, RAMLooping: %s)\n", cachedsamples, pSample->SamplesTotal, MaxRAMPos, (RAMLoop) ? "yes" : "no"));      }
         }  
         else { // RAM only voice  
             MaxRAMPos = cachedsamples;  
             if (pSample->Loops) {  
                 RAMLoop        = true;  
                 LoopCyclesLeft = pSample->LoopPlayCount;  
             }  
             else RAMLoop = false;  
             dmsg(4,("RAM only voice launched (Looping: %s)\n", (RAMLoop) ? "yes" : "no"));  
         }  
82    
83        Voice::SampleInfo Voice::GetSampleInfo() {
84            SampleInfo si;
85            si.SampleRate       = pSample->SamplesPerSecond;
86            si.ChannelCount     = pSample->Channels;
87            si.FrameSize        = pSample->FrameSize;
88            si.BitDepth         = pSample->BitDepth;
89            si.TotalFrameCount  = (uint)pSample->SamplesTotal;
90    
91          // calculate initial pitch value          si.HasLoops       = pRegion->SampleLoops;
92          {          si.LoopStart      = (si.HasLoops) ? pRegion->pSampleLoops[0].LoopStart  : 0;
93              double pitchbasecents = pDimRgn->FineTune * 10 + (int) pEngine->ScaleTuning[MIDIKey % 12];          si.LoopLength     = (si.HasLoops) ? pRegion->pSampleLoops[0].LoopLength : 0;
94              if (pDimRgn->PitchTrack) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;          si.LoopPlayCount  = pSample->LoopPlayCount;
95              this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents) * (double(pSample->SamplesPerSecond) / double(pEngine->pAudioOutputDevice->SampleRate()));          si.Unpitched      = !pRegion->PitchTrack;
             this->PitchBend = RTMath::CentsToFreqRatio(((double) PitchBend / 8192.0) * 200.0); // pitchbend wheel +-2 semitones = 200 cents  
         }  
96    
97            return si;
98        }
99    
100          Volume = pDimRgn->GetVelocityAttenuation(pNoteOnEvent->Velocity) / 32768.0f; // we downscale by 32768 to convert from int16 value range to DSP value range (which is -1.0..1.0)      Voice::RegionInfo Voice::GetRegionInfo() {
101            RegionInfo ri;
102            ri.UnityNote = pRegion->UnityNote;
103            ri.FineTune  = pRegion->FineTune;
104            ri.Pan       = pRegion->Pan;
105            ri.SampleStartOffset = pRegion->SampleStartOffset;
106    
107            ri.EG2PreAttack        = pRegion->EG2PreAttack;
108            ri.EG2Attack           = pRegion->EG2Attack;
109            ri.EG2Decay1           = pRegion->EG2Decay1;
110            ri.EG2Decay2           = pRegion->EG2Decay2;
111            ri.EG2Sustain          = pRegion->EG2Sustain;
112            ri.EG2InfiniteSustain  = pRegion->EG2InfiniteSustain;
113            ri.EG2Release          = pRegion->EG2Release;
114    
115          // setup EG 1 (VCA EG)          ri.EG3Attack     = pRegion->EG3Attack;
116          {          ri.EG3Depth      = pRegion->EG3Depth;
117              // get current value of EG1 controller          ri.VCFEnabled    = pRegion->VCFEnabled;
118              double eg1controllervalue;          ri.VCFType       = Filter::vcf_type_t(pRegion->VCFType);
119              switch (pDimRgn->EG1Controller.type) {          ri.VCFResonance  = pRegion->VCFResonance;
                 case ::gig::eg1_ctrl_t::type_none: // no controller defined  
                     eg1controllervalue = 0;  
                     break;  
                 case ::gig::eg1_ctrl_t::type_channelaftertouch:  
                     eg1controllervalue = 0; // TODO: aftertouch not yet supported  
                     break;  
                 case ::gig::eg1_ctrl_t::type_velocity:  
                     eg1controllervalue = pNoteOnEvent->Velocity;  
                     break;  
                 case ::gig::eg1_ctrl_t::type_controlchange: // MIDI control change controller  
                     eg1controllervalue = pEngine->ControllerTable[pDimRgn->EG1Controller.controller_number];  
                     break;  
             }  
             if (pDimRgn->EG1ControllerInvert) eg1controllervalue = 127 - eg1controllervalue;  
120    
121              // calculate influence of EG1 controller on EG1's parameters (TODO: needs to be fine tuned)          ri.ReleaseTriggerDecay = 0.01053 * (256 >> pRegion->ReleaseTriggerDecay);
             double eg1attack  = (pDimRgn->EG1ControllerAttackInfluence)  ? 0.0001 * (double) (1 << pDimRgn->EG1ControllerAttackInfluence)  * eg1controllervalue : 0.0;  
             double eg1decay   = (pDimRgn->EG1ControllerDecayInfluence)   ? 0.0001 * (double) (1 << pDimRgn->EG1ControllerDecayInfluence)   * eg1controllervalue : 0.0;  
             double eg1release = (pDimRgn->EG1ControllerReleaseInfluence) ? 0.0001 * (double) (1 << pDimRgn->EG1ControllerReleaseInfluence) * eg1controllervalue : 0.0;  
   
             pEG1->Trigger(pDimRgn->EG1PreAttack,  
                           pDimRgn->EG1Attack + eg1attack,  
                           pDimRgn->EG1Hold,  
                           pSample->LoopStart,  
                           pDimRgn->EG1Decay1 + eg1decay,  
                           pDimRgn->EG1Decay2 + eg1decay,  
                           pDimRgn->EG1InfiniteSustain,  
                           pDimRgn->EG1Sustain,  
                           pDimRgn->EG1Release + eg1release,  
                           Delay);  
         }  
122    
123            return ri;
124        }
125    
126      #if ENABLE_FILTER      Voice::InstrumentInfo Voice::GetInstrumentInfo() {
127          // setup EG 2 (VCF Cutoff EG)          InstrumentInfo ii;
128          {          ii.FineTune = GetGigEngineChannel()->pInstrument->FineTune;
129              // get current value of EG2 controller          ii.PitchbendRange = GetGigEngineChannel()->pInstrument->PitchbendRange;
             double eg2controllervalue;  
             switch (pDimRgn->EG2Controller.type) {  
                 case ::gig::eg2_ctrl_t::type_none: // no controller defined  
                     eg2controllervalue = 0;  
                     break;  
                 case ::gig::eg2_ctrl_t::type_channelaftertouch:  
                     eg2controllervalue = 0; // TODO: aftertouch not yet supported  
                     break;  
                 case ::gig::eg2_ctrl_t::type_velocity:  
                     eg2controllervalue = pNoteOnEvent->Velocity;  
                     break;  
                 case ::gig::eg2_ctrl_t::type_controlchange: // MIDI control change controller  
                     eg2controllervalue = pEngine->ControllerTable[pDimRgn->EG2Controller.controller_number];  
                     break;  
             }  
             if (pDimRgn->EG2ControllerInvert) eg2controllervalue = 127 - eg2controllervalue;  
130    
131              // calculate influence of EG2 controller on EG2's parameters (TODO: needs to be fine tuned)          return ii;
132              double eg2attack  = (pDimRgn->EG2ControllerAttackInfluence)  ? 0.0001 * (double) (1 << pDimRgn->EG2ControllerAttackInfluence)  * eg2controllervalue : 0.0;      }
             double eg2decay   = (pDimRgn->EG2ControllerDecayInfluence)   ? 0.0001 * (double) (1 << pDimRgn->EG2ControllerDecayInfluence)   * eg2controllervalue : 0.0;  
             double eg2release = (pDimRgn->EG2ControllerReleaseInfluence) ? 0.0001 * (double) (1 << pDimRgn->EG2ControllerReleaseInfluence) * eg2controllervalue : 0.0;  
   
             pEG2->Trigger(pDimRgn->EG2PreAttack,  
                           pDimRgn->EG2Attack + eg2attack,  
                           false,  
                           pSample->LoopStart,  
                           pDimRgn->EG2Decay1 + eg2decay,  
                           pDimRgn->EG2Decay2 + eg2decay,  
                           pDimRgn->EG2InfiniteSustain,  
                           pDimRgn->EG2Sustain,  
                           pDimRgn->EG2Release + eg2release,  
                           Delay);  
         }  
     #endif // ENABLE_FILTER  
133    
134        double Voice::GetSampleAttenuation() {
135            return pRegion->SampleAttenuation;
136        }
137    
138          // setup EG 3 (VCO EG)      double Voice::GetVelocityAttenuation(uint8_t MIDIKeyVelocity) {
139          {          return pRegion->GetVelocityAttenuation(MIDIKeyVelocity);
140            double eg3depth = RTMath::CentsToFreqRatio(pDimRgn->EG3Depth);      }
           pEG3->Trigger(eg3depth, pDimRgn->EG3Attack, Delay);  
         }  
141    
142        double Voice::GetVelocityRelease(uint8_t MIDIKeyVelocity) {
143            return pRegion->GetVelocityRelease(MIDIKeyVelocity);
144        }
145    
146          // setup LFO 1 (VCA LFO)      void Voice::ProcessCCEvent(RTList<Event>::Iterator& itEvent) {
147          {          if (itEvent->Type == Event::type_control_change && itEvent->Param.CC.Controller) { // if (valid) MIDI control change event
148              uint16_t lfo1_internal_depth;              if (pRegion->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange &&
149              switch (pDimRgn->LFO1Controller) {                  itEvent->Param.CC.Controller == pRegion->AttenuationController.controller_number) {
150                  case ::gig::lfo1_ctrl_internal:                  CrossfadeSmoother.update(AbstractEngine::CrossfadeCurve[CrossfadeAttenuation(itEvent->Param.CC.Value)]);
                     lfo1_internal_depth  = pDimRgn->LFO1InternalDepth;  
                     pLFO1->ExtController = 0; // no external controller  
                     break;  
                 case ::gig::lfo1_ctrl_modwheel:  
                     lfo1_internal_depth  = 0;  
                     pLFO1->ExtController = 1; // MIDI controller 1  
                     break;  
                 case ::gig::lfo1_ctrl_breath:  
                     lfo1_internal_depth  = 0;  
                     pLFO1->ExtController = 2; // MIDI controller 2  
                     break;  
                 case ::gig::lfo1_ctrl_internal_modwheel:  
                     lfo1_internal_depth  = pDimRgn->LFO1InternalDepth;  
                     pLFO1->ExtController = 1; // MIDI controller 1  
                     break;  
                 case ::gig::lfo1_ctrl_internal_breath:  
                     lfo1_internal_depth  = pDimRgn->LFO1InternalDepth;  
                     pLFO1->ExtController = 2; // MIDI controller 2  
                     break;  
                 default:  
                     lfo1_internal_depth  = 0;  
                     pLFO1->ExtController = 0; // no external controller  
151              }              }
             pLFO1->Trigger(pDimRgn->LFO1Frequency,  
                           lfo1_internal_depth,  
                           pDimRgn->LFO1ControlDepth,  
                           pEngine->ControllerTable[pLFO1->ExtController],  
                           pDimRgn->LFO1FlipPhase,  
                           pEngine->SampleRate,  
                           Delay);  
152          }          }
153        }
154    
155      #if ENABLE_FILTER      void Voice::ProcessChannelPressureEvent(RTList<Event>::Iterator& itEvent) {
156          // setup LFO 2 (VCF Cutoff LFO)          if (itEvent->Type == Event::type_channel_pressure) { // if (valid) MIDI channel pressure (aftertouch) event
157          {              if (pRegion->AttenuationController.type == ::gig::attenuation_ctrl_t::type_channelaftertouch) {
158              uint16_t lfo2_internal_depth;                  CrossfadeSmoother.update(AbstractEngine::CrossfadeCurve[CrossfadeAttenuation(itEvent->Param.ChannelPressure.Value)]);
             switch (pDimRgn->LFO2Controller) {  
                 case ::gig::lfo2_ctrl_internal:  
                     lfo2_internal_depth  = pDimRgn->LFO2InternalDepth;  
                     pLFO2->ExtController = 0; // no external controller  
                     break;  
                 case ::gig::lfo2_ctrl_modwheel:  
                     lfo2_internal_depth  = 0;  
                     pLFO2->ExtController = 1; // MIDI controller 1  
                     break;  
                 case ::gig::lfo2_ctrl_foot:  
                     lfo2_internal_depth  = 0;  
                     pLFO2->ExtController = 4; // MIDI controller 4  
                     break;  
                 case ::gig::lfo2_ctrl_internal_modwheel:  
                     lfo2_internal_depth  = pDimRgn->LFO2InternalDepth;  
                     pLFO2->ExtController = 1; // MIDI controller 1  
                     break;  
                 case ::gig::lfo2_ctrl_internal_foot:  
                     lfo2_internal_depth  = pDimRgn->LFO2InternalDepth;  
                     pLFO2->ExtController = 4; // MIDI controller 4  
                     break;  
                 default:  
                     lfo2_internal_depth  = 0;  
                     pLFO2->ExtController = 0; // no external controller  
159              }              }
             pLFO2->Trigger(pDimRgn->LFO2Frequency,  
                           lfo2_internal_depth,  
                           pDimRgn->LFO2ControlDepth,  
                           pEngine->ControllerTable[pLFO2->ExtController],  
                           pDimRgn->LFO2FlipPhase,  
                           pEngine->SampleRate,  
                           Delay);  
160          }          }
161      #endif // ENABLE_FILTER      }
162    
163          // setup LFO 3 (VCO LFO)      void Voice::ProcessPolyphonicKeyPressureEvent(RTList<Event>::Iterator& itEvent) {
164          {          // Not used so far
165              uint16_t lfo3_internal_depth;      }
             switch (pDimRgn->LFO3Controller) {  
                 case ::gig::lfo3_ctrl_internal:  
                     lfo3_internal_depth  = pDimRgn->LFO3InternalDepth;  
                     pLFO3->ExtController = 0; // no external controller  
                     break;  
                 case ::gig::lfo3_ctrl_modwheel:  
                     lfo3_internal_depth  = 0;  
                     pLFO3->ExtController = 1; // MIDI controller 1  
                     break;  
                 case ::gig::lfo3_ctrl_aftertouch:  
                     lfo3_internal_depth  = 0;  
                     pLFO3->ExtController = 0; // TODO: aftertouch not implemented yet  
                     break;  
                 case ::gig::lfo3_ctrl_internal_modwheel:  
                     lfo3_internal_depth  = pDimRgn->LFO3InternalDepth;  
                     pLFO3->ExtController = 1; // MIDI controller 1  
                     break;  
                 case ::gig::lfo3_ctrl_internal_aftertouch:  
                     lfo3_internal_depth  = pDimRgn->LFO3InternalDepth;  
                     pLFO1->ExtController = 0; // TODO: aftertouch not implemented yet  
                     break;  
                 default:  
                     lfo3_internal_depth  = 0;  
                     pLFO3->ExtController = 0; // no external controller  
             }  
             pLFO3->Trigger(pDimRgn->LFO3Frequency,  
                           lfo3_internal_depth,  
                           pDimRgn->LFO3ControlDepth,  
                           pEngine->ControllerTable[pLFO3->ExtController],  
                           false,  
                           pEngine->SampleRate,  
                           Delay);  
         }  
166    
167      #if ENABLE_FILTER      uint8_t Voice::MinCutoff() const {
168          #if FORCE_FILTER_USAGE          // If there's a cutoff controller defined then VCFVelocityScale means
169          FilterLeft.Enabled = FilterRight.Enabled = true;          // "minimum cutoff". If there is no MIDI controller defined for cutoff
170          #else // use filter only if instrument file told so          // then VCFVelocityScale is already taken into account on libgig side
171          FilterLeft.Enabled = FilterRight.Enabled = pDimRgn->VCFEnabled;          // instead by call to pRegion->GetVelocityCutoff(MIDIKeyVelocity).
172          #endif // FORCE_FILTER_USAGE          return pRegion->VCFVelocityScale;
173          if (pDimRgn->VCFEnabled) {      }
             #ifdef OVERRIDE_FILTER_CUTOFF_CTRL  
             VCFCutoffCtrl.controller = OVERRIDE_FILTER_CUTOFF_CTRL;  
             #else // use the one defined in the instrument file  
             switch (pDimRgn->VCFCutoffController) {  
                 case ::gig::vcf_cutoff_ctrl_modwheel:  
                     VCFCutoffCtrl.controller = 1;  
                     break;  
                 case ::gig::vcf_cutoff_ctrl_effect1:  
                     VCFCutoffCtrl.controller = 12;  
                     break;  
                 case ::gig::vcf_cutoff_ctrl_effect2:  
                     VCFCutoffCtrl.controller = 13;  
                     break;  
                 case ::gig::vcf_cutoff_ctrl_breath:  
                     VCFCutoffCtrl.controller = 2;  
                     break;  
                 case ::gig::vcf_cutoff_ctrl_foot:  
                     VCFCutoffCtrl.controller = 4;  
                     break;  
                 case ::gig::vcf_cutoff_ctrl_sustainpedal:  
                     VCFCutoffCtrl.controller = 64;  
                     break;  
                 case ::gig::vcf_cutoff_ctrl_softpedal:  
                     VCFCutoffCtrl.controller = 67;  
                     break;  
                 case ::gig::vcf_cutoff_ctrl_genpurpose7:  
                     VCFCutoffCtrl.controller = 82;  
                     break;  
                 case ::gig::vcf_cutoff_ctrl_genpurpose8:  
                     VCFCutoffCtrl.controller = 83;  
                     break;  
                 case ::gig::vcf_cutoff_ctrl_aftertouch: //TODO: not implemented yet  
                 case ::gig::vcf_cutoff_ctrl_none:  
                 default:  
                     VCFCutoffCtrl.controller = 0;  
                     break;  
             }  
             #endif // OVERRIDE_FILTER_CUTOFF_CTRL  
174    
175              #ifdef OVERRIDE_FILTER_RES_CTRL      // This is called on any cutoff controller changes, however not when the
176              VCFResonanceCtrl.controller = OVERRIDE_FILTER_RES_CTRL;      // voice is triggered. So the initial cutoff value is retrieved by a call
177              #else // use the one defined in the instrument file      // to CalculateFinalCutoff() instead.
178              switch (pDimRgn->VCFResonanceController) {      void Voice::ProcessCutoffEvent(RTList<Event>::Iterator& itEvent) {
179                  case ::gig::vcf_res_ctrl_genpurpose3:          if (VCFCutoffCtrl.value == itEvent->Param.CC.Value) return;
180                      VCFResonanceCtrl.controller = 18;          float ccvalue = VCFCutoffCtrl.value = itEvent->Param.CC.Value;
                     break;  
                 case ::gig::vcf_res_ctrl_genpurpose4:  
                     VCFResonanceCtrl.controller = 19;  
                     break;  
                 case ::gig::vcf_res_ctrl_genpurpose5:  
                     VCFResonanceCtrl.controller = 80;  
                     break;  
                 case ::gig::vcf_res_ctrl_genpurpose6:  
                     VCFResonanceCtrl.controller = 81;  
                     break;  
                 case ::gig::vcf_res_ctrl_none:  
                 default:  
                     VCFResonanceCtrl.controller = 0;  
             }  
             #endif // OVERRIDE_FILTER_RES_CTRL  
181    
182              #ifndef OVERRIDE_FILTER_TYPE          // if the selected filter type is an official GigaStudio filter type
183              FilterLeft.SetType(pDimRgn->VCFType);          // then we preserve the original (no matter how odd) historical GSt
184              FilterRight.SetType(pDimRgn->VCFType);          // behaviour identically; for our own filter types though we deviate to
185              #else // override filter type          // more meaningful behaviours where appropriate
186              FilterLeft.SetType(OVERRIDE_FILTER_TYPE);          const bool isGStFilter = isGStFilterType(pRegion->VCFType);
             FilterRight.SetType(OVERRIDE_FILTER_TYPE);  
             #endif // OVERRIDE_FILTER_TYPE  
   
             VCFCutoffCtrl.value    = pEngine->ControllerTable[VCFCutoffCtrl.controller];  
             VCFResonanceCtrl.value = pEngine->ControllerTable[VCFResonanceCtrl.controller];  
   
             // calculate cutoff frequency  
             float cutoff = (!VCFCutoffCtrl.controller)  
                 ? exp((float) (127 - pNoteOnEvent->Velocity) * (float) pDimRgn->VCFVelocityScale * 6.2E-5f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX  
                 : exp((float) VCFCutoffCtrl.value * 0.00787402f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX;  
   
             // calculate resonance  
             float resonance = (float) VCFResonanceCtrl.value * 0.00787f;   // 0.0..1.0  
             if (pDimRgn->VCFKeyboardTracking) {  
                 resonance += (float) (pNoteOnEvent->Key - pDimRgn->VCFKeyboardTrackingBreakpoint) * 0.00787f;  
             }  
             Constrain(resonance, 0.0, 1.0); // correct resonance if outside allowed value range (0.0..1.0)  
187    
188              VCFCutoffCtrl.fvalue    = cutoff - FILTER_CUTOFF_MIN;          if (pRegion->VCFCutoffControllerInvert) ccvalue = 127 - ccvalue;
189              VCFResonanceCtrl.fvalue = resonance;          // interpret "minimum cutoff" not simply as hard limit, rather
190            // restrain it to min_cutoff..127 range, but spanned / remapped over
191            // the entire controller range (0..127) to avoid a "dead" lower
192            // controller zone (that is to avoid a certain CC value range where
193            // the controller would not change the cutoff frequency)
194            ccvalue = MinCutoff() + (ccvalue / 127.f) * float(127 - MinCutoff());
195    
196              FilterLeft.SetParameters(cutoff,  resonance, pEngine->SampleRate);          float cutoff = CutoffBase * ccvalue;
197              FilterRight.SetParameters(cutoff, resonance, pEngine->SampleRate);          if (cutoff > 127.0f) cutoff = 127.0f;
198    
199              FilterUpdateCounter = -1;          // the filter implementations of the original GSt filter types take an
200            // abstract cutoff parameter range of 0..127, whereas our own filter
201            // types take a cutoff parameter in Hz, so remap here:
202            // 0 .. 127 [lin] -> 21 Hz .. 18 kHz [x^4] (center @2.2 kHz)
203            if (!isGStFilter) {
204                cutoff = (cutoff + 29.f) / (127.f + 29.f);
205                cutoff = cutoff * cutoff * cutoff * cutoff * 18000.f;
206                if (cutoff > 0.49f * pEngine->SampleRate)
207                    cutoff = 0.49f * pEngine->SampleRate;
208          }          }
         else {  
             VCFCutoffCtrl.controller    = 0;  
             VCFResonanceCtrl.controller = 0;  
         }  
     #endif // ENABLE_FILTER  
209    
210          return 0; // success          fFinalCutoff = VCFCutoffCtrl.fvalue = cutoff;
211      }      }
212    
213      /**      double Voice::CalculateCrossfadeVolume(uint8_t MIDIKeyVelocity) {
214       *  Renders the audio data for this voice for the current audio fragment.          float crossfadeVolume;
215       *  The sample input data can either come from RAM (cached sample or sample          switch (pRegion->AttenuationController.type) {
216       *  part) or directly from disk. The output signal will be rendered by              case ::gig::attenuation_ctrl_t::type_channelaftertouch:
217       *  resampling / interpolation. If this voice is a disk streaming voice and                  crossfadeVolume = Engine::CrossfadeCurve[CrossfadeAttenuation(GetGigEngineChannel()->ControllerTable[128])];
      *  the voice completely played back the cached RAM part of the sample, it  
      *  will automatically switch to disk playback for the next RenderAudio()  
      *  call.  
      *  
      *  @param Samples - number of samples to be rendered in this audio fragment cycle  
      */  
     void Voice::Render(uint Samples) {  
   
         // Reset the synthesis parameter matrix  
         pEngine->ResetSynthesisParameters(Event::destination_vca, this->Volume * this->CrossfadeVolume * pEngine->GlobalVolume);  
         pEngine->ResetSynthesisParameters(Event::destination_vco, this->PitchBase);  
     #if ENABLE_FILTER  
         pEngine->ResetSynthesisParameters(Event::destination_vcfc, VCFCutoffCtrl.fvalue);  
         pEngine->ResetSynthesisParameters(Event::destination_vcfr, VCFResonanceCtrl.fvalue);  
     #endif // ENABLE_FILTER  
   
   
         // Apply events to the synthesis parameter matrix  
         ProcessEvents(Samples);  
   
   
         // Let all modulators write their parameter changes to the synthesis parameter matrix for the current audio fragment  
         pEG1->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, pTriggerEvent, this->Pos, this->PitchBase * this->PitchBend, pKillEvent);  
     #if ENABLE_FILTER  
         pEG2->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, pTriggerEvent, this->Pos, this->PitchBase * this->PitchBend);  
     #endif // ENABLE_FILTER  
         pEG3->Process(Samples);  
         pLFO1->Process(Samples);  
     #if ENABLE_FILTER  
         pLFO2->Process(Samples);  
     #endif // ENABLE_FILTER  
         pLFO3->Process(Samples);  
   
   
     #if ENABLE_FILTER  
         CalculateBiquadParameters(Samples); // calculate the final biquad filter parameters  
     #endif // ENABLE_FILTER  
   
   
         switch (this->PlaybackState) {  
   
             case playback_state_ram: {  
                     if (RAMLoop) InterpolateAndLoop(Samples, (sample_t*) pSample->GetCache().pStart, Delay);  
                     else         InterpolateNoLoop(Samples, (sample_t*) pSample->GetCache().pStart, Delay);  
                     if (DiskVoice) {  
                         // check if we reached the allowed limit of the sample RAM cache  
                         if (Pos > MaxRAMPos) {  
                             dmsg(5,("Voice: switching to disk playback (Pos=%f)\n", Pos));  
                             this->PlaybackState = playback_state_disk;  
                         }  
                     }  
                     else if (Pos >= pSample->GetCache().Size / pSample->FrameSize) {  
                         this->PlaybackState = playback_state_end;  
                     }  
                 }  
                 break;  
   
             case playback_state_disk: {  
                     if (!DiskStreamRef.pStream) {  
                         // check if the disk thread created our ordered disk stream in the meantime  
                         DiskStreamRef.pStream = pDiskThread->AskForCreatedStream(DiskStreamRef.OrderID);  
                         if (!DiskStreamRef.pStream) {  
                             std::cout << stderr << "Disk stream not available in time!" << std::endl << std::flush;  
                             KillImmediately();  
                             return;  
                         }  
                         DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (RTMath::DoubleToInt(Pos) - MaxRAMPos));  
                         Pos -= RTMath::DoubleToInt(Pos);  
                     }  
   
                     // add silence sample at the end if we reached the end of the stream (for the interpolator)  
                     if (DiskStreamRef.State == Stream::state_end && DiskStreamRef.pStream->GetReadSpace() < (pEngine->MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels) {  
                         DiskStreamRef.pStream->WriteSilence((pEngine->MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels);  
                         this->PlaybackState = playback_state_end;  
                     }  
   
                     sample_t* ptr = DiskStreamRef.pStream->GetReadPtr(); // get the current read_ptr within the ringbuffer where we read the samples from  
                     InterpolateNoLoop(Samples, ptr, Delay);  
                     DiskStreamRef.pStream->IncrementReadPos(RTMath::DoubleToInt(Pos) * pSample->Channels);  
                     Pos -= RTMath::DoubleToInt(Pos);  
                 }  
218                  break;                  break;
219                case ::gig::attenuation_ctrl_t::type_velocity:
220              case playback_state_end:                  crossfadeVolume = Engine::CrossfadeCurve[CrossfadeAttenuation(MIDIKeyVelocity)];
                 KillImmediately(); // free voice  
221                  break;                  break;
222                case ::gig::attenuation_ctrl_t::type_controlchange: //FIXME: currently not sample accurate
223                    crossfadeVolume = Engine::CrossfadeCurve[CrossfadeAttenuation(GetGigEngineChannel()->ControllerTable[pRegion->AttenuationController.controller_number])];
224                    break;
225                case ::gig::attenuation_ctrl_t::type_none: // no crossfade defined
226                default:
227                    crossfadeVolume = 1.0f;
228          }          }
229    
230            return crossfadeVolume;
231        }
232    
233          // Reset synthesis event lists (except VCO, as VCO events apply channel wide currently)      double Voice::GetEG1ControllerValue(uint8_t MIDIKeyVelocity) {
234          pEngine->pSynthesisEvents[Event::destination_vca]->clear();          double eg1controllervalue = 0;
235      #if ENABLE_FILTER          switch (pRegion->EG1Controller.type) {
236          pEngine->pSynthesisEvents[Event::destination_vcfc]->clear();              case ::gig::eg1_ctrl_t::type_none: // no controller defined
237          pEngine->pSynthesisEvents[Event::destination_vcfr]->clear();                  eg1controllervalue = 0;
238      #endif // ENABLE_FILTER                  break;
239                case ::gig::eg1_ctrl_t::type_channelaftertouch:
240          // Reset delay                  eg1controllervalue = GetGigEngineChannel()->ControllerTable[128];
241          Delay = 0;                  break;
242                case ::gig::eg1_ctrl_t::type_velocity:
243          pTriggerEvent = NULL;                  eg1controllervalue = MIDIKeyVelocity;
244                    break;
245          // If release stage finished, let the voice be killed              case ::gig::eg1_ctrl_t::type_controlchange: // MIDI control change controller
246          if (pEG1->GetStage() == EGADSR::stage_end) this->PlaybackState = playback_state_end;                  eg1controllervalue = GetGigEngineChannel()->ControllerTable[pRegion->EG1Controller.controller_number];
247      }                  break;
   
     /**  
      *  Resets voice variables. Should only be called if rendering process is  
      *  suspended / not running.  
      */  
     void Voice::Reset() {  
         pLFO1->Reset();  
         pLFO2->Reset();  
         pLFO3->Reset();  
         DiskStreamRef.pStream = NULL;  
         DiskStreamRef.hStream = 0;  
         DiskStreamRef.State   = Stream::state_unused;  
         DiskStreamRef.OrderID = 0;  
         Active = false;  
     }  
   
     /**  
      *  Process the control change event lists of the engine for the current  
      *  audio fragment. Event values will be applied to the synthesis parameter  
      *  matrix.  
      *  
      *  @param Samples - number of samples to be rendered in this audio fragment cycle  
      */  
     void Voice::ProcessEvents(uint Samples) {  
   
         // dispatch control change events  
         Event* pCCEvent = pEngine->pCCEvents->first();  
         if (Delay) { // skip events that happened before this voice was triggered  
             while (pCCEvent && pCCEvent->FragmentPos() <= Delay) pCCEvent = pEngine->pCCEvents->next();  
         }  
         while (pCCEvent) {  
             if (pCCEvent->Controller) { // if valid MIDI controller  
                 #if ENABLE_FILTER  
                 if (pCCEvent->Controller == VCFCutoffCtrl.controller) {  
                     pEngine->pSynthesisEvents[Event::destination_vcfc]->alloc_assign(*pCCEvent);  
                 }  
                 if (pCCEvent->Controller == VCFResonanceCtrl.controller) {  
                     pEngine->pSynthesisEvents[Event::destination_vcfr]->alloc_assign(*pCCEvent);  
                 }  
                 #endif // ENABLE_FILTER  
                 if (pCCEvent->Controller == pLFO1->ExtController) {  
                     pLFO1->SendEvent(pCCEvent);  
                 }  
                 #if ENABLE_FILTER  
                 if (pCCEvent->Controller == pLFO2->ExtController) {  
                     pLFO2->SendEvent(pCCEvent);  
                 }  
                 #endif // ENABLE_FILTER  
                 if (pCCEvent->Controller == pLFO3->ExtController) {  
                     pLFO3->SendEvent(pCCEvent);  
                 }  
                 if (pDimRgn->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange &&  
                     pCCEvent->Controller == pDimRgn->AttenuationController.controller_number) { // if crossfade event  
                     pEngine->pSynthesisEvents[Event::destination_vca]->alloc_assign(*pCCEvent);  
                 }  
             }  
   
             pCCEvent = pEngine->pCCEvents->next();  
         }  
   
   
         // process pitch events  
         {  
             RTEList<Event>* pVCOEventList = pEngine->pSynthesisEvents[Event::destination_vco];  
             Event* pVCOEvent = pVCOEventList->first();  
             if (Delay) { // skip events that happened before this voice was triggered  
                 while (pVCOEvent && pVCOEvent->FragmentPos() <= Delay) pVCOEvent = pVCOEventList->next();  
             }  
             // apply old pitchbend value until first pitch event occurs  
             if (this->PitchBend != 1.0) {  
                 uint end = (pVCOEvent) ? pVCOEvent->FragmentPos() : Samples;  
                 for (uint i = Delay; i < end; i++) {  
                     pEngine->pSynthesisParameters[Event::destination_vco][i] *= this->PitchBend;  
                 }  
             }  
             float pitch;  
             while (pVCOEvent) {  
                 Event* pNextVCOEvent = pVCOEventList->next();  
   
                 // calculate the influence length of this event (in sample points)  
                 uint end = (pNextVCOEvent) ? pNextVCOEvent->FragmentPos() : Samples;  
   
                 pitch = RTMath::CentsToFreqRatio(((double) pVCOEvent->Pitch / 8192.0) * 200.0); // +-two semitones = +-200 cents  
   
                 // apply pitch value to the pitch parameter sequence  
                 for (uint i = pVCOEvent->FragmentPos(); i < end; i++) {  
                     pEngine->pSynthesisParameters[Event::destination_vco][i] *= pitch;  
                 }  
   
                 pVCOEvent = pNextVCOEvent;  
             }  
             if (pVCOEventList->last()) this->PitchBend = pitch;  
         }  
   
         // process volume / attenuation events (TODO: we only handle and _expect_ crossfade events here ATM !)  
         {  
             RTEList<Event>* pVCAEventList = pEngine->pSynthesisEvents[Event::destination_vca];  
             Event* pVCAEvent = pVCAEventList->first();  
             if (Delay) { // skip events that happened before this voice was triggered  
                 while (pVCAEvent && pVCAEvent->FragmentPos() <= Delay) pVCAEvent = pVCAEventList->next();  
             }  
             float crossfadevolume;  
             while (pVCAEvent) {  
                 Event* pNextVCAEvent = pVCAEventList->next();  
   
                 // calculate the influence length of this event (in sample points)  
                 uint end = (pNextVCAEvent) ? pNextVCAEvent->FragmentPos() : Samples;  
   
                 crossfadevolume = CrossfadeAttenuation(pVCAEvent->Value);  
   
                 float effective_volume = crossfadevolume * this->Volume * pEngine->GlobalVolume;  
   
                 // apply volume value to the volume parameter sequence  
                 for (uint i = pVCAEvent->FragmentPos(); i < end; i++) {  
                     pEngine->pSynthesisParameters[Event::destination_vca][i] = effective_volume;  
                 }  
   
                 pVCAEvent = pNextVCAEvent;  
             }  
             if (pVCAEventList->last()) this->CrossfadeVolume = crossfadevolume;  
248          }          }
249            if (pRegion->EG1ControllerInvert) eg1controllervalue = 127 - eg1controllervalue;
250    
251      #if ENABLE_FILTER          return eg1controllervalue;
252          // process filter cutoff events      }
         {  
             RTEList<Event>* pCutoffEventList = pEngine->pSynthesisEvents[Event::destination_vcfc];  
             Event* pCutoffEvent = pCutoffEventList->first();  
             if (Delay) { // skip events that happened before this voice was triggered  
                 while (pCutoffEvent && pCutoffEvent->FragmentPos() <= Delay) pCutoffEvent = pCutoffEventList->next();  
             }  
             float cutoff;  
             while (pCutoffEvent) {  
                 Event* pNextCutoffEvent = pCutoffEventList->next();  
   
                 // calculate the influence length of this event (in sample points)  
                 uint end = (pNextCutoffEvent) ? pNextCutoffEvent->FragmentPos() : Samples;  
   
                 cutoff = exp((float) pCutoffEvent->Value * 0.00787402f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX - FILTER_CUTOFF_MIN;  
   
                 // apply cutoff frequency to the cutoff parameter sequence  
                 for (uint i = pCutoffEvent->FragmentPos(); i < end; i++) {  
                     pEngine->pSynthesisParameters[Event::destination_vcfc][i] = cutoff;  
                 }  
253    
254                  pCutoffEvent = pNextCutoffEvent;      Voice::EGInfo Voice::CalculateEG1ControllerInfluence(double eg1ControllerValue) {
255              }          EGInfo eg;
256              if (pCutoffEventList->last()) VCFCutoffCtrl.fvalue = cutoff; // needed for initialization of parameter matrix next time          // (eg1attack is different from the others)
257            if (pRegion->EG1Attack < 1e-8 && // attack in gig == 0
258                (pRegion->EG1ControllerAttackInfluence == 0 ||
259                 eg1ControllerValue <= 10)) { // strange GSt special case
260                eg.Attack = 0; // this will force the attack to be 0 in the call to EG1.trigger
261            } else {
262                eg.Attack  = (pRegion->EG1ControllerAttackInfluence)  ?
263                    1 + 0.031 * (double) (pRegion->EG1ControllerAttackInfluence == 1 ?
264                                          1 : 1 << pRegion->EG1ControllerAttackInfluence) * eg1ControllerValue : 1.0;
265            }
266            eg.Decay   = (pRegion->EG1ControllerDecayInfluence)   ? 1 + 0.00775 * (double) (1 << pRegion->EG1ControllerDecayInfluence)   * eg1ControllerValue : 1.0;
267            eg.Release = (pRegion->EG1ControllerReleaseInfluence) ? 1 + 0.00775 * (double) (1 << pRegion->EG1ControllerReleaseInfluence) * eg1ControllerValue : 1.0;
268    
269            return eg;
270        }
271    
272        double Voice::GetEG2ControllerValue(uint8_t MIDIKeyVelocity) {
273            double eg2controllervalue = 0;
274            switch (pRegion->EG2Controller.type) {
275                case ::gig::eg2_ctrl_t::type_none: // no controller defined
276                    eg2controllervalue = 0;
277                    break;
278                case ::gig::eg2_ctrl_t::type_channelaftertouch:
279                    eg2controllervalue = GetGigEngineChannel()->ControllerTable[128];
280                    break;
281                case ::gig::eg2_ctrl_t::type_velocity:
282                    eg2controllervalue = MIDIKeyVelocity;
283                    break;
284                case ::gig::eg2_ctrl_t::type_controlchange: // MIDI control change controller
285                    eg2controllervalue = GetGigEngineChannel()->ControllerTable[pRegion->EG2Controller.controller_number];
286                    break;
287          }          }
288            if (pRegion->EG2ControllerInvert) eg2controllervalue = 127 - eg2controllervalue;
289    
290          // process filter resonance events          return eg2controllervalue;
291          {      }
             RTEList<Event>* pResonanceEventList = pEngine->pSynthesisEvents[Event::destination_vcfr];  
             Event* pResonanceEvent = pResonanceEventList->first();  
             if (Delay) { // skip events that happened before this voice was triggered  
                 while (pResonanceEvent && pResonanceEvent->FragmentPos() <= Delay) pResonanceEvent = pResonanceEventList->next();  
             }  
             while (pResonanceEvent) {  
                 Event* pNextResonanceEvent = pResonanceEventList->next();  
   
                 // calculate the influence length of this event (in sample points)  
                 uint end = (pNextResonanceEvent) ? pNextResonanceEvent->FragmentPos() : Samples;  
   
                 // convert absolute controller value to differential  
                 int ctrldelta = pResonanceEvent->Value - VCFResonanceCtrl.value;  
                 VCFResonanceCtrl.value = pResonanceEvent->Value;  
   
                 float resonancedelta = (float) ctrldelta * 0.00787f; // 0.0..1.0  
292    
293                  // apply cutoff frequency to the cutoff parameter sequence      Voice::EGInfo Voice::CalculateEG2ControllerInfluence(double eg2ControllerValue) {
294                  for (uint i = pResonanceEvent->FragmentPos(); i < end; i++) {          EGInfo eg;
295                      pEngine->pSynthesisParameters[Event::destination_vcfr][i] += resonancedelta;          eg.Attack  = (pRegion->EG2ControllerAttackInfluence)  ? 1 + 0.00775 * (double) (1 << pRegion->EG2ControllerAttackInfluence)  * eg2ControllerValue : 1.0;
296                  }          eg.Decay   = (pRegion->EG2ControllerDecayInfluence)   ? 1 + 0.00775 * (double) (1 << pRegion->EG2ControllerDecayInfluence)   * eg2ControllerValue : 1.0;
297            eg.Release = (pRegion->EG2ControllerReleaseInfluence) ? 1 + 0.00775 * (double) (1 << pRegion->EG2ControllerReleaseInfluence) * eg2ControllerValue : 1.0;
298    
299                  pResonanceEvent = pNextResonanceEvent;          return eg;
             }  
             if (pResonanceEventList->last()) VCFResonanceCtrl.fvalue = pResonanceEventList->last()->Value * 0.00787f; // needed for initialization of parameter matrix next time  
         }  
     #endif // ENABLE_FILTER  
300      }      }
301    
302      #if ENABLE_FILTER      void Voice::InitLFO1() {
303      /**          uint16_t lfo1_internal_depth;
304       * Calculate all necessary, final biquad filter parameters.          switch (pRegion->LFO1Controller) {
305       *              case ::gig::lfo1_ctrl_internal:
306       * @param Samples - number of samples to be rendered in this audio fragment cycle                  lfo1_internal_depth  = pRegion->LFO1InternalDepth;
307       */                  pLFO1->ExtController = 0; // no external controller
308      void Voice::CalculateBiquadParameters(uint Samples) {                  bLFO1Enabled         = (lfo1_internal_depth > 0);
309          if (!FilterLeft.Enabled) return;                  break;
310                case ::gig::lfo1_ctrl_modwheel:
311          biquad_param_t bqbase;                  lfo1_internal_depth  = 0;
312          biquad_param_t bqmain;                  pLFO1->ExtController = 1; // MIDI controller 1
313          float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0];                  bLFO1Enabled         = (pRegion->LFO1ControlDepth > 0);
314          float prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][0];                  break;
315          FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);              case ::gig::lfo1_ctrl_breath:
316          pEngine->pBasicFilterParameters[0] = bqbase;                  lfo1_internal_depth  = 0;
317          pEngine->pMainFilterParameters[0]  = bqmain;                  pLFO1->ExtController = 2; // MIDI controller 2
318                    bLFO1Enabled         = (pRegion->LFO1ControlDepth > 0);
319          float* bq;                  break;
320          for (int i = 1; i < Samples; i++) {              case ::gig::lfo1_ctrl_internal_modwheel:
321              // recalculate biquad parameters if cutoff or resonance differ from previous sample point                  lfo1_internal_depth  = pRegion->LFO1InternalDepth;
322              if (!(i & FILTER_UPDATE_MASK)) if (pEngine->pSynthesisParameters[Event::destination_vcfr][i] != prev_res ||                  pLFO1->ExtController = 1; // MIDI controller 1
323                                                 pEngine->pSynthesisParameters[Event::destination_vcfc][i] != prev_cutoff) {                  bLFO1Enabled         = (lfo1_internal_depth > 0 || pRegion->LFO1ControlDepth > 0);
324                  prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][i];                  break;
325                  prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][i];              case ::gig::lfo1_ctrl_internal_breath:
326                  FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);                  lfo1_internal_depth  = pRegion->LFO1InternalDepth;
327              }                  pLFO1->ExtController = 2; // MIDI controller 2
328                    bLFO1Enabled         = (lfo1_internal_depth > 0 || pRegion->LFO1ControlDepth > 0);
329              //same as 'pEngine->pBasicFilterParameters[i] = bqbase;'                  break;
330              bq    = (float*) &pEngine->pBasicFilterParameters[i];              default:
331              bq[0] = bqbase.a1;                  lfo1_internal_depth  = 0;
332              bq[1] = bqbase.a2;                  pLFO1->ExtController = 0; // no external controller
333              bq[2] = bqbase.b0;                  bLFO1Enabled         = false;
334              bq[3] = bqbase.b1;          }
335              bq[4] = bqbase.b2;          if (bLFO1Enabled) {
336                pLFO1->trigger(fromGigLfoWave(pRegion->LFO1WaveForm),
337              // same as 'pEngine->pMainFilterParameters[i] = bqmain;'                             pRegion->LFO1Frequency,
338              bq    = (float*) &pEngine->pMainFilterParameters[i];                             pRegion->LFO1Phase,
339              bq[0] = bqmain.a1;                             LFO::start_level_mid, // see https://sourceforge.net/p/linuxsampler/mailman/linuxsampler-devel/thread/2189307.cNP0Xbctxq%40silver/#msg36774029
340              bq[1] = bqmain.a2;                             lfo1_internal_depth,
341              bq[2] = bqmain.b0;                             pRegion->LFO1ControlDepth,
342              bq[3] = bqmain.b1;                             pRegion->LFO1FlipPhase,
343              bq[4] = bqmain.b2;                             pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
344                pLFO1->updateByMIDICtrlValue(pLFO1->ExtController ? GetGigEngineChannel()->ControllerTable[pLFO1->ExtController] : 0);
345                pLFO1->setScriptDepthFactor(
346                    pNote->Override.AmpLFODepth.Value,
347                    pNote->Override.AmpLFODepth.Final
348                );
349                if (pNote->Override.AmpLFOFreq.isFinal())
350                    pLFO1->setScriptFrequencyFinal(
351                        pNote->Override.AmpLFOFreq.Value, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE
352                    );
353                else
354                    pLFO1->setScriptFrequencyFactor(
355                        pNote->Override.AmpLFOFreq.Value, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE
356                    );
357          }          }
358      }      }
     #endif // ENABLE_FILTER  
359    
360      /**      void Voice::InitLFO2() {
361       *  Interpolates the input audio data (without looping).          uint16_t lfo2_internal_depth;
362       *          switch (pRegion->LFO2Controller) {
363       *  @param Samples - number of sample points to be rendered in this audio              case ::gig::lfo2_ctrl_internal:
364       *                   fragment cycle                  lfo2_internal_depth  = pRegion->LFO2InternalDepth;
365       *  @param pSrc    - pointer to input sample data                  pLFO2->ExtController = 0; // no external controller
366       *  @param Skip    - number of sample points to skip in output buffer                  bLFO2Enabled         = (lfo2_internal_depth > 0);
367       */                  break;
368      void Voice::InterpolateNoLoop(uint Samples, sample_t* pSrc, uint Skip) {              case ::gig::lfo2_ctrl_modwheel:
369          int i = Skip;                  lfo2_internal_depth  = 0;
370                    pLFO2->ExtController = 1; // MIDI controller 1
371          // FIXME: assuming either mono or stereo                  bLFO2Enabled         = (pRegion->LFO2ControlDepth > 0);
372          if (this->pSample->Channels == 2) { // Stereo Sample                  break;
373              while (i < Samples) InterpolateStereo(pSrc, i);              case ::gig::lfo2_ctrl_foot:
374          }                  lfo2_internal_depth  = 0;
375          else { // Mono Sample                  pLFO2->ExtController = 4; // MIDI controller 4
376              while (i < Samples) InterpolateMono(pSrc, i);                  bLFO2Enabled         = (pRegion->LFO2ControlDepth > 0);
377                    break;
378                case ::gig::lfo2_ctrl_internal_modwheel:
379                    lfo2_internal_depth  = pRegion->LFO2InternalDepth;
380                    pLFO2->ExtController = 1; // MIDI controller 1
381                    bLFO2Enabled         = (lfo2_internal_depth > 0 || pRegion->LFO2ControlDepth > 0);
382                    break;
383                case ::gig::lfo2_ctrl_internal_foot:
384                    lfo2_internal_depth  = pRegion->LFO2InternalDepth;
385                    pLFO2->ExtController = 4; // MIDI controller 4
386                    bLFO2Enabled         = (lfo2_internal_depth > 0 || pRegion->LFO2ControlDepth > 0);
387                    break;
388                default:
389                    lfo2_internal_depth  = 0;
390                    pLFO2->ExtController = 0; // no external controller
391                    bLFO2Enabled         = false;
392            }
393            if (bLFO2Enabled) {
394                pLFO2->trigger(fromGigLfoWave(pRegion->LFO2WaveForm),
395                               pRegion->LFO2Frequency,
396                               pRegion->LFO2Phase,
397                               LFO::start_level_mid, // see https://sourceforge.net/p/linuxsampler/mailman/linuxsampler-devel/thread/2189307.cNP0Xbctxq%40silver/#msg36774029
398                               lfo2_internal_depth,
399                               pRegion->LFO2ControlDepth,
400                               pRegion->LFO2FlipPhase,
401                               pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
402                pLFO2->updateByMIDICtrlValue(pLFO2->ExtController ? GetGigEngineChannel()->ControllerTable[pLFO2->ExtController] : 0);
403                pLFO2->setScriptDepthFactor(
404                    pNote->Override.CutoffLFODepth.Value,
405                    pNote->Override.CutoffLFODepth.Final
406                );
407                if (pNote->Override.CutoffLFOFreq.isFinal())
408                    pLFO2->setScriptFrequencyFinal(pNote->Override.CutoffLFOFreq.Value, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
409                else
410                    pLFO2->setScriptFrequencyFactor(pNote->Override.CutoffLFOFreq.Value, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
411          }          }
412      }      }
413    
414      /**      void Voice::InitLFO3() {
415       *  Interpolates the input audio data, this method honors looping.          uint16_t lfo3_internal_depth;
416       *          switch (pRegion->LFO3Controller) {
417       *  @param Samples - number of sample points to be rendered in this audio              case ::gig::lfo3_ctrl_internal:
418       *                   fragment cycle                  lfo3_internal_depth  = pRegion->LFO3InternalDepth;
419       *  @param pSrc    - pointer to input sample data                  pLFO3->ExtController = 0; // no external controller
420       *  @param Skip    - number of sample points to skip in output buffer                  bLFO3Enabled         = (lfo3_internal_depth > 0);
421       */                  break;
422      void Voice::InterpolateAndLoop(uint Samples, sample_t* pSrc, uint Skip) {              case ::gig::lfo3_ctrl_modwheel:
423          int i = Skip;                  lfo3_internal_depth  = 0;
424                    pLFO3->ExtController = 1; // MIDI controller 1
425          // FIXME: assuming either mono or stereo                  bLFO3Enabled         = (pRegion->LFO3ControlDepth > 0);
426          if (pSample->Channels == 2) { // Stereo Sample                  break;
427              if (pSample->LoopPlayCount) {              case ::gig::lfo3_ctrl_aftertouch:
428                  // render loop (loop count limited)                  lfo3_internal_depth  = 0;
429                  while (i < Samples && LoopCyclesLeft) {                  pLFO3->ExtController = CTRL_TABLE_IDX_AFTERTOUCH;
430                      InterpolateStereo(pSrc, i);                  bLFO3Enabled         = true;
431                      if (Pos > pSample->LoopEnd) {                  break;
432                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;              case ::gig::lfo3_ctrl_internal_modwheel:
433                          LoopCyclesLeft--;                  lfo3_internal_depth  = pRegion->LFO3InternalDepth;
434                      }                  pLFO3->ExtController = 1; // MIDI controller 1
435                  }                  bLFO3Enabled         = (lfo3_internal_depth > 0 || pRegion->LFO3ControlDepth > 0);
436                  // render on without loop                  break;
437                  while (i < Samples) InterpolateStereo(pSrc, i);              case ::gig::lfo3_ctrl_internal_aftertouch:
438              }                  lfo3_internal_depth  = pRegion->LFO3InternalDepth;
439              else { // render loop (endless loop)                  pLFO3->ExtController = CTRL_TABLE_IDX_AFTERTOUCH;
440                  while (i < Samples) {                  bLFO3Enabled         = (lfo3_internal_depth > 0 || pRegion->LFO3ControlDepth > 0);
441                      InterpolateStereo(pSrc, i);                  break;
442                      if (Pos > pSample->LoopEnd) {              default:
443                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);                  lfo3_internal_depth  = 0;
444                      }                  pLFO3->ExtController = 0; // no external controller
445                  }                  bLFO3Enabled         = false;
446              }          }
447          }          if (bLFO3Enabled) {
448          else { // Mono Sample              pLFO3->trigger(fromGigLfoWave(pRegion->LFO3WaveForm),
449              if (pSample->LoopPlayCount) {                             pRegion->LFO3Frequency,
450                  // render loop (loop count limited)                             pRegion->LFO3Phase,
451                  while (i < Samples && LoopCyclesLeft) {                             LFO::start_level_max, // see https://sourceforge.net/p/linuxsampler/mailman/linuxsampler-devel/thread/2189307.cNP0Xbctxq%40silver/#msg36774029
452                      InterpolateMono(pSrc, i);                             lfo3_internal_depth,
453                      if (Pos > pSample->LoopEnd) {                             pRegion->LFO3ControlDepth,
454                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;                             pRegion->LFO3FlipPhase,
455                          LoopCyclesLeft--;                             pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
456                      }              pLFO3->updateByMIDICtrlValue(pLFO3->ExtController ? GetGigEngineChannel()->ControllerTable[pLFO3->ExtController] : 0);
457                  }              pLFO3->setScriptDepthFactor(
458                  // render on without loop                  pNote->Override.PitchLFODepth.Value,
459                  while (i < Samples) InterpolateMono(pSrc, i);                  pNote->Override.PitchLFODepth.Final
460              }              );
461              else { // render loop (endless loop)              if (pNote->Override.PitchLFOFreq.isFinal())
462                  while (i < Samples) {                  pLFO3->setScriptFrequencyFinal(pNote->Override.PitchLFOFreq.Value, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
463                      InterpolateMono(pSrc, i);              else
464                      if (Pos > pSample->LoopEnd) {                  pLFO3->setScriptFrequencyFactor(pNote->Override.PitchLFOFreq.Value, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
465                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;          }
466                      }      }
467                  }  
468              }      float Voice::CalculateCutoffBase(uint8_t MIDIKeyVelocity) {
469            float cutoff = pRegion->GetVelocityCutoff(MIDIKeyVelocity);
470            if (pRegion->VCFKeyboardTracking) {
471                cutoff *= RTMath::CentsToFreqRatioUnlimited((MIDIKey() - pRegion->VCFKeyboardTrackingBreakpoint) * 100);
472            }
473            return cutoff;
474        }
475    
476        // This is just called when the voice is triggered. On any subsequent cutoff
477        // controller changes ProcessCutoffEvent() is called instead.
478        float Voice::CalculateFinalCutoff(float cutoffBase) {
479            // if the selected filter type is an official GigaStudio filter type
480            // then we preserve the original (no matter how odd) historical GSt
481            // behaviour identically; for our own filter types though we deviate to
482            // more meaningful behaviours where appropriate
483            const bool isGStFilter = isGStFilterType(pRegion->VCFType);
484    
485            // get current cutoff CC or velocity value (always 0..127)
486            float cvalue;
487            if (VCFCutoffCtrl.controller) {
488                cvalue = GetGigEngineChannel()->ControllerTable[VCFCutoffCtrl.controller];
489                if (pRegion->VCFCutoffControllerInvert) cvalue = 127 - cvalue;
490                if (isGStFilter) {
491                    // VCFVelocityScale in this case means "minimum cutoff" for GSt
492                    if (cvalue < MinCutoff()) cvalue = MinCutoff();
493                } else {
494                    // for our own filter types we interpret "minimum cutoff"
495                    // differently: GSt handles this as a simple hard limit with the
496                    // consequence that a certain range of the controller is simply
497                    // dead; so for our filter types we rather remap that to
498                    // restrain within the min_cutoff..127 range as well, but
499                    // effectively spanned over the entire controller range (0..127)
500                    // to avoid such a "dead" lower controller zone
501                    cvalue = MinCutoff() + (cvalue / 127.f) * float(127 - MinCutoff());
502                }
503            } else {
504                // in case of velocity, VCFVelocityScale parameter is already
505                // handled on libgig side (so by calling
506                // pRegion->GetVelocityCutoff(velo) in CalculateCutoffBase() above)
507                cvalue = pRegion->VCFCutoff;
508            }
509    
510            float fco = cutoffBase * cvalue;
511            if (fco > 127.0f) fco = 127.0f;
512    
513            // the filter implementations of the original GSt filter types take an
514            // abstract cutoff parameter range of 0..127, ...
515            if (isGStFilter)
516                return fco;
517    
518            // ... whereas our own filter types take a cutoff parameter in Hz, so
519            // remap here 0 .. 127 [lin] -> 21 Hz .. 18 kHz [x^4] (center @2.2 kHz)
520            fco = (fco + 29.f) / (127.f + 29.f);
521            fco = fco * fco * fco * fco * 18000.f;
522            if (fco > 0.49f * pEngine->SampleRate)
523                fco = 0.49f * pEngine->SampleRate;
524            return fco;
525        }
526    
527        uint8_t Voice::GetVCFCutoffCtrl() {
528            uint8_t ctrl;
529            switch (pRegion->VCFCutoffController) {
530                case ::gig::vcf_cutoff_ctrl_modwheel:
531                    ctrl = 1;
532                    break;
533                case ::gig::vcf_cutoff_ctrl_effect1:
534                    ctrl = 12;
535                    break;
536                case ::gig::vcf_cutoff_ctrl_effect2:
537                    ctrl = 13;
538                    break;
539                case ::gig::vcf_cutoff_ctrl_breath:
540                    ctrl = 2;
541                    break;
542                case ::gig::vcf_cutoff_ctrl_foot:
543                    ctrl = 4;
544                    break;
545                case ::gig::vcf_cutoff_ctrl_sustainpedal:
546                    ctrl = 64;
547                    break;
548                case ::gig::vcf_cutoff_ctrl_softpedal:
549                    ctrl = 67;
550                    break;
551                case ::gig::vcf_cutoff_ctrl_genpurpose7:
552                    ctrl = 82;
553                    break;
554                case ::gig::vcf_cutoff_ctrl_genpurpose8:
555                    ctrl = 83;
556                    break;
557                case ::gig::vcf_cutoff_ctrl_aftertouch:
558                    ctrl = CTRL_TABLE_IDX_AFTERTOUCH;
559                    break;
560                case ::gig::vcf_cutoff_ctrl_none:
561                default:
562                    ctrl = 0;
563                    break;
564          }          }
565    
566            return ctrl;
567      }      }
568    
569      /**      uint8_t Voice::GetVCFResonanceCtrl() {
570       *  Immediately kill the voice. This method should not be used to kill          uint8_t ctrl;
571       *  a normal, active voice, because it doesn't take care of things like          switch (pRegion->VCFResonanceController) {
572       *  fading down the volume level to avoid clicks and regular processing              case ::gig::vcf_res_ctrl_genpurpose3:
573       *  until the kill event actually occured!                  ctrl = 18;
574       *                  break;
575       *  @see Kill()              case ::gig::vcf_res_ctrl_genpurpose4:
576       */                  ctrl = 19;
577      void Voice::KillImmediately() {                  break;
578          if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {              case ::gig::vcf_res_ctrl_genpurpose5:
579              pDiskThread->OrderDeletionOfStream(&DiskStreamRef);                  ctrl = 80;
580                    break;
581                case ::gig::vcf_res_ctrl_genpurpose6:
582                    ctrl = 81;
583                    break;
584                case ::gig::vcf_res_ctrl_none:
585                default:
586                    ctrl = 0;
587          }          }
588          Reset();  
589            return ctrl;
590      }      }
591    
592      /**      void Voice::TriggerEG1(const EGInfo& egInfo, double velrelease, double velocityAttenuation, uint sampleRate, uint8_t velocity) {
593       *  Kill the voice in regular sense. Let the voice render audio until          EG1.setStateOptions(
594       *  the kill event actually occured and then fade down the volume level              pRegion->EG1Options.AttackCancel,
595       *  very quickly and let the voice die finally. Unlike a normal release              pRegion->EG1Options.AttackHoldCancel,
596       *  of a voice, a kill process cannot be cancalled and is therefore              pRegion->EG1Options.Decay1Cancel,
597       *  usually used for voice stealing and key group conflicts.              pRegion->EG1Options.Decay2Cancel,
598       *              pRegion->EG1Options.ReleaseCancel
599       *  @param pKillEvent - event which caused the voice to be killed          );
600       */          EG1.trigger(pRegion->EG1PreAttack,
601      void Voice::Kill(Event* pKillEvent) {                      (pNote && pNote->Override.Attack.isFinal()) ?
602          if (pTriggerEvent && pKillEvent->FragmentPos() <= pTriggerEvent->FragmentPos()) return;                          pNote->Override.Attack.Value :
603          this->pKillEvent = pKillEvent;                          RTMath::Max(pRegion->EG1Attack, 0.0316) * egInfo.Attack,
604                        pRegion->EG1Hold,
605                        (pNote && pNote->Override.Decay.isFinal()) ?
606                            pNote->Override.Decay.Value :
607                            pRegion->EG1Decay1 * egInfo.Decay * velrelease,
608                        (pNote && pNote->Override.Decay.isFinal()) ?
609                            pNote->Override.Decay.Value :
610                            pRegion->EG1Decay2 * egInfo.Decay * velrelease,
611                        pRegion->EG1InfiniteSustain,
612                        (pNote && pNote->Override.Sustain.Final) ?
613                            uint(pNote->Override.Sustain.Value * 1000.f) :
614                            pRegion->EG1Sustain * (pNote ? pNote->Override.Sustain.Value : 1.f),
615                        (pNote && pNote->Override.Release.isFinal()) ?
616                            pNote->Override.Release.Value :
617                            RTMath::Max(pRegion->EG1Release * velrelease, 0.014) * egInfo.Release,
618                        velocityAttenuation,
619                        sampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
620        }
621    
622        void Voice::TriggerEG2(const EGInfo& egInfo, double velrelease, double velocityAttenuation, uint sampleRate, uint8_t velocity) {
623            EG2.setStateOptions(
624                pRegion->EG2Options.AttackCancel,
625                pRegion->EG2Options.AttackHoldCancel,
626                pRegion->EG2Options.Decay1Cancel,
627                pRegion->EG2Options.Decay2Cancel,
628                pRegion->EG2Options.ReleaseCancel
629            );
630            EG2.trigger(uint(RgnInfo.EG2PreAttack),
631                        (pNote && pNote->Override.CutoffAttack.isFinal()) ?
632                            pNote->Override.CutoffAttack.Value :
633                            RgnInfo.EG2Attack * egInfo.Attack,
634                        false,
635                        (pNote && pNote->Override.CutoffDecay.isFinal()) ?
636                            pNote->Override.CutoffDecay.Value :
637                            RgnInfo.EG2Decay1 * egInfo.Decay * velrelease,
638                        (pNote && pNote->Override.CutoffDecay.isFinal()) ?
639                            pNote->Override.CutoffDecay.Value :
640                            RgnInfo.EG2Decay2 * egInfo.Decay * velrelease,
641                        RgnInfo.EG2InfiniteSustain,
642                        (pNote && pNote->Override.CutoffSustain.Final) ?
643                            uint(pNote->Override.CutoffSustain.Value * 1000.f) :
644                            uint(RgnInfo.EG2Sustain),
645                        (pNote && pNote->Override.CutoffRelease.isFinal()) ?
646                            pNote->Override.CutoffRelease.Value :
647                            RgnInfo.EG2Release * egInfo.Release * velrelease,
648                        velocityAttenuation,
649                        sampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
650        }
651    
652        void Voice::ProcessGroupEvent(RTList<Event>::Iterator& itEvent) {
653            dmsg(4,("Voice %p processGroupEvents event type=%d", (void*)this, itEvent->Type));
654    
655            // TODO: The SustainPedal condition could be wrong, maybe the
656            // check should be if this Voice is in release stage or is a
657            // release sample instead. Need to test this in GSt.
658            // -- Andreas
659            //
660            // Commented sustain pedal check out. I don't think voices of the same
661            // note should be stopped at all, because it doesn't sound naturally
662            // with a drumkit.
663            // -- Christian, 2013-01-08
664            if (itEvent->Param.Note.Key != HostKey() /*||
665                !GetGigEngineChannel()->SustainPedal*/) {
666                dmsg(4,("Voice %p - kill", (void*)this));
667    
668                // kill the voice fast
669                pEG1->enterFadeOutStage();
670            }
671        }
672    
673        void Voice::CalculateFadeOutCoeff(float FadeOutTime, float SampleRate) {
674            EG1.CalculateFadeOutCoeff(FadeOutTime, SampleRate);
675        }
676    
677        int Voice::CalculatePan(uint8_t pan) {
678            int p;
679            // Gst behaviour: -64 and 63 are special cases
680            if (RgnInfo.Pan == -64)     p = pan * 2 - 127;
681            else if (RgnInfo.Pan == 63) p = pan * 2;
682            else                        p = pan + RgnInfo.Pan;
683    
684            if (p < 0) return 0;
685            if (p > 127) return 127;
686            return p;
687        }
688    
689        release_trigger_t Voice::GetReleaseTriggerFlags() {
690            release_trigger_t flags =
691                (pRegion->NoNoteOffReleaseTrigger) ?
692                    release_trigger_none : release_trigger_noteoff; //HACK: currently this method is actually only called by EngineBase if it already knows that this voice requires release trigger, so I took the short way instead of checking (again) the existence of a ::gig::dimension_releasetrigger
693            switch (pRegion->SustainReleaseTrigger) {
694                case ::gig::sust_rel_trg_none:
695                    break;
696                case ::gig::sust_rel_trg_maxvelocity:
697                    flags |= release_trigger_sustain_maxvelocity;
698                    break;
699                case ::gig::sust_rel_trg_keyvelocity:
700                    flags |= release_trigger_sustain_keyvelocity;
701                    break;
702            }
703            return flags;
704      }      }
705    
706  }} // namespace LinuxSampler::gig  }} // namespace LinuxSampler::gig

Legend:
Removed from v.245  
changed lines
  Added in v.3721

  ViewVC Help
Powered by ViewVC