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

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

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

revision 287 by schoenebeck, Sat Oct 16 17:38:03 2004 UTC revision 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 - 2008 Christian Schoenebeck                       *
7     *   Copyright (C) 2009 Christian Schoenebeck and Grigor Iliev             *
8     *   Copyright (C) 2010 - 2017 Christian Schoenebeck and Andreas Persson   *
9   *                                                                         *   *                                                                         *
10   *   This program is free software; you can redistribute it and/or modify  *   *   This program is free software; you can redistribute it and/or modify  *
11   *   it under the terms of the GNU General Public License as published by  *   *   it under the terms of the GNU General Public License as published by  *
# Line 20  Line 23 
23   *   MA  02111-1307  USA                                                   *   *   MA  02111-1307  USA                                                   *
24   ***************************************************************************/   ***************************************************************************/
25    
26  #include "EGADSR.h"  #include "../../common/Features.h"
27  #include "Manipulator.h"  #include "Synthesizer.h"
28    #include "Profiler.h"
29    #include "Engine.h"
30    #include "EngineChannel.h"
31    
32  #include "Voice.h"  #include "Voice.h"
33    
34  namespace LinuxSampler { namespace gig {  namespace LinuxSampler { namespace gig {
35    
36      const float Voice::FILTER_CUTOFF_COEFF(CalculateFilterCutoffCoeff());      // 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;  
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 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 something failed  
      */  
     int Voice::Trigger(Pool<Event>::Iterator& itNoteOnEvent, int PitchBend, ::gig::Instrument* pInstrument, int iLayer, bool ReleaseTriggerVoice, bool VoiceStealing) {  
         if (!pInstrument) {  
            dmsg(1,("voice::trigger: !pInstrument\n"));  
            exit(EXIT_FAILURE);  
         }  
   
         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) {  
             std::cerr << "gig::Voice: No Region defined for MIDI key " << MIDIKey << std::endl << std::flush;  
             KillImmediately();  
             return -1;  
         }  
   
         KeyGroup = pRegion->KeyGroup;  
   
         // get current dimension values to select the right dimension region  
         //FIXME: controller values for selecting the dimension region here are currently not sample accurate  
         uint DimValues[5] = {0,0,0,0,0};  
         for (int i = pRegion->Dimensions - 1; i >= 0; i--) {  
             switch (pRegion->pDimensionDefinitions[i].dimension) {  
                 case ::gig::dimension_samplechannel:  
                     DimValues[i] = 0; //TODO: we currently ignore this dimension  
                     break;  
                 case ::gig::dimension_layer:  
                     DimValues[i] = iLayer;  
                     // if this is the 1st layer then spawn further voices for all the other layers  
                     if (iLayer == 0)  
                         for (int iNewLayer = 1; iNewLayer < pRegion->pDimensionDefinitions[i].zones; iNewLayer++)  
                             itChildVoice = pEngine->LaunchVoice(itNoteOnEvent, iNewLayer, ReleaseTriggerVoice, VoiceStealing);  
                     break;  
                 case ::gig::dimension_velocity:  
                     DimValues[i] = itNoteOnEvent->Param.Note.Velocity;  
                     break;  
                 case ::gig::dimension_channelaftertouch:  
                     DimValues[i] = 0; //TODO: we currently ignore this dimension  
                     break;  
                 case ::gig::dimension_releasetrigger:  
                     Type = (ReleaseTriggerVoice) ? type_release_trigger : (!iLayer) ? type_release_trigger_required : type_normal;  
                     DimValues[i] = (uint) ReleaseTriggerVoice;  
                     break;  
                 case ::gig::dimension_keyboard:  
                     DimValues[i] = (uint) itNoteOnEvent->Param.Note.Key;  
                     break;  
                 case ::gig::dimension_modwheel:  
                     DimValues[i] = pEngine->ControllerTable[1];  
                     break;  
                 case ::gig::dimension_breath:  
                     DimValues[i] = pEngine->ControllerTable[2];  
                     break;  
                 case ::gig::dimension_foot:  
                     DimValues[i] = pEngine->ControllerTable[4];  
                     break;  
                 case ::gig::dimension_portamentotime:  
                     DimValues[i] = pEngine->ControllerTable[5];  
                     break;  
                 case ::gig::dimension_effect1:  
                     DimValues[i] = pEngine->ControllerTable[12];  
                     break;  
                 case ::gig::dimension_effect2:  
                     DimValues[i] = pEngine->ControllerTable[13];  
                     break;  
                 case ::gig::dimension_genpurpose1:  
                     DimValues[i] = pEngine->ControllerTable[16];  
                     break;  
                 case ::gig::dimension_genpurpose2:  
                     DimValues[i] = pEngine->ControllerTable[17];  
                     break;  
                 case ::gig::dimension_genpurpose3:  
                     DimValues[i] = pEngine->ControllerTable[18];  
                     break;  
                 case ::gig::dimension_genpurpose4:  
                     DimValues[i] = pEngine->ControllerTable[19];  
                     break;  
                 case ::gig::dimension_sustainpedal:  
                     DimValues[i] = pEngine->ControllerTable[64];  
                     break;  
                 case ::gig::dimension_portamento:  
                     DimValues[i] = pEngine->ControllerTable[65];  
                     break;  
                 case ::gig::dimension_sostenutopedal:  
                     DimValues[i] = pEngine->ControllerTable[66];  
                     break;  
                 case ::gig::dimension_softpedal:  
                     DimValues[i] = pEngine->ControllerTable[67];  
                     break;  
                 case ::gig::dimension_genpurpose5:  
                     DimValues[i] = pEngine->ControllerTable[80];  
                     break;  
                 case ::gig::dimension_genpurpose6:  
                     DimValues[i] = pEngine->ControllerTable[81];  
                     break;  
                 case ::gig::dimension_genpurpose7:  
                     DimValues[i] = pEngine->ControllerTable[82];  
                     break;  
                 case ::gig::dimension_genpurpose8:  
                     DimValues[i] = pEngine->ControllerTable[83];  
                     break;  
                 case ::gig::dimension_effect1depth:  
                     DimValues[i] = pEngine->ControllerTable[91];  
                     break;  
                 case ::gig::dimension_effect2depth:  
                     DimValues[i] = pEngine->ControllerTable[92];  
                     break;  
                 case ::gig::dimension_effect3depth:  
                     DimValues[i] = pEngine->ControllerTable[93];  
                     break;  
                 case ::gig::dimension_effect4depth:  
                     DimValues[i] = pEngine->ControllerTable[94];  
                     break;  
                 case ::gig::dimension_effect5depth:  
                     DimValues[i] = pEngine->ControllerTable[95];  
                     break;  
                 case ::gig::dimension_none:  
                     std::cerr << "gig::Voice::Trigger() Error: dimension=none\n" << std::flush;  
                     break;  
                 default:  
                     std::cerr << "gig::Voice::Trigger() Error: Unknown dimension\n" << std::flush;  
             }  
         }  
         pDimRgn = pRegion->GetDimensionRegionByValue(DimValues[4],DimValues[3],DimValues[2],DimValues[1],DimValues[0]);  
   
         // get starting crossfade volume level  
         switch (pDimRgn->AttenuationController.type) {  
             case ::gig::attenuation_ctrl_t::type_channelaftertouch:  
                 CrossfadeVolume = 1.0f; //TODO: aftertouch not supported yet  
                 break;  
             case ::gig::attenuation_ctrl_t::type_velocity:  
                 CrossfadeVolume = CrossfadeAttenuation(itNoteOnEvent->Param.Note.Velocity);  
                 break;  
             case ::gig::attenuation_ctrl_t::type_controlchange: //FIXME: currently not sample accurate  
                 CrossfadeVolume = CrossfadeAttenuation(pEngine->ControllerTable[pDimRgn->AttenuationController.controller_number]);  
                 break;  
             case ::gig::attenuation_ctrl_t::type_none: // no crossfade defined  
             default:  
                 CrossfadeVolume = 1.0f;  
         }  
   
         PanLeft  = 1.0f - float(RTMath::Max(pDimRgn->Pan, 0)) /  63.0f;  
         PanRight = 1.0f - float(RTMath::Min(pDimRgn->Pan, 0)) / -64.0f;  
   
         pSample = pDimRgn->pSample; // sample won't change until the voice is finished  
   
         Pos = pDimRgn->SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)  
   
         // Check if the sample needs disk streaming or is too short for that  
         long cachedsamples = pSample->GetCache().Size / pSample->FrameSize;  
         DiskVoice          = cachedsamples < pSample->SamplesTotal;  
   
         if (DiskVoice) { // voice to be streamed from disk  
             MaxRAMPos = cachedsamples - (pEngine->MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels; //TODO: this calculation is too pessimistic and may better be moved to Render() method, so it calculates MaxRAMPos dependent to the current demand of sample points to be rendered (e.g. in case of JACK)  
   
             // check if there's a loop defined which completely fits into the cached (RAM) part of the sample  
             if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) {  
                 RAMLoop        = true;  
                 LoopCyclesLeft = pSample->LoopPlayCount;  
             }  
             else RAMLoop = false;  
   
             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"));  
         }  
54    
55        void Voice::SetEngine(LinuxSampler::Engine* pEngine) {
56            Engine* engine = static_cast<Engine*>(pEngine);
57            this->pEngine     = engine;
58            this->pDiskThread = engine->pDiskThread;
59            dmsg(6,("Voice::SetEngine()\n"));
60        }
61    
62          // calculate initial pitch value      Voice::SampleInfo Voice::GetSampleInfo() {
63          {          SampleInfo si;
64              double pitchbasecents = pDimRgn->FineTune * 10 + (int) pEngine->ScaleTuning[MIDIKey % 12];          si.SampleRate       = pSample->SamplesPerSecond;
65              if (pDimRgn->PitchTrack) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;          si.ChannelCount     = pSample->Channels;
66              this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents) * (double(pSample->SamplesPerSecond) / double(pEngine->pAudioOutputDevice->SampleRate()));          si.FrameSize        = pSample->FrameSize;
67              this->PitchBend = RTMath::CentsToFreqRatio(((double) PitchBend / 8192.0) * 200.0); // pitchbend wheel +-2 semitones = 200 cents          si.BitDepth         = pSample->BitDepth;
68          }          si.TotalFrameCount  = (uint)pSample->SamplesTotal;
69    
70            si.HasLoops       = pRegion->SampleLoops;
71            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          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)          return si;
77        }
78    
79        Voice::RegionInfo Voice::GetRegionInfo() {
80            RegionInfo ri;
81            ri.UnityNote = pRegion->UnityNote;
82            ri.FineTune  = pRegion->FineTune;
83            ri.Pan       = pRegion->Pan;
84            ri.SampleStartOffset = pRegion->SampleStartOffset;
85    
86          // setup EG 1 (VCA EG)          ri.EG2PreAttack        = pRegion->EG2PreAttack;
87          {          ri.EG2Attack           = pRegion->EG2Attack;
88              // get current value of EG1 controller          ri.EG2Decay1           = pRegion->EG2Decay1;
89              double eg1controllervalue;          ri.EG2Decay2           = pRegion->EG2Decay2;
90              switch (pDimRgn->EG1Controller.type) {          ri.EG2Sustain          = pRegion->EG2Sustain;
91                  case ::gig::eg1_ctrl_t::type_none: // no controller defined          ri.EG2InfiniteSustain  = pRegion->EG2InfiniteSustain;
92                      eg1controllervalue = 0;          ri.EG2Release          = pRegion->EG2Release;
                     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 = pEngine->ControllerTable[pDimRgn->EG1Controller.controller_number];  
                     break;  
             }  
             if (pDimRgn->EG1ControllerInvert) eg1controllervalue = 127 - eg1controllervalue;  
93    
94              // calculate influence of EG1 controller on EG1's parameters (TODO: needs to be fine tuned)          ri.EG3Attack     = pRegion->EG3Attack;
95              double eg1attack  = (pDimRgn->EG1ControllerAttackInfluence)  ? 0.0001 * (double) (1 << pDimRgn->EG1ControllerAttackInfluence)  * eg1controllervalue : 0.0;          ri.EG3Depth      = pRegion->EG3Depth;
96              double eg1decay   = (pDimRgn->EG1ControllerDecayInfluence)   ? 0.0001 * (double) (1 << pDimRgn->EG1ControllerDecayInfluence)   * eg1controllervalue : 0.0;          ri.VCFEnabled    = pRegion->VCFEnabled;
97              double eg1release = (pDimRgn->EG1ControllerReleaseInfluence) ? 0.0001 * (double) (1 << pDimRgn->EG1ControllerReleaseInfluence) * eg1controllervalue : 0.0;          ri.VCFType       = Filter::vcf_type_t(pRegion->VCFType);
98            ri.VCFResonance  = pRegion->VCFResonance;
             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);  
         }  
