/[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 411 by schoenebeck, Sat Feb 26 02:01:14 2005 UTC revision 3625 by schoenebeck, Thu Oct 3 13:37:25 2019 UTC
# Line 3  Line 3 
3   *   LinuxSampler - modular, streaming capable sampler                     *   *   LinuxSampler - modular, streaming capable sampler                     *
4   *                                                                         *   *                                                                         *
5   *   Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck   *   *   Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck   *
6   *   Copyright (C) 2005 Christian Schoenebeck                              *   *   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 21  Line 23 
23   *   MA  02111-1307  USA                                                   *   *   MA  02111-1307  USA                                                   *
24   ***************************************************************************/   ***************************************************************************/
25    
 #include "EGADSR.h"  
 #include "Manipulator.h"  
26  #include "../../common/Features.h"  #include "../../common/Features.h"
27  #include "Synthesizer.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());      // converts ::gig::lfo_wave_t (libgig) -> LFO::wave_t (LinuxSampler)
37        inline LFO::wave_t fromGigLfoWave(::gig::lfo_wave_t wave) {
38      const int Voice::FILTER_UPDATE_MASK(CalculateFilterUpdateMask());          // simply assuming equally mapped enums on both sides
39            return static_cast<LFO::wave_t>(wave);
     float Voice::CalculateFilterCutoffCoeff() {  
         return log(FILTER_CUTOFF_MIN / FILTER_CUTOFF_MAX);  
     }  
   
     int Voice::CalculateFilterUpdateMask() {  
         if (FILTER_UPDATE_PERIOD <= 0) return 0;  
         int power_of_two;  
         for (power_of_two = 0; 1<<power_of_two < FILTER_UPDATE_PERIOD; power_of_two++);  
         return (1 << power_of_two) - 1;  
40      }      }
41    
42      Voice::Voice() {      Voice::Voice() {
43          pEngine     = NULL;          pEngine = NULL;
44          pDiskThread = NULL;          pEG1 = &EG1;
45          PlaybackState = playback_state_end;          pEG2 = &EG2;
         pEG1   = NULL;  
         pEG2   = NULL;  
         pEG3   = NULL;  
         pVCAManipulator  = NULL;  
         pVCFCManipulator = NULL;  
         pVCOManipulator  = NULL;  
         pLFO1  = NULL;  
         pLFO2  = NULL;  
         pLFO3  = NULL;  
         KeyGroup = 0;  
         SynthesisMode = 0; // set all mode bits to 0 first  
         // select synthesis implementation (currently either pure C++ or MMX+SSE(1))  
         #if ARCH_X86  
         SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, Features::supportsMMX() && Features::supportsSSE());  
         #else  
         SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, false);  
         #endif  
         SYNTHESIS_MODE_SET_PROFILING(SynthesisMode, true);  
   
         FilterLeft.Reset();  
         FilterRight.Reset();  
46      }      }
47    
48      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"));  
49      }      }
50    
51      /**      EngineChannel* Voice::GetGigEngineChannel() {
52       *  Initializes and triggers the voice, a disk stream will be launched if          return static_cast<EngineChannel*>(pEngineChannel);
53       *  needed.      }
      *  
      *  @param pEngineChannel      - engine channel on which this voice was ordered  
      *  @param itNoteOnEvent       - 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)  
      *  @param VoiceStealing       - wether the voice is allowed to steal voices for further subvoices  
      *  @returns 0 on success, a value < 0 if the voice wasn't triggered  
      *           (either due to an error or e.g. because no region is  
      *           defined for the given key)  
      */  
     int Voice::Trigger(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent, int PitchBend, ::gig::Instrument* pInstrument, int iLayer, bool ReleaseTriggerVoice, bool VoiceStealing) {  
         this->pEngineChannel = pEngineChannel;  
         if (!pInstrument) {  
            dmsg(1,("voice::trigger: !pInstrument\n"));  
            exit(EXIT_FAILURE);  
         }  
         if (itNoteOnEvent->FragmentPos() > pEngine->MaxSamplesPerCycle) { // FIXME: should be removed before the final release (purpose: just a sanity check for debugging)  
             dmsg(1,("Voice::Trigger(): ERROR, TriggerDelay > Totalsamples\n"));  
         }  
   
         Type            = type_normal;  
         MIDIKey         = itNoteOnEvent->Param.Note.Key;  
         pRegion         = pInstrument->GetRegion(MIDIKey);  
         PlaybackState   = playback_state_ram; // we always start playback from RAM cache and switch then to disk if needed  
         Delay           = itNoteOnEvent->FragmentPos();  
         itTriggerEvent  = itNoteOnEvent;  
         itKillEvent     = Pool<Event>::Iterator();  
         itChildVoice    = Pool<Voice>::Iterator();  
   
         if (!pRegion) {  
             dmsg(4, ("gig::Voice: No Region defined for MIDI key %d\n", MIDIKey));  
             return -1;  
         }  
   
         KeyGroup = pRegion->KeyGroup;  
54    
55          // get current dimension values to select the right dimension region      void Voice::SetEngine(LinuxSampler::Engine* pEngine) {
56          //FIXME: controller values for selecting the dimension region here are currently not sample accurate          Engine* engine = static_cast<Engine*>(pEngine);
57          uint DimValues[8] = { 0 };          this->pEngine     = engine;
58          for (int i = pRegion->Dimensions - 1; i >= 0; i--) {          this->pDiskThread = engine->pDiskThread;
59              switch (pRegion->pDimensionDefinitions[i].dimension) {          dmsg(6,("Voice::SetEngine()\n"));
60                  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++)  
                             itChildVoice = pEngine->LaunchVoice(pEngineChannel, itNoteOnEvent, iNewLayer, ReleaseTriggerVoice, VoiceStealing);  
                     break;  
                 case ::gig::dimension_velocity:  
                     DimValues[i] = itNoteOnEvent->Param.Note.Velocity;  
                     break;  
                 case ::gig::dimension_channelaftertouch:  
                     DimValues[i] = 0; //TODO: we currently ignore this dimension  
                     break;  
                 case ::gig::dimension_releasetrigger:  
                     Type = (ReleaseTriggerVoice) ? type_release_trigger : (!iLayer) ? type_release_trigger_required : type_normal;  
                     DimValues[i] = (uint) ReleaseTriggerVoice;  
                     break;  
                 case ::gig::dimension_keyboard:  
                     DimValues[i] = (uint) pEngineChannel->CurrentKeyDimension;  
                     break;  
                 case ::gig::dimension_modwheel:  
                     DimValues[i] = pEngineChannel->ControllerTable[1];  
                     break;  
                 case ::gig::dimension_breath:  
                     DimValues[i] = pEngineChannel->ControllerTable[2];  
                     break;  
                 case ::gig::dimension_foot:  
                     DimValues[i] = pEngineChannel->ControllerTable[4];  
                     break;  
                 case ::gig::dimension_portamentotime:  
                     DimValues[i] = pEngineChannel->ControllerTable[5];  
                     break;  
                 case ::gig::dimension_effect1:  
                     DimValues[i] = pEngineChannel->ControllerTable[12];  
                     break;  
                 case ::gig::dimension_effect2:  
                     DimValues[i] = pEngineChannel->ControllerTable[13];  
                     break;  
                 case ::gig::dimension_genpurpose1:  
                     DimValues[i] = pEngineChannel->ControllerTable[16];  
                     break;  
                 case ::gig::dimension_genpurpose2:  
                     DimValues[i] = pEngineChannel->ControllerTable[17];  
                     break;  
                 case ::gig::dimension_genpurpose3:  
                     DimValues[i] = pEngineChannel->ControllerTable[18];  
                     break;  
                 case ::gig::dimension_genpurpose4:  
                     DimValues[i] = pEngineChannel->ControllerTable[19];  
                     break;  
                 case ::gig::dimension_sustainpedal:  
                     DimValues[i] = pEngineChannel->ControllerTable[64];  
                     break;  
                 case ::gig::dimension_portamento:  
                     DimValues[i] = pEngineChannel->ControllerTable[65];  
                     break;  
                 case ::gig::dimension_sostenutopedal:  
                     DimValues[i] = pEngineChannel->ControllerTable[66];  
                     break;  
                 case ::gig::dimension_softpedal:  
                     DimValues[i] = pEngineChannel->ControllerTable[67];  
                     break;  
                 case ::gig::dimension_genpurpose5:  
                     DimValues[i] = pEngineChannel->ControllerTable[80];  
                     break;  
                 case ::gig::dimension_genpurpose6:  
                     DimValues[i] = pEngineChannel->ControllerTable[81];  
                     break;  
                 case ::gig::dimension_genpurpose7:  
                     DimValues[i] = pEngineChannel->ControllerTable[82];  
                     break;  
                 case ::gig::dimension_genpurpose8:  
                     DimValues[i] = pEngineChannel->ControllerTable[83];  
                     break;  
                 case ::gig::dimension_effect1depth:  
                     DimValues[i] = pEngineChannel->ControllerTable[91];  
                     break;  
                 case ::gig::dimension_effect2depth:  
                     DimValues[i] = pEngineChannel->ControllerTable[92];  
                     break;  
                 case ::gig::dimension_effect3depth:  
                     DimValues[i] = pEngineChannel->ControllerTable[93];  
                     break;  
                 case ::gig::dimension_effect4depth:  
                     DimValues[i] = pEngineChannel->ControllerTable[94];  
                     break;  
                 case ::gig::dimension_effect5depth:  
                     DimValues[i] = pEngineChannel->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);  
61    
62          pSample = pDimRgn->pSample; // sample won't change until the voice is finished      Voice::SampleInfo Voice::GetSampleInfo() {
63          if (!pSample || !pSample->SamplesTotal) return -1; // no need to continue if sample is silent          SampleInfo si;
64            si.SampleRate       = pSample->SamplesPerSecond;
65            si.ChannelCount     = pSample->Channels;
66            si.FrameSize        = pSample->FrameSize;
67            si.BitDepth         = pSample->BitDepth;
68            si.TotalFrameCount  = (uint)pSample->SamplesTotal;
69    
70          // select channel mode (mono or stereo)          si.HasLoops       = pRegion->SampleLoops;
71          SYNTHESIS_MODE_SET_CHANNELS(SynthesisMode, pSample->Channels == 2);          si.LoopStart      = (si.HasLoops) ? pRegion->pSampleLoops[0].LoopStart  : 0;
72            si.LoopLength     = (si.HasLoops) ? pRegion->pSampleLoops[0].LoopLength : 0;
73            si.LoopPlayCount  = pSample->LoopPlayCount;
74            si.Unpitched      = !pRegion->PitchTrack;
75    
76          // get starting crossfade volume level          return si;
77          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(itNoteOnEvent->Param.Note.Velocity);  
                 break;  
             case ::gig::attenuation_ctrl_t::type_controlchange: //FIXME: currently not sample accurate  
                 CrossfadeVolume = CrossfadeAttenuation(pEngineChannel->ControllerTable[pDimRgn->AttenuationController.controller_number]);  
                 break;  
             case ::gig::attenuation_ctrl_t::type_none: // no crossfade defined  
             default:  
                 CrossfadeVolume = 1.0f;  
         }  
