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

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

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

revision 2012 by iliev, Fri Oct 23 17:53:17 2009 UTC revision 2218 by iliev, Thu Jul 28 08:05:57 2011 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 - 2009 Christian Schoenebeck                       *   *   Copyright (C) 2005 - 2008 Christian Schoenebeck                       *
7     *   Copyright (C) 2009 - 2011 Christian Schoenebeck and Grigor Iliev      *
8   *                                                                         *   *                                                                         *
9   *   This program is free software; you can redistribute it and/or modify  *   *   This program is free software; you can redistribute it and/or modify  *
10   *   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 22 
22   *   MA  02111-1307  USA                                                   *   *   MA  02111-1307  USA                                                   *
23   ***************************************************************************/   ***************************************************************************/
24    
25  #include "../../common/Features.h"  #include "Voice.h"
26  #include "../gig/Synthesizer.h"  
 #include "../gig/Profiler.h"  
27  #include "Engine.h"  #include "Engine.h"
28  #include "EngineChannel.h"  #include "EngineChannel.h"
29    
30  #include "Voice.h"  #define LN_10_DIV_20 0.115129254649702
31    
32  namespace LinuxSampler { namespace sfz {  namespace LinuxSampler { namespace sfz {
33    
34      typedef LinuxSampler::gig::Profiler Profiler; // TODO: remove      typedef LinuxSampler::VoiceBase<EngineChannel, ::sfz::Region, Sample, DiskThread> SfzVoice;
35        Voice::Voice(): SignalRack(this), SfzVoice(&SignalRack) {
     Voice::Voice() {  
36          pEngine     = NULL;          pEngine     = NULL;
         pDiskThread = NULL;  
         PlaybackState = playback_state_end;  
         pLFO1 = new LFOUnsigned(1.0f);  // amplitude EG (0..1 range)  
         pLFO2 = new LFOUnsigned(1.0f);  // filter EG (0..1 range)  
         pLFO3 = new LFOSigned(1200.0f); // pitch EG (-1200..+1200 range)  
         KeyGroup = 0;  
         SynthesisMode = 0; // set all mode bits to 0 first  
         // select synthesis implementation (asm core is not supported ATM)  
         #if 0 // CONFIG_ASM && ARCH_X86  
         SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, Features::supportsMMX() && Features::supportsSSE());  
         #else  
         SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, false);  
         #endif  
         SYNTHESIS_MODE_SET_PROFILING(SynthesisMode, Profiler::isEnabled());  
   
         finalSynthesisParameters.filterLeft.Reset();  
         finalSynthesisParameters.filterRight.Reset();  
37      }      }
38    
39      Voice::~Voice() {      Voice::~Voice() {
40          if (pLFO1) delete pLFO1;  
41          if (pLFO2) delete pLFO2;      }
42          if (pLFO3) delete pLFO3;  
43        EngineChannel* Voice::GetSfzEngineChannel() {
44            return static_cast<EngineChannel*>(pEngineChannel);
45      }      }
46    
47      void Voice::SetEngine(LinuxSampler::Engine* pEngine) {      void Voice::SetEngine(LinuxSampler::Engine* pEngine) {
# Line 67  namespace LinuxSampler { namespace sfz { Line 51  namespace LinuxSampler { namespace sfz {
51          dmsg(6,("Voice::SetEngine()\n"));          dmsg(6,("Voice::SetEngine()\n"));
52      }      }
53    
54      /**      Voice::SampleInfo Voice::GetSampleInfo() {
55       *  Initializes and triggers the voice, a disk stream will be launched if          SampleInfo si;
56       *  needed.          si.SampleRate       = pSample->GetSampleRate();
57       *          si.ChannelCount     = pSample->GetChannelCount();
58       *  @param pEngineChannel - engine channel on which this voice was ordered          si.FrameSize        = pSample->GetFrameSize();
59       *  @param itNoteOnEvent  - event that caused triggering of this voice          si.BitDepth         = (pSample->GetFrameSize() / pSample->GetChannelCount()) * 8;
60       *  @param PitchBend      - MIDI detune factor (-8192 ... +8191)          si.TotalFrameCount  = pSample->GetTotalFrameCount();
61       *  @param pRegion        - points to the dimension region which provides sample wave(s) and articulation data  
62       *  @param VoiceType      - type of this voice          si.HasLoops       = pRegion->HasLoop();
63       *  @param iKeyGroup      - a value > 0 defines a key group in which this voice is member of          si.LoopStart      = pRegion->GetLoopStart();
64       *  @returns 0 on success, a value < 0 if the voice wasn't triggered          si.LoopLength     = pRegion->GetLoopEnd() - pRegion->GetLoopStart();
65       *           (either due to an error or e.g. because no region is          si.LoopPlayCount  = pRegion->GetLoopCount();
66       *           defined for the given key)          si.Unpitched      = pRegion->pitch_keytrack == 0;
67       */          return si;
68      int Voice::Trigger(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent, int PitchBend, ::sfz::Region* pRegion, type_t VoiceType, int iKeyGroup) {      }
69          this->pEngineChannel = pEngineChannel;  
70          this->pRegion        = pRegion;      Voice::RegionInfo Voice::GetRegionInfo() {
71          Orphan = false;          RegionInfo ri;
72            ri.UnityNote = pRegion->pitch_keycenter;
73          #if CONFIG_DEVMODE          ri.FineTune  = pRegion->tune + pRegion->transpose * 100;
74          if (itNoteOnEvent->FragmentPos() > pEngine->MaxSamplesPerCycle) { // just a sanity check for debugging          ri.Pan       = int(pRegion->pan * 0.63); // convert from -100..100 to -64..63
75              dmsg(1,("Voice::Trigger(): ERROR, TriggerDelay > Totalsamples\n"));          ri.SampleStartOffset = pRegion->offset ? *(pRegion->offset) : 0;
76          }  
77          #endif // CONFIG_DEVMODE          ri.EG2PreAttack        = pRegion->fileg_start * 10;
78            ri.EG2Attack           = pRegion->fileg_attack;
79            //ri.EG2Hold             = pRegion->fileg_hold; // TODO:
80            ri.EG2Decay1           = pRegion->fileg_decay;
81            ri.EG2Decay2           = pRegion->fileg_decay;
82            ri.EG2Sustain          = pRegion->fileg_sustain * 10;
83            ri.EG2InfiniteSustain  = true;
84            ri.EG2Release          = pRegion->fileg_release;
85    
86            ri.EG3Attack     = pRegion->pitcheg_attack;
87            ri.EG3Depth      = 0; // TODO:
88            ri.VCFEnabled    = pRegion->cutoff;
89            switch (pRegion->fil_type) {
90            case ::sfz::LPF_1P:
91                ri.VCFType = Filter::vcf_type_1p_lowpass;
92                break;
93            case ::sfz::LPF_2P:
94                ri.VCFType = Filter::vcf_type_2p_lowpass;
95                break;
96            case ::sfz::LPF_4P:
97                ri.VCFType = Filter::vcf_type_4p_lowpass;
98                break;
99            case ::sfz::LPF_6P:
100                ri.VCFType = Filter::vcf_type_6p_lowpass;
101                break;
102            case ::sfz::HPF_1P:
103                ri.VCFType = Filter::vcf_type_1p_highpass;
104                break;
105            case ::sfz::HPF_2P:
106                ri.VCFType = Filter::vcf_type_2p_highpass;
107                break;
108            case ::sfz::HPF_4P:
109                ri.VCFType = Filter::vcf_type_4p_highpass;
110                break;
111            case ::sfz::HPF_6P:
112                ri.VCFType = Filter::vcf_type_6p_highpass;
113                break;
114            case ::sfz::BPF_1P:
115            case ::sfz::BPF_2P:
116                ri.VCFType = Filter::vcf_type_2p_bandpass;
117                break;
118            case ::sfz::BRF_1P:
119            case ::sfz::BRF_2P:
120                ri.VCFType = Filter::vcf_type_2p_bandreject;
121                break;
122            case ::sfz::APF_1P:
123            case ::sfz::PKF_2P:
124            default:
125                ri.VCFEnabled = false;
126                break;
127            }
128    
129            ri.VCFResonance  = pRegion->resonance;
130    
131            // rt_decay is in dB. Precalculate a suitable value for exp in
132            // GetReleaseTriggerAttenuation: -ln(10) / 20 * rt_decay
133            ri.ReleaseTriggerDecay = -LN_10_DIV_20 * pRegion->rt_decay;
134    
135            return ri;
136        }
137    
138        Voice::InstrumentInfo Voice::GetInstrumentInfo() {
139            InstrumentInfo ii;
140            ii.FineTune = 0; // TODO:
141            ii.PitchbendRange = 2; // TODO:
142    
143            return ii;
144        }
145    
146        double Voice::GetSampleAttenuation() {
147            return exp(LN_10_DIV_20 * pRegion->volume);
148        }
149    
150        double Voice::GetVelocityAttenuation(uint8_t MIDIKeyVelocity) {
151            return pRegion->amp_velcurve[MIDIKeyVelocity];
152        }
153    
154        double Voice::GetVelocityRelease(uint8_t MIDIKeyVelocity) {
155            return 127.0 / MIDIKeyVelocity;
156        }
157    
158        void Voice::ProcessCCEvent(RTList<Event>::Iterator& itEvent) {
159            /*if (itEvent->Type == Event::type_control_change && itEvent->Param.CC.Controller) { // if (valid) MIDI control change event
160                if (pRegion->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange &&
161                    itEvent->Param.CC.Controller == pRegion->AttenuationController.controller_number) {
162                    CrossfadeSmoother.update(AbstractEngine::CrossfadeCurve[CrossfadeAttenuation(itEvent->Param.CC.Value)]);
163                }
164            }*/ // TODO: ^^^
165        }
166    
167          Type            = VoiceType;      void Voice::ProcessCutoffEvent(RTList<Event>::Iterator& itEvent) {
168          MIDIKey         = itNoteOnEvent->Param.Note.Key;          int ccvalue = itEvent->Param.CC.Value;
169          PlaybackState   = playback_state_init; // mark voice as triggered, but no audio rendered yet          if (VCFCutoffCtrl.value == ccvalue) return;
170          Delay           = itNoteOnEvent->FragmentPos();          VCFCutoffCtrl.value = ccvalue;
         itTriggerEvent  = itNoteOnEvent;  
         itKillEvent     = Pool<Event>::Iterator();  
         KeyGroup        = iKeyGroup;  
         pSample         = pRegion->pSample; // sample won't change until the voice is finished  
   
         /*// calculate volume  
         const double velocityAttenuation = pRegion->GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity);  
   
         // For 16 bit samples, we downscale by 32768 to convert from  
         // int16 value range to DSP value range (which is  
         // -1.0..1.0). For 24 bit, we downscale from int32.  
         float volume = velocityAttenuation / (pSample->BitDepth == 16 ? 32768.0f : 32768.0f * 65536.0f);  
   
         float volume = pRegion->SampleAttenuation * pEngineChannel->GlobalVolume * GLOBAL_VOLUME;  
          */ // TODO: ^^^  
         float volume = pEngineChannel->GlobalVolume * GLOBAL_VOLUME;  
   
         // the volume of release triggered samples depends on note length  
         /**if (Type == type_release_trigger) {  
             float noteLength = float(pEngine->FrameTime + Delay -  
                                      pEngineChannel->pMIDIKeyInfo[MIDIKey].NoteOnTime) / pEngine->SampleRate;  
             float attenuation = 1 - 0.01053 * (256 >> pRegion->ReleaseTriggerDecay) * noteLength;  
             if (attenuation <= 0) return -1;  
             volume *= attenuation;  
         }  
          */ // TODO: ^^^  
171    
172          // select channel mode (mono or stereo)          float cutoff = CutoffBase * RTMath::CentsToFreqRatioUnlimited(
173          SYNTHESIS_MODE_SET_CHANNELS(SynthesisMode, pSample->GetChannelCount() == 2);              ccvalue / 127.0f * pRegion->cutoff_oncc[VCFCutoffCtrl.controller]);
174          // select bit depth (16 or 24)          if (cutoff > 0.49 * pEngine->SampleRate) cutoff = 0.49 * pEngine->SampleRate;
         SYNTHESIS_MODE_SET_BITDEPTH24(SynthesisMode, (pSample->GetFrameSize() / pSample->GetChannelCount()) > 2);  
175    
176          // get starting crossfade volume level          VCFCutoffCtrl.fvalue = cutoff; // needed for initialization of fFinalCutoff next time
177            fFinalCutoff = cutoff;
178        }
179    
180        double Voice::CalculateCrossfadeVolume(uint8_t MIDIKeyVelocity) {
181          /*float crossfadeVolume;          /*float crossfadeVolume;
182          switch (pRegion->AttenuationController.type) {          switch (pRegion->AttenuationController.type) {
183              case ::gig::attenuation_ctrl_t::type_channelaftertouch:              case ::gig::attenuation_ctrl_t::type_channelaftertouch:
184                  crossfadeVolume = Engine::CrossfadeCurve[CrossfadeAttenuation(pEngineChannel->ControllerTable[128])];                  crossfadeVolume = Engine::CrossfadeCurve[CrossfadeAttenuation(GetSfzEngineChannel()->ControllerTable[128])];
185                  break;                  break;
186              case ::gig::attenuation_ctrl_t::type_velocity:              case ::gig::attenuation_ctrl_t::type_velocity:
187                  crossfadeVolume = Engine::CrossfadeCurve[CrossfadeAttenuation(itNoteOnEvent->Param.Note.Velocity)];                  crossfadeVolume = Engine::CrossfadeCurve[CrossfadeAttenuation(MIDIKeyVelocity)];
188                  break;                  break;
189              case ::gig::attenuation_ctrl_t::type_controlchange: //FIXME: currently not sample accurate              case ::gig::attenuation_ctrl_t::type_controlchange: //FIXME: currently not sample accurate
190                  crossfadeVolume = Engine::CrossfadeCurve[CrossfadeAttenuation(pEngineChannel->ControllerTable[pRegion->AttenuationController.controller_number])];                  crossfadeVolume = Engine::CrossfadeCurve[CrossfadeAttenuation(GetSfzEngineChannel()->ControllerTable[pRegion->AttenuationController.controller_number])];
191                  break;                  break;
192              case ::gig::attenuation_ctrl_t::type_none: // no crossfade defined              case ::gig::attenuation_ctrl_t::type_none: // no crossfade defined
193              default:              default:
194                  crossfadeVolume = 1.0f;                  crossfadeVolume = 1.0f;
         }*/ // TODO: ^^^  
   
         VolumeLeft  = volume * Engine::PanCurve[64 - pRegion->pan];  
         VolumeRight = volume * Engine::PanCurve[64 + pRegion->pan];  
   
         float subfragmentRate = pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;  
         //CrossfadeSmoother.trigger(crossfadeVolume, subfragmentRate); // TODO:  
         VolumeSmoother.trigger(pEngineChannel->MidiVolume, subfragmentRate);  
         PanLeftSmoother.trigger(pEngineChannel->GlobalPanLeft, subfragmentRate);  
         PanRightSmoother.trigger(pEngineChannel->GlobalPanRight, subfragmentRate);  
   
         /*finalSynthesisParameters.dPos = pRegion->SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)  
         Pos = pRegion->SampleStartOffset;*/ // TODO: ^^^  
         Pos = finalSynthesisParameters.dPos = 0;  
   
         // Check if the sample needs disk streaming or is too short for that  
         long cachedsamples = pSample->GetCache().Size / pSample->GetFrameSize();  
         DiskVoice          = cachedsamples < pSample->GetTotalFrameCount();  
   
         //const DLS::sample_loop_t& loopinfo = pRegion->pSampleLoops[0]; // TODO:  
   
         if (DiskVoice) { // voice to be streamed from disk  
             if (cachedsamples > (pEngine->MaxSamplesPerCycle << CONFIG_MAX_PITCH)) {  
                 MaxRAMPos = cachedsamples - (pEngine->MaxSamplesPerCycle << CONFIG_MAX_PITCH) / pSample->GetChannelCount(); //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)  
             } else {  
                 // The cache is too small to fit a max sample buffer.  
                 // Setting MaxRAMPos to 0 will probably cause a click  
                 // in the audio, but it's better than not handling  
                 // this case at all, which would have caused the  
                 // unsigned MaxRAMPos to be set to a negative number.  
                 MaxRAMPos = 0;  
             }  
   
             // check if there's a loop defined which completely fits into the cached (RAM) part of the sample  
             //RAMLoop = (pRegion->SampleLoops && (loopinfo.LoopStart + loopinfo.LoopLength) <= MaxRAMPos); // TODO:  
             if (pDiskThread->OrderNewStream(&DiskStreamRef, pRegion, MaxRAMPos, false) < 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->GetTotalFrameCount(), MaxRAMPos, (RAMLoop) ? "yes" : "no"));  
         }  
         else { // RAM only voice  
             MaxRAMPos = cachedsamples;  
             /*RAMLoop = (pRegion->SampleLoops != 0);  
             dmsg(4,("RAM only voice launched (Looping: %s)\n", (RAMLoop) ? "yes" : "no")); */ // TODO:  
         }  
         /*if (RAMLoop) {  
             loop.uiTotalCycles = pSample->LoopPlayCount;  
             loop.uiCyclesLeft  = pSample->LoopPlayCount;  
             loop.uiStart       = loopinfo.LoopStart;  
             loop.uiEnd         = loopinfo.LoopStart + loopinfo.LoopLength;  
             loop.uiSize        = loopinfo.LoopLength;  
         }*/ // TODO: ^^^  
   
         // calculate initial pitch value  
         {  
             double pitchbasecents = /* TODO: pEngineChannel->pInstrument->FineTune*/ + pRegion->tune + pEngine->ScaleTuning[MIDIKey % 12];  
   
             // GSt behaviour: maximum transpose up is 40 semitones. If  
             // MIDI key is more than 40 semitones above unity note,  
             // the transpose is not done.  
             /*if (pRegion->PitchTrack && (MIDIKey - (int) pRegion->UnityNote) < 40) pitchbasecents += (MIDIKey - (int) pRegion->UnityNote) * 100;  
   
             this->PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(pSample->SamplesPerSecond) / double(pEngine->SampleRate));  
             this->PitchBendRange = 1.0 / 8192.0 * 100.0 * pEngineChannel->pInstrument->PitchbendRange;  
             this->PitchBend = RTMath::CentsToFreqRatio(PitchBend * PitchBendRange);*/ // TODO: ^^^  
         }  
   
         // the length of the decay and release curves are dependent on the velocity  
         //const double velrelease = 1 / pRegion->GetVelocityRelease(itNoteOnEvent->Param.Note.Velocity); //TODO:  
   
         // setup EG 1 (VCA EG)  
         {  
         /*    // get current value of EG1 controller  
             double eg1controllervalue;  
             switch (pRegion->EG1Controller.type) {  
                 case ::gig::eg1_ctrl_t::type_none: // no controller defined  
                     eg1controllervalue = 0;  
                     break;  
                 case ::gig::eg1_ctrl_t::type_channelaftertouch:  
                     eg1controllervalue = pEngineChannel->ControllerTable[128];  
                     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[pRegion->EG1Controller.controller_number];  
                     break;  
             }  
             if (pRegion->EG1ControllerInvert) eg1controllervalue = 127 - eg1controllervalue;  
   
             // calculate influence of EG1 controller on EG1's parameters  
             // (eg1attack is different from the others)  
             double eg1attack  = (pRegion->EG1ControllerAttackInfluence)  ?  
                 1 + 0.031 * (double) (pRegion->EG1ControllerAttackInfluence == 1 ?  
                                       1 : 1 << pRegion->EG1ControllerAttackInfluence) * eg1controllervalue : 1.0;  
             double eg1decay   = (pRegion->EG1ControllerDecayInfluence)   ? 1 + 0.00775 * (double) (1 << pRegion->EG1ControllerDecayInfluence)   * eg1controllervalue : 1.0;  
             double eg1release = (pRegion->EG1ControllerReleaseInfluence) ? 1 + 0.00775 * (double) (1 << pRegion->EG1ControllerReleaseInfluence) * eg1controllervalue : 1.0;  
   
             EG1.trigger(pRegion->EG1PreAttack,  
                         pRegion->EG1Attack * eg1attack,  
                         pRegion->EG1Hold,  
                         pRegion->EG1Decay1 * eg1decay * velrelease,  
                         pRegion->EG1Decay2 * eg1decay * velrelease,  
                         pRegion->EG1InfiniteSustain,  
                         pRegion->EG1Sustain,  
                         pRegion->EG1Release * eg1release * velrelease,  
                         velocityAttenuation,  
                         pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);  
         }*/ // TODO: ^^^  
             EG1.trigger(0,  
                         0,  
                         false,  
                         0,  
                         0,  
                         true,  
                         100,  
                         0,  
                         1,  
                         pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);  
         }  
   
 #ifdef CONFIG_INTERPOLATE_VOLUME  
         // setup initial volume in synthesis parameters  
 #ifdef CONFIG_PROCESS_MUTED_CHANNELS  
         if (pEngineChannel->GetMute()) {  
             finalSynthesisParameters.fFinalVolumeLeft  = 0;  
             finalSynthesisParameters.fFinalVolumeRight = 0;  
         }  
         else  
 #else  
         {  
             //float finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * EG1.getLevel(); // TODO:  
             float finalVolume = pEngineChannel->MidiVolume;  
   
             finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * pEngineChannel->GlobalPanLeft;  
             finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * pEngineChannel->GlobalPanRight;  
         }  
 #endif  
 #endif  
   
         // setup EG 2 (VCF Cutoff EG)  
         /*{  
             // get current value of EG2 controller  
             double eg2controllervalue;  
             switch (pRegion->EG2Controller.type) {  
                 case ::gig::eg2_ctrl_t::type_none: // no controller defined  
                     eg2controllervalue = 0;  
                     break;  
                 case ::gig::eg2_ctrl_t::type_channelaftertouch:  
                     eg2controllervalue = pEngineChannel->ControllerTable[128];  
                     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[pRegion->EG2Controller.controller_number];  
                     break;  
             }  
             if (pRegion->EG2ControllerInvert) eg2controllervalue = 127 - eg2controllervalue;  
   
             // calculate influence of EG2 controller on EG2's parameters  
             double eg2attack  = (pRegion->EG2ControllerAttackInfluence)  ? 1 + 0.00775 * (double) (1 << pRegion->EG2ControllerAttackInfluence)  * eg2controllervalue : 1.0;  
             double eg2decay   = (pRegion->EG2ControllerDecayInfluence)   ? 1 + 0.00775 * (double) (1 << pRegion->EG2ControllerDecayInfluence)   * eg2controllervalue : 1.0;  
             double eg2release = (pRegion->EG2ControllerReleaseInfluence) ? 1 + 0.00775 * (double) (1 << pRegion->EG2ControllerReleaseInfluence) * eg2controllervalue : 1.0;  
   
             EG2.trigger(pRegion->EG2PreAttack,  
                         pRegion->EG2Attack * eg2attack,  
                         false,  
                         pRegion->EG2Decay1 * eg2decay * velrelease,  
                         pRegion->EG2Decay2 * eg2decay * velrelease,  
                         pRegion->EG2InfiniteSustain,  
                         pRegion->EG2Sustain,  
                         pRegion->EG2Release * eg2release * velrelease,  
                         velocityAttenuation,  
                         pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);  
195          }          }
196    
197            return crossfadeVolume;*/ // TODO: ^^^
198            return 1.0f;
199        }
200    
201          // setup EG 3 (VCO EG)      double Voice::GetEG1ControllerValue(uint8_t MIDIKeyVelocity) {
202          {          /*double eg1controllervalue = 0;
203              // if portamento mode is on, we dedicate EG3 purely for portamento, otherwise if portamento is off we do as told by the patch          switch (pRegion->EG1Controller.type) {
204              bool  bPortamento = pEngineChannel->PortamentoMode && pEngineChannel->PortamentoPos >= 0.0f;              case ::gig::eg1_ctrl_t::type_none: // no controller defined
205              float eg3depth = (bPortamento)                  eg1controllervalue = 0;
206                                   ? RTMath::CentsToFreqRatio((pEngineChannel->PortamentoPos - (float) MIDIKey) * 100)                  break;
207                                   : RTMath::CentsToFreqRatio(pRegion->EG3Depth);              case ::gig::eg1_ctrl_t::type_channelaftertouch:
208              float eg3time = (bPortamento)                  eg1controllervalue = GetSfzEngineChannel()->ControllerTable[128];
209                                  ? pEngineChannel->PortamentoTime                  break;
210                                  : pRegion->EG3Attack;              case ::gig::eg1_ctrl_t::type_velocity:
211              EG3.trigger(eg3depth, eg3time, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  eg1controllervalue = MIDIKeyVelocity;
212              dmsg(5,("PortamentoPos=%f, depth=%f, time=%f\n", pEngineChannel->PortamentoPos, eg3depth, eg3time));                  break;
213                case ::gig::eg1_ctrl_t::type_controlchange: // MIDI control change controller
214                    eg1controllervalue = GetSfzEngineChannel()->ControllerTable[pRegion->EG1Controller.controller_number];
215                    break;
216          }          }
217            if (pRegion->EG1ControllerInvert) eg1controllervalue = 127 - eg1controllervalue;
218    
219            return eg1controllervalue;*/ // TODO: ^^^
220            return 0;
221        }
222    
223          // setup LFO 1 (VCA LFO)      Voice::EGInfo Voice::CalculateEG1ControllerInfluence(double eg1ControllerValue) {
224          {          /*EGInfo eg;
225              uint16_t lfo1_internal_depth;          // (eg1attack is different from the others)
226              switch (pRegion->LFO1Controller) {          eg.Attack  = (pRegion->EG1ControllerAttackInfluence)  ?
227                  case ::gig::lfo1_ctrl_internal:              1 + 0.031 * (double) (pRegion->EG1ControllerAttackInfluence == 1 ?
228                      lfo1_internal_depth  = pRegion->LFO1InternalDepth;                                    1 : 1 << pRegion->EG1ControllerAttackInfluence) * eg1ControllerValue : 1.0;
229                      pLFO1->ExtController = 0; // no external controller          eg.Decay   = (pRegion->EG1ControllerDecayInfluence)   ? 1 + 0.00775 * (double) (1 << pRegion->EG1ControllerDecayInfluence)   * eg1ControllerValue : 1.0;
230                      bLFO1Enabled         = (lfo1_internal_depth > 0);          eg.Release = (pRegion->EG1ControllerReleaseInfluence) ? 1 + 0.00775 * (double) (1 << pRegion->EG1ControllerReleaseInfluence) * eg1ControllerValue : 1.0;
231                      break;  
232                  case ::gig::lfo1_ctrl_modwheel:          return eg;*/ // TODO: ^^^
233                      lfo1_internal_depth  = 0;          EGInfo eg;
234                      pLFO1->ExtController = 1; // MIDI controller 1          eg.Attack = 1.0;
235                      bLFO1Enabled         = (pRegion->LFO1ControlDepth > 0);          eg.Decay = 1.0;
236                      break;          eg.Release = 1.0;
237                  case ::gig::lfo1_ctrl_breath:          return eg;
238                      lfo1_internal_depth  = 0;      }
239                      pLFO1->ExtController = 2; // MIDI controller 2  
240                      bLFO1Enabled         = (pRegion->LFO1ControlDepth > 0);      void Voice::TriggerEG1(const EGInfo& egInfo, double velrelease, double velocityAttenuation, uint sampleRate, uint8_t velocity) {
241                      break;  
242                  case ::gig::lfo1_ctrl_internal_modwheel:          // TODO: controller modulation
243                      lfo1_internal_depth  = pRegion->LFO1InternalDepth;  
244                      pLFO1->ExtController = 1; // MIDI controller 1          // first check if there is a v2 EG for amplitude
245                      bLFO1Enabled         = (lfo1_internal_depth > 0 || pRegion->LFO1ControlDepth > 0);          for (int i = 0 ; i < pRegion->eg.size() ; i++) {
246                      break;              if (pRegion->eg[i].amplitude > 0) {
247                  case ::gig::lfo1_ctrl_internal_breath:                  // TODO: actually use the value of the amplitude parameter
248                      lfo1_internal_depth  = pRegion->LFO1InternalDepth;                  pEG1 = &EG1;
249                      pLFO1->ExtController = 2; // MIDI controller 2                  EG1.trigger(pRegion->eg[i], sampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE, velocity);
250                      bLFO1Enabled         = (lfo1_internal_depth > 0 || pRegion->LFO1ControlDepth > 0);                  return;
                     break;  
                 default:  
                     lfo1_internal_depth  = 0;  
                     pLFO1->ExtController = 0; // no external controller  
                     bLFO1Enabled         = false;  
             }  
             if (bLFO1Enabled) {  
                 pLFO1->trigger(pRegion->LFO1Frequency,  
                                start_level_min,  
                                lfo1_internal_depth,  
                                pRegion->LFO1ControlDepth,  
                                pRegion->LFO1FlipPhase,  
                                pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);  
                 pLFO1->update(pLFO1->ExtController ? pEngineChannel->ControllerTable[pLFO1->ExtController] : 0);  
251              }              }
252          }          }
253    
254            // otherwise use the v1 EGADSR
255          // setup LFO 2 (VCF Cutoff LFO)          pEG1 = &EGADSR1;
256          {          EGADSR1.trigger(uint(pRegion->ampeg_start * 10),
257              uint16_t lfo2_internal_depth;                          std::max(0.0, pRegion->ampeg_attack + pRegion->ampeg_vel2attack * velrelease),
258              switch (pRegion->LFO2Controller) {                          std::max(0.0, pRegion->ampeg_hold + pRegion->ampeg_vel2hold * velrelease),
259                  case ::gig::lfo2_ctrl_internal:                          std::max(0.0, pRegion->ampeg_decay + pRegion->ampeg_vel2decay * velrelease),
260                      lfo2_internal_depth  = pRegion->LFO2InternalDepth;                          uint(std::min(std::max(0.0, 10 * (pRegion->ampeg_sustain + pRegion->ampeg_vel2sustain * velrelease)), 1000.0)),
261                      pLFO2->ExtController = 0; // no external controller                          std::max(0.0, pRegion->ampeg_release + pRegion->ampeg_vel2release * velrelease),
262                      bLFO2Enabled         = (lfo2_internal_depth > 0);                          sampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
263                      break;      }
264                  case ::gig::lfo2_ctrl_modwheel:  
265                      lfo2_internal_depth  = 0;      double Voice::GetEG2ControllerValue(uint8_t MIDIKeyVelocity) {
266                      pLFO2->ExtController = 1; // MIDI controller 1          /*double eg2controllervalue = 0;
267                      bLFO2Enabled         = (pRegion->LFO2ControlDepth > 0);          switch (pRegion->EG2Controller.type) {
268                      break;              case ::gig::eg2_ctrl_t::type_none: // no controller defined
269                  case ::gig::lfo2_ctrl_foot:                  eg2controllervalue = 0;
270                      lfo2_internal_depth  = 0;                  break;
271                      pLFO2->ExtController = 4; // MIDI controller 4              case ::gig::eg2_ctrl_t::type_channelaftertouch:
272                      bLFO2Enabled         = (pRegion->LFO2ControlDepth > 0);                  eg2controllervalue = GetSfzEngineChannel()->ControllerTable[128];
273                      break;                  break;
274                  case ::gig::lfo2_ctrl_internal_modwheel:              case ::gig::eg2_ctrl_t::type_velocity:
275                      lfo2_internal_depth  = pRegion->LFO2InternalDepth;                  eg2controllervalue = MIDIKeyVelocity;
276                      pLFO2->ExtController = 1; // MIDI controller 1                  break;
277                      bLFO2Enabled         = (lfo2_internal_depth > 0 || pRegion->LFO2ControlDepth > 0);              case ::gig::eg2_ctrl_t::type_controlchange: // MIDI control change controller
278                      break;                  eg2controllervalue = GetSfzEngineChannel()->ControllerTable[pRegion->EG2Controller.controller_number];
279                  case ::gig::lfo2_ctrl_internal_foot:                  break;
                     lfo2_internal_depth  = pRegion->LFO2InternalDepth;  
                     pLFO2->ExtController = 4; // MIDI controller 4  
                     bLFO2Enabled         = (lfo2_internal_depth > 0 || pRegion->LFO2ControlDepth > 0);  
                     break;  
                 default:  
                     lfo2_internal_depth  = 0;  
                     pLFO2->ExtController = 0; // no external controller  
                     bLFO2Enabled         = false;  
             }  
             if (bLFO2Enabled) {  
                 pLFO2->trigger(pRegion->LFO2Frequency,  
                                start_level_max,  
                                lfo2_internal_depth,  
                                pRegion->LFO2ControlDepth,  
                                pRegion->LFO2FlipPhase,  
                                pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);  
                 pLFO2->update(pLFO2->ExtController ? pEngineChannel->ControllerTable[pLFO2->ExtController] : 0);  
             }  
280          }          }
281            if (pRegion->EG2ControllerInvert) eg2controllervalue = 127 - eg2controllervalue;
282    
283            return eg2controllervalue;*/ // TODO: ^^^
284            return 0;
285        }
286    
287          // setup LFO 3 (VCO LFO)      Voice::EGInfo Voice::CalculateEG2ControllerInfluence(double eg2ControllerValue) {
288          {          /*EGInfo eg;
289              uint16_t lfo3_internal_depth;          eg.Attack  = (pRegion->EG2ControllerAttackInfluence)  ? 1 + 0.00775 * (double) (1 << pRegion->EG2ControllerAttackInfluence)  * eg2ControllerValue : 1.0;
290              switch (pRegion->LFO3Controller) {          eg.Decay   = (pRegion->EG2ControllerDecayInfluence)   ? 1 + 0.00775 * (double) (1 << pRegion->EG2ControllerDecayInfluence)   * eg2ControllerValue : 1.0;
291                  case ::gig::lfo3_ctrl_internal:          eg.Release = (pRegion->EG2ControllerReleaseInfluence) ? 1 + 0.00775 * (double) (1 << pRegion->EG2ControllerReleaseInfluence) * eg2ControllerValue : 1.0;
                     lfo3_internal_depth  = pRegion->LFO3InternalDepth;  
                     pLFO3->ExtController = 0; // no external controller  
                     bLFO3Enabled         = (lfo3_internal_depth > 0);  
                     break;  
                 case ::gig::lfo3_ctrl_modwheel:  
                     lfo3_internal_depth  = 0;  
                     pLFO3->ExtController = 1; // MIDI controller 1  
                     bLFO3Enabled         = (pRegion->LFO3ControlDepth > 0);  
                     break;  
                 case ::gig::lfo3_ctrl_aftertouch:  
                     lfo3_internal_depth  = 0;  
                     pLFO3->ExtController = 128;  
                     bLFO3Enabled         = true;  
                     break;  
                 case ::gig::lfo3_ctrl_internal_modwheel:  
                     lfo3_internal_depth  = pRegion->LFO3InternalDepth;  
                     pLFO3->ExtController = 1; // MIDI controller 1  
                     bLFO3Enabled         = (lfo3_internal_depth > 0 || pRegion->LFO3ControlDepth > 0);  
                     break;  
                 case ::gig::lfo3_ctrl_internal_aftertouch:  
                     lfo3_internal_depth  = pRegion->LFO3InternalDepth;  
                     pLFO1->ExtController = 128;  
                     bLFO3Enabled         = (lfo3_internal_depth > 0 || pRegion->LFO3ControlDepth > 0);  
                     break;  
                 default:  
                     lfo3_internal_depth  = 0;  
                     pLFO3->ExtController = 0; // no external controller  
                     bLFO3Enabled         = false;  
             }  
             if (bLFO3Enabled) {  
                 pLFO3->trigger(pRegion->LFO3Frequency,  
                                start_level_mid,  
                                lfo3_internal_depth,  
                                pRegion->LFO3ControlDepth,  
                                false,  
                                pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);  
                 pLFO3->update(pLFO3->ExtController ? pEngineChannel->ControllerTable[pLFO3->ExtController] : 0);  
             }  
         }*/ // TODO: ^^^  
   
292    
293          /*#if CONFIG_FORCE_FILTER          return eg;*/ // TODO: ^^^
294          const bool bUseFilter = true;          EGInfo eg;
295          #else // use filter only if instrument file told so          eg.Attack = 1.0;
296          const bool bUseFilter = pRegion->VCFEnabled;          eg.Decay = 1.0;
297          #endif // CONFIG_FORCE_FILTER          eg.Release = 1.0;
298          SYNTHESIS_MODE_SET_FILTER(SynthesisMode, bUseFilter);          return eg;
299          if (bUseFilter) {      }
             #ifdef CONFIG_OVERRIDE_CUTOFF_CTRL  
             VCFCutoffCtrl.controller = CONFIG_OVERRIDE_CUTOFF_CTRL;  
             #else // use the one defined in the instrument file  
             switch (pRegion->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:  
                     VCFCutoffCtrl.controller = 128;  
                     break;  
                 case ::gig::vcf_cutoff_ctrl_none:  
                 default:  
                     VCFCutoffCtrl.controller = 0;  
                     break;  
             }  
             #endif // CONFIG_OVERRIDE_CUTOFF_CTRL  
300    
301              #ifdef CONFIG_OVERRIDE_RESONANCE_CTRL      void Voice::TriggerEG2(const EGInfo& egInfo, double velrelease, double velocityAttenuation, uint sampleRate, uint8_t velocity) {
             VCFResonanceCtrl.controller = CONFIG_OVERRIDE_RESONANCE_CTRL;  
             #else // use the one defined in the instrument file  
             switch (pRegion->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 // CONFIG_OVERRIDE_RESONANCE_CTRL  
302    
303              #ifndef CONFIG_OVERRIDE_FILTER_TYPE          // TODO: the sfz filter EG should modulate cents, not hertz,
304              finalSynthesisParameters.filterLeft.SetType(pRegion->VCFType);          // so we can't use the EG or EGADSR as it is. Disable for now.
             finalSynthesisParameters.filterRight.SetType(pRegion->VCFType);  
             #else // override filter type  
             finalSynthesisParameters.filterLeft.SetType(CONFIG_OVERRIDE_FILTER_TYPE);  
             finalSynthesisParameters.filterRight.SetType(CONFIG_OVERRIDE_FILTER_TYPE);  
             #endif // CONFIG_OVERRIDE_FILTER_TYPE  
   
             VCFCutoffCtrl.value    = pEngineChannel->ControllerTable[VCFCutoffCtrl.controller];  
             VCFResonanceCtrl.value = pEngineChannel->ControllerTable[VCFResonanceCtrl.controller];  
   
             // calculate cutoff frequency  
             float cutoff = pRegion->GetVelocityCutoff(itNoteOnEvent->Param.Note.Velocity);  
             if (pRegion->VCFKeyboardTracking) {  
                 cutoff *= exp((itNoteOnEvent->Param.Note.Key - pRegion->VCFKeyboardTrackingBreakpoint) * 0.057762265f); // (ln(2) / 12)  
             }  
             CutoffBase = cutoff;  
305    
306              int cvalue;          pEG2 = &EGADSR2;
307              if (VCFCutoffCtrl.controller) {          EGADSR2.trigger(0,
308                  cvalue = pEngineChannel->ControllerTable[VCFCutoffCtrl.controller];                          0,
309                  if (pRegion->VCFCutoffControllerInvert) cvalue = 127 - cvalue;                          false,
310                  // VCFVelocityScale in this case means Minimum cutoff                          0,
311                  if (cvalue < pRegion->VCFVelocityScale) cvalue = pRegion->VCFVelocityScale;                          1000,
312              }                          0,
313              else {                          sampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
314                  cvalue = pRegion->VCFCutoff;      }
             }  
             cutoff *= float(cvalue);  
             if (cutoff > 127.0f) cutoff = 127.0f;  
   
             // calculate resonance  
             float resonance = (float) (VCFResonanceCtrl.controller ? VCFResonanceCtrl.value : pRegion->VCFResonance);  
315    
316              VCFCutoffCtrl.fvalue    = cutoff;      void Voice::InitLFO1() {
317              VCFResonanceCtrl.fvalue = resonance;          /*uint16_t lfo1_internal_depth;
318          }          switch (pRegion->LFO1Controller) {
319          else {              case ::gig::lfo1_ctrl_internal:
320              VCFCutoffCtrl.controller    = 0;                  lfo1_internal_depth  = pRegion->LFO1InternalDepth;
321              VCFResonanceCtrl.controller = 0;                  pLFO1->ExtController = 0; // no external controller
322                    bLFO1Enabled         = (lfo1_internal_depth > 0);
323                    break;
324                case ::gig::lfo1_ctrl_modwheel:
325                    lfo1_internal_depth  = 0;
326                    pLFO1->ExtController = 1; // MIDI controller 1
327                    bLFO1Enabled         = (pRegion->LFO1ControlDepth > 0);
328                    break;
329                case ::gig::lfo1_ctrl_breath:
330                    lfo1_internal_depth  = 0;
331                    pLFO1->ExtController = 2; // MIDI controller 2
332                    bLFO1Enabled         = (pRegion->LFO1ControlDepth > 0);
333                    break;
334                case ::gig::lfo1_ctrl_internal_modwheel:
335                    lfo1_internal_depth  = pRegion->LFO1InternalDepth;
336                    pLFO1->ExtController = 1; // MIDI controller 1
337                    bLFO1Enabled         = (lfo1_internal_depth > 0 || pRegion->LFO1ControlDepth > 0);
338                    break;
339                case ::gig::lfo1_ctrl_internal_breath:
340                    lfo1_internal_depth  = pRegion->LFO1InternalDepth;
341                    pLFO1->ExtController = 2; // MIDI controller 2
342                    bLFO1Enabled         = (lfo1_internal_depth > 0 || pRegion->LFO1ControlDepth > 0);
343                    break;
344                default:
345                    lfo1_internal_depth  = 0;
346                    pLFO1->ExtController = 0; // no external controller
347                    bLFO1Enabled         = false;
348            }
349            if (bLFO1Enabled) {
350                pLFO1->trigger(pRegion->LFO1Frequency,
351                               start_level_min,
352                               lfo1_internal_depth,
353                               pRegion->LFO1ControlDepth,
354                               pRegion->LFO1FlipPhase,
355                               pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
356                pLFO1->update(pLFO1->ExtController ? GetSfzEngineChannel()->ControllerTable[pLFO1->ExtController] : 0);
357          }*/ // TODO: ^^^          }*/ // TODO: ^^^
358            bLFO1Enabled = false;
         return 0; // success  
359      }      }
360    
361      /**      void Voice::InitLFO2() {
362       *  Renders the audio data for this voice for the current audio fragment.          /*uint16_t lfo2_internal_depth;
363       *  The sample input data can either come from RAM (cached sample or sample          switch (pRegion->LFO2Controller) {
364       *  part) or directly from disk. The output signal will be rendered by              case ::gig::lfo2_ctrl_internal:
365       *  resampling / interpolation. If this voice is a disk streaming voice and                  lfo2_internal_depth  = pRegion->LFO2InternalDepth;
366       *  the voice completely played back the cached RAM part of the sample, it                  pLFO2->ExtController = 0; // no external controller
367       *  will automatically switch to disk playback for the next RenderAudio()                  bLFO2Enabled         = (lfo2_internal_depth > 0);
      *  call.  
      *  
      *  @param Samples - number of samples to be rendered in this audio fragment cycle  
      */  
     void Voice::Render(uint Samples) {  
         // select default values for synthesis mode bits  
         SYNTHESIS_MODE_SET_LOOP(SynthesisMode, false);  
   
         switch (this->PlaybackState) {  
   
             case playback_state_init:  
                 this->PlaybackState = playback_state_ram; // we always start playback from RAM cache and switch then to disk if needed  
                 // no break - continue with playback_state_ram  
   
             case playback_state_ram: {  
                     //if (RAMLoop) SYNTHESIS_MODE_SET_LOOP(SynthesisMode, true); // enable looping  
   
                     // render current fragment  
                     Synthesize(Samples, (sample_t*) pSample->GetCache().pStart, Delay);  
   
                     if (DiskVoice) {  
                         // check if we reached the allowed limit of the sample RAM cache  
                         if (finalSynthesisParameters.dPos > MaxRAMPos) {  
                             dmsg(5,("Voice: switching to disk playback (Pos=%f)\n", finalSynthesisParameters.dPos));  
                             this->PlaybackState = playback_state_disk;  
                         }  
                     } else if (finalSynthesisParameters.dPos >= pSample->GetCache().Size / pSample->GetFrameSize()) {  
                         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->GetChannelCount() * (int(finalSynthesisParameters.dPos) - MaxRAMPos));  
                         finalSynthesisParameters.dPos -= int(finalSynthesisParameters.dPos);  
                         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 << CONFIG_MAX_PITCH) * pSample->GetChannelCount() + 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 = (sample_t*)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) finalSynthesisParameters.dPos;  
                     const int readSampleWords = iPos * pSample->GetChannelCount(); // amount of sample words actually been read  
                     DiskStreamRef.pStream->IncrementReadPos(readSampleWords);  
                     finalSynthesisParameters.dPos -= iPos; // just keep fractional part of playback position  
   
                     // 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;  
                     }  
                 }  