99    
100            ri.ReleaseTriggerDecay = 0.01053 * (256 >> pRegion->ReleaseTriggerDecay);
101    
102      #if ENABLE_FILTER          return ri;
103          // setup EG 2 (VCF Cutoff EG)      }
         {  
             // get current value of EG2 controller  
             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 = itNoteOnEvent->Param.Note.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;  
104    
105              // calculate influence of EG2 controller on EG2's parameters (TODO: needs to be fine tuned)      Voice::InstrumentInfo Voice::GetInstrumentInfo() {
106              double eg2attack  = (pDimRgn->EG2ControllerAttackInfluence)  ? 0.0001 * (double) (1 << pDimRgn->EG2ControllerAttackInfluence)  * eg2controllervalue : 0.0;          InstrumentInfo ii;
107              double eg2decay   = (pDimRgn->EG2ControllerDecayInfluence)   ? 0.0001 * (double) (1 << pDimRgn->EG2ControllerDecayInfluence)   * eg2controllervalue : 0.0;          ii.FineTune = GetGigEngineChannel()->pInstrument->FineTune;
108              double eg2release = (pDimRgn->EG2ControllerReleaseInfluence) ? 0.0001 * (double) (1 << pDimRgn->EG2ControllerReleaseInfluence) * eg2controllervalue : 0.0;          ii.PitchbendRange = GetGigEngineChannel()->pInstrument->PitchbendRange;
   
             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  
109    
110            return ii;
111        }
112    
113          // setup EG 3 (VCO EG)      double Voice::GetSampleAttenuation() {
114          {          return pRegion->SampleAttenuation;
115            double eg3depth = RTMath::CentsToFreqRatio(pDimRgn->EG3Depth);      }
           pEG3->Trigger(eg3depth, pDimRgn->EG3Attack, Delay);  
         }  