78    
79          PanLeft  = 1.0f - float(RTMath::Max(pDimRgn->Pan, 0)) /  63.0f;      Voice::RegionInfo Voice::GetRegionInfo() {
80          PanRight = 1.0f - float(RTMath::Min(pDimRgn->Pan, 0)) / -64.0f;          RegionInfo ri;
81            ri.UnityNote = pRegion->UnityNote;
82            ri.FineTune  = pRegion->FineTune;
83            ri.Pan       = pRegion->Pan;
84            ri.SampleStartOffset = pRegion->SampleStartOffset;
85    
86          Pos = pDimRgn->SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)          ri.EG2PreAttack        = pRegion->EG2PreAttack;
87            ri.EG2Attack           = pRegion->EG2Attack;
88            ri.EG2Decay1           = pRegion->EG2Decay1;
89            ri.EG2Decay2           = pRegion->EG2Decay2;
90            ri.EG2Sustain          = pRegion->EG2Sustain;
91            ri.EG2InfiniteSustain  = pRegion->EG2InfiniteSustain;
92            ri.EG2Release          = pRegion->EG2Release;
93    
94          // Check if the sample needs disk streaming or is too short for that          ri.EG3Attack     = pRegion->EG3Attack;
95          long cachedsamples = pSample->GetCache().Size / pSample->FrameSize;          ri.EG3Depth      = pRegion->EG3Depth;
96          DiskVoice          = cachedsamples < pSample->SamplesTotal;          ri.VCFEnabled    = pRegion->VCFEnabled;
97            ri.VCFType       = Filter::vcf_type_t(pRegion->VCFType);
98          if (DiskVoice) { // voice to be streamed from disk          ri.VCFResonance  = pRegion->VCFResonance;
             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;  
   
             if (pDiskThread->OrderNewStream(&DiskStreamRef, pSample, MaxRAMPos, !RAMLoop) < 0) {  
                 dmsg(1,("Disk stream order failed!\n"));  
                 KillImmediately();  
                 return -1;  
             }  
             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"));  
         }  
99    
100            ri.ReleaseTriggerDecay = 0.01053 * (256 >> pRegion->ReleaseTriggerDecay);
101    
102          // calculate initial pitch value          return ri;
103          {      }
             double pitchbasecents = pDimRgn->FineTune + (int) pEngine->ScaleTuning[MIDIKey % 12];  
             if (pDimRgn->PitchTrack) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;  
             this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents) * (double(pSample->SamplesPerSecond) / double(pEngine->pAudioOutputDevice->SampleRate()));  
             this->PitchBend = RTMath::CentsToFreqRatio(((double) PitchBend / 8192.0) * 200.0); // pitchbend wheel +-2 semitones = 200 cents  
         }  
104    
105          Volume = pDimRgn->GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity) / 32768.0f; // we downscale by 32768 to convert from int16 value range to DSP value range (which is -1.0..1.0)      Voice::InstrumentInfo Voice::GetInstrumentInfo() {
106            InstrumentInfo ii;
107            ii.FineTune = GetGigEngineChannel()->pInstrument->FineTune;
108            ii.PitchbendRange = GetGigEngineChannel()->pInstrument->PitchbendRange;
109    
110          Volume *= pDimRgn->SampleAttenuation;          return ii;
111        }
112    
113          // setup EG 1 (VCA EG)      double Voice::GetSampleAttenuation() {
114          {          return pRegion->SampleAttenuation;
115              // 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 = itNoteOnEvent->Param.Note.Velocity;  
                     break;  
                 case ::gig::eg1_ctrl_t::type_controlchange: // MIDI control change controller  
                     eg1controllervalue = pEngineChannel->ControllerTable[pDimRgn->EG1Controller.controller_number];  
                     break;  
             }  
             if (pDimRgn->EG1ControllerInvert) eg1controllervalue = 127 - eg1controllervalue;  
116    
117              // calculate influence of EG1 controller on EG1's parameters (TODO: needs to be fine tuned)      double Voice::GetVelocityAttenuation(uint8_t MIDIKeyVelocity) {
118              double eg1attack  = (pDimRgn->EG1ControllerAttackInfluence)  ? 0.0001 * (double) (1 << pDimRgn->EG1ControllerAttackInfluence)  * eg1controllervalue : 0.0;          return pRegion->GetVelocityAttenuation(MIDIKeyVelocity);
119              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);  
         }  
