/[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 56 by schoenebeck, Tue Apr 27 09:21:58 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      // FIXME: no support for layers (nor crossfades) yet      // sanity checks: fromGigLfoWave() assumes equally mapped enums
37        static_assert(int64_t(::gig::lfo_wave_sine) == int64_t(LFO::wave_sine),
38      const float Voice::FILTER_CUTOFF_COEFF(CalculateFilterCutoffCoeff());                    "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                      "enum LFO::wave_t not equally value mapped to libgig's enum ::gig::lfo_wave_t");
45    
46        // converts ::gig::lfo_wave_t (libgig) -> LFO::wave_t (LinuxSampler)
47        inline LFO::wave_t fromGigLfoWave(::gig::lfo_wave_t wave) {
48            // 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;  
67      }      }
68    
69      Voice::~Voice() {      Voice::~Voice() {
70          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::SetOutput(AudioOutputDevice* pAudioOutputDevice) {  
         this->pOutputLeft        = pAudioOutputDevice->Channel(0)->Buffer();  
         this->pOutputRight       = pAudioOutputDevice->Channel(1)->Buffer();  
         this->MaxSamplesPerCycle = pAudioOutputDevice->MaxSamplesPerCycle();  
         this->SampleRate         = pAudioOutputDevice->SampleRate();  
     }  
   
     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(1,("Voice::SetEngine()\n"));  
     }  
   
     /**  
      *  Initializes and triggers the voice, a disk stream will be launched if  
      *  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  
      *  @returns            0 on success, a value < 0 if something failed  
      */  
     int Voice::Trigger(Event* pNoteOnEvent, int PitchBend, ::gig::Instrument* pInstrument) {  
         if (!pInstrument) {  
            dmsg(1,("voice::trigger: !pInstrument\n"));  
            exit(EXIT_FAILURE);  
         }  
   
         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  
         Pos             = 0;  
         Delay           = pNoteOnEvent->FragmentPos();  
         pTriggerEvent   = pNoteOnEvent;  
   
         if (!pRegion) {  
             std::cerr << "Audio Thread: No Region defined for MIDI key " << MIDIKey << std::endl << std::flush;  
             Kill();  
             return -1;  
         }  
   
         //TODO: current MIDI controller values are not taken into account yet  
         ::gig::DimensionRegion* pDimRgn = NULL;  
         for (int i = pRegion->Dimensions - 1; i >= 0; i--) { // Check if instrument has a velocity split  
             if (pRegion->pDimensionDefinitions[i].dimension == ::gig::dimension_velocity) {  
                 uint DimValues[5] = {0,0,0,0,0};  
                     DimValues[i] = pNoteOnEvent->Velocity;  
                 pDimRgn = pRegion->GetDimensionRegionByValue(DimValues[4],DimValues[3],DimValues[2],DimValues[1],DimValues[0]);  
                 break;  
             }  
         }  
         if (!pDimRgn) { // if there was no velocity split  
             pDimRgn = pRegion->GetDimensionRegionByValue(0,0,0,0,0);  
         }  
   
         pSample = pDimRgn->pSample; // sample won't change until the voice is finished  
71    
72          // Check if the sample needs disk streaming or is too short for that      EngineChannel* Voice::GetGigEngineChannel() {
73          long cachedsamples = pSample->GetCache().Size / pSample->FrameSize;          return static_cast<EngineChannel*>(pEngineChannel);
74          DiskVoice          = cachedsamples < pSample->SamplesTotal;      }
75    
76          if (DiskVoice) { // voice to be streamed from disk      void Voice::SetEngine(LinuxSampler::Engine* pEngine) {
77              MaxRAMPos = cachedsamples - (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)          Engine* engine = static_cast<Engine*>(pEngine);
78            this->pEngine     = engine;
79            this->pDiskThread = engine->pDiskThread;
80            dmsg(6,("Voice::SetEngine()\n"));
81        }
82    
83              // check if there's a loop defined which completely fits into the cached (RAM) part of the sample      Voice::SampleInfo Voice::GetSampleInfo() {
84              if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) {          SampleInfo si;
85                  RAMLoop        = true;          si.SampleRate       = pSample->SamplesPerSecond;
86                  LoopCyclesLeft = pSample->LoopPlayCount;          si.ChannelCount     = pSample->Channels;
87              }          si.FrameSize        = pSample->FrameSize;
88              else RAMLoop = false;          si.BitDepth         = pSample->BitDepth;
89            si.TotalFrameCount  = (uint)pSample->SamplesTotal;
90    
91              if (pDiskThread->OrderNewStream(&DiskStreamRef, pSample, MaxRAMPos, !RAMLoop) < 0) {          si.HasLoops       = pRegion->SampleLoops;
92                  dmsg(1,("Disk stream order failed!\n"));          si.LoopStart      = (si.HasLoops) ? pRegion->pSampleLoops[0].LoopStart  : 0;
93                  Kill();          si.LoopLength     = (si.HasLoops) ? pRegion->pSampleLoops[0].LoopLength : 0;
94                  return -1;          si.LoopPlayCount  = pSample->LoopPlayCount;
95              }          si.Unpitched      = !pRegion->PitchTrack;
             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"));  
         }  