116    
117        double Voice::GetVelocityAttenuation(uint8_t MIDIKeyVelocity) {
118            return pRegion->GetVelocityAttenuation(MIDIKeyVelocity);
119        }
120    
121          // setup LFO 1 (VCA LFO)      double Voice::GetVelocityRelease(uint8_t MIDIKeyVelocity) {
122          {          return pRegion->GetVelocityRelease(MIDIKeyVelocity);
123              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,  
                           pEngine->SampleRate,  
                           Delay);  
         }  
124    
125      #if ENABLE_FILTER      void Voice::ProcessCCEvent(RTList<Event>::Iterator& itEvent) {
126          // setup LFO 2 (VCF Cutoff LFO)          if (itEvent->Type == Event::type_control_change && itEvent->Param.CC.Controller) { // if (valid) MIDI control change event
127          {              if (pRegion->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange &&
128              uint16_t lfo2_internal_depth;                  itEvent->Param.CC.Controller == pRegion->AttenuationController.controller_number) {
129              switch (pDimRgn->LFO2Controller) {                  CrossfadeSmoother.update(AbstractEngine::CrossfadeCurve[CrossfadeAttenuation(itEvent->Param.CC.Value)]);
                 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  
130              }              }
             pLFO2->Trigger(pDimRgn->LFO2Frequency,  
                           lfo2_internal_depth,  
                           pDimRgn->LFO2ControlDepth,  
                           pEngine->ControllerTable[pLFO2->ExtController],  
                           pDimRgn->LFO2FlipPhase,  
                           pEngine->SampleRate,  
                           Delay);  
131          }          }
132      #endif // ENABLE_FILTER      }
133    
134          // setup LFO 3 (VCO LFO)      void Voice::ProcessChannelPressureEvent(RTList<Event>::Iterator& itEvent) {
135          {          if (itEvent->Type == Event::type_channel_pressure) { // if (valid) MIDI channel pressure (aftertouch) event
136              uint16_t lfo3_internal_depth;              if (pRegion->AttenuationController.type == ::gig::attenuation_ctrl_t::type_channelaftertouch) {
137              switch (pDimRgn->LFO3Controller) {                  CrossfadeSmoother.update(AbstractEngine::CrossfadeCurve[CrossfadeAttenuation(itEvent->Param.ChannelPressure.Value)]);
                 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  
138              }              }
             pLFO3->Trigger(pDimRgn->LFO3Frequency,  
                           lfo3_internal_depth,  
                           pDimRgn->LFO3ControlDepth,  
                           pEngine->ControllerTable[pLFO3->ExtController],  
                           false,  
                           pEngine->SampleRate,  
                           Delay);  
139          }          }
140        }
141    
142      #if ENABLE_FILTER      void Voice::ProcessPolyphonicKeyPressureEvent(RTList<Event>::Iterator& itEvent) {
143          #if FORCE_FILTER_USAGE          // Not used so far
144          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  
   
             #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    = pEngine->ControllerTable[VCFCutoffCtrl.controller];  
             VCFResonanceCtrl.value = pEngine->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;  
   
             FilterLeft.SetParameters(cutoff,  resonance, pEngine->SampleRate);  
             FilterRight.SetParameters(cutoff, resonance, pEngine->SampleRate);  