120    
121        double Voice::GetVelocityRelease(uint8_t MIDIKeyVelocity) {
122            return pRegion->GetVelocityRelease(MIDIKeyVelocity);
123        }
124    
125          // setup EG 2 (VCF Cutoff EG)      void Voice::ProcessCCEvent(RTList<Event>::Iterator& itEvent) {
126          {          if (itEvent->Type == Event::type_control_change && itEvent->Param.CC.Controller) { // if (valid) MIDI control change event
127              // get current value of EG2 controller              if (pRegion->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange &&
128              double eg2controllervalue;                  itEvent->Param.CC.Controller == pRegion->AttenuationController.controller_number) {
129              switch (pDimRgn->EG2Controller.type) {                  CrossfadeSmoother.update(AbstractEngine::CrossfadeCurve[CrossfadeAttenuation(itEvent->Param.CC.Value)]);
                 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 = itNoteOnEvent->Param.Note.Velocity;  
                     break;  
                 case ::gig::eg2_ctrl_t::type_controlchange: // MIDI control change controller  
                     eg2controllervalue = pEngineChannel->ControllerTable[pDimRgn->EG2Controller.controller_number];  
                     break;  
130              }              }
             if (pDimRgn->EG2ControllerInvert) eg2controllervalue = 127 - eg2controllervalue;  
   
             // calculate influence of EG2 controller on EG2's parameters (TODO: needs to be fine tuned)  
             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);  
         }  
   
   
         // setup EG 3 (VCO EG)  
         {  
           double eg3depth = RTMath::CentsToFreqRatio(pDimRgn->EG3Depth);  
           pEG3->Trigger(eg3depth, pDimRgn->EG3Attack, Delay);  
131          }          }
132        }
133    
134        void Voice::ProcessChannelPressureEvent(RTList<Event>::Iterator& itEvent) {
135          // setup LFO 1 (VCA LFO)          if (itEvent->Type == Event::type_channel_pressure) { // if (valid) MIDI channel pressure (aftertouch) event
136          {              if (pRegion->AttenuationController.type == ::gig::attenuation_ctrl_t::type_channelaftertouch) {
137              uint16_t lfo1_internal_depth;                  CrossfadeSmoother.update(AbstractEngine::CrossfadeCurve[CrossfadeAttenuation(itEvent->Param.ChannelPressure.Value)]);
             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  
138              }              }
             pLFO1->Trigger(pDimRgn->LFO1Frequency,  
                           lfo1_internal_depth,  
                           pDimRgn->LFO1ControlDepth,  
                           pEngineChannel->ControllerTable[pLFO1->ExtController],  
                           pDimRgn->LFO1FlipPhase,  
                           pEngine->SampleRate,  
                           Delay);  
139          }          }
140        }
141    
142        void Voice::ProcessPolyphonicKeyPressureEvent(RTList<Event>::Iterator& itEvent) {
143            // Not used so far
144        }
145    
146          // setup LFO 2 (VCF Cutoff LFO)      void Voice::ProcessCutoffEvent(RTList<Event>::Iterator& itEvent) {
147          {          int ccvalue = itEvent->Param.CC.Value;
148              uint16_t lfo2_internal_depth;          if (VCFCutoffCtrl.value == ccvalue) return;
149              switch (pDimRgn->LFO2Controller) {          VCFCutoffCtrl.value = ccvalue;
150                  case ::gig::lfo2_ctrl_internal:          if (pRegion->VCFCutoffControllerInvert)  ccvalue = 127 - ccvalue;
151                      lfo2_internal_depth  = pDimRgn->LFO2InternalDepth;          if (ccvalue < pRegion->VCFVelocityScale) ccvalue = pRegion->VCFVelocityScale;
152                      pLFO2->ExtController = 0; // no external controller          float cutoff = CutoffBase * float(ccvalue);
153                      break;          if (cutoff > 127.0f) cutoff = 127.0f;
                 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,  
                           pEngineChannel->ControllerTable[pLFO2->ExtController],  
                           pDimRgn->LFO2FlipPhase,  
                           pEngine->SampleRate,  
                           Delay);  
         }  