96    
97            return si;
98        }
99    
100          // calculate initial pitch value      Voice::RegionInfo Voice::GetRegionInfo() {
101          {          RegionInfo ri;
102              double pitchbasecents = pDimRgn->FineTune * 10;          ri.UnityNote = pRegion->UnityNote;
103              if (pDimRgn->PitchTrack) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;          ri.FineTune  = pRegion->FineTune;
104              this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents);          ri.Pan       = pRegion->Pan;
105              this->PitchBend = RTMath::CentsToFreqRatio(((double) PitchBend / 8192.0) * 200.0); // pitchbend wheel +-2 semitones = 200 cents          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          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)          ri.EG3Attack     = pRegion->EG3Attack;
116            ri.EG3Depth      = pRegion->EG3Depth;
117            ri.VCFEnabled    = pRegion->VCFEnabled;
118          // setup EG 1 (VCA EG)          ri.VCFType       = Filter::vcf_type_t(pRegion->VCFType);
119          {          ri.VCFResonance  = pRegion->VCFResonance;
             // get current value of EG1 controller  
             double eg1controllervalue;  
             switch (pDimRgn->EG1Controller.type) {  
                 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  
   
   
         // setup EG 3 (VCO EG)  
         {  
           double eg3depth = RTMath::CentsToFreqRatio(pDimRgn->EG3Depth);  
           pEG3->Trigger(eg3depth, pDimRgn->EG3Attack, Delay);  
         }  
133    
134        double Voice::GetSampleAttenuation() {
135            return pRegion->SampleAttenuation;
136        }
137    
138          // setup LFO 1 (VCA LFO)      double Voice::GetVelocityAttenuation(uint8_t MIDIKeyVelocity) {
139          {          return pRegion->GetVelocityAttenuation(MIDIKeyVelocity);
140              uint16_t lfo1_internal_depth;      }
             switch (pDimRgn->LFO1Controller) {  
                 case ::gig::lfo1_ctrl_internal:  
                     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  
             }  
             pLFO1->Trigger(pDimRgn->LFO1Frequency,  
                           lfo1_internal_depth,  
                           pDimRgn->LFO1ControlDepth,  
                           pEngine->ControllerTable[pLFO1->ExtController],  
                           pDimRgn->LFO1FlipPhase,  
                           this->SampleRate,  
                           Delay);  
         }  
   
     #if ENABLE_FILTER  
         // setup LFO 2 (VCF Cutoff LFO)  
         {  
             uint16_t lfo2_internal_depth;  
             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  
             }  
             pLFO2->Trigger(pDimRgn->LFO2Frequency,  
                           lfo2_internal_depth,  
                           pDimRgn->LFO2ControlDepth,  
                           pEngine->ControllerTable[pLFO2->ExtController],  
                           pDimRgn->LFO2FlipPhase,  
                           Delay);  
         }  
     #endif // ENABLE_FILTER  
   
         // setup LFO 3 (VCO LFO)  
         {  
             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,  
                           this->SampleRate,  
                           Delay);  
         }  
   
     #if ENABLE_FILTER  
         #if FORCE_FILTER_USAGE  
         FilterLeft.Enabled = FilterRight.Enabled = true;  
         #else // use filter only if instrument file told so  
         FilterLeft.Enabled = FilterRight.Enabled = pDimRgn->VCFEnabled;  
         #endif // FORCE_FILTER_USAGE  
         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  