368                  break;                  break;
369                case ::gig::lfo2_ctrl_modwheel:
370              case playback_state_end:                  lfo2_internal_depth  = 0;
371                  std::cerr << "gig::Voice::Render(): entered with playback_state_end, this is a bug!\n" << std::flush;                  pLFO2->ExtController = 1; // MIDI controller 1
372                    bLFO2Enabled         = (pRegion->LFO2ControlDepth > 0);
373                  break;                  break;
374          }              case ::gig::lfo2_ctrl_foot:
375                    lfo2_internal_depth  = 0;
376          // Reset delay                  pLFO2->ExtController = 4; // MIDI controller 4
377          Delay = 0;                  bLFO2Enabled         = (pRegion->LFO2ControlDepth > 0);
378                    break;
379          itTriggerEvent = Pool<Event>::Iterator();              case ::gig::lfo2_ctrl_internal_modwheel:
380                    lfo2_internal_depth  = pRegion->LFO2InternalDepth;
381          // If sample stream or release stage finished, kill the voice                  pLFO2->ExtController = 1; // MIDI controller 1
382          if (PlaybackState == playback_state_end || EG1.getSegmentType() == EGADSR::segment_end) KillImmediately();                  bLFO2Enabled         = (lfo2_internal_depth > 0 || pRegion->LFO2ControlDepth > 0);
383                    break;
384                case ::gig::lfo2_ctrl_internal_foot:
385                    lfo2_internal_depth  = pRegion->LFO2InternalDepth;
386                    pLFO2->ExtController = 4; // MIDI controller 4
387                    bLFO2Enabled         = (lfo2_internal_depth > 0 || pRegion->LFO2ControlDepth > 0);
388                    break;
389                default:
390                    lfo2_internal_depth  = 0;
391                    pLFO2->ExtController = 0; // no external controller
392                    bLFO2Enabled         = false;
393            }
394            if (bLFO2Enabled) {
395                pLFO2->trigger(pRegion->LFO2Frequency,
396                               start_level_max,
397                               lfo2_internal_depth,
398                               pRegion->LFO2ControlDepth,
399                               pRegion->LFO2FlipPhase,
400                               pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
401                pLFO2->update(pLFO2->ExtController ? GetSfzEngineChannel()->ControllerTable[pLFO2->ExtController] : 0);
402            }*/ // TODO: ^^^
403            bLFO2Enabled = false;
404      }      }
405    
406      /**      void Voice::InitLFO3() {
407       *  Resets voice variables. Should only be called if rendering process is          /*uint16_t lfo3_internal_depth;
408       *  suspended / not running.          switch (pRegion->LFO3Controller) {
409       */              case ::gig::lfo3_ctrl_internal:
410      void Voice::Reset() {                  lfo3_internal_depth  = pRegion->LFO3InternalDepth;
411          finalSynthesisParameters.filterLeft.Reset();                  pLFO3->ExtController = 0; // no external controller
412          finalSynthesisParameters.filterRight.Reset();                  bLFO3Enabled         = (lfo3_internal_depth > 0);
413          DiskStreamRef.pStream = NULL;                  break;
414          DiskStreamRef.hStream = 0;              case ::gig::lfo3_ctrl_modwheel:
415          DiskStreamRef.State   = Stream::state_unused;                  lfo3_internal_depth  = 0;
416          DiskStreamRef.OrderID = 0;                  pLFO3->ExtController = 1; // MIDI controller 1
417          PlaybackState = playback_state_end;                  bLFO3Enabled         = (pRegion->LFO3ControlDepth > 0);
418          itTriggerEvent = Pool<Event>::Iterator();                  break;
419          itKillEvent    = Pool<Event>::Iterator();              case ::gig::lfo3_ctrl_aftertouch:
420      }                  lfo3_internal_depth  = 0;
421                    pLFO3->ExtController = 128;
422      /**                  bLFO3Enabled         = true;
423       * Process given list of MIDI note on, note off and sustain pedal events                  break;
424       * for the given time.              case ::gig::lfo3_ctrl_internal_modwheel:
425       *                  lfo3_internal_depth  = pRegion->LFO3InternalDepth;
426       * @param itEvent - iterator pointing to the next event to be processed                  pLFO3->ExtController = 1; // MIDI controller 1
427       * @param End     - youngest time stamp where processing should be stopped                  bLFO3Enabled         = (lfo3_internal_depth > 0 || pRegion->LFO3ControlDepth > 0);
428       */                  break;
429      void Voice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) {              case ::gig::lfo3_ctrl_internal_aftertouch:
430          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {                  lfo3_internal_depth  = pRegion->LFO3InternalDepth;
431              if (itEvent->Type == Event::type_release) {                  pLFO1->ExtController = 128;
432                  EG1.update(EGADSR::event_release, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  bLFO3Enabled         = (lfo3_internal_depth > 0 || pRegion->LFO3ControlDepth > 0);
433                  EG2.update(EGADSR::event_release, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  break;
434              } else if (itEvent->Type == Event::type_cancel_release) {              default:
435                  EG1.update(EGADSR::event_cancel_release, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  lfo3_internal_depth  = 0;
436                  EG2.update(EGADSR::event_cancel_release, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  pLFO3->ExtController = 0; // no external controller
437              }                  bLFO3Enabled         = false;
438          }          }
439            if (bLFO3Enabled) {
440                pLFO3->trigger(pRegion->LFO3Frequency,
441                               start_level_mid,
442                               lfo3_internal_depth,
443                               pRegion->LFO3ControlDepth,
444                               false,
445                               pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
446                pLFO3->update(pLFO3->ExtController ? GetSfzEngineChannel()->ControllerTable[pLFO3->ExtController] : 0);
447            }*/ // TODO: ^^^
448            bLFO3Enabled = false;
449      }      }
450    
451      /**      float Voice::CalculateCutoffBase(uint8_t MIDIKeyVelocity) {
452       * Process given list of MIDI control change and pitch bend events for          float cutoff = *pRegion->cutoff;
453       * the given time.          cutoff *= RTMath::CentsToFreqRatioUnlimited(
454       *              MIDIKeyVelocity / 127.0f * pRegion->fil_veltrack +
455       * @param itEvent - iterator pointing to the next event to be processed              (MIDIKey - pRegion->fil_keycenter) * pRegion->fil_keytrack);
456       * @param End     - youngest time stamp where processing should be stopped          return cutoff;
457       */      }
458      void Voice::processCCEvents(RTList<Event>::Iterator& itEvent, uint End) {  
459          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {      float Voice::CalculateFinalCutoff(float cutoffBase) {
460              if (itEvent->Type == Event::type_control_change &&          float cutoff;
461                  itEvent->Param.CC.Controller) { // if (valid) MIDI control change event          if (VCFCutoffCtrl.controller) {
462                  if (itEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {              int ccvalue = GetSfzEngineChannel()->ControllerTable[VCFCutoffCtrl.controller];
463                      processCutoffEvent(itEvent);              cutoff = CutoffBase * RTMath::CentsToFreqRatioUnlimited(
464                  }                  ccvalue / 127.0f * pRegion->cutoff_oncc[VCFCutoffCtrl.controller]);
465                  if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {          } else {
466                      processResonanceEvent(itEvent);              cutoff = cutoffBase;
467                  }          }
468                  if (itEvent->Param.CC.Controller == pLFO1->ExtController) {          if (cutoff > 0.49 * pEngine->SampleRate) cutoff = 0.49 * pEngine->SampleRate;
469                      pLFO1->update(itEvent->Param.CC.Value);          return cutoff;
470                  }      }
471                  if (itEvent->Param.CC.Controller == pLFO2->ExtController) {  
472                      pLFO2->update(itEvent->Param.CC.Value);      uint8_t Voice::GetVCFCutoffCtrl() {
473                  }          // TODO: the sfz format allows several CC for the same
474                  if (itEvent->Param.CC.Controller == pLFO3->ExtController) {          // modulation destination. The Voice interface needs to be
475                      pLFO3->update(itEvent->Param.CC.Value);          // changed to support that.
476                  }          if (pRegion->cutoff_cc) return pRegion->cutoff_cc;
477                  /*if (pRegion->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange &&          else if (pRegion->cutoff_chanaft) return 128;
478                      itEvent->Param.CC.Controller == pRegion->AttenuationController.controller_number) {          return 0;
479                      CrossfadeSmoother.update(Engine::CrossfadeCurve[CrossfadeAttenuation(itEvent->Param.CC.Value)]);      }
480                  }*/ // TODO:  
481                  if (itEvent->Param.CC.Controller == 7) { // volume      uint8_t Voice::GetVCFResonanceCtrl() {
482                      VolumeSmoother.update(Engine::VolumeCurve[itEvent->Param.CC.Value]);          /*uint8_t ctrl;
483                  } else if (itEvent->Param.CC.Controller == 10) { // panpot          switch (pRegion->VCFResonanceController) {
484                      PanLeftSmoother.update(Engine::PanCurve[128 - itEvent->Param.CC.Value]);              case ::gig::vcf_res_ctrl_genpurpose3:
485                      PanRightSmoother.update(Engine::PanCurve[itEvent->Param.CC.Value]);                  ctrl = 18;
486                  }                  break;
487              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event              case ::gig::vcf_res_ctrl_genpurpose4:
488                  processPitchEvent(itEvent);                  ctrl = 19;
489              }                  break;
490                case ::gig::vcf_res_ctrl_genpurpose5:
491                    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          }          }
     }  
500    
501      void Voice::processPitchEvent(RTList<Event>::Iterator& itEvent) {          return ctrl;*/ // TODO: ^^^
502          PitchBend = RTMath::CentsToFreqRatio(itEvent->Param.Pitch.Pitch * PitchBendRange);          return 0;
503      }      }
504    
505      void Voice::processCutoffEvent(RTList<Event>::Iterator& itEvent) {      float Voice::GetReleaseTriggerAttenuation(float noteLength) {
506          /*int ccvalue = itEvent->Param.CC.Value;          // pow(10, -rt_decay * noteLength / 20):
507          if (VCFCutoffCtrl.value == ccvalue) return;          return expf(RgnInfo.ReleaseTriggerDecay * noteLength);
         VCFCutoffCtrl.value == ccvalue;  
         if (pRegion->VCFCutoffControllerInvert)  ccvalue = 127 - ccvalue;  
         if (ccvalue < pRegion->VCFVelocityScale) ccvalue = pRegion->VCFVelocityScale;  
         float cutoff = CutoffBase * float(ccvalue);  
         if (cutoff > 127.0f) cutoff = 127.0f;  
   
         VCFCutoffCtrl.fvalue = cutoff; // needed for initialization of fFinalCutoff next time  
         fFinalCutoff = cutoff;*/ // TODO: ^^^  
508      }      }
509    
510      void Voice::processResonanceEvent(RTList<Event>::Iterator& itEvent) {      void Voice::ProcessGroupEvent(RTList<Event>::Iterator& itEvent) {
511          // convert absolute controller value to differential          dmsg(4,("Voice %x processGroupEvents event type=%d", this, itEvent->Type));
512          const int ctrldelta = itEvent->Param.CC.Value - VCFResonanceCtrl.value;          if (itEvent->Type == Event::type_control_change ||
513          VCFResonanceCtrl.value = itEvent->Param.CC.Value;              (Type & Voice::type_controller_triggered) ||
514          const float resonancedelta = (float) ctrldelta;              itEvent->Param.Note.Key != MIDIKey) {
515          fFinalResonance += resonancedelta;              dmsg(4,("Voice %x - kill", this));
516          // needed for initialization of parameter              if (pRegion->off_mode == ::sfz::OFF_NORMAL) {
517          VCFResonanceCtrl.fvalue = itEvent->Param.CC.Value;                  // turn off the voice by entering release envelope stage
518      }                  EnterReleaseStage();
   
     /**  
      *  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) {  
         finalSynthesisParameters.pOutLeft  = &pEngineChannel->pChannelLeft->Buffer()[Skip];  
         finalSynthesisParameters.pOutRight = &pEngineChannel->pChannelRight->Buffer()[Skip];  
         finalSynthesisParameters.pSrc      = pSrc;  
   
         RTList<Event>::Iterator itCCEvent = pEngineChannel->pEvents->first();  
         RTList<Event>::Iterator itNoteEvent = pEngineChannel->pMIDIKeyInfo[MIDIKey].pEvents->first();  
           
   
         if (itTriggerEvent) { // skip events that happened before this voice was triggered  
             while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;  
             // we can't simply compare the timestamp here, because note events  
             // might happen on the same time stamp, so we have to deal on the  
             // actual sequence the note events arrived instead (see bug #112)  
             for (; itNoteEvent; ++itNoteEvent) {  
                 if (itTriggerEvent == itNoteEvent) {  
                     ++itNoteEvent;  
                     break;  
                 }  
             }  
         }  
   
         uint killPos;  
         if (itKillEvent) {  
             int maxFadeOutPos = Samples - pEngine->MinFadeOutSamples;  
             if (maxFadeOutPos < 0) {  
                 // There's not enough space in buffer to do a fade out  
                 // from max volume (this can only happen for audio  
                 // drivers that use Samples < MaxSamplesPerCycle).  
                 // End the EG1 here, at pos 0, with a shorter max fade  
                 // out time.  
                 EG1.enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);  
                 itKillEvent = Pool<Event>::Iterator();  
519              } else {              } else {
520                  killPos = RTMath::Min(itKillEvent->FragmentPos(), maxFadeOutPos);                  // kill the voice fast
521                    SignalRack.EnterFadeOutStage();
522              }              }
523          }          }
   
         uint i = Skip;  
         /*while (i < Samples) {  
             int iSubFragmentEnd = RTMath::Min(i + CONFIG_DEFAULT_SUBFRAGMENT_SIZE, Samples);  
   
             // initialize all final synthesis parameters  
             fFinalCutoff    = VCFCutoffCtrl.fvalue;  
             fFinalResonance = VCFResonanceCtrl.fvalue;  
   
             // process MIDI control change and pitchbend events for this subfragment  
             processCCEvents(itCCEvent, iSubFragmentEnd);  
   
             finalSynthesisParameters.fFinalPitch = PitchBase * PitchBend;  
             float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render();  
 #ifdef CONFIG_PROCESS_MUTED_CHANNELS  
             if (pEngineChannel->GetMute()) fFinalVolume = 0;  
 #endif  
   
             // process transition events (note on, note off & sustain pedal)  
             processTransitionEvents(itNoteEvent, iSubFragmentEnd);  
   
             // if the voice was killed in this subfragment, or if the  
             // filter EG is finished, switch EG1 to fade out stage  
             if ((itKillEvent && killPos <= iSubFragmentEnd) ||  
                 (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&  
                  EG2.getSegmentType() == EGADSR::segment_end)) {  
                 EG1.enterFadeOutStage();  
                 itKillEvent = Pool<Event>::Iterator();  
             }  
   
             // process envelope generators  
             switch (EG1.getSegmentType()) {  
                 case EGADSR::segment_lin:  
                     fFinalVolume *= EG1.processLin();  
                     break;  
                 case EGADSR::segment_exp:  
                     fFinalVolume *= EG1.processExp();  
                     break;  
                 case EGADSR::segment_end:  
                     fFinalVolume *= EG1.getLevel();  
                     break; // noop  
             }  
             switch (EG2.getSegmentType()) {  
                 case EGADSR::segment_lin:  
                     fFinalCutoff *= EG2.processLin();  
                     break;  
                 case EGADSR::segment_exp:  
                     fFinalCutoff *= EG2.processExp();  
                     break;  
                 case EGADSR::segment_end:  
                     fFinalCutoff *= EG2.getLevel();  
                     break; // noop  
             }  
             if (EG3.active()) finalSynthesisParameters.fFinalPitch *= EG3.render();  
   
             // process low frequency oscillators  
             if (bLFO1Enabled) fFinalVolume *= (1.0f - pLFO1->render());  
             if (bLFO2Enabled) fFinalCutoff *= pLFO2->render();  
             if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());  
   
             // limit the pitch so we don't read outside the buffer  
             finalSynthesisParameters.fFinalPitch = RTMath::Min(finalSynthesisParameters.fFinalPitch, float(1 << CONFIG_MAX_PITCH));  
   
             // if filter enabled then update filter coefficients  
             if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode)) {  
                 finalSynthesisParameters.filterLeft.SetParameters(fFinalCutoff, fFinalResonance, pEngine->SampleRate);  
                 finalSynthesisParameters.filterRight.SetParameters(fFinalCutoff, fFinalResonance, pEngine->SampleRate);  
             }  
   
             // do we need resampling?  
             const float __PLUS_ONE_CENT  = 1.000577789506554859250142541782224725466f;  
             const float __MINUS_ONE_CENT = 0.9994225441413807496009516495583113737666f;  
             const bool bResamplingRequired = !(finalSynthesisParameters.fFinalPitch <= __PLUS_ONE_CENT &&  
                                                finalSynthesisParameters.fFinalPitch >= __MINUS_ONE_CENT);  
             SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, bResamplingRequired);  
   
             fFinalVolume = 1.0;  
             // prepare final synthesis parameters structure  
             finalSynthesisParameters.uiToGo            = iSubFragmentEnd - i;  
 #ifdef CONFIG_INTERPOLATE_VOLUME  
             finalSynthesisParameters.fFinalVolumeDeltaLeft  = 1;  
             finalSynthesisParameters.fFinalVolumeDeltaRight = 1;  
 #else  
             finalSynthesisParameters.fFinalVolumeLeft  =1;  
             finalSynthesisParameters.fFinalVolumeRight =1;  
 #endif  
             // render audio for one subfragment  
             //RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);  
   
             // stop the rendering if volume EG is finished  
             if (EG1.getSegmentType() == EGADSR::segment_end) break;  
   
             const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;  
   
             // increment envelopes' positions  
             if (EG1.active()) {  
   
                 // if sample has a loop and loop start has been reached in this subfragment, send a special event to EG1 to let it finish the attack hold stage  
                 if (pRegion->SampleLoops && Pos <= pRegion->pSampleLoops[0].LoopStart && pRegion->pSampleLoops[0].LoopStart < newPos) {  
                     EG1.update(EGADSR::event_hold_end, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);  
                 } // TODO:  
   
                 EG1.increment(1);  
                 if (!EG1.toStageEndLeft()) EG1.update(EGADSR::event_stage_end, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);  
             }  
             if (EG2.active()) {  
                 EG2.increment(1);  
                 if (!EG2.toStageEndLeft()) EG2.update(EGADSR::event_stage_end, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);  
             }  
             EG3.increment(1);  
             if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached  
   
             Pos = newPos;  
             i = iSubFragmentEnd;  
         }*/  
   
             int32_t* pSrc2 = NULL;  
             if((pSample->GetFrameSize() / pSample->GetChannelCount()) == 4) pSrc2 = (int32_t*)pSrc;  
             for(int j = 0; j < Samples; j++) {  
                 int lp, rp;  
                 if(pSample->GetChannelCount() == 1) {  
                     lp = (int)(finalSynthesisParameters.dPos + j);  
                     rp = (int)(finalSynthesisParameters.dPos + j);  
                 } else {  
                     lp = (int)(finalSynthesisParameters.dPos + j) * 2;  
                     rp = (int)(finalSynthesisParameters.dPos + j) * 2 + 1;  
                 }  
                 float left, right;  
                 if(pSrc2 != NULL) {  
                     left = pSrc2[lp]; right = pSrc2[rp];  
                 } else {  
                     left = pSrc[lp]; right = pSrc[rp];  
                 }  
                 float f = (pSrc2 == NULL ? 32768.0f : 32768.0f * 65536.0f);  
                 left /= f; right /= f;  
                 finalSynthesisParameters.pOutLeft[j] += left;  
                 finalSynthesisParameters.pOutRight[j] += right;  
             }  
             finalSynthesisParameters.dPos += Samples;  
524      }      }
525        
526      /** @brief Update current portamento position.      void Voice::SetSampleStartOffset() {
527       *          if (DiskVoice && RgnInfo.SampleStartOffset > pSample->MaxOffset) {
528       * Will be called when portamento mode is enabled to get the final              // The offset is applied to the RAM buffer
529       * portamento position of this active voice from where the next voice(s)              finalSynthesisParameters.dPos = 0;
530       * might continue to slide on.              Pos = 0;
531       *          } else {
532       * @param itNoteOffEvent - event which causes this voice to die soon              finalSynthesisParameters.dPos = RgnInfo.SampleStartOffset; // offset where we should start playback of sample
533       */              Pos = RgnInfo.SampleStartOffset;
     void Voice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {  
         const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());  
         pEngineChannel->PortamentoPos = (float) MIDIKey + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;  
     }  
   
     /**  
      *  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!  
      *  
      * If it's necessary to know when the voice's disk stream was actually  
      * deleted, then one can set the optional @a bRequestNotification  
      * parameter and this method will then return the handle of the disk  
      * stream (unique identifier) and one can use this handle to poll the  
      * disk thread if this stream has been deleted. In any case this method  
      * will return immediately and will not block until the stream actually  
      * was deleted.  
      *  
      * @param bRequestNotification - (optional) whether the disk thread shall  
      *                                provide a notification once it deleted  
      *                               the respective disk stream  
      *                               (default=false)  
      * @returns handle to the voice's disk stream or @c Stream::INVALID_HANDLE  
      *          if the voice did not use a disk stream at all  
      * @see Kill()  
      */  
     Stream::Handle Voice::KillImmediately(bool bRequestNotification) {  
         Stream::Handle hStream = Stream::INVALID_HANDLE;  
         if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {  
             pDiskThread->OrderDeletionOfStream(&DiskStreamRef, bRequestNotification);  
             hStream = DiskStreamRef.hStream;  
534          }          }
         Reset();  
         return hStream;  
     }  
   
     /**  
      *  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) {  
         #if CONFIG_DEVMODE  
         if (!itKillEvent) dmsg(1,("gig::Voice::Kill(): ERROR, !itKillEvent !!!\n"));  
         if (itKillEvent && !itKillEvent.isValid()) dmsg(1,("gig::Voice::Kill(): ERROR, itKillEvent invalid !!!\n"));  
         #endif // CONFIG_DEVMODE  
   
         if (itTriggerEvent && itKillEvent->FragmentPos() <= itTriggerEvent->FragmentPos()) return;  
         this->itKillEvent = itKillEvent;  
535      }      }
536    
537  }} // namespace LinuxSampler::sfz  }} // namespace LinuxSampler::sfz

Legend:
Removed from v.2012  
changed lines
  Added in v.2218

  ViewVC Help
Powered by ViewVC