154    
155            VCFCutoffCtrl.fvalue = cutoff; // needed for initialization of fFinalCutoff next time
156            fFinalCutoff = cutoff;
157        }
158    
159          // setup LFO 3 (VCO LFO)      double Voice::CalculateCrossfadeVolume(uint8_t MIDIKeyVelocity) {
160          {          float crossfadeVolume;
161              uint16_t lfo3_internal_depth;          switch (pRegion->AttenuationController.type) {
162              switch (pDimRgn->LFO3Controller) {              case ::gig::attenuation_ctrl_t::type_channelaftertouch:
163                  case ::gig::lfo3_ctrl_internal:                  crossfadeVolume = Engine::CrossfadeCurve[CrossfadeAttenuation(GetGigEngineChannel()->ControllerTable[128])];
164                      lfo3_internal_depth  = pDimRgn->LFO3InternalDepth;                  break;
165                      pLFO3->ExtController = 0; // no external controller              case ::gig::attenuation_ctrl_t::type_velocity:
166                      break;                  crossfadeVolume = Engine::CrossfadeCurve[CrossfadeAttenuation(MIDIKeyVelocity)];
167                  case ::gig::lfo3_ctrl_modwheel:                  break;
168                      lfo3_internal_depth  = 0;              case ::gig::attenuation_ctrl_t::type_controlchange: //FIXME: currently not sample accurate
169                      pLFO3->ExtController = 1; // MIDI controller 1                  crossfadeVolume = Engine::CrossfadeCurve[CrossfadeAttenuation(GetGigEngineChannel()->ControllerTable[pRegion->AttenuationController.controller_number])];
170                      break;                  break;
171                  case ::gig::lfo3_ctrl_aftertouch:              case ::gig::attenuation_ctrl_t::type_none: // no crossfade defined
172                      lfo3_internal_depth  = 0;              default:
173                      pLFO3->ExtController = 0; // TODO: aftertouch not implemented yet                  crossfadeVolume = 1.0f;
                     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,  
                           pEngineChannel->ControllerTable[pLFO3->ExtController],  
                           false,  
                           pEngine->SampleRate,  
                           Delay);  
174          }          }
175    
176            return crossfadeVolume;
177        }
178    
179          #if FORCE_FILTER_USAGE      double Voice::GetEG1ControllerValue(uint8_t MIDIKeyVelocity) {
180          const bool bUseFilter = true;          double eg1controllervalue = 0;
181          #else // use filter only if instrument file told so          switch (pRegion->EG1Controller.type) {
182          const bool bUseFilter = pDimRgn->VCFEnabled;              case ::gig::eg1_ctrl_t::type_none: // no controller defined
183          #endif // FORCE_FILTER_USAGE                  eg1controllervalue = 0;
184          SYNTHESIS_MODE_SET_FILTER(SynthesisMode, bUseFilter);                  break;
185          if (bUseFilter) {              case ::gig::eg1_ctrl_t::type_channelaftertouch:
186              #ifdef OVERRIDE_FILTER_CUTOFF_CTRL                  eg1controllervalue = GetGigEngineChannel()->ControllerTable[128];
187              VCFCutoffCtrl.controller = OVERRIDE_FILTER_CUTOFF_CTRL;                  break;
188              #else // use the one defined in the instrument file              case ::gig::eg1_ctrl_t::type_velocity:
189              switch (pDimRgn->VCFCutoffController) {                  eg1controllervalue = MIDIKeyVelocity;
190                  case ::gig::vcf_cutoff_ctrl_modwheel:                  break;
191                      VCFCutoffCtrl.controller = 1;              case ::gig::eg1_ctrl_t::type_controlchange: // MIDI control change controller
192                      break;                  eg1controllervalue = GetGigEngineChannel()->ControllerTable[pRegion->EG1Controller.controller_number];
193                  case ::gig::vcf_cutoff_ctrl_effect1:                  break;
                     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  
   
             #ifdef OVERRIDE_FILTER_RES_CTRL  
             VCFResonanceCtrl.controller = OVERRIDE_FILTER_RES_CTRL;  
             #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  
   
             #ifndef OVERRIDE_FILTER_TYPE  
             FilterLeft.SetType(pDimRgn->VCFType);  
             FilterRight.SetType(pDimRgn->VCFType);  
             #else // override filter type  
             FilterLeft.SetType(OVERRIDE_FILTER_TYPE);  
             FilterRight.SetType(OVERRIDE_FILTER_TYPE);  
             #endif // OVERRIDE_FILTER_TYPE  
   
             VCFCutoffCtrl.value    = pEngineChannel->ControllerTable[VCFCutoffCtrl.controller];  
             VCFResonanceCtrl.value = pEngineChannel->ControllerTable[VCFResonanceCtrl.controller];  
   
             // calculate cutoff frequency  
             float cutoff = (!VCFCutoffCtrl.controller)  
                 ? exp((float) (127 - itNoteOnEvent->Param.Note.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) (itNoteOnEvent->Param.Note.Key - pDimRgn->VCFKeyboardTrackingBreakpoint) * 0.00787f;  
             }  
             Constrain(resonance, 0.0, 1.0); // correct resonance if outside allowed value range (0.0..1.0)  
   
             VCFCutoffCtrl.fvalue    = cutoff - FILTER_CUTOFF_MIN;  
             VCFResonanceCtrl.fvalue = resonance;  
   
             FilterUpdateCounter = -1;  
         }  
         else {  
             VCFCutoffCtrl.controller    = 0;  
             VCFResonanceCtrl.controller = 0;  
194          }          }
195            if (pRegion->EG1ControllerInvert) eg1controllervalue = 127 - eg1controllervalue;
196    
197          return 0; // success          return eg1controllervalue;
198      }      }
199    
200      /**      Voice::EGInfo Voice::CalculateEG1ControllerInfluence(double eg1ControllerValue) {
201       *  Renders the audio data for this voice for the current audio fragment.          EGInfo eg;
202       *  The sample input data can either come from RAM (cached sample or sample          // (eg1attack is different from the others)
203       *  part) or directly from disk. The output signal will be rendered by          if (pRegion->EG1Attack < 1e-8 && // attack in gig == 0
204       *  resampling / interpolation. If this voice is a disk streaming voice and              (pRegion->EG1ControllerAttackInfluence == 0 ||
205       *  the voice completely played back the cached RAM part of the sample, it               eg1ControllerValue <= 10)) { // strange GSt special case
206       *  will automatically switch to disk playback for the next RenderAudio()              eg.Attack = 0; // this will force the attack to be 0 in the call to EG1.trigger
207       *  call.          } else {
208       *              eg.Attack  = (pRegion->EG1ControllerAttackInfluence)  ?
209       *  @param Samples - number of samples to be rendered in this audio fragment cycle                  1 + 0.031 * (double) (pRegion->EG1ControllerAttackInfluence == 1 ?
210       */                                        1 : 1 << pRegion->EG1ControllerAttackInfluence) * eg1ControllerValue : 1.0;
211      void Voice::Render(uint Samples) {          }
212            eg.Decay   = (pRegion->EG1ControllerDecayInfluence)   ? 1 + 0.00775 * (double) (1 << pRegion->EG1ControllerDecayInfluence)   * eg1ControllerValue : 1.0;
213          // select default values for synthesis mode bits          eg.Release = (pRegion->EG1ControllerReleaseInfluence) ? 1 + 0.00775 * (double) (1 << pRegion->EG1ControllerReleaseInfluence) * eg1ControllerValue : 1.0;
214          SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, (PitchBase * PitchBend) != 1.0f);  
215          SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, true);          return eg;
216          SYNTHESIS_MODE_SET_LOOP(SynthesisMode, false);      }
217    
218          // Reset the synthesis parameter matrix      double Voice::GetEG2ControllerValue(uint8_t MIDIKeyVelocity) {
219            double eg2controllervalue = 0;
220          pEngine->ResetSynthesisParameters(Event::destination_vca, this->Volume * this->CrossfadeVolume * pEngineChannel->GlobalVolume);          switch (pRegion->EG2Controller.type) {
221          pEngine->ResetSynthesisParameters(Event::destination_vco, this->PitchBase);              case ::gig::eg2_ctrl_t::type_none: // no controller defined
222          pEngine->ResetSynthesisParameters(Event::destination_vcfc, VCFCutoffCtrl.fvalue);                  eg2controllervalue = 0;
223          pEngine->ResetSynthesisParameters(Event::destination_vcfr, VCFResonanceCtrl.fvalue);                  break;
224                case ::gig::eg2_ctrl_t::type_channelaftertouch:
225          // Apply events to the synthesis parameter matrix                  eg2controllervalue = GetGigEngineChannel()->ControllerTable[128];
226          ProcessEvents(Samples);                  break;
227                case ::gig::eg2_ctrl_t::type_velocity:
228          // Let all modulators write their parameter changes to the synthesis parameter matrix for the current audio fragment                  eg2controllervalue = MIDIKeyVelocity;
229          pEG1->Process(Samples, pEngineChannel->pMIDIKeyInfo[MIDIKey].pEvents, itTriggerEvent, this->Pos, this->PitchBase * this->PitchBend, itKillEvent);                  break;
230          pEG2->Process(Samples, pEngineChannel->pMIDIKeyInfo[MIDIKey].pEvents, itTriggerEvent, this->Pos, this->PitchBase * this->PitchBend);              case ::gig::eg2_ctrl_t::type_controlchange: // MIDI control change controller
231          if (pEG3->Process(Samples)) { // if pitch EG is active                  eg2controllervalue = GetGigEngineChannel()->ControllerTable[pRegion->EG2Controller.controller_number];
232              SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, true);                  break;
             SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, false);  
         }  
         pLFO1->Process(Samples);  
         pLFO2->Process(Samples);  
         if (pLFO3->Process(Samples)) { // if pitch LFO modulation is active  
             SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, true);  
             SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, false);  