145    
146              FilterUpdateCounter = -1;      void Voice::ProcessCutoffEvent(RTList<Event>::Iterator& itEvent) {
147          }          int ccvalue = itEvent->Param.CC.Value;
148          else {          if (VCFCutoffCtrl.value == ccvalue) return;
149              VCFCutoffCtrl.controller    = 0;          VCFCutoffCtrl.value = ccvalue;
150              VCFResonanceCtrl.controller = 0;          if (pRegion->VCFCutoffControllerInvert)  ccvalue = 127 - ccvalue;
151          }          if (ccvalue < pRegion->VCFVelocityScale) ccvalue = pRegion->VCFVelocityScale;
152      #endif // ENABLE_FILTER          float cutoff = CutoffBase * float(ccvalue);
153            if (cutoff > 127.0f) cutoff = 127.0f;
154    
155          return 0; // success          VCFCutoffCtrl.fvalue = cutoff; // needed for initialization of fFinalCutoff next time
156            fFinalCutoff = cutoff;
157      }      }
158    
159      /**      double Voice::CalculateCrossfadeVolume(uint8_t MIDIKeyVelocity) {
160       *  Renders the audio data for this voice for the current audio fragment.          float crossfadeVolume;
161       *  The sample input data can either come from RAM (cached sample or sample          switch (pRegion->AttenuationController.type) {
162       *  part) or directly from disk. The output signal will be rendered by              case ::gig::attenuation_ctrl_t::type_channelaftertouch:
163       *  resampling / interpolation. If this voice is a disk streaming voice and                  crossfadeVolume = Engine::CrossfadeCurve[CrossfadeAttenuation(GetGigEngineChannel()->ControllerTable[128])];
      *  the voice completely played back the cached RAM part of the sample, it  
      *  will automatically switch to disk playback for the next RenderAudio()  
      *  call.  
      *  
      *  @param Samples - number of samples to be rendered in this audio fragment cycle  
      */  
     void Voice::Render(uint Samples) {  
   
         // Reset the synthesis parameter matrix  
         pEngine->ResetSynthesisParameters(Event::destination_vca, this->Volume * this->CrossfadeVolume * pEngine->GlobalVolume);  
         pEngine->ResetSynthesisParameters(Event::destination_vco, this->PitchBase);  
     #if ENABLE_FILTER  
         pEngine->ResetSynthesisParameters(Event::destination_vcfc, VCFCutoffCtrl.fvalue);  
         pEngine->ResetSynthesisParameters(Event::destination_vcfr, VCFResonanceCtrl.fvalue);  
     #endif // ENABLE_FILTER  
   
   
         // Apply events to the synthesis parameter matrix  
         ProcessEvents(Samples);  
   
   
         // Let all modulators write their parameter changes to the synthesis parameter matrix for the current audio fragment  
         pEG1->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, itTriggerEvent, this->Pos, this->PitchBase * this->PitchBend, itKillEvent);  
     #if ENABLE_FILTER  
         pEG2->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, itTriggerEvent, this->Pos, this->PitchBase * this->PitchBend);  
     #endif // ENABLE_FILTER  
         pEG3->Process(Samples);  
         pLFO1->Process(Samples);  
     #if ENABLE_FILTER  
         pLFO2->Process(Samples);  
     #endif // ENABLE_FILTER  
         pLFO3->Process(Samples);  
   
   
     #if ENABLE_FILTER  
         CalculateBiquadParameters(Samples); // calculate the final biquad filter parameters  
     #endif // ENABLE_FILTER  
   
   
         switch (this->PlaybackState) {  
   
             case playback_state_ram: {  
                     if (RAMLoop) InterpolateAndLoop(Samples, (sample_t*) pSample->GetCache().pStart, Delay);  
                     else         InterpolateNoLoop(Samples, (sample_t*) pSample->GetCache().pStart, Delay);  
                     if (DiskVoice) {  
                         // check if we reached the allowed limit of the sample RAM cache  
                         if (Pos > MaxRAMPos) {  
                             dmsg(5,("Voice: switching to disk playback (Pos=%f)\n", Pos));  
                             this->PlaybackState = playback_state_disk;  
                         }  
                     }  
                     else if (Pos >= pSample->GetCache().Size / pSample->FrameSize) {  
                         this->PlaybackState = playback_state_end;  
                     }  
                 }  
                 break;  
   
             case playback_state_disk: {  
                     if (!DiskStreamRef.pStream) {  
                         // check if the disk thread created our ordered disk stream in the meantime  
                         DiskStreamRef.pStream = pDiskThread->AskForCreatedStream(DiskStreamRef.OrderID);  
                         if (!DiskStreamRef.pStream) {  
                             std::cout << stderr << "Disk stream not available in time!" << std::endl << std::flush;  
                             KillImmediately();  
                             return;  
                         }  
                         DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (RTMath::DoubleToInt(Pos) - MaxRAMPos));  
                         Pos -= RTMath::DoubleToInt(Pos);  
                     }  
   
                     // add silence sample at the end if we reached the end of the stream (for the interpolator)  
                     if (DiskStreamRef.State == Stream::state_end && DiskStreamRef.pStream->GetReadSpace() < (pEngine->MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels) {  
                         DiskStreamRef.pStream->WriteSilence((pEngine->MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels);  
                         this->PlaybackState = playback_state_end;  
                     }  
   
                     sample_t* ptr = DiskStreamRef.pStream->GetReadPtr(); // get the current read_ptr within the ringbuffer where we read the samples from  
                     InterpolateNoLoop(Samples, ptr, Delay);  
                     DiskStreamRef.pStream->IncrementReadPos(RTMath::DoubleToInt(Pos) * pSample->Channels);  
                     Pos -= RTMath::DoubleToInt(Pos);  
                 }  
164                  break;                  break;
165                case ::gig::attenuation_ctrl_t::type_velocity:
166              case playback_state_end:                  crossfadeVolume = Engine::CrossfadeCurve[CrossfadeAttenuation(MIDIKeyVelocity)];
167                  std::cerr << "gig::Voice::Render(): entered with playback_state_end, this is a bug!\n" << std::flush;                  break;
168                case ::gig::attenuation_ctrl_t::type_controlchange: //FIXME: currently not sample accurate
169                    crossfadeVolume = Engine::CrossfadeCurve[CrossfadeAttenuation(GetGigEngineChannel()->ControllerTable[pRegion->AttenuationController.controller_number])];
170                  break;                  break;
171                case ::gig::attenuation_ctrl_t::type_none: // no crossfade defined
172                default:
173                    crossfadeVolume = 1.0f;
174          }          }
175    
176            return crossfadeVolume;
177        }
178    
179          // Reset synthesis event lists (except VCO, as VCO events apply channel wide currently)      double Voice::GetEG1ControllerValue(uint8_t MIDIKeyVelocity) {
180          pEngine->pSynthesisEvents[Event::destination_vca]->clear();          double eg1controllervalue = 0;
181      #if ENABLE_FILTER          switch (pRegion->EG1Controller.type) {
182          pEngine->pSynthesisEvents[Event::destination_vcfc]->clear();              case ::gig::eg1_ctrl_t::type_none: // no controller defined
183          pEngine->pSynthesisEvents[Event::destination_vcfr]->clear();                  eg1controllervalue = 0;
184      #endif // ENABLE_FILTER                  break;
185                case ::gig::eg1_ctrl_t::type_channelaftertouch:
186          // Reset delay                  eg1controllervalue = GetGigEngineChannel()->ControllerTable[128];
187          Delay = 0;                  break;
188                case ::gig::eg1_ctrl_t::type_velocity:
189          itTriggerEvent = Pool<Event>::Iterator();                  eg1controllervalue = MIDIKeyVelocity;
190                    break;
191          // If sample stream or release stage finished, kill the voice              case ::gig::eg1_ctrl_t::type_controlchange: // MIDI control change controller
192          if (PlaybackState == playback_state_end || pEG1->GetStage() == EGADSR::stage_end) KillImmediately();                  eg1controllervalue = GetGigEngineChannel()->ControllerTable[pRegion->EG1Controller.controller_number];
193      }                  break;
   
     /**  
      *  Resets voice variables. Should only be called if rendering process is  
      *  suspended / not running.  
      */  
     void Voice::Reset() {  
         pLFO1->Reset();  
         pLFO2->Reset();  
         pLFO3->Reset();  
         DiskStreamRef.pStream = NULL;  
         DiskStreamRef.hStream = 0;  
         DiskStreamRef.State   = Stream::state_unused;  
         DiskStreamRef.OrderID = 0;  
         PlaybackState = playback_state_end;  
         itTriggerEvent = Pool<Event>::Iterator();  
         itKillEvent    = Pool<Event>::Iterator();  
     }  
   
     /**  
      *  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  
         RTList<Event>::Iterator itCCEvent = pEngine->pCCEvents->first();  
         if (Delay) { // skip events that happened before this voice was triggered  
             while (itCCEvent && itCCEvent->FragmentPos() <= Delay) ++itCCEvent;  
         }  
         while (itCCEvent) {  
             if (itCCEvent->Param.CC.Controller) { // if valid MIDI controller  
                 #if ENABLE_FILTER  
                 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;  
                 }  
                 #endif // ENABLE_FILTER  
                 if (itCCEvent->Param.CC.Controller == pLFO1->ExtController) {  
                     pLFO1->SendEvent(itCCEvent);  
                 }  
                 #if ENABLE_FILTER  
                 if (itCCEvent->Param.CC.Controller == pLFO2->ExtController) {  
                     pLFO2->SendEvent(itCCEvent);  
                 }  
                 #endif // ENABLE_FILTER  
                 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;  
                 }  
             }  
   
             ++itCCEvent;  
194          }          }
195            if (pRegion->EG1ControllerInvert) eg1controllervalue = 127 - eg1controllervalue;
196    
197            return eg1controllervalue;
198        }
199    
200          // process pitch events      Voice::EGInfo Voice::CalculateEG1ControllerInfluence(double eg1ControllerValue) {
201          {          EGInfo eg;
202              RTList<Event>* pVCOEventList = pEngine->pSynthesisEvents[Event::destination_vco];          // (eg1attack is different from the others)
203              RTList<Event>::Iterator itVCOEvent = pVCOEventList->first();          if (pRegion->EG1Attack < 1e-8 && // attack in gig == 0
204              if (Delay) { // skip events that happened before this voice was triggered              (pRegion->EG1ControllerAttackInfluence == 0 ||
205                  while (itVCOEvent && itVCOEvent->FragmentPos() <= Delay) ++itVCOEvent;               eg1ControllerValue <= 10)) { // strange GSt special case
206              }              eg.Attack = 0; // this will force the attack to be 0 in the call to EG1.trigger
207              // apply old pitchbend value until first pitch event occurs          } else {
208              if (this->PitchBend != 1.0) {              eg.Attack  = (pRegion->EG1ControllerAttackInfluence)  ?
209                  uint end = (itVCOEvent) ? itVCOEvent->FragmentPos() : Samples;                  1 + 0.031 * (double) (pRegion->EG1ControllerAttackInfluence == 1 ?
210                  for (uint i = Delay; i < end; i++) {                                        1 : 1 << pRegion->EG1ControllerAttackInfluence) * eg1ControllerValue : 1.0;
211                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= this->PitchBend;          }
212                  }          eg.Decay   = (pRegion->EG1ControllerDecayInfluence)   ? 1 + 0.00775 * (double) (1 << pRegion->EG1ControllerDecayInfluence)   * eg1ControllerValue : 1.0;
213              }          eg.Release = (pRegion->EG1ControllerReleaseInfluence) ? 1 + 0.00775 * (double) (1 << pRegion->EG1ControllerReleaseInfluence) * eg1ControllerValue : 1.0;
214              float pitch;  
215              while (itVCOEvent) {          return eg;
216                  RTList<Event>::Iterator itNextVCOEvent = itVCOEvent;      }
217                  ++itNextVCOEvent;  
218        double Voice::GetEG2ControllerValue(uint8_t MIDIKeyVelocity) {
219                  // calculate the influence length of this event (in sample points)          double eg2controllervalue = 0;
220                  uint end = (itNextVCOEvent) ? itNextVCOEvent->FragmentPos() : Samples;          switch (pRegion->EG2Controller.type) {
221                case ::gig::eg2_ctrl_t::type_none: // no controller defined
222                  pitch = RTMath::CentsToFreqRatio(((double) itVCOEvent->Param.Pitch.Pitch / 8192.0) * 200.0); // +-two semitones = +-200 cents                  eg2controllervalue = 0;
223                    break;
224                  // apply pitch value to the pitch parameter sequence              case ::gig::eg2_ctrl_t::type_channelaftertouch:
225                  for (uint i = itVCOEvent->FragmentPos(); i < end; i++) {                  eg2controllervalue = GetGigEngineChannel()->ControllerTable[128];
226                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= pitch;                  break;
227                  }              case ::gig::eg2_ctrl_t::type_velocity:
228                    eg2controllervalue = MIDIKeyVelocity;
229                  itVCOEvent = itNextVCOEvent;                  break;
230              }              case ::gig::eg2_ctrl_t::type_controlchange: // MIDI control change controller
231              if (!pVCOEventList->isEmpty()) this->PitchBend = pitch;                  eg2controllervalue = GetGigEngineChannel()->ControllerTable[pRegion->EG2Controller.controller_number];
232                    break;
233          }          }
234            if (pRegion->EG2ControllerInvert) eg2controllervalue = 127 - eg2controllervalue;
235    
236          // process volume / attenuation events (TODO: we only handle and _expect_ crossfade events here ATM !)          return eg2controllervalue;
237          {      }
             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 * pEngine->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;  
                 }  
238    
239                  itVCAEvent = itNextVCAEvent;      Voice::EGInfo Voice::CalculateEG2ControllerInfluence(double eg2ControllerValue) {
240              }          EGInfo eg;
241              if (!pVCAEventList->isEmpty()) this->CrossfadeVolume = crossfadevolume;          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      #if ENABLE_FILTER          return eg;
246          // process filter cutoff events      }
         {  
             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;  
                 }  
247    
248                  itCutoffEvent = itNextCutoffEvent;      void Voice::InitLFO1() {
249              }          uint16_t lfo1_internal_depth;
250              if (!pCutoffEventList->isEmpty()) VCFCutoffCtrl.fvalue = cutoff; // needed for initialization of parameter matrix next time          switch (pRegion->LFO1Controller) {
251                case ::gig::lfo1_ctrl_internal:
252                    lfo1_internal_depth  = pRegion->LFO1InternalDepth;
253                    pLFO1->ExtController = 0; // no external controller
254                    bLFO1Enabled         = (lfo1_internal_depth > 0);
255                    break;
256                case ::gig::lfo1_ctrl_modwheel:
257                    lfo1_internal_depth  = 0;
258                    pLFO1->ExtController = 1; // MIDI controller 1
259                    bLFO1Enabled         = (pRegion->LFO1ControlDepth > 0);
260                    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          // process filter resonance events      void Voice::InitLFO2() {
307          {          uint16_t lfo2_internal_depth;
308              RTList<Event>* pResonanceEventList = pEngine->pSynthesisEvents[Event::destination_vcfr];          switch (pRegion->LFO2Controller) {
309              RTList<Event>::Iterator itResonanceEvent = pResonanceEventList->first();              case ::gig::lfo2_ctrl_internal:
310              if (Delay) { // skip events that happened before this voice was triggered                  lfo2_internal_depth  = pRegion->LFO2InternalDepth;
311                  while (itResonanceEvent && itResonanceEvent->FragmentPos() <= Delay) ++itResonanceEvent;                  pLFO2->ExtController = 0; // no external controller
312              }                  bLFO2Enabled         = (lfo2_internal_depth > 0);
313              while (itResonanceEvent) {                  break;
314                  RTList<Event>::Iterator itNextResonanceEvent = itResonanceEvent;              case ::gig::lfo2_ctrl_modwheel:
315                  ++itNextResonanceEvent;                  lfo2_internal_depth  = 0;
316                    pLFO2->ExtController = 1; // MIDI controller 1
317                  // calculate the influence length of this event (in sample points)                  bLFO2Enabled         = (pRegion->LFO2ControlDepth > 0);
318                  uint end = (itNextResonanceEvent) ? itNextResonanceEvent->FragmentPos() : Samples;                  break;
319                case ::gig::lfo2_ctrl_foot:
320                  // convert absolute controller value to differential                  lfo2_internal_depth  = 0;
321                  int ctrldelta = itResonanceEvent->Param.CC.Value - VCFResonanceCtrl.value;                  pLFO2->ExtController = 4; // MIDI controller 4
322                  VCFResonanceCtrl.value = itResonanceEvent->Param.CC.Value;                  bLFO2Enabled         = (pRegion->LFO2ControlDepth > 0);
323                    break;
324                  float resonancedelta = (float) ctrldelta * 0.00787f; // 0.0..1.0              case ::gig::lfo2_ctrl_internal_modwheel:
325                    lfo2_internal_depth  = pRegion->LFO2InternalDepth;
326                  // apply cutoff frequency to the cutoff parameter sequence                  pLFO2->ExtController = 1; // MIDI controller 1
327                  for (uint i = itResonanceEvent->FragmentPos(); i < end; i++) {                  bLFO2Enabled         = (lfo2_internal_depth > 0 || pRegion->LFO2ControlDepth > 0);
328                      pEngine->pSynthesisParameters[Event::destination_vcfr][i] += resonancedelta;                  break;
329                  }              case ::gig::lfo2_ctrl_internal_foot:
330                    lfo2_internal_depth  = pRegion->LFO2InternalDepth;
331                  itResonanceEvent = itNextResonanceEvent;                  pLFO2->ExtController = 4; // MIDI controller 4
332              }                  bLFO2Enabled         = (lfo2_internal_depth > 0 || pRegion->LFO2ControlDepth > 0);
333              if (!pResonanceEventList->isEmpty()) VCFResonanceCtrl.fvalue = pResonanceEventList->last()->Param.CC.Value * 0.00787f; // needed for initialization of parameter matrix next time                  break;
334                default:
335                    lfo2_internal_depth  = 0;
336                    pLFO2->ExtController = 0; // no external controller
337                    bLFO2Enabled         = false;
338            }
339            if (bLFO2Enabled) {
340                pLFO2->trigger(fromGigLfoWave(pRegion->LFO2WaveForm),
341                               pRegion->LFO2Frequency,
342                               pRegion->LFO2Phase,
343                               LFO::start_level_mid, // see https://sourceforge.net/p/linuxsampler/mailman/linuxsampler-devel/thread/2189307.cNP0Xbctxq%40silver/#msg36774029
344                               lfo2_internal_depth,
345                               pRegion->LFO2ControlDepth,
346                               pRegion->LFO2FlipPhase,
347                               pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
348                pLFO2->updateByMIDICtrlValue(pLFO2->ExtController ? GetGigEngineChannel()->ControllerTable[pLFO2->ExtController] : 0);
349                pLFO2->setScriptDepthFactor(
350                    pNote->Override.CutoffLFODepth.Value,
351                    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          }          }
     #endif // ENABLE_FILTER  
358      }      }
359    
360      #if ENABLE_FILTER      void Voice::InitLFO3() {
361      /**          uint16_t lfo3_internal_depth;
362       * Calculate all necessary, final biquad filter parameters.          switch (pRegion->LFO3Controller) {
363       *              case ::gig::lfo3_ctrl_internal:
364       * @param Samples - number of samples to be rendered in this audio fragment cycle                  lfo3_internal_depth  = pRegion->LFO3InternalDepth;
365       */                  pLFO3->ExtController = 0; // no external controller
366      void Voice::CalculateBiquadParameters(uint Samples) {                  bLFO3Enabled         = (lfo3_internal_depth > 0);
367          if (!FilterLeft.Enabled) return;                  break;
368                case ::gig::lfo3_ctrl_modwheel:
369          biquad_param_t bqbase;                  lfo3_internal_depth  = 0;
370          biquad_param_t bqmain;                  pLFO3->ExtController = 1; // MIDI controller 1
371          float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0];                  bLFO3Enabled         = (pRegion->LFO3ControlDepth > 0);
372          float prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][0];                  break;
373          FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);              case ::gig::lfo3_ctrl_aftertouch:
374          pEngine->pBasicFilterParameters[0] = bqbase;                  lfo3_internal_depth  = 0;
375          pEngine->pMainFilterParameters[0]  = bqmain;                  pLFO3->ExtController = CTRL_TABLE_IDX_AFTERTOUCH;
376                    bLFO3Enabled         = true;
377          float* bq;                  break;
378          for (int i = 1; i < Samples; i++) {              case ::gig::lfo3_ctrl_internal_modwheel:
379              // recalculate biquad parameters if cutoff or resonance differ from previous sample point                  lfo3_internal_depth  = pRegion->LFO3InternalDepth;
380              if (!(i & FILTER_UPDATE_MASK)) if (pEngine->pSynthesisParameters[Event::destination_vcfr][i] != prev_res ||                  pLFO3->ExtController = 1; // MIDI controller 1
381                                                 pEngine->pSynthesisParameters[Event::destination_vcfc][i] != prev_cutoff) {                  bLFO3Enabled         = (lfo3_internal_depth > 0 || pRegion->LFO3ControlDepth > 0);
382                  prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][i];                  break;
383                  prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][i];              case ::gig::lfo3_ctrl_internal_aftertouch:
384                  FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);                  lfo3_internal_depth  = pRegion->LFO3InternalDepth;
385              }                  pLFO3->ExtController = CTRL_TABLE_IDX_AFTERTOUCH;
386                    bLFO3Enabled         = (lfo3_internal_depth > 0 || pRegion->LFO3ControlDepth > 0);
387              //same as 'pEngine->pBasicFilterParameters[i] = bqbase;'                  break;
388              bq    = (float*) &pEngine->pBasicFilterParameters[i];              default:
389              bq[0] = bqbase.a1;                  lfo3_internal_depth  = 0;
390              bq[1] = bqbase.a2;                  pLFO3->ExtController = 0; // no external controller
391              bq[2] = bqbase.b0;                  bLFO3Enabled         = false;
392              bq[3] = bqbase.b1;          }
393              bq[4] = bqbase.b2;          if (bLFO3Enabled) {
394                pLFO3->trigger(fromGigLfoWave(pRegion->LFO3WaveForm),
395              // same as 'pEngine->pMainFilterParameters[i] = bqmain;'                             pRegion->LFO3Frequency,
396              bq    = (float*) &pEngine->pMainFilterParameters[i];                             pRegion->LFO3Phase,
397              bq[0] = bqmain.a1;                             LFO::start_level_max, // see https://sourceforge.net/p/linuxsampler/mailman/linuxsampler-devel/thread/2189307.cNP0Xbctxq%40silver/#msg36774029
398              bq[1] = bqmain.a2;                             lfo3_internal_depth,
399              bq[2] = bqmain.b0;                             pRegion->LFO3ControlDepth,
400              bq[3] = bqmain.b1;                             pRegion->LFO3FlipPhase,
401              bq[4] = bqmain.b2;                             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      }      }
     #endif // ENABLE_FILTER  