141    
142              #ifdef OVERRIDE_FILTER_RES_CTRL      double Voice::GetVelocityRelease(uint8_t MIDIKeyVelocity) {
143              VCFResonanceCtrl.controller = OVERRIDE_FILTER_RES_CTRL;          return pRegion->GetVelocityRelease(MIDIKeyVelocity);
144              #else // use the one defined in the instrument file      }
             switch (pDimRgn->VCFResonanceController) {  
                 case ::gig::vcf_res_ctrl_genpurpose3:  
                     VCFResonanceCtrl.controller = 18;  
                     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  
145    
146              #ifndef OVERRIDE_FILTER_TYPE      void Voice::ProcessCCEvent(RTList<Event>::Iterator& itEvent) {
147              FilterLeft.SetType(pDimRgn->VCFType);          if (itEvent->Type == Event::type_control_change && itEvent->Param.CC.Controller) { // if (valid) MIDI control change event
148              FilterRight.SetType(pDimRgn->VCFType);              if (pRegion->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange &&
149              #else // override filter type                  itEvent->Param.CC.Controller == pRegion->AttenuationController.controller_number) {
150              FilterLeft.SetType(OVERRIDE_FILTER_TYPE);                  CrossfadeSmoother.update(AbstractEngine::CrossfadeCurve[CrossfadeAttenuation(itEvent->Param.CC.Value)]);
             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;  
151              }              }
152              Constrain(resonance, 0.0, 1.0); // correct resonance if outside allowed value range (0.0..1.0)          }
153        }
             VCFCutoffCtrl.fvalue    = cutoff - FILTER_CUTOFF_MIN;  
             VCFResonanceCtrl.fvalue = resonance;  
   
             FilterLeft.SetParameters(cutoff,  resonance, SampleRate);  
             FilterRight.SetParameters(cutoff, resonance, SampleRate);  