233          }          }
234            if (pRegion->EG2ControllerInvert) eg2controllervalue = 127 - eg2controllervalue;
235    
236          if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode))          return eg2controllervalue;
237                  CalculateBiquadParameters(Samples); // calculate the final biquad filter parameters      }
238    
239          switch (this->PlaybackState) {      Voice::EGInfo Voice::CalculateEG2ControllerInfluence(double eg2ControllerValue) {
240            EGInfo eg;
241            eg.Attack  = (pRegion->EG2ControllerAttackInfluence)  ? 1 + 0.00775 * (double) (1 << pRegion->EG2ControllerAttackInfluence)  * eg2ControllerValue : 1.0;
242            eg.Decay   = (pRegion->EG2ControllerDecayInfluence)   ? 1 + 0.00775 * (double) (1 << pRegion->EG2ControllerDecayInfluence)   * eg2ControllerValue : 1.0;
243            eg.Release = (pRegion->EG2ControllerReleaseInfluence) ? 1 + 0.00775 * (double) (1 << pRegion->EG2ControllerReleaseInfluence) * eg2ControllerValue : 1.0;
244    
245              case playback_state_ram: {          return eg;
246                      if (RAMLoop) SYNTHESIS_MODE_SET_LOOP(SynthesisMode, true); // enable looping      }
247    
248                      // render current fragment      void Voice::InitLFO1() {
249                      Synthesize(Samples, (sample_t*) pSample->GetCache().pStart, Delay);          uint16_t lfo1_internal_depth;
250            switch (pRegion->LFO1Controller) {
251                      if (DiskVoice) {              case ::gig::lfo1_ctrl_internal:
252                          // check if we reached the allowed limit of the sample RAM cache                  lfo1_internal_depth  = pRegion->LFO1InternalDepth;
253                          if (Pos > MaxRAMPos) {                  pLFO1->ExtController = 0; // no external controller
254                              dmsg(5,("Voice: switching to disk playback (Pos=%f)\n", Pos));                  bLFO1Enabled         = (lfo1_internal_depth > 0);
                             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 * (int(Pos) - MaxRAMPos));  
                         Pos -= int(Pos);  
                         RealSampleWordsLeftToRead = -1; // -1 means no silence has been added yet  
                     }  
   
                     const int sampleWordsLeftToRead = DiskStreamRef.pStream->GetReadSpace();  
   
                     // add silence sample at the end if we reached the end of the stream (for the interpolator)  
                     if (DiskStreamRef.State == Stream::state_end) {  
                         const int maxSampleWordsPerCycle = (pEngine->MaxSamplesPerCycle << MAX_PITCH) * pSample->Channels + 6; // +6 for the interpolator algorithm  
                         if (sampleWordsLeftToRead <= maxSampleWordsPerCycle) {  
                             // remember how many sample words there are before any silence has been added  
                             if (RealSampleWordsLeftToRead < 0) RealSampleWordsLeftToRead = sampleWordsLeftToRead;  
                             DiskStreamRef.pStream->WriteSilence(maxSampleWordsPerCycle - sampleWordsLeftToRead);  
                         }  
                     }  
   
                     sample_t* ptr = DiskStreamRef.pStream->GetReadPtr(); // get the current read_ptr within the ringbuffer where we read the samples from  
   
                     // render current audio fragment  
                     Synthesize(Samples, ptr, Delay);  
   
                     const int iPos = (int) Pos;  
                     const int readSampleWords = iPos * pSample->Channels; // amount of sample words actually been read  
                     DiskStreamRef.pStream->IncrementReadPos(readSampleWords);  
                     Pos -= iPos; // just keep fractional part of Pos  
   
                     // change state of voice to 'end' if we really reached the end of the sample data  
                     if (RealSampleWordsLeftToRead >= 0) {  
                         RealSampleWordsLeftToRead -= readSampleWords;  
                         if (RealSampleWordsLeftToRead <= 0) this->PlaybackState = playback_state_end;  
                     }  
                 }  
255                  break;                  break;
256                case ::gig::lfo1_ctrl_modwheel:
257              case playback_state_end:                  lfo1_internal_depth  = 0;
258                  std::cerr << "gig::Voice::Render(): entered with playback_state_end, this is a bug!\n" << std::flush;                  pLFO1->ExtController = 1; // MIDI controller 1
259                    bLFO1Enabled         = (pRegion->LFO1ControlDepth > 0);
260                  break;                  break;
261                case ::gig::lfo1_ctrl_breath:
262                    lfo1_internal_depth  = 0;
263                    pLFO1->ExtController = 2; // MIDI controller 2
264                    bLFO1Enabled         = (pRegion->LFO1ControlDepth > 0);
265                    break;
266                case ::gig::lfo1_ctrl_internal_modwheel:
267                    lfo1_internal_depth  = pRegion->LFO1InternalDepth;
268                    pLFO1->ExtController = 1; // MIDI controller 1
269                    bLFO1Enabled         = (lfo1_internal_depth > 0 || pRegion->LFO1ControlDepth > 0);
270                    break;
271                case ::gig::lfo1_ctrl_internal_breath:
272                    lfo1_internal_depth  = pRegion->LFO1InternalDepth;
273                    pLFO1->ExtController = 2; // MIDI controller 2
274                    bLFO1Enabled         = (lfo1_internal_depth > 0 || pRegion->LFO1ControlDepth > 0);
275                    break;
276                default:
277                    lfo1_internal_depth  = 0;
278                    pLFO1->ExtController = 0; // no external controller
279                    bLFO1Enabled         = false;
280            }
281            if (bLFO1Enabled) {
282                pLFO1->trigger(fromGigLfoWave(pRegion->LFO1WaveForm),
283                               pRegion->LFO1Frequency,
284                               pRegion->LFO1Phase,
285                               LFO::start_level_mid, // see https://sourceforge.net/p/linuxsampler/mailman/linuxsampler-devel/thread/2189307.cNP0Xbctxq%40silver/#msg36774029
286                               lfo1_internal_depth,
287                               pRegion->LFO1ControlDepth,
288                               pRegion->LFO1FlipPhase,
289                               pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
290                pLFO1->updateByMIDICtrlValue(pLFO1->ExtController ? GetGigEngineChannel()->ControllerTable[pLFO1->ExtController] : 0);
291                pLFO1->setScriptDepthFactor(
292                    pNote->Override.AmpLFODepth.Value,
293                    pNote->Override.AmpLFODepth.Final
294                );
295                if (pNote->Override.AmpLFOFreq.isFinal())
296                    pLFO1->setScriptFrequencyFinal(
297                        pNote->Override.AmpLFOFreq.Value, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE
298                    );
299                else
300                    pLFO1->setScriptFrequencyFactor(
301                        pNote->Override.AmpLFOFreq.Value, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE
302                    );
303          }          }
304        }
305    
306          // Reset synthesis event lists (except VCO, as VCO events apply channel wide currently)      void Voice::InitLFO2() {
307          pEngine->pSynthesisEvents[Event::destination_vca]->clear();          uint16_t lfo2_internal_depth;
308          pEngine->pSynthesisEvents[Event::destination_vcfc]->clear();          switch (pRegion->LFO2Controller) {
309          pEngine->pSynthesisEvents[Event::destination_vcfr]->clear();              case ::gig::lfo2_ctrl_internal:
310                    lfo2_internal_depth  = pRegion->LFO2InternalDepth;
311          // Reset delay                  pLFO2->ExtController = 0; // no external controller
312          Delay = 0;                  bLFO2Enabled         = (lfo2_internal_depth > 0);
313                    break;
314          itTriggerEvent = Pool<Event>::Iterator();              case ::gig::lfo2_ctrl_modwheel:
315                    lfo2_internal_depth  = 0;
316          // If sample stream or release stage finished, kill the voice                  pLFO2->ExtController = 1; // MIDI controller 1
317          if (PlaybackState == playback_state_end || pEG1->GetStage() == EGADSR::stage_end) KillImmediately();                  bLFO2Enabled         = (pRegion->LFO2ControlDepth > 0);
318      }                  break;
319                case ::gig::lfo2_ctrl_foot:
320      /**                  lfo2_internal_depth  = 0;
321       *  Resets voice variables. Should only be called if rendering process is                  pLFO2->ExtController = 4; // MIDI controller 4
322       *  suspended / not running.                  bLFO2Enabled         = (pRegion->LFO2ControlDepth > 0);
323       */                  break;
324      void Voice::Reset() {              case ::gig::lfo2_ctrl_internal_modwheel:
325          pLFO1->Reset();                  lfo2_internal_depth  = pRegion->LFO2InternalDepth;
326          pLFO2->Reset();                  pLFO2->ExtController = 1; // MIDI controller 1
327          pLFO3->Reset();                  bLFO2Enabled         = (lfo2_internal_depth > 0 || pRegion->LFO2ControlDepth > 0);
328          FilterLeft.Reset();                  break;
329          FilterRight.Reset();              case ::gig::lfo2_ctrl_internal_foot:
330          DiskStreamRef.pStream = NULL;                  lfo2_internal_depth  = pRegion->LFO2InternalDepth;
331          DiskStreamRef.hStream = 0;                  pLFO2->ExtController = 4; // MIDI controller 4
332          DiskStreamRef.State   = Stream::state_unused;                  bLFO2Enabled         = (lfo2_internal_depth > 0 || pRegion->LFO2ControlDepth > 0);
333          DiskStreamRef.OrderID = 0;                  break;
334          PlaybackState = playback_state_end;              default:
335          itTriggerEvent = Pool<Event>::Iterator();                  lfo2_internal_depth  = 0;
336          itKillEvent    = Pool<Event>::Iterator();                  pLFO2->ExtController = 0; // no external controller
337      }                  bLFO2Enabled         = false;
338            }
339      /**          if (bLFO2Enabled) {
340       *  Process the control change event lists of the engine for the current              pLFO2->trigger(fromGigLfoWave(pRegion->LFO2WaveForm),
341       *  audio fragment. Event values will be applied to the synthesis parameter                             pRegion->LFO2Frequency,
342       *  matrix.                             pRegion->LFO2Phase,
343       *                             LFO::start_level_mid, // see https://sourceforge.net/p/linuxsampler/mailman/linuxsampler-devel/thread/2189307.cNP0Xbctxq%40silver/#msg36774029
344       *  @param Samples - number of samples to be rendered in this audio fragment cycle                             lfo2_internal_depth,
345       */                             pRegion->LFO2ControlDepth,
346      void Voice::ProcessEvents(uint Samples) {                             pRegion->LFO2FlipPhase,
347                               pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
348          // dispatch control change events              pLFO2->updateByMIDICtrlValue(pLFO2->ExtController ? GetGigEngineChannel()->ControllerTable[pLFO2->ExtController] : 0);
349          RTList<Event>::Iterator itCCEvent = pEngine->pCCEvents->first();              pLFO2->setScriptDepthFactor(
350          if (Delay) { // skip events that happened before this voice was triggered                  pNote->Override.CutoffLFODepth.Value,
351              while (itCCEvent && itCCEvent->FragmentPos() <= Delay) ++itCCEvent;                  pNote->Override.CutoffLFODepth.Final
352                );
353                if (pNote->Override.CutoffLFOFreq.isFinal())
354                    pLFO2->setScriptFrequencyFinal(pNote->Override.CutoffLFOFreq.Value, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
355                else
356                    pLFO2->setScriptFrequencyFactor(pNote->Override.CutoffLFOFreq.Value, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
357          }          }
358          while (itCCEvent) {      }
             if (itCCEvent->Param.CC.Controller) { // if valid MIDI controller  
                 if (itCCEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {  
                     *pEngine->pSynthesisEvents[Event::destination_vcfc]->allocAppend() = *itCCEvent;  
                 }  
                 if (itCCEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {  
                     *pEngine->pSynthesisEvents[Event::destination_vcfr]->allocAppend() = *itCCEvent;  
                 }  
                 if (itCCEvent->Param.CC.Controller == pLFO1->ExtController) {  
                     pLFO1->SendEvent(itCCEvent);  
                 }  
                 if (itCCEvent->Param.CC.Controller == pLFO2->ExtController) {  
                     pLFO2->SendEvent(itCCEvent);  
                 }  
                 if (itCCEvent->Param.CC.Controller == pLFO3->ExtController) {  
                     pLFO3->SendEvent(itCCEvent);  
                 }  
                 if (pDimRgn->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange &&  
                     itCCEvent->Param.CC.Controller == pDimRgn->AttenuationController.controller_number) { // if crossfade event  
                     *pEngine->pSynthesisEvents[Event::destination_vca]->allocAppend() = *itCCEvent;  
                 }  
             }  
359    
360              ++itCCEvent;      void Voice::InitLFO3() {
361            uint16_t lfo3_internal_depth;
362            switch (pRegion->LFO3Controller) {
363                case ::gig::lfo3_ctrl_internal:
364                    lfo3_internal_depth  = pRegion->LFO3InternalDepth;
365                    pLFO3->ExtController = 0; // no external controller
366                    bLFO3Enabled         = (lfo3_internal_depth > 0);
367                    break;
368                case ::gig::lfo3_ctrl_modwheel:
369                    lfo3_internal_depth  = 0;
370                    pLFO3->ExtController = 1; // MIDI controller 1
371                    bLFO3Enabled         = (pRegion->LFO3ControlDepth > 0);
372                    break;
373                case ::gig::lfo3_ctrl_aftertouch:
374                    lfo3_internal_depth  = 0;
375                    pLFO3->ExtController = CTRL_TABLE_IDX_AFTERTOUCH;
376                    bLFO3Enabled         = true;
377                    break;
378                case ::gig::lfo3_ctrl_internal_modwheel:
379                    lfo3_internal_depth  = pRegion->LFO3InternalDepth;
380                    pLFO3->ExtController = 1; // MIDI controller 1
381                    bLFO3Enabled         = (lfo3_internal_depth > 0 || pRegion->LFO3ControlDepth > 0);
382                    break;
383                case ::gig::lfo3_ctrl_internal_aftertouch:
384                    lfo3_internal_depth  = pRegion->LFO3InternalDepth;
385                    pLFO3->ExtController = CTRL_TABLE_IDX_AFTERTOUCH;
386                    bLFO3Enabled         = (lfo3_internal_depth > 0 || pRegion->LFO3ControlDepth > 0);
387                    break;
388                default:
389                    lfo3_internal_depth  = 0;
390                    pLFO3->ExtController = 0; // no external controller
391                    bLFO3Enabled         = false;
392            }
393            if (bLFO3Enabled) {
394                pLFO3->trigger(fromGigLfoWave(pRegion->LFO3WaveForm),
395                               pRegion->LFO3Frequency,
396                               pRegion->LFO3Phase,
397                               LFO::start_level_max, // see https://sourceforge.net/p/linuxsampler/mailman/linuxsampler-devel/thread/2189307.cNP0Xbctxq%40silver/#msg36774029
398                               lfo3_internal_depth,
399                               pRegion->LFO3ControlDepth,
400                               pRegion->LFO3FlipPhase,
401                               pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
402                pLFO3->updateByMIDICtrlValue(pLFO3->ExtController ? GetGigEngineChannel()->ControllerTable[pLFO3->ExtController] : 0);
403                pLFO3->setScriptDepthFactor(
404                    pNote->Override.PitchLFODepth.Value,
405                    pNote->Override.PitchLFODepth.Final
406                );
407                if (pNote->Override.PitchLFOFreq.isFinal())
408                    pLFO3->setScriptFrequencyFinal(pNote->Override.PitchLFOFreq.Value, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
409                else
410                    pLFO3->setScriptFrequencyFactor(pNote->Override.PitchLFOFreq.Value, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
411          }          }
412        }
413    
414        float Voice::CalculateCutoffBase(uint8_t MIDIKeyVelocity) {
415          // process pitch events          float cutoff = pRegion->GetVelocityCutoff(MIDIKeyVelocity);
416          {          if (pRegion->VCFKeyboardTracking) {
417              RTList<Event>* pVCOEventList = pEngine->pSynthesisEvents[Event::destination_vco];              cutoff *= RTMath::CentsToFreqRatioUnlimited((MIDIKey() - pRegion->VCFKeyboardTrackingBreakpoint) * 100);
418              RTList<Event>::Iterator itVCOEvent = pVCOEventList->first();          }
419              if (Delay) { // skip events that happened before this voice was triggered          return cutoff;
420                  while (itVCOEvent && itVCOEvent->FragmentPos() <= Delay) ++itVCOEvent;      }
421              }  
422              // apply old pitchbend value until first pitch event occurs      float Voice::CalculateFinalCutoff(float cutoffBase) {
423              if (this->PitchBend != 1.0) {          int cvalue;
424                  uint end = (itVCOEvent) ? itVCOEvent->FragmentPos() : Samples;          if (VCFCutoffCtrl.controller) {
425                  for (uint i = Delay; i < end; i++) {              cvalue = GetGigEngineChannel()->ControllerTable[VCFCutoffCtrl.controller];
426                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= this->PitchBend;              if (pRegion->VCFCutoffControllerInvert) cvalue = 127 - cvalue;
427                  }              // VCFVelocityScale in this case means Minimum cutoff
428              }              if (cvalue < pRegion->VCFVelocityScale) cvalue = pRegion->VCFVelocityScale;
             float pitch;  
             while (itVCOEvent) {  
                 RTList<Event>::Iterator itNextVCOEvent = itVCOEvent;  
                 ++itNextVCOEvent;  
   
                 // calculate the influence length of this event (in sample points)  
                 uint end = (itNextVCOEvent) ? itNextVCOEvent->FragmentPos() : Samples;  
   
                 pitch = RTMath::CentsToFreqRatio(((double) itVCOEvent->Param.Pitch.Pitch / 8192.0) * 200.0); // +-two semitones = +-200 cents  
   
                 // apply pitch value to the pitch parameter sequence  
                 for (uint i = itVCOEvent->FragmentPos(); i < end; i++) {  
                     pEngine->pSynthesisParameters[Event::destination_vco][i] *= pitch;  
                 }  
   
                 itVCOEvent = itNextVCOEvent;  
             }  
             if (!pVCOEventList->isEmpty()) {  
                 this->PitchBend = pitch;  
                 SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, true);  
                 SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, false);  
             }  
429          }          }
430            else {
431          // process volume / attenuation events (TODO: we only handle and _expect_ crossfade events here ATM !)              cvalue = pRegion->VCFCutoff;
         {  
             RTList<Event>* pVCAEventList = pEngine->pSynthesisEvents[Event::destination_vca];  
             RTList<Event>::Iterator itVCAEvent = pVCAEventList->first();  
             if (Delay) { // skip events that happened before this voice was triggered  
                 while (itVCAEvent && itVCAEvent->FragmentPos() <= Delay) ++itVCAEvent;  
             }  
             float crossfadevolume;  
             while (itVCAEvent) {  
                 RTList<Event>::Iterator itNextVCAEvent = itVCAEvent;  
                 ++itNextVCAEvent;  
   
                 // calculate the influence length of this event (in sample points)  
                 uint end = (itNextVCAEvent) ? itNextVCAEvent->FragmentPos() : Samples;  
   
                 crossfadevolume = CrossfadeAttenuation(itVCAEvent->Param.CC.Value);  
   
                 float effective_volume = crossfadevolume * this->Volume * pEngineChannel->GlobalVolume;  
   
                 // apply volume value to the volume parameter sequence  
                 for (uint i = itVCAEvent->FragmentPos(); i < end; i++) {  
                     pEngine->pSynthesisParameters[Event::destination_vca][i] = effective_volume;  
                 }  
   
                 itVCAEvent = itNextVCAEvent;  
             }  
             if (!pVCAEventList->isEmpty()) this->CrossfadeVolume = crossfadevolume;  
432          }          }
433            float fco = cutoffBase * float(cvalue);
434            if (fco > 127.0f) fco = 127.0f;
435    
436          // process filter cutoff events          return fco;
437          {      }
             RTList<Event>* pCutoffEventList = pEngine->pSynthesisEvents[Event::destination_vcfc];  
             RTList<Event>::Iterator itCutoffEvent = pCutoffEventList->first();  
             if (Delay) { // skip events that happened before this voice was triggered  
                 while (itCutoffEvent && itCutoffEvent->FragmentPos() <= Delay) ++itCutoffEvent;  
             }  
             float cutoff;  
             while (itCutoffEvent) {  
                 RTList<Event>::Iterator itNextCutoffEvent = itCutoffEvent;  
                 ++itNextCutoffEvent;  
   
                 // calculate the influence length of this event (in sample points)  
                 uint end = (itNextCutoffEvent) ? itNextCutoffEvent->FragmentPos() : Samples;  
   
                 cutoff = exp((float) itCutoffEvent->Param.CC.Value * 0.00787402f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX - FILTER_CUTOFF_MIN;  
   
                 // apply cutoff frequency to the cutoff parameter sequence  
                 for (uint i = itCutoffEvent->FragmentPos(); i < end; i++) {  
                     pEngine->pSynthesisParameters[Event::destination_vcfc][i] = cutoff;  
                 }  
438    
439                  itCutoffEvent = itNextCutoffEvent;      uint8_t Voice::GetVCFCutoffCtrl() {
440              }          uint8_t ctrl;
441              if (!pCutoffEventList->isEmpty()) VCFCutoffCtrl.fvalue = cutoff; // needed for initialization of parameter matrix next time          switch (pRegion->VCFCutoffController) {
442                case ::gig::vcf_cutoff_ctrl_modwheel:
443                    ctrl = 1;
444                    break;
445                case ::gig::vcf_cutoff_ctrl_effect1:
446                    ctrl = 12;
447                    break;
448                case ::gig::vcf_cutoff_ctrl_effect2:
449                    ctrl = 13;
450                    break;
451                case ::gig::vcf_cutoff_ctrl_breath:
452                    ctrl = 2;
453                    break;
454                case ::gig::vcf_cutoff_ctrl_foot:
455                    ctrl = 4;
456                    break;
457                case ::gig::vcf_cutoff_ctrl_sustainpedal:
458                    ctrl = 64;
459                    break;
460                case ::gig::vcf_cutoff_ctrl_softpedal:
461                    ctrl = 67;
462                    break;
463                case ::gig::vcf_cutoff_ctrl_genpurpose7:
464                    ctrl = 82;
465                    break;
466                case ::gig::vcf_cutoff_ctrl_genpurpose8:
467                    ctrl = 83;
468                    break;
469                case ::gig::vcf_cutoff_ctrl_aftertouch:
470                    ctrl = CTRL_TABLE_IDX_AFTERTOUCH;
471                    break;
472                case ::gig::vcf_cutoff_ctrl_none:
473                default:
474                    ctrl = 0;
475                    break;
476          }          }
477    
478          // process filter resonance events          return ctrl;
         {  
             RTList<Event>* pResonanceEventList = pEngine->pSynthesisEvents[Event::destination_vcfr];  
             RTList<Event>::Iterator itResonanceEvent = pResonanceEventList->first();  
             if (Delay) { // skip events that happened before this voice was triggered  
                 while (itResonanceEvent && itResonanceEvent->FragmentPos() <= Delay) ++itResonanceEvent;  
             }  
             while (itResonanceEvent) {  
                 RTList<Event>::Iterator itNextResonanceEvent = itResonanceEvent;  
                 ++itNextResonanceEvent;  
   
                 // calculate the influence length of this event (in sample points)  
                 uint end = (itNextResonanceEvent) ? itNextResonanceEvent->FragmentPos() : Samples;  
   
                 // convert absolute controller value to differential  
                 int ctrldelta = itResonanceEvent->Param.CC.Value - VCFResonanceCtrl.value;  
                 VCFResonanceCtrl.value = itResonanceEvent->Param.CC.Value;  
   
                 float resonancedelta = (float) ctrldelta * 0.00787f; // 0.0..1.0  
   
                 // apply cutoff frequency to the cutoff parameter sequence  
                 for (uint i = itResonanceEvent->FragmentPos(); i < end; i++) {  
                     pEngine->pSynthesisParameters[Event::destination_vcfr][i] += resonancedelta;  
                 }  
   
                 itResonanceEvent = itNextResonanceEvent;  
             }  
             if (!pResonanceEventList->isEmpty()) VCFResonanceCtrl.fvalue = pResonanceEventList->last()->Param.CC.Value * 0.00787f; // needed for initialization of parameter matrix next time  
         }  
479      }      }
480    
481      /**      uint8_t Voice::GetVCFResonanceCtrl() {
482       * Calculate all necessary, final biquad filter parameters.          uint8_t ctrl;
483       *          switch (pRegion->VCFResonanceController) {
484       * @param Samples - number of samples to be rendered in this audio fragment cycle              case ::gig::vcf_res_ctrl_genpurpose3:
485       */                  ctrl = 18;
486      void Voice::CalculateBiquadParameters(uint Samples) {                  break;
487          biquad_param_t bqbase;              case ::gig::vcf_res_ctrl_genpurpose4:
488          biquad_param_t bqmain;                  ctrl = 19;
489          float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0];                  break;
490          float prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][0];              case ::gig::vcf_res_ctrl_genpurpose5:
491          FilterLeft.SetParameters( &bqbase, &bqmain, prev_cutoff + FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate);                  ctrl = 80;
492          FilterRight.SetParameters(&bqbase, &bqmain, prev_cutoff + FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate);                  break;
493          pEngine->pBasicFilterParameters[0] = bqbase;              case ::gig::vcf_res_ctrl_genpurpose6:
494          pEngine->pMainFilterParameters[0]  = bqmain;                  ctrl = 81;
495                    break;
496          float* bq;              case ::gig::vcf_res_ctrl_none:
497          for (int i = 1; i < Samples; i++) {              default:
498              // recalculate biquad parameters if cutoff or resonance differ from previous sample point                  ctrl = 0;
             if (!(i & FILTER_UPDATE_MASK)) {  
                 if (pEngine->pSynthesisParameters[Event::destination_vcfr][i] != prev_res ||  
                     pEngine->pSynthesisParameters[Event::destination_vcfc][i] != prev_cutoff)  
                 {  
                     prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][i];  
                     prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][i];  
                     FilterLeft.SetParameters( &bqbase, &bqmain, prev_cutoff + FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate);  
                     FilterRight.SetParameters(&bqbase, &bqmain, prev_cutoff + FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate);  
                 }  
             }  
   
             //same as 'pEngine->pBasicFilterParameters[i] = bqbase;'  
             bq    = (float*) &pEngine->pBasicFilterParameters[i];  
             bq[0] = bqbase.b0;  
             bq[1] = bqbase.b1;  
             bq[2] = bqbase.b2;  
             bq[3] = bqbase.a1;  
             bq[4] = bqbase.a2;  
   
             // same as 'pEngine->pMainFilterParameters[i] = bqmain;'  
             bq    = (float*) &pEngine->pMainFilterParameters[i];  
             bq[0] = bqmain.b0;  
             bq[1] = bqmain.b1;  
             bq[2] = bqmain.b2;  
             bq[3] = bqmain.a1;  
             bq[4] = bqmain.a2;  