413    
414      /**      float Voice::CalculateCutoffBase(uint8_t MIDIKeyVelocity) {
415       *  Interpolates the input audio data (without looping).          float cutoff = pRegion->GetVelocityCutoff(MIDIKeyVelocity);
416       *          if (pRegion->VCFKeyboardTracking) {
417       *  @param Samples - number of sample points to be rendered in this audio              cutoff *= RTMath::CentsToFreqRatioUnlimited((MIDIKey() - pRegion->VCFKeyboardTrackingBreakpoint) * 100);
418       *                   fragment cycle          }
419       *  @param pSrc    - pointer to input sample data          return cutoff;
420       *  @param Skip    - number of sample points to skip in output buffer      }
421       */  
422      void Voice::InterpolateNoLoop(uint Samples, sample_t* pSrc, uint Skip) {      float Voice::CalculateFinalCutoff(float cutoffBase) {
423          int i = Skip;          int cvalue;
424            if (VCFCutoffCtrl.controller) {
425          // FIXME: assuming either mono or stereo              cvalue = GetGigEngineChannel()->ControllerTable[VCFCutoffCtrl.controller];
426          if (this->pSample->Channels == 2) { // Stereo Sample              if (pRegion->VCFCutoffControllerInvert) cvalue = 127 - cvalue;
427              while (i < Samples) InterpolateStereo(pSrc, i);              // VCFVelocityScale in this case means Minimum cutoff
428                if (cvalue < pRegion->VCFVelocityScale) cvalue = pRegion->VCFVelocityScale;
429          }          }
430          else { // Mono Sample          else {
431              while (i < Samples) InterpolateMono(pSrc, i);              cvalue = pRegion->VCFCutoff;
432          }          }
433            float fco = cutoffBase * float(cvalue);
434            if (fco > 127.0f) fco = 127.0f;
435    
436            return fco;
437      }      }
438    
439      /**      uint8_t Voice::GetVCFCutoffCtrl() {
440       *  Interpolates the input audio data, this method honors looping.          uint8_t ctrl;
441       *          switch (pRegion->VCFCutoffController) {
442       *  @param Samples - number of sample points to be rendered in this audio              case ::gig::vcf_cutoff_ctrl_modwheel:
443       *                   fragment cycle                  ctrl = 1;
444       *  @param pSrc    - pointer to input sample data                  break;
445       *  @param Skip    - number of sample points to skip in output buffer              case ::gig::vcf_cutoff_ctrl_effect1:
446       */                  ctrl = 12;
447      void Voice::InterpolateAndLoop(uint Samples, sample_t* pSrc, uint Skip) {                  break;
448          int i = Skip;              case ::gig::vcf_cutoff_ctrl_effect2:
449                    ctrl = 13;
450          // FIXME: assuming either mono or stereo                  break;
451          if (pSample->Channels == 2) { // Stereo Sample              case ::gig::vcf_cutoff_ctrl_breath:
452              if (pSample->LoopPlayCount) {                  ctrl = 2;
453                  // render loop (loop count limited)                  break;
454                  while (i < Samples && LoopCyclesLeft) {              case ::gig::vcf_cutoff_ctrl_foot:
455                      InterpolateStereo(pSrc, i);                  ctrl = 4;
456                      if (Pos > pSample->LoopEnd) {                  break;
457                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;              case ::gig::vcf_cutoff_ctrl_sustainpedal:
458                          LoopCyclesLeft--;                  ctrl = 64;
459                      }                  break;
460                  }              case ::gig::vcf_cutoff_ctrl_softpedal:
461                  // render on without loop                  ctrl = 67;
462                  while (i < Samples) InterpolateStereo(pSrc, i);                  break;
463              }              case ::gig::vcf_cutoff_ctrl_genpurpose7:
464              else { // render loop (endless loop)                  ctrl = 82;
465                  while (i < Samples) {                  break;
466                      InterpolateStereo(pSrc, i);              case ::gig::vcf_cutoff_ctrl_genpurpose8:
467                      if (Pos > pSample->LoopEnd) {                  ctrl = 83;
468                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);                  break;
469                      }              case ::gig::vcf_cutoff_ctrl_aftertouch:
470                  }                  ctrl = CTRL_TABLE_IDX_AFTERTOUCH;
471              }                  break;
472          }              case ::gig::vcf_cutoff_ctrl_none:
473          else { // Mono Sample              default:
474              if (pSample->LoopPlayCount) {                  ctrl = 0;
475                  // render loop (loop count limited)                  break;
                 while (i < Samples && LoopCyclesLeft) {  
                     InterpolateMono(pSrc, i);  
                     if (Pos > pSample->LoopEnd) {  
                         Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;  
                         LoopCyclesLeft--;  
                     }  
                 }  
                 // render on without loop  
                 while (i < Samples) InterpolateMono(pSrc, i);  
             }  
             else { // render loop (endless loop)  
                 while (i < Samples) {  
                     InterpolateMono(pSrc, i);  
                     if (Pos > pSample->LoopEnd) {  
                         Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;  
                     }  
                 }  
             }  
476          }          }
477    
478            return ctrl;
479      }      }
480    
481      /**      uint8_t Voice::GetVCFResonanceCtrl() {
482       *  Immediately kill the voice. This method should not be used to kill          uint8_t ctrl;
483       *  a normal, active voice, because it doesn't take care of things like          switch (pRegion->VCFResonanceController) {
484       *  fading down the volume level to avoid clicks and regular processing              case ::gig::vcf_res_ctrl_genpurpose3:
485       *  until the kill event actually occured!                  ctrl = 18;
486       *                  break;
487       *  @see Kill()              case ::gig::vcf_res_ctrl_genpurpose4:
488       */                  ctrl = 19;
489      void Voice::KillImmediately() {                  break;
490          if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {              case ::gig::vcf_res_ctrl_genpurpose5:
491              pDiskThread->OrderDeletionOfStream(&DiskStreamRef);                  ctrl = 80;
492                    break;
493                case ::gig::vcf_res_ctrl_genpurpose6:
494                    ctrl = 81;
495                    break;
496                case ::gig::vcf_res_ctrl_none:
497                default:
498                    ctrl = 0;
499          }          }
         Reset();  
     }  