154    
155              FilterUpdateCounter = -1;      void Voice::ProcessChannelPressureEvent(RTList<Event>::Iterator& itEvent) {
156          }          if (itEvent->Type == Event::type_channel_pressure) { // if (valid) MIDI channel pressure (aftertouch) event
157          else {              if (pRegion->AttenuationController.type == ::gig::attenuation_ctrl_t::type_channelaftertouch) {
158              VCFCutoffCtrl.controller    = 0;                  CrossfadeSmoother.update(AbstractEngine::CrossfadeCurve[CrossfadeAttenuation(itEvent->Param.ChannelPressure.Value)]);
             VCFResonanceCtrl.controller = 0;  
         }  
     #endif // ENABLE_FILTER  
   
         // ************************************************  
         // TODO: ARTICULATION DATA HANDLING IS MISSING HERE  
         // ************************************************  
   
         return 0; // success  
     }  
   
     /**  
      *  Renders the audio data for this voice for the current audio fragment.  
      *  The sample input data can either come from RAM (cached sample or sample  
      *  part) or directly from disk. The output signal will be rendered by  
      *  resampling / interpolation. If this voice is a disk streaming voice and  
      *  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);  
         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);  
     #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);  
   
   
         switch (this->PlaybackState) {  
   
             case playback_state_ram: {  
                     if (RAMLoop) InterpolateAndLoop(Samples, (sample_t*) pSample->GetCache().pStart, Delay);  
                     else         Interpolate(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;  
                             Kill();  
                             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() < (MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels) {  
                         DiskStreamRef.pStream->WriteSilence((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  
                     Interpolate(Samples, ptr, Delay);  
                     DiskStreamRef.pStream->IncrementReadPos(RTMath::DoubleToInt(Pos) * pSample->Channels);  
                     Pos -= RTMath::DoubleToInt(Pos);  
                 }  
                 break;  
   
             case playback_state_end:  
                 Kill(); // free voice  
                 break;  
         }  
   
   
     #if ENABLE_FILTER  
         // Reset synthesis event lists (except VCO, as VCO events apply channel wide currently)  
         pEngine->pSynthesisEvents[Event::destination_vcfc]->clear();  
         pEngine->pSynthesisEvents[Event::destination_vcfr]->clear();  
     #endif // ENABLE_FILTER  
   
         // Reset delay  
         Delay = 0;  
   
         pTriggerEvent = NULL;  
   
         // If release stage finished, let the voice be killed  
         if (pEG1->GetStage() == EGADSR::stage_end) this->PlaybackState = playback_state_end;  
     }  
   
     /**  
      *  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);  
                 }  
159              }              }
   
             pCCEvent = pEngine->pCCEvents->next();  
160          }          }
161        }
162    
163        void Voice::ProcessPolyphonicKeyPressureEvent(RTList<Event>::Iterator& itEvent) {
164            // Not used so far
165        }
166    
167          // process pitch events      uint8_t Voice::MinCutoff() const {
168          {          // If there's a cutoff controller defined then VCFVelocityScale means
169              RTEList<Event>* pVCOEventList = pEngine->pSynthesisEvents[Event::destination_vco];          // "minimum cutoff". If there is no MIDI controller defined for cutoff
170              Event* pVCOEvent = pVCOEventList->first();          // then VCFVelocityScale is already taken into account on libgig side
171              if (Delay) { // skip events that happened before this voice was triggered          // instead by call to pRegion->GetVelocityCutoff(MIDIKeyVelocity).
172                  while (pVCOEvent && pVCOEvent->FragmentPos() <= Delay) pVCOEvent = pVCOEventList->next();          return pRegion->VCFVelocityScale;
173              }      }
             // 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();  
174    
175                  // calculate the influence length of this event (in sample points)      // This is called on any cutoff controller changes, however not when the
176                  uint end = (pNextVCOEvent) ? pNextVCOEvent->FragmentPos() : Samples;      // voice is triggered. So the initial cutoff value is retrieved by a call
177        // to CalculateFinalCutoff() instead.
178        void Voice::ProcessCutoffEvent(RTList<Event>::Iterator& itEvent) {
179            if (VCFCutoffCtrl.value == itEvent->Param.CC.Value) return;
180            float ccvalue = VCFCutoffCtrl.value = itEvent->Param.CC.Value;
181    
182                  pitch = RTMath::CentsToFreqRatio(((double) pVCOEvent->Pitch / 8192.0) * 200.0); // +-two semitones = +-200 cents          // if the selected filter type is an official GigaStudio filter type
183            // then we preserve the original (no matter how odd) historical GSt
184            // behaviour identically; for our own filter types though we deviate to
185            // more meaningful behaviours where appropriate
186            const bool isGStFilter = isGStFilterType(pRegion->VCFType);
187    
188                  // apply pitch value to the pitch parameter sequence          if (pRegion->VCFCutoffControllerInvert) ccvalue = 127 - ccvalue;
189                  for (uint i = pVCOEvent->FragmentPos(); i < end; i++) {          // interpret "minimum cutoff" not simply as hard limit, rather
190                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= pitch;          // 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                  pVCOEvent = pNextVCOEvent;          // the controller would not change the cutoff frequency)
194              }          ccvalue = MinCutoff() + (ccvalue / 127.f) * float(127 - MinCutoff());
             if (pVCOEventList->last()) this->PitchBend = pitch;  
         }  
195    
196            float cutoff = CutoffBase * ccvalue;
197            if (cutoff > 127.0f) cutoff = 127.0f;
198    
199      #if ENABLE_FILTER          // the filter implementations of the original GSt filter types take an
200          // process filter cutoff events          // abstract cutoff parameter range of 0..127, whereas our own filter
201          {          // types take a cutoff parameter in Hz, so remap here:
202              RTEList<Event>* pCutoffEventList = pEngine->pSynthesisEvents[Event::destination_vcfc];          // 0 .. 127 [lin] -> 21 Hz .. 18 kHz [x^4] (center @2.2 kHz)
203              Event* pCutoffEvent = pCutoffEventList->first();          if (!isGStFilter) {
204              if (Delay) { // skip events that happened before this voice was triggered              cutoff = (cutoff + 29.f) / (127.f + 29.f);
205                  while (pCutoffEvent && pCutoffEvent->FragmentPos() <= Delay) pCutoffEvent = pCutoffEventList->next();              cutoff = cutoff * cutoff * cutoff * cutoff * 18000.f;
206              }              if (cutoff > 0.49f * pEngine->SampleRate)
207              float cutoff;                  cutoff = 0.49f * pEngine->SampleRate;
208              while (pCutoffEvent) {          }
                 Event* pNextCutoffEvent = pCutoffEventList->next();  
209    
210                  // calculate the influence length of this event (in sample points)          fFinalCutoff = VCFCutoffCtrl.fvalue = cutoff;
211                  uint end = (pNextCutoffEvent) ? pNextCutoffEvent->FragmentPos() : Samples;      }
212    
213                  cutoff = exp((float) pCutoffEvent->Value * 0.00787402f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX - FILTER_CUTOFF_MIN;      double Voice::CalculateCrossfadeVolume(uint8_t MIDIKeyVelocity) {
214            float crossfadeVolume;
215            switch (pRegion->AttenuationController.type) {
216                case ::gig::attenuation_ctrl_t::type_channelaftertouch:
217                    crossfadeVolume = Engine::CrossfadeCurve[CrossfadeAttenuation(GetGigEngineChannel()->ControllerTable[128])];
218                    break;
219                case ::gig::attenuation_ctrl_t::type_velocity:
220                    crossfadeVolume = Engine::CrossfadeCurve[CrossfadeAttenuation(MIDIKeyVelocity)];
221                    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                  // apply cutoff frequency to the cutoff parameter sequence          return crossfadeVolume;
231                  for (uint i = pCutoffEvent->FragmentPos(); i < end; i++) {      }
                     pEngine->pSynthesisParameters[Event::destination_vcfc][i] = cutoff;  
                 }  
232    
233                  pCutoffEvent = pNextCutoffEvent;      double Voice::GetEG1ControllerValue(uint8_t MIDIKeyVelocity) {
234              }          double eg1controllervalue = 0;
235              if (pCutoffEventList->last()) VCFCutoffCtrl.fvalue = cutoff; // needed for initialization of parameter matrix next time          switch (pRegion->EG1Controller.type) {
236                case ::gig::eg1_ctrl_t::type_none: // no controller defined
237                    eg1controllervalue = 0;
238                    break;
239                case ::gig::eg1_ctrl_t::type_channelaftertouch:
240                    eg1controllervalue = GetGigEngineChannel()->ControllerTable[128];
241                    break;
242                case ::gig::eg1_ctrl_t::type_velocity:
243                    eg1controllervalue = MIDIKeyVelocity;
244                    break;
245                case ::gig::eg1_ctrl_t::type_controlchange: // MIDI control change controller
246                    eg1controllervalue = GetGigEngineChannel()->ControllerTable[pRegion->EG1Controller.controller_number];
247                    break;
248          }          }
249            if (pRegion->EG1ControllerInvert) eg1controllervalue = 127 - eg1controllervalue;
250    
251          // process filter resonance events          return eg1controllervalue;
252          {      }
             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();  
253    
254                  // calculate the influence length of this event (in sample points)      Voice::EGInfo Voice::CalculateEG1ControllerInfluence(double eg1ControllerValue) {
255                  uint end = (pNextResonanceEvent) ? pNextResonanceEvent->FragmentPos() : Samples;          EGInfo eg;
256            // (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                  // convert absolute controller value to differential          return eg2controllervalue;
291                  int ctrldelta = pResonanceEvent->Value - VCFResonanceCtrl.value;      }
                 VCFResonanceCtrl.value = pResonanceEvent->Value;  
292    
293                  float resonancedelta = (float) ctrldelta * 0.00787f; // 0.0..1.0      Voice::EGInfo Voice::CalculateEG2ControllerInfluence(double eg2ControllerValue) {
294            EGInfo eg;
295            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                  // apply cutoff frequency to the cutoff parameter sequence          return eg;
300                  for (uint i = pResonanceEvent->FragmentPos(); i < end; i++) {      }
                     pEngine->pSynthesisParameters[Event::destination_vcfr][i] += resonancedelta;  
                 }  
301    
302                  pResonanceEvent = pNextResonanceEvent;      void Voice::InitLFO1() {
303              }          uint16_t lfo1_internal_depth;
304              if (pResonanceEventList->last()) VCFResonanceCtrl.fvalue = pResonanceEventList->last()->Value * 0.00787f; // needed for initialization of parameter matrix next time          switch (pRegion->LFO1Controller) {
305                case ::gig::lfo1_ctrl_internal:
306                    lfo1_internal_depth  = pRegion->LFO1InternalDepth;
307                    pLFO1->ExtController = 0; // no external controller
308                    bLFO1Enabled         = (lfo1_internal_depth > 0);
309                    break;
310                case ::gig::lfo1_ctrl_modwheel:
311                    lfo1_internal_depth  = 0;
312                    pLFO1->ExtController = 1; // MIDI controller 1
313                    bLFO1Enabled         = (pRegion->LFO1ControlDepth > 0);
314                    break;
315                case ::gig::lfo1_ctrl_breath:
316                    lfo1_internal_depth  = 0;
317                    pLFO1->ExtController = 2; // MIDI controller 2
318                    bLFO1Enabled         = (pRegion->LFO1ControlDepth > 0);
319                    break;
320                case ::gig::lfo1_ctrl_internal_modwheel:
321                    lfo1_internal_depth  = pRegion->LFO1InternalDepth;
322                    pLFO1->ExtController = 1; // MIDI controller 1
323                    bLFO1Enabled         = (lfo1_internal_depth > 0 || pRegion->LFO1ControlDepth > 0);
324                    break;
325                case ::gig::lfo1_ctrl_internal_breath:
326                    lfo1_internal_depth  = pRegion->LFO1InternalDepth;
327                    pLFO1->ExtController = 2; // MIDI controller 2
328                    bLFO1Enabled         = (lfo1_internal_depth > 0 || pRegion->LFO1ControlDepth > 0);
329                    break;
330                default:
331                    lfo1_internal_depth  = 0;
332                    pLFO1->ExtController = 0; // no external controller
333                    bLFO1Enabled         = false;
334            }
335            if (bLFO1Enabled) {
336                pLFO1->trigger(fromGigLfoWave(pRegion->LFO1WaveForm),
337                               pRegion->LFO1Frequency,
338                               pRegion->LFO1Phase,
339                               LFO::start_level_mid, // see https://sourceforge.net/p/linuxsampler/mailman/linuxsampler-devel/thread/2189307.cNP0Xbctxq%40silver/#msg36774029
340                               lfo1_internal_depth,
341                               pRegion->LFO1ControlDepth,
342                               pRegion->LFO1FlipPhase,
343                               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          }          }
     #endif // ENABLE_FILTER  
358      }      }
359    
360      /**      void Voice::InitLFO2() {
361       *  Interpolates the input audio data (no loop).          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::Interpolate(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) {              case ::gig::lfo2_ctrl_foot:
374                  InterpolateOneStep_Stereo(pSrc, i,                  lfo2_internal_depth  = 0;
375                                            pEngine->pSynthesisParameters[Event::destination_vca][i],                  pLFO2->ExtController = 4; // MIDI controller 4
376                                            pEngine->pSynthesisParameters[Event::destination_vco][i],                  bLFO2Enabled         = (pRegion->LFO2ControlDepth > 0);
377                                            pEngine->pSynthesisParameters[Event::destination_vcfc][i],                  break;
378                                            pEngine->pSynthesisParameters[Event::destination_vcfr][i]);              case ::gig::lfo2_ctrl_internal_modwheel:
379              }                  lfo2_internal_depth  = pRegion->LFO2InternalDepth;
380          }                  pLFO2->ExtController = 1; // MIDI controller 1
381          else { // Mono Sample                  bLFO2Enabled         = (lfo2_internal_depth > 0 || pRegion->LFO2ControlDepth > 0);
382              while (i < Samples) {                  break;
383                  InterpolateOneStep_Mono(pSrc, i,              case ::gig::lfo2_ctrl_internal_foot:
384                                          pEngine->pSynthesisParameters[Event::destination_vca][i],                  lfo2_internal_depth  = pRegion->LFO2InternalDepth;
385                                          pEngine->pSynthesisParameters[Event::destination_vco][i],                  pLFO2->ExtController = 4; // MIDI controller 4
386                                          pEngine->pSynthesisParameters[Event::destination_vcfc][i],                  bLFO2Enabled         = (lfo2_internal_depth > 0 || pRegion->LFO2ControlDepth > 0);
387                                          pEngine->pSynthesisParameters[Event::destination_vcfr][i]);                  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                      InterpolateOneStep_Stereo(pSrc, i,                  bLFO3Enabled         = true;
431                                                pEngine->pSynthesisParameters[Event::destination_vca][i],                  break;
432                                                pEngine->pSynthesisParameters[Event::destination_vco][i],              case ::gig::lfo3_ctrl_internal_modwheel:
433                                                pEngine->pSynthesisParameters[Event::destination_vcfc][i],                  lfo3_internal_depth  = pRegion->LFO3InternalDepth;
434                                                pEngine->pSynthesisParameters[Event::destination_vcfr][i]);                  pLFO3->ExtController = 1; // MIDI controller 1
435                      if (Pos > pSample->LoopEnd) {                  bLFO3Enabled         = (lfo3_internal_depth > 0 || pRegion->LFO3ControlDepth > 0);
436                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;                  break;
437                          LoopCyclesLeft--;              case ::gig::lfo3_ctrl_internal_aftertouch:
438                      }                  lfo3_internal_depth  = pRegion->LFO3InternalDepth;
439                  }                  pLFO3->ExtController = CTRL_TABLE_IDX_AFTERTOUCH;
440                  // render on without loop                  bLFO3Enabled         = (lfo3_internal_depth > 0 || pRegion->LFO3ControlDepth > 0);
441                  while (i < Samples) {                  break;
442                      InterpolateOneStep_Stereo(pSrc, i,              default:
443                                                pEngine->pSynthesisParameters[Event::destination_vca][i],                  lfo3_internal_depth  = 0;
444                                                pEngine->pSynthesisParameters[Event::destination_vco][i],                  pLFO3->ExtController = 0; // no external controller
445                                                pEngine->pSynthesisParameters[Event::destination_vcfc][i],                  bLFO3Enabled         = false;
446                                                pEngine->pSynthesisParameters[Event::destination_vcfr][i]);          }
447                  }          if (bLFO3Enabled) {
448              }              pLFO3->trigger(fromGigLfoWave(pRegion->LFO3WaveForm),
449              else { // render loop (endless loop)                             pRegion->LFO3Frequency,
450                  while (i < Samples) {                             pRegion->LFO3Phase,
451                      InterpolateOneStep_Stereo(pSrc, i,                             LFO::start_level_max, // see https://sourceforge.net/p/linuxsampler/mailman/linuxsampler-devel/thread/2189307.cNP0Xbctxq%40silver/#msg36774029
452                                                pEngine->pSynthesisParameters[Event::destination_vca][i],                             lfo3_internal_depth,
453                                                pEngine->pSynthesisParameters[Event::destination_vco][i],                             pRegion->LFO3ControlDepth,
454                                                pEngine->pSynthesisParameters[Event::destination_vcfc][i],                             pRegion->LFO3FlipPhase,
455                                                pEngine->pSynthesisParameters[Event::destination_vcfr][i]);                             pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
456                      if (Pos > pSample->LoopEnd) {              pLFO3->updateByMIDICtrlValue(pLFO3->ExtController ? GetGigEngineChannel()->ControllerTable[pLFO3->ExtController] : 0);
457                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);              pLFO3->setScriptDepthFactor(
458                      }                  pNote->Override.PitchLFODepth.Value,
459                  }                  pNote->Override.PitchLFODepth.Final
460              }              );
461          }              if (pNote->Override.PitchLFOFreq.isFinal())
462          else { // Mono Sample                  pLFO3->setScriptFrequencyFinal(pNote->Override.PitchLFOFreq.Value, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
463              if (pSample->LoopPlayCount) {              else
464                  // render loop (loop count limited)                  pLFO3->setScriptFrequencyFactor(pNote->Override.PitchLFOFreq.Value, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
465                  while (i < Samples && LoopCyclesLeft) {          }
466                      InterpolateOneStep_Mono(pSrc, i,      }
467                                              pEngine->pSynthesisParameters[Event::destination_vca][i],  
468                                              pEngine->pSynthesisParameters[Event::destination_vco][i],      float Voice::CalculateCutoffBase(uint8_t MIDIKeyVelocity) {
469                                              pEngine->pSynthesisParameters[Event::destination_vcfc][i],          float cutoff = pRegion->GetVelocityCutoff(MIDIKeyVelocity);
470                                              pEngine->pSynthesisParameters[Event::destination_vcfr][i]);          if (pRegion->VCFKeyboardTracking) {
471                      if (Pos > pSample->LoopEnd) {              cutoff *= RTMath::CentsToFreqRatioUnlimited((MIDIKey() - pRegion->VCFKeyboardTrackingBreakpoint) * 100);
472                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;          }
473                          LoopCyclesLeft--;          return cutoff;
474                      }      }
475                  }  
476                  // render on without loop      // This is just called when the voice is triggered. On any subsequent cutoff
477                  while (i < Samples) {      // controller changes ProcessCutoffEvent() is called instead.
478                      InterpolateOneStep_Mono(pSrc, i,      float Voice::CalculateFinalCutoff(float cutoffBase) {
479                                              pEngine->pSynthesisParameters[Event::destination_vca][i],          // if the selected filter type is an official GigaStudio filter type
480                                              pEngine->pSynthesisParameters[Event::destination_vco][i],          // then we preserve the original (no matter how odd) historical GSt
481                                              pEngine->pSynthesisParameters[Event::destination_vcfc][i],          // behaviour identically; for our own filter types though we deviate to
482                                              pEngine->pSynthesisParameters[Event::destination_vcfr][i]);          // more meaningful behaviours where appropriate
483                  }          const bool isGStFilter = isGStFilterType(pRegion->VCFType);
484              }  
485              else { // render loop (endless loop)          // get current cutoff CC or velocity value (always 0..127)
486                  while (i < Samples) {          float cvalue;
487                      InterpolateOneStep_Mono(pSrc, i,          if (VCFCutoffCtrl.controller) {
488                                              pEngine->pSynthesisParameters[Event::destination_vca][i],              cvalue = GetGigEngineChannel()->ControllerTable[VCFCutoffCtrl.controller];
489                                              pEngine->pSynthesisParameters[Event::destination_vco][i],              if (pRegion->VCFCutoffControllerInvert) cvalue = 127 - cvalue;
490                                              pEngine->pSynthesisParameters[Event::destination_vcfc][i],              if (isGStFilter) {
491                                              pEngine->pSynthesisParameters[Event::destination_vcfr][i]);                  // VCFVelocityScale in this case means "minimum cutoff" for GSt
492                      if (Pos > pSample->LoopEnd) {                  if (cvalue < MinCutoff()) cvalue = MinCutoff();
493                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;              } 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.          uint8_t ctrl;
571       */          switch (pRegion->VCFResonanceController) {
572      void Voice::Kill() {              case ::gig::vcf_res_ctrl_genpurpose3:
573          if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {                  ctrl = 18;
574              pDiskThread->OrderDeletionOfStream(&DiskStreamRef);                  break;
575                case ::gig::vcf_res_ctrl_genpurpose4:
576                    ctrl = 19;
577                    break;
578                case ::gig::vcf_res_ctrl_genpurpose5:
579                    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    
589            return ctrl;
590        }
591    
592        void Voice::TriggerEG1(const EGInfo& egInfo, double velrelease, double velocityAttenuation, uint sampleRate, uint8_t velocity) {
593            EG1.setStateOptions(
594                pRegion->EG1Options.AttackCancel,
595                pRegion->EG1Options.AttackHoldCancel,
596                pRegion->EG1Options.Decay1Cancel,
597                pRegion->EG1Options.Decay2Cancel,
598                pRegion->EG1Options.ReleaseCancel
599            );
600            EG1.trigger(pRegion->EG1PreAttack,
601                        (pNote && pNote->Override.Attack.isFinal()) ?
602                            pNote->Override.Attack.Value :
603                            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          Reset();          return flags;
704      }      }
705    
706  }} // namespace LinuxSampler::gig  }} // namespace LinuxSampler::gig

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

  ViewVC Help
Powered by ViewVC