499          }          }
     }  
500    
501      /**          return ctrl;
      *  Synthesizes the current audio fragment for this voice.  
      *  
      *  @param Samples - number of sample points to be rendered in this audio  
      *                   fragment cycle  
      *  @param pSrc    - pointer to input sample data  
      *  @param Skip    - number of sample points to skip in output buffer  
      */  
     void Voice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {  
         RunSynthesisFunction(SynthesisMode, *this, Samples, pSrc, Skip);  
     }  
   
     /**  
      *  Immediately kill the voice. This method should not be used to kill  
      *  a normal, active voice, because it doesn't take care of things like  
      *  fading down the volume level to avoid clicks and regular processing  
      *  until the kill event actually occured!  
      *  
      *  @see Kill()  
      */  
     void Voice::KillImmediately() {  
         if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {  
             pDiskThread->OrderDeletionOfStream(&DiskStreamRef);  
         }  
         Reset();  
502      }      }
503    
504      /**      void Voice::TriggerEG1(const EGInfo& egInfo, double velrelease, double velocityAttenuation, uint sampleRate, uint8_t velocity) {
505       *  Kill the voice in regular sense. Let the voice render audio until          EG1.setStateOptions(
506       *  the kill event actually occured and then fade down the volume level              pRegion->EG1Options.AttackCancel,
507       *  very quickly and let the voice die finally. Unlike a normal release              pRegion->EG1Options.AttackHoldCancel,
508       *  of a voice, a kill process cannot be cancalled and is therefore              pRegion->EG1Options.Decay1Cancel,
509       *  usually used for voice stealing and key group conflicts.              pRegion->EG1Options.Decay2Cancel,
510       *              pRegion->EG1Options.ReleaseCancel
511       *  @param itKillEvent - event which caused the voice to be killed          );
512       */          EG1.trigger(pRegion->EG1PreAttack,
513      void Voice::Kill(Pool<Event>::Iterator& itKillEvent) {                      (pNote && pNote->Override.Attack.isFinal()) ?
514          //FIXME: just two sanity checks for debugging, can be removed                          pNote->Override.Attack.Value :
515          if (!itKillEvent) dmsg(1,("gig::Voice::Kill(): ERROR, !itKillEvent !!!\n"));                          RTMath::Max(pRegion->EG1Attack, 0.0316) * egInfo.Attack,
516          if (itKillEvent && !itKillEvent.isValid()) dmsg(1,("gig::Voice::Kill(): ERROR, itKillEvent invalid !!!\n"));                      pRegion->EG1Hold,
517                        (pNote && pNote->Override.Decay.isFinal()) ?
518          if (itTriggerEvent && itKillEvent->FragmentPos() <= itTriggerEvent->FragmentPos()) return;                          pNote->Override.Decay.Value :
519          this->itKillEvent = itKillEvent;                          pRegion->EG1Decay1 * egInfo.Decay * velrelease,
520                        (pNote && pNote->Override.Decay.isFinal()) ?
521                            pNote->Override.Decay.Value :
522                            pRegion->EG1Decay2 * egInfo.Decay * velrelease,
523                        pRegion->EG1InfiniteSustain,
524                        (pNote && pNote->Override.Sustain.Final) ?
525                            uint(pNote->Override.Sustain.Value * 1000.f) :
526                            pRegion->EG1Sustain * (pNote ? pNote->Override.Sustain.Value : 1.f),
527                        (pNote && pNote->Override.Release.isFinal()) ?
528                            pNote->Override.Release.Value :
529                            RTMath::Max(pRegion->EG1Release * velrelease, 0.014) * egInfo.Release,
530                        velocityAttenuation,
531                        sampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
532        }
533    
534        void Voice::TriggerEG2(const EGInfo& egInfo, double velrelease, double velocityAttenuation, uint sampleRate, uint8_t velocity) {
535            EG2.setStateOptions(
536                pRegion->EG2Options.AttackCancel,
537                pRegion->EG2Options.AttackHoldCancel,
538                pRegion->EG2Options.Decay1Cancel,
539                pRegion->EG2Options.Decay2Cancel,
540                pRegion->EG2Options.ReleaseCancel
541            );
542            EG2.trigger(uint(RgnInfo.EG2PreAttack),
543                        (pNote && pNote->Override.CutoffAttack.isFinal()) ?
544                            pNote->Override.CutoffAttack.Value :
545                            RgnInfo.EG2Attack * egInfo.Attack,
546                        false,
547                        (pNote && pNote->Override.CutoffDecay.isFinal()) ?
548                            pNote->Override.CutoffDecay.Value :
549                            RgnInfo.EG2Decay1 * egInfo.Decay * velrelease,
550                        (pNote && pNote->Override.CutoffDecay.isFinal()) ?
551                            pNote->Override.CutoffDecay.Value :
552                            RgnInfo.EG2Decay2 * egInfo.Decay * velrelease,
553                        RgnInfo.EG2InfiniteSustain,
554                        (pNote && pNote->Override.CutoffSustain.Final) ?
555                            uint(pNote->Override.CutoffSustain.Value * 1000.f) :
556                            uint(RgnInfo.EG2Sustain),
557                        (pNote && pNote->Override.CutoffRelease.isFinal()) ?
558                            pNote->Override.CutoffRelease.Value :
559                            RgnInfo.EG2Release * egInfo.Release * velrelease,
560                        velocityAttenuation,
561                        sampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
562        }
563    
564        void Voice::ProcessGroupEvent(RTList<Event>::Iterator& itEvent) {
565            dmsg(4,("Voice %p processGroupEvents event type=%d", (void*)this, itEvent->Type));
566    
567            // TODO: The SustainPedal condition could be wrong, maybe the
568            // check should be if this Voice is in release stage or is a
569            // release sample instead. Need to test this in GSt.
570            // -- Andreas
571            //
572            // Commented sustain pedal check out. I don't think voices of the same
573            // note should be stopped at all, because it doesn't sound naturally
574            // with a drumkit.
575            // -- Christian, 2013-01-08
576            if (itEvent->Param.Note.Key != HostKey() /*||
577                !GetGigEngineChannel()->SustainPedal*/) {
578                dmsg(4,("Voice %p - kill", (void*)this));
579    
580                // kill the voice fast
581                pEG1->enterFadeOutStage();
582            }
583        }
584    
585        void Voice::CalculateFadeOutCoeff(float FadeOutTime, float SampleRate) {
586            EG1.CalculateFadeOutCoeff(FadeOutTime, SampleRate);
587        }
588    
589        int Voice::CalculatePan(uint8_t pan) {
590            int p;
591            // Gst behaviour: -64 and 63 are special cases
592            if (RgnInfo.Pan == -64)     p = pan * 2 - 127;
593            else if (RgnInfo.Pan == 63) p = pan * 2;
594            else                        p = pan + RgnInfo.Pan;
595    
596            if (p < 0) return 0;
597            if (p > 127) return 127;
598            return p;
599        }
600    
601        release_trigger_t Voice::GetReleaseTriggerFlags() {
602            release_trigger_t flags =
603                (pRegion->NoNoteOffReleaseTrigger) ?
604                    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
605            switch (pRegion->SustainReleaseTrigger) {
606                case ::gig::sust_rel_trg_none:
607                    break;
608                case ::gig::sust_rel_trg_maxvelocity:
609                    flags |= release_trigger_sustain_maxvelocity;
610                    break;
611                case ::gig::sust_rel_trg_keyvelocity:
612                    flags |= release_trigger_sustain_keyvelocity;
613                    break;
614            }
615            return flags;
616      }      }
617    
618  }} // namespace LinuxSampler::gig  }} // namespace LinuxSampler::gig

Legend:
Removed from v.411  
changed lines
  Added in v.3625

  ViewVC Help
Powered by ViewVC