500    
501      /**          return ctrl;
502       *  Kill the voice in regular sense. Let the voice render audio until      }
      *  the kill event actually occured and then fade down the volume level  
      *  very quickly and let the voice die finally. Unlike a normal release  
      *  of a voice, a kill process cannot be cancalled and is therefore  
      *  usually used for voice stealing and key group conflicts.  
      *  
      *  @param itKillEvent - event which caused the voice to be killed  
      */  
     void Voice::Kill(Pool<Event>::Iterator& itKillEvent) {  
         //FIXME: just two sanity checks for debugging, can be removed  
         if (!itKillEvent) dmsg(1,("gig::Voice::Kill(): ERROR, !itKillEvent !!!\n"));  
         if (itKillEvent && !itKillEvent.isValid()) dmsg(1,("gig::Voice::Kill(): ERROR, itKillEvent invalid !!!\n"));  
503    
504          if (itTriggerEvent && itKillEvent->FragmentPos() <= itTriggerEvent->FragmentPos()) return;      void Voice::TriggerEG1(const EGInfo& egInfo, double velrelease, double velocityAttenuation, uint sampleRate, uint8_t velocity) {
505          this->itKillEvent = itKillEvent;          EG1.setStateOptions(
506                pRegion->EG1Options.AttackCancel,
507                pRegion->EG1Options.AttackHoldCancel,
508                pRegion->EG1Options.Decay1Cancel,
509                pRegion->EG1Options.Decay2Cancel,
510                pRegion->EG1Options.ReleaseCancel
511            );
512            EG1.trigger(pRegion->EG1PreAttack,
513                        (pNote && pNote->Override.Attack.isFinal()) ?
514                            pNote->Override.Attack.Value :
515                            RTMath::Max(pRegion->EG1Attack, 0.0316) * egInfo.Attack,
516                        pRegion->EG1Hold,
517                        (pNote && pNote->Override.Decay.isFinal()) ?
518                            pNote->Override.Decay.Value :
519                            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.287  
changed lines
  Added in v.3625

  ViewVC Help
Powered by ViewVC