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

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

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

revision 56 by schoenebeck, Tue Apr 27 09:21:58 2004 UTC revision 769 by schoenebeck, Sat Sep 3 11:14:30 2005 UTC
# Line 3  Line 3 
3   *   LinuxSampler - modular, streaming capable sampler                     *   *   LinuxSampler - modular, streaming capable sampler                     *
4   *                                                                         *   *                                                                         *
5   *   Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck   *   *   Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck   *
6     *   Copyright (C) 2005 Christian Schoenebeck                              *
7   *                                                                         *   *                                                                         *
8   *   This program is free software; you can redistribute it and/or modify  *   *   This program is free software; you can redistribute it and/or modify  *
9   *   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 21 
21   *   MA  02111-1307  USA                                                   *   *   MA  02111-1307  USA                                                   *
22   ***************************************************************************/   ***************************************************************************/
23    
24  #include "EGADSR.h"  #include "../../common/Features.h"
25  #include "Manipulator.h"  #include "Synthesizer.h"
26    
27  #include "Voice.h"  #include "Voice.h"
28    
29  namespace LinuxSampler { namespace gig {  namespace LinuxSampler { namespace gig {
30    
     // FIXME: no support for layers (nor crossfades) yet  
   
31      const float Voice::FILTER_CUTOFF_COEFF(CalculateFilterCutoffCoeff());      const float Voice::FILTER_CUTOFF_COEFF(CalculateFilterCutoffCoeff());
32    
33      float Voice::CalculateFilterCutoffCoeff() {      float Voice::CalculateFilterCutoffCoeff() {
34          return log(FILTER_CUTOFF_MIN / FILTER_CUTOFF_MAX);          return log(CONFIG_FILTER_CUTOFF_MAX / CONFIG_FILTER_CUTOFF_MIN);
35      }      }
36    
37      Voice::Voice() {      Voice::Voice() {
38          pEngine     = NULL;          pEngine     = NULL;
39          pDiskThread = NULL;          pDiskThread = NULL;
40          Active = false;          PlaybackState = playback_state_end;
41          pEG1   = NULL;          pLFO1 = new LFOUnsigned(1.0f);  // amplitude EG (0..1 range)
42          pEG2   = NULL;          pLFO2 = new LFOUnsigned(1.0f);  // filter EG (0..1 range)
43          pEG3   = NULL;          pLFO3 = new LFOSigned(1200.0f); // pitch EG (-1200..+1200 range)
44          pVCAManipulator  = NULL;          KeyGroup = 0;
45          pVCFCManipulator = NULL;          SynthesisMode = 0; // set all mode bits to 0 first
46          pVCOManipulator  = NULL;          // select synthesis implementation (currently either pure C++ or MMX+SSE(1))
47          pLFO1  = NULL;          #if CONFIG_ASM && ARCH_X86
48          pLFO2  = NULL;          SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, Features::supportsMMX() && Features::supportsSSE());
49          pLFO3  = NULL;          #else
50            SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, false);
51            #endif
52            SYNTHESIS_MODE_SET_PROFILING(SynthesisMode, true);
53    
54            FilterLeft.Reset();
55            FilterRight.Reset();
56      }      }
57    
58      Voice::~Voice() {      Voice::~Voice() {
         if (pEG1)  delete pEG1;  
         if (pEG2)  delete pEG2;  
         if (pEG3)  delete pEG3;  
59          if (pLFO1) delete pLFO1;          if (pLFO1) delete pLFO1;
60          if (pLFO2) delete pLFO2;          if (pLFO2) delete pLFO2;
61          if (pLFO3) delete pLFO3;          if (pLFO3) delete pLFO3;
         if (pVCAManipulator)  delete pVCAManipulator;  
         if (pVCFCManipulator) delete pVCFCManipulator;  
         if (pVCOManipulator)  delete pVCOManipulator;  
     }  
   
     void Voice::SetOutput(AudioOutputDevice* pAudioOutputDevice) {  
         this->pOutputLeft        = pAudioOutputDevice->Channel(0)->Buffer();  
         this->pOutputRight       = pAudioOutputDevice->Channel(1)->Buffer();  
         this->MaxSamplesPerCycle = pAudioOutputDevice->MaxSamplesPerCycle();  
         this->SampleRate         = pAudioOutputDevice->SampleRate();  
62      }      }
63    
64      void Voice::SetEngine(Engine* pEngine) {      void Voice::SetEngine(Engine* pEngine) {
65          this->pEngine = 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.  
   
66          this->pDiskThread = pEngine->pDiskThread;          this->pDiskThread = pEngine->pDiskThread;
67          dmsg(1,("Voice::SetEngine()\n"));          dmsg(6,("Voice::SetEngine()\n"));
68      }      }
69    
70      /**      /**
71       *  Initializes and triggers the voice, a disk stream will be launched if       *  Initializes and triggers the voice, a disk stream will be launched if
72       *  needed.       *  needed.
73       *       *
74       *  @param pNoteOnEvent - event that caused triggering of this voice       *  @param pEngineChannel - engine channel on which this voice was ordered
75       *  @param PitchBend    - MIDI detune factor (-8192 ... +8191)       *  @param itNoteOnEvent  - event that caused triggering of this voice
76       *  @param pInstrument  - points to the loaded instrument which provides sample wave(s) and articulation data       *  @param PitchBend      - MIDI detune factor (-8192 ... +8191)
77       *  @returns            0 on success, a value < 0 if something failed       *  @param pDimRgn        - points to the dimension region which provides sample wave(s) and articulation data
78         *  @param VoiceType      - type of this voice
79         *  @param iKeyGroup      - a value > 0 defines a key group in which this voice is member of
80         *  @returns 0 on success, a value < 0 if the voice wasn't triggered
81         *           (either due to an error or e.g. because no region is
82         *           defined for the given key)
83       */       */
84      int Voice::Trigger(Event* pNoteOnEvent, int PitchBend, ::gig::Instrument* pInstrument) {      int Voice::Trigger(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent, int PitchBend, ::gig::DimensionRegion* pDimRgn, type_t VoiceType, int iKeyGroup) {
85          if (!pInstrument) {          this->pEngineChannel = pEngineChannel;
86             dmsg(1,("voice::trigger: !pInstrument\n"));          this->pDimRgn        = pDimRgn;
87             exit(EXIT_FAILURE);  
88          }          #if CONFIG_DEVMODE
89            if (itNoteOnEvent->FragmentPos() > pEngine->MaxSamplesPerCycle) { // just a sanity check for debugging
90          Active          = true;              dmsg(1,("Voice::Trigger(): ERROR, TriggerDelay > Totalsamples\n"));
91          MIDIKey         = pNoteOnEvent->Key;          }
92          pRegion         = pInstrument->GetRegion(MIDIKey);          #endif // CONFIG_DEVMODE
93          PlaybackState   = playback_state_ram; // we always start playback from RAM cache and switch then to disk if needed  
94          Pos             = 0;          Type            = VoiceType;
95          Delay           = pNoteOnEvent->FragmentPos();          MIDIKey         = itNoteOnEvent->Param.Note.Key;
96          pTriggerEvent   = pNoteOnEvent;          PlaybackState   = playback_state_init; // mark voice as triggered, but no audio rendered yet
97            Delay           = itNoteOnEvent->FragmentPos();
98          if (!pRegion) {          itTriggerEvent  = itNoteOnEvent;
99              std::cerr << "Audio Thread: No Region defined for MIDI key " << MIDIKey << std::endl << std::flush;          itKillEvent     = Pool<Event>::Iterator();
100              Kill();          KeyGroup        = iKeyGroup;
101              return -1;          pSample         = pDimRgn->pSample; // sample won't change until the voice is finished
102          }  
103            // calculate volume
104          //TODO: current MIDI controller values are not taken into account yet          const double velocityAttenuation = pDimRgn->GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity);
105          ::gig::DimensionRegion* pDimRgn = NULL;  
106          for (int i = pRegion->Dimensions - 1; i >= 0; i--) { // Check if instrument has a velocity split          Volume = velocityAttenuation / 32768.0f; // we downscale by 32768 to convert from int16 value range to DSP value range (which is -1.0..1.0)
107              if (pRegion->pDimensionDefinitions[i].dimension == ::gig::dimension_velocity) {  
108                  uint DimValues[5] = {0,0,0,0,0};          Volume *= pDimRgn->SampleAttenuation;
109                      DimValues[i] = pNoteOnEvent->Velocity;  
110                  pDimRgn = pRegion->GetDimensionRegionByValue(DimValues[4],DimValues[3],DimValues[2],DimValues[1],DimValues[0]);          // the volume of release triggered samples depends on note length
111            if (Type == type_release_trigger) {
112                float noteLength = float(pEngine->FrameTime + Delay -
113                                         pEngineChannel->pMIDIKeyInfo[MIDIKey].NoteOnTime) / pEngine->SampleRate;
114                float attenuation = 1 - 0.01053 * (256 >> pDimRgn->ReleaseTriggerDecay) * noteLength;
115                if (attenuation <= 0) return -1;
116                Volume *= attenuation;
117            }
118    
119            // select channel mode (mono or stereo)
120            SYNTHESIS_MODE_SET_CHANNELS(SynthesisMode, pSample->Channels == 2);
121    
122            // get starting crossfade volume level
123            switch (pDimRgn->AttenuationController.type) {
124                case ::gig::attenuation_ctrl_t::type_channelaftertouch:
125                    CrossfadeVolume = 1.0f; //TODO: aftertouch not supported yet
126                  break;                  break;
127              }              case ::gig::attenuation_ctrl_t::type_velocity:
128          }                  CrossfadeVolume = CrossfadeAttenuation(itNoteOnEvent->Param.Note.Velocity);
129          if (!pDimRgn) { // if there was no velocity split                  break;
130              pDimRgn = pRegion->GetDimensionRegionByValue(0,0,0,0,0);              case ::gig::attenuation_ctrl_t::type_controlchange: //FIXME: currently not sample accurate
131                    CrossfadeVolume = CrossfadeAttenuation(pEngineChannel->ControllerTable[pDimRgn->AttenuationController.controller_number]);
132                    break;
133                case ::gig::attenuation_ctrl_t::type_none: // no crossfade defined
134                default:
135                    CrossfadeVolume = 1.0f;
136          }          }
137    
138          pSample = pDimRgn->pSample; // sample won't change until the voice is finished          PanLeft  = 1.0f - float(RTMath::Max(pDimRgn->Pan, 0)) /  63.0f;
139            PanRight = 1.0f - float(RTMath::Min(pDimRgn->Pan, 0)) / -64.0f;
140    
141            Pos = pDimRgn->SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)
142    
143          // Check if the sample needs disk streaming or is too short for that          // Check if the sample needs disk streaming or is too short for that
144          long cachedsamples = pSample->GetCache().Size / pSample->FrameSize;          long cachedsamples = pSample->GetCache().Size / pSample->FrameSize;
145          DiskVoice          = cachedsamples < pSample->SamplesTotal;          DiskVoice          = cachedsamples < pSample->SamplesTotal;
146    
147          if (DiskVoice) { // voice to be streamed from disk          if (DiskVoice) { // voice to be streamed from disk
148              MaxRAMPos = cachedsamples - (MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels; //TODO: this calculation is too pessimistic and may better be moved to Render() method, so it calculates MaxRAMPos dependent to the current demand of sample points to be rendered (e.g. in case of JACK)              MaxRAMPos = cachedsamples - (pEngine->MaxSamplesPerCycle << CONFIG_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)
149    
150              // check if there's a loop defined which completely fits into the cached (RAM) part of the sample              // check if there's a loop defined which completely fits into the cached (RAM) part of the sample
151              if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) {              if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) {
# Line 159  namespace LinuxSampler { namespace gig { Line 156  namespace LinuxSampler { namespace gig {
156    
157              if (pDiskThread->OrderNewStream(&DiskStreamRef, pSample, MaxRAMPos, !RAMLoop) < 0) {              if (pDiskThread->OrderNewStream(&DiskStreamRef, pSample, MaxRAMPos, !RAMLoop) < 0) {
158                  dmsg(1,("Disk stream order failed!\n"));                  dmsg(1,("Disk stream order failed!\n"));
159                  Kill();                  KillImmediately();
160                  return -1;                  return -1;
161              }              }
162              dmsg(4,("Disk voice launched (cached samples: %d, total Samples: %d, MaxRAMPos: %d, RAMLooping: %s)\n", cachedsamples, pSample->SamplesTotal, MaxRAMPos, (RAMLoop) ? "yes" : "no"));              dmsg(4,("Disk voice launched (cached samples: %d, total Samples: %d, MaxRAMPos: %d, RAMLooping: %s)\n", cachedsamples, pSample->SamplesTotal, MaxRAMPos, (RAMLoop) ? "yes" : "no"));
# Line 177  namespace LinuxSampler { namespace gig { Line 174  namespace LinuxSampler { namespace gig {
174    
175          // calculate initial pitch value          // calculate initial pitch value
176          {          {
177              double pitchbasecents = pDimRgn->FineTune * 10;              double pitchbasecents = pDimRgn->FineTune + (int) pEngine->ScaleTuning[MIDIKey % 12];
178              if (pDimRgn->PitchTrack) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;              if (pDimRgn->PitchTrack) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;
179              this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents);              this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents) * (double(pSample->SamplesPerSecond) / double(pEngine->SampleRate));
180              this->PitchBend = RTMath::CentsToFreqRatio(((double) PitchBend / 8192.0) * 200.0); // pitchbend wheel +-2 semitones = 200 cents              this->PitchBend = RTMath::CentsToFreqRatio(((double) PitchBend / 8192.0) * 200.0); // pitchbend wheel +-2 semitones = 200 cents
181          }          }
182    
183            // the length of the decay and release curves are dependent on the velocity
184          Volume = pDimRgn->GetVelocityAttenuation(pNoteOnEvent->Velocity) / 32768.0f; // we downscale by 32768 to convert from int16 value range to DSP value range (which is -1.0..1.0)          const double velrelease = 1 / pDimRgn->GetVelocityRelease(itNoteOnEvent->Param.Note.Velocity);
   
185    
186          // setup EG 1 (VCA EG)          // setup EG 1 (VCA EG)
187          {          {
# Line 199  namespace LinuxSampler { namespace gig { Line 195  namespace LinuxSampler { namespace gig {
195                      eg1controllervalue = 0; // TODO: aftertouch not yet supported                      eg1controllervalue = 0; // TODO: aftertouch not yet supported
196                      break;                      break;
197                  case ::gig::eg1_ctrl_t::type_velocity:                  case ::gig::eg1_ctrl_t::type_velocity:
198                      eg1controllervalue = pNoteOnEvent->Velocity;                      eg1controllervalue = itNoteOnEvent->Param.Note.Velocity;
199                      break;                      break;
200                  case ::gig::eg1_ctrl_t::type_controlchange: // MIDI control change controller                  case ::gig::eg1_ctrl_t::type_controlchange: // MIDI control change controller
201                      eg1controllervalue = pEngine->ControllerTable[pDimRgn->EG1Controller.controller_number];                      eg1controllervalue = pEngineChannel->ControllerTable[pDimRgn->EG1Controller.controller_number];
202                      break;                      break;
203              }              }
204              if (pDimRgn->EG1ControllerInvert) eg1controllervalue = 127 - eg1controllervalue;              if (pDimRgn->EG1ControllerInvert) eg1controllervalue = 127 - eg1controllervalue;
205    
206              // calculate influence of EG1 controller on EG1's parameters (TODO: needs to be fine tuned)              // calculate influence of EG1 controller on EG1's parameters
207              double eg1attack  = (pDimRgn->EG1ControllerAttackInfluence)  ? 0.0001 * (double) (1 << pDimRgn->EG1ControllerAttackInfluence)  * eg1controllervalue : 0.0;              // (eg1attack is different from the others)
208              double eg1decay   = (pDimRgn->EG1ControllerDecayInfluence)   ? 0.0001 * (double) (1 << pDimRgn->EG1ControllerDecayInfluence)   * eg1controllervalue : 0.0;              double eg1attack  = (pDimRgn->EG1ControllerAttackInfluence)  ?
209              double eg1release = (pDimRgn->EG1ControllerReleaseInfluence) ? 0.0001 * (double) (1 << pDimRgn->EG1ControllerReleaseInfluence) * eg1controllervalue : 0.0;                  1 + 0.031 * (double) (pDimRgn->EG1ControllerAttackInfluence == 1 ?
210                                          1 : 1 << pDimRgn->EG1ControllerAttackInfluence) * eg1controllervalue : 1.0;
211              pEG1->Trigger(pDimRgn->EG1PreAttack,              double eg1decay   = (pDimRgn->EG1ControllerDecayInfluence)   ? 1 + 0.00775 * (double) (1 << pDimRgn->EG1ControllerDecayInfluence)   * eg1controllervalue : 1.0;
212                            pDimRgn->EG1Attack + eg1attack,              double eg1release = (pDimRgn->EG1ControllerReleaseInfluence) ? 1 + 0.00775 * (double) (1 << pDimRgn->EG1ControllerReleaseInfluence) * eg1controllervalue : 1.0;
213                            pDimRgn->EG1Hold,  
214                            pSample->LoopStart,              EG1.trigger(pDimRgn->EG1PreAttack,
215                            pDimRgn->EG1Decay1 + eg1decay,                          pDimRgn->EG1Attack * eg1attack,
216                            pDimRgn->EG1Decay2 + eg1decay,                          pDimRgn->EG1Hold,
217                            pDimRgn->EG1InfiniteSustain,                          pSample->LoopStart,
218                            pDimRgn->EG1Sustain,                          pDimRgn->EG1Decay1 * eg1decay * velrelease,
219                            pDimRgn->EG1Release + eg1release,                          pDimRgn->EG1Decay2 * eg1decay * velrelease,
220                            Delay);                          pDimRgn->EG1InfiniteSustain,
221                            pDimRgn->EG1Sustain,
222                            pDimRgn->EG1Release * eg1release * velrelease,
223                            velocityAttenuation,
224                            pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
225          }          }
226    
227    
     #if ENABLE_FILTER  
228          // setup EG 2 (VCF Cutoff EG)          // setup EG 2 (VCF Cutoff EG)
229          {          {
230              // get current value of EG2 controller              // get current value of EG2 controller
# Line 238  namespace LinuxSampler { namespace gig { Line 237  namespace LinuxSampler { namespace gig {
237                      eg2controllervalue = 0; // TODO: aftertouch not yet supported                      eg2controllervalue = 0; // TODO: aftertouch not yet supported
238                      break;                      break;
239                  case ::gig::eg2_ctrl_t::type_velocity:                  case ::gig::eg2_ctrl_t::type_velocity:
240                      eg2controllervalue = pNoteOnEvent->Velocity;                      eg2controllervalue = itNoteOnEvent->Param.Note.Velocity;
241                      break;                      break;
242                  case ::gig::eg2_ctrl_t::type_controlchange: // MIDI control change controller                  case ::gig::eg2_ctrl_t::type_controlchange: // MIDI control change controller
243                      eg2controllervalue = pEngine->ControllerTable[pDimRgn->EG2Controller.controller_number];                      eg2controllervalue = pEngineChannel->ControllerTable[pDimRgn->EG2Controller.controller_number];
244                      break;                      break;
245              }              }
246              if (pDimRgn->EG2ControllerInvert) eg2controllervalue = 127 - eg2controllervalue;              if (pDimRgn->EG2ControllerInvert) eg2controllervalue = 127 - eg2controllervalue;
247    
248              // calculate influence of EG2 controller on EG2's parameters (TODO: needs to be fine tuned)              // calculate influence of EG2 controller on EG2's parameters
249              double eg2attack  = (pDimRgn->EG2ControllerAttackInfluence)  ? 0.0001 * (double) (1 << pDimRgn->EG2ControllerAttackInfluence)  * eg2controllervalue : 0.0;              double eg2attack  = (pDimRgn->EG2ControllerAttackInfluence)  ? 1 + 0.00775 * (double) (1 << pDimRgn->EG2ControllerAttackInfluence)  * eg2controllervalue : 1.0;
250              double eg2decay   = (pDimRgn->EG2ControllerDecayInfluence)   ? 0.0001 * (double) (1 << pDimRgn->EG2ControllerDecayInfluence)   * eg2controllervalue : 0.0;              double eg2decay   = (pDimRgn->EG2ControllerDecayInfluence)   ? 1 + 0.00775 * (double) (1 << pDimRgn->EG2ControllerDecayInfluence)   * eg2controllervalue : 1.0;
251              double eg2release = (pDimRgn->EG2ControllerReleaseInfluence) ? 0.0001 * (double) (1 << pDimRgn->EG2ControllerReleaseInfluence) * eg2controllervalue : 0.0;              double eg2release = (pDimRgn->EG2ControllerReleaseInfluence) ? 1 + 0.00775 * (double) (1 << pDimRgn->EG2ControllerReleaseInfluence) * eg2controllervalue : 1.0;
252    
253              pEG2->Trigger(pDimRgn->EG2PreAttack,              EG2.trigger(pDimRgn->EG2PreAttack,
254                            pDimRgn->EG2Attack + eg2attack,                          pDimRgn->EG2Attack * eg2attack,
255                            false,                          false,
256                            pSample->LoopStart,                          pSample->LoopStart,
257                            pDimRgn->EG2Decay1 + eg2decay,                          pDimRgn->EG2Decay1 * eg2decay * velrelease,
258                            pDimRgn->EG2Decay2 + eg2decay,                          pDimRgn->EG2Decay2 * eg2decay * velrelease,
259                            pDimRgn->EG2InfiniteSustain,                          pDimRgn->EG2InfiniteSustain,
260                            pDimRgn->EG2Sustain,                          pDimRgn->EG2Sustain,
261                            pDimRgn->EG2Release + eg2release,                          pDimRgn->EG2Release * eg2release * velrelease,
262                            Delay);                          velocityAttenuation,
263                            pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
264          }          }
     #endif // ENABLE_FILTER  
265    
266    
267          // setup EG 3 (VCO EG)          // setup EG 3 (VCO EG)
268          {          {
269            double eg3depth = RTMath::CentsToFreqRatio(pDimRgn->EG3Depth);            double eg3depth = RTMath::CentsToFreqRatio(pDimRgn->EG3Depth);
270            pEG3->Trigger(eg3depth, pDimRgn->EG3Attack, Delay);            EG3.trigger(eg3depth, pDimRgn->EG3Attack, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
271          }          }
272    
273    
# Line 279  namespace LinuxSampler { namespace gig { Line 278  namespace LinuxSampler { namespace gig {
278                  case ::gig::lfo1_ctrl_internal:                  case ::gig::lfo1_ctrl_internal:
279                      lfo1_internal_depth  = pDimRgn->LFO1InternalDepth;                      lfo1_internal_depth  = pDimRgn->LFO1InternalDepth;
280                      pLFO1->ExtController = 0; // no external controller                      pLFO1->ExtController = 0; // no external controller
281                        bLFO1Enabled         = (lfo1_internal_depth > 0);
282                      break;                      break;
283                  case ::gig::lfo1_ctrl_modwheel:                  case ::gig::lfo1_ctrl_modwheel:
284                      lfo1_internal_depth  = 0;                      lfo1_internal_depth  = 0;
285                      pLFO1->ExtController = 1; // MIDI controller 1                      pLFO1->ExtController = 1; // MIDI controller 1
286                        bLFO1Enabled         = (pDimRgn->LFO1ControlDepth > 0);
287                      break;                      break;
288                  case ::gig::lfo1_ctrl_breath:                  case ::gig::lfo1_ctrl_breath:
289                      lfo1_internal_depth  = 0;                      lfo1_internal_depth  = 0;
290                      pLFO1->ExtController = 2; // MIDI controller 2                      pLFO1->ExtController = 2; // MIDI controller 2
291                        bLFO1Enabled         = (pDimRgn->LFO1ControlDepth > 0);
292                      break;                      break;
293                  case ::gig::lfo1_ctrl_internal_modwheel:                  case ::gig::lfo1_ctrl_internal_modwheel:
294                      lfo1_internal_depth  = pDimRgn->LFO1InternalDepth;                      lfo1_internal_depth  = pDimRgn->LFO1InternalDepth;
295                      pLFO1->ExtController = 1; // MIDI controller 1                      pLFO1->ExtController = 1; // MIDI controller 1
296                        bLFO1Enabled         = (lfo1_internal_depth > 0 || pDimRgn->LFO1ControlDepth > 0);
297                      break;                      break;
298                  case ::gig::lfo1_ctrl_internal_breath:                  case ::gig::lfo1_ctrl_internal_breath:
299                      lfo1_internal_depth  = pDimRgn->LFO1InternalDepth;                      lfo1_internal_depth  = pDimRgn->LFO1InternalDepth;
300                      pLFO1->ExtController = 2; // MIDI controller 2                      pLFO1->ExtController = 2; // MIDI controller 2
301                        bLFO1Enabled         = (lfo1_internal_depth > 0 || pDimRgn->LFO1ControlDepth > 0);
302                      break;                      break;
303                  default:                  default:
304                      lfo1_internal_depth  = 0;                      lfo1_internal_depth  = 0;
305                      pLFO1->ExtController = 0; // no external controller                      pLFO1->ExtController = 0; // no external controller
306                        bLFO1Enabled         = false;
307              }              }
308              pLFO1->Trigger(pDimRgn->LFO1Frequency,              if (bLFO1Enabled) pLFO1->trigger(pDimRgn->LFO1Frequency,
309                            lfo1_internal_depth,                                               start_level_max,
310                            pDimRgn->LFO1ControlDepth,                                               lfo1_internal_depth,
311                            pEngine->ControllerTable[pLFO1->ExtController],                                               pDimRgn->LFO1ControlDepth,
312                            pDimRgn->LFO1FlipPhase,                                               pDimRgn->LFO1FlipPhase,
313                            this->SampleRate,                                               pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
                           Delay);  
314          }          }
315    
316      #if ENABLE_FILTER  
317          // setup LFO 2 (VCF Cutoff LFO)          // setup LFO 2 (VCF Cutoff LFO)
318          {          {
319              uint16_t lfo2_internal_depth;              uint16_t lfo2_internal_depth;
# Line 317  namespace LinuxSampler { namespace gig { Line 321  namespace LinuxSampler { namespace gig {
321                  case ::gig::lfo2_ctrl_internal:                  case ::gig::lfo2_ctrl_internal:
322                      lfo2_internal_depth  = pDimRgn->LFO2InternalDepth;                      lfo2_internal_depth  = pDimRgn->LFO2InternalDepth;
323                      pLFO2->ExtController = 0; // no external controller                      pLFO2->ExtController = 0; // no external controller
324                        bLFO2Enabled         = (lfo2_internal_depth > 0);
325                      break;                      break;
326                  case ::gig::lfo2_ctrl_modwheel:                  case ::gig::lfo2_ctrl_modwheel:
327                      lfo2_internal_depth  = 0;                      lfo2_internal_depth  = 0;
328                      pLFO2->ExtController = 1; // MIDI controller 1                      pLFO2->ExtController = 1; // MIDI controller 1
329                        bLFO2Enabled         = (pDimRgn->LFO2ControlDepth > 0);
330                      break;                      break;
331                  case ::gig::lfo2_ctrl_foot:                  case ::gig::lfo2_ctrl_foot:
332                      lfo2_internal_depth  = 0;                      lfo2_internal_depth  = 0;
333                      pLFO2->ExtController = 4; // MIDI controller 4                      pLFO2->ExtController = 4; // MIDI controller 4
334                        bLFO2Enabled         = (pDimRgn->LFO2ControlDepth > 0);
335                      break;                      break;
336                  case ::gig::lfo2_ctrl_internal_modwheel:                  case ::gig::lfo2_ctrl_internal_modwheel:
337                      lfo2_internal_depth  = pDimRgn->LFO2InternalDepth;                      lfo2_internal_depth  = pDimRgn->LFO2InternalDepth;
338                      pLFO2->ExtController = 1; // MIDI controller 1                      pLFO2->ExtController = 1; // MIDI controller 1
339                        bLFO2Enabled         = (lfo2_internal_depth > 0 || pDimRgn->LFO2ControlDepth > 0);
340                      break;                      break;
341                  case ::gig::lfo2_ctrl_internal_foot:                  case ::gig::lfo2_ctrl_internal_foot:
342                      lfo2_internal_depth  = pDimRgn->LFO2InternalDepth;                      lfo2_internal_depth  = pDimRgn->LFO2InternalDepth;
343                      pLFO2->ExtController = 4; // MIDI controller 4                      pLFO2->ExtController = 4; // MIDI controller 4
344                        bLFO2Enabled         = (lfo2_internal_depth > 0 || pDimRgn->LFO2ControlDepth > 0);
345                      break;                      break;
346                  default:                  default:
347                      lfo2_internal_depth  = 0;                      lfo2_internal_depth  = 0;
348                      pLFO2->ExtController = 0; // no external controller                      pLFO2->ExtController = 0; // no external controller
349                        bLFO2Enabled         = false;
350              }              }
351              pLFO2->Trigger(pDimRgn->LFO2Frequency,              if (bLFO2Enabled) pLFO2->trigger(pDimRgn->LFO2Frequency,
352                            lfo2_internal_depth,                                               start_level_max,
353                            pDimRgn->LFO2ControlDepth,                                               lfo2_internal_depth,
354                            pEngine->ControllerTable[pLFO2->ExtController],                                               pDimRgn->LFO2ControlDepth,
355                            pDimRgn->LFO2FlipPhase,                                               pDimRgn->LFO2FlipPhase,
356                            Delay);                                               pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
357          }          }
358      #endif // ENABLE_FILTER  
359    
360          // setup LFO 3 (VCO LFO)          // setup LFO 3 (VCO LFO)
361          {          {
# Line 354  namespace LinuxSampler { namespace gig { Line 364  namespace LinuxSampler { namespace gig {
364                  case ::gig::lfo3_ctrl_internal:                  case ::gig::lfo3_ctrl_internal:
365                      lfo3_internal_depth  = pDimRgn->LFO3InternalDepth;                      lfo3_internal_depth  = pDimRgn->LFO3InternalDepth;
366                      pLFO3->ExtController = 0; // no external controller                      pLFO3->ExtController = 0; // no external controller
367                        bLFO3Enabled         = (lfo3_internal_depth > 0);
368                      break;                      break;
369                  case ::gig::lfo3_ctrl_modwheel:                  case ::gig::lfo3_ctrl_modwheel:
370                      lfo3_internal_depth  = 0;                      lfo3_internal_depth  = 0;
371                      pLFO3->ExtController = 1; // MIDI controller 1                      pLFO3->ExtController = 1; // MIDI controller 1
372                        bLFO3Enabled         = (pDimRgn->LFO3ControlDepth > 0);
373                      break;                      break;
374                  case ::gig::lfo3_ctrl_aftertouch:                  case ::gig::lfo3_ctrl_aftertouch:
375                      lfo3_internal_depth  = 0;                      lfo3_internal_depth  = 0;
376                      pLFO3->ExtController = 0; // TODO: aftertouch not implemented yet                      pLFO3->ExtController = 0; // TODO: aftertouch not implemented yet
377                        bLFO3Enabled         = false; // see TODO comment in line above
378                      break;                      break;
379                  case ::gig::lfo3_ctrl_internal_modwheel:                  case ::gig::lfo3_ctrl_internal_modwheel:
380                      lfo3_internal_depth  = pDimRgn->LFO3InternalDepth;                      lfo3_internal_depth  = pDimRgn->LFO3InternalDepth;
381                      pLFO3->ExtController = 1; // MIDI controller 1                      pLFO3->ExtController = 1; // MIDI controller 1
382                        bLFO3Enabled         = (lfo3_internal_depth > 0 || pDimRgn->LFO3ControlDepth > 0);
383                      break;                      break;
384                  case ::gig::lfo3_ctrl_internal_aftertouch:                  case ::gig::lfo3_ctrl_internal_aftertouch:
385                      lfo3_internal_depth  = pDimRgn->LFO3InternalDepth;                      lfo3_internal_depth  = pDimRgn->LFO3InternalDepth;
386                      pLFO1->ExtController = 0; // TODO: aftertouch not implemented yet                      pLFO1->ExtController = 0; // TODO: aftertouch not implemented yet
387                        bLFO3Enabled         = (lfo3_internal_depth > 0 /*|| pDimRgn->LFO3ControlDepth > 0*/); // see TODO comment in line above
388                      break;                      break;
389                  default:                  default:
390                      lfo3_internal_depth  = 0;                      lfo3_internal_depth  = 0;
391                      pLFO3->ExtController = 0; // no external controller                      pLFO3->ExtController = 0; // no external controller
392                        bLFO3Enabled         = false;
393              }              }
394              pLFO3->Trigger(pDimRgn->LFO3Frequency,              if (bLFO3Enabled) pLFO3->trigger(pDimRgn->LFO3Frequency,
395                            lfo3_internal_depth,                                               start_level_mid,
396                            pDimRgn->LFO3ControlDepth,                                               lfo3_internal_depth,
397                            pEngine->ControllerTable[pLFO3->ExtController],                                               pDimRgn->LFO3ControlDepth,
398                            false,                                               false,
399                            this->SampleRate,                                               pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
                           Delay);  
400          }          }
401    
402      #if ENABLE_FILTER  
403          #if FORCE_FILTER_USAGE          #if CONFIG_FORCE_FILTER
404          FilterLeft.Enabled = FilterRight.Enabled = true;          const bool bUseFilter = true;
405          #else // use filter only if instrument file told so          #else // use filter only if instrument file told so
406          FilterLeft.Enabled = FilterRight.Enabled = pDimRgn->VCFEnabled;          const bool bUseFilter = pDimRgn->VCFEnabled;
407          #endif // FORCE_FILTER_USAGE          #endif // CONFIG_FORCE_FILTER
408          if (pDimRgn->VCFEnabled) {          SYNTHESIS_MODE_SET_FILTER(SynthesisMode, bUseFilter);
409              #ifdef OVERRIDE_FILTER_CUTOFF_CTRL          if (bUseFilter) {
410              VCFCutoffCtrl.controller = OVERRIDE_FILTER_CUTOFF_CTRL;              #ifdef CONFIG_OVERRIDE_CUTOFF_CTRL
411                VCFCutoffCtrl.controller = CONFIG_OVERRIDE_CUTOFF_CTRL;
412              #else // use the one defined in the instrument file              #else // use the one defined in the instrument file
413              switch (pDimRgn->VCFCutoffController) {              switch (pDimRgn->VCFCutoffController) {
414                  case ::gig::vcf_cutoff_ctrl_modwheel:                  case ::gig::vcf_cutoff_ctrl_modwheel:
# Line 428  namespace LinuxSampler { namespace gig { Line 444  namespace LinuxSampler { namespace gig {
444                      VCFCutoffCtrl.controller = 0;                      VCFCutoffCtrl.controller = 0;
445                      break;                      break;
446              }              }
447              #endif // OVERRIDE_FILTER_CUTOFF_CTRL              #endif // CONFIG_OVERRIDE_CUTOFF_CTRL
448    
449              #ifdef OVERRIDE_FILTER_RES_CTRL              #ifdef CONFIG_OVERRIDE_RESONANCE_CTRL
450              VCFResonanceCtrl.controller = OVERRIDE_FILTER_RES_CTRL;              VCFResonanceCtrl.controller = CONFIG_OVERRIDE_RESONANCE_CTRL;
451              #else // use the one defined in the instrument file              #else // use the one defined in the instrument file
452              switch (pDimRgn->VCFResonanceController) {              switch (pDimRgn->VCFResonanceController) {
453                  case ::gig::vcf_res_ctrl_genpurpose3:                  case ::gig::vcf_res_ctrl_genpurpose3:
# Line 450  namespace LinuxSampler { namespace gig { Line 466  namespace LinuxSampler { namespace gig {
466                  default:                  default:
467                      VCFResonanceCtrl.controller = 0;                      VCFResonanceCtrl.controller = 0;
468              }              }
469              #endif // OVERRIDE_FILTER_RES_CTRL              #endif // CONFIG_OVERRIDE_RESONANCE_CTRL
470    
471              #ifndef OVERRIDE_FILTER_TYPE              #ifndef CONFIG_OVERRIDE_FILTER_TYPE
472              FilterLeft.SetType(pDimRgn->VCFType);              FilterLeft.SetType(pDimRgn->VCFType);
473              FilterRight.SetType(pDimRgn->VCFType);              FilterRight.SetType(pDimRgn->VCFType);
474              #else // override filter type              #else // override filter type
475              FilterLeft.SetType(OVERRIDE_FILTER_TYPE);              FilterLeft.SetType(CONFIG_OVERRIDE_FILTER_TYPE);
476              FilterRight.SetType(OVERRIDE_FILTER_TYPE);              FilterRight.SetType(CONFIG_OVERRIDE_FILTER_TYPE);
477              #endif // OVERRIDE_FILTER_TYPE              #endif // CONFIG_OVERRIDE_FILTER_TYPE
478    
479              VCFCutoffCtrl.value    = pEngine->ControllerTable[VCFCutoffCtrl.controller];              VCFCutoffCtrl.value    = pEngineChannel->ControllerTable[VCFCutoffCtrl.controller];
480              VCFResonanceCtrl.value = pEngine->ControllerTable[VCFResonanceCtrl.controller];              VCFResonanceCtrl.value = pEngineChannel->ControllerTable[VCFResonanceCtrl.controller];
481    
482              // calculate cutoff frequency              // calculate cutoff frequency
483              float cutoff = (!VCFCutoffCtrl.controller)              float cutoff = pDimRgn->GetVelocityCutoff(itNoteOnEvent->Param.Note.Velocity);
484                  ? exp((float) (127 - pNoteOnEvent->Velocity) * (float) pDimRgn->VCFVelocityScale * 6.2E-5f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX              if (pDimRgn->VCFKeyboardTracking) {
485                  : exp((float) VCFCutoffCtrl.value * 0.00787402f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX;                  cutoff *= exp((itNoteOnEvent->Param.Note.Key - pDimRgn->VCFKeyboardTrackingBreakpoint) * 0.057762265f); // (ln(2) / 12)
486                }
487                CutoffBase = cutoff;
488    
489                int cvalue;
490                if (VCFCutoffCtrl.controller) {
491                    cvalue = pEngineChannel->ControllerTable[VCFCutoffCtrl.controller];
492                    if (pDimRgn->VCFCutoffControllerInvert) cvalue = 127 - cvalue;
493                    if (cvalue < pDimRgn->VCFVelocityScale) cvalue = pDimRgn->VCFVelocityScale;
494                }
495                else {
496                    cvalue = pDimRgn->VCFCutoff;
497                }
498                cutoff *= float(cvalue) * 0.00787402f; // (1 / 127)
499                if (cutoff > 1.0) cutoff = 1.0;
500                cutoff = exp(cutoff * FILTER_CUTOFF_COEFF) * CONFIG_FILTER_CUTOFF_MIN;
501    
502              // calculate resonance              // calculate resonance
503              float resonance = (float) VCFResonanceCtrl.value * 0.00787f;   // 0.0..1.0              float resonance = (float) VCFResonanceCtrl.value * 0.00787f;   // 0.0..1.0
504              if (pDimRgn->VCFKeyboardTracking) {              if (pDimRgn->VCFKeyboardTracking) {
505                  resonance += (float) (pNoteOnEvent->Key - pDimRgn->VCFKeyboardTrackingBreakpoint) * 0.00787f;                  resonance += (float) (itNoteOnEvent->Param.Note.Key - pDimRgn->VCFKeyboardTrackingBreakpoint) * 0.00787f;
506              }              }
507              Constrain(resonance, 0.0, 1.0); // correct resonance if outside allowed value range (0.0..1.0)              Constrain(resonance, 0.0, 1.0); // correct resonance if outside allowed value range (0.0..1.0)
508    
509              VCFCutoffCtrl.fvalue    = cutoff - FILTER_CUTOFF_MIN;              VCFCutoffCtrl.fvalue    = cutoff - CONFIG_FILTER_CUTOFF_MIN;
510              VCFResonanceCtrl.fvalue = resonance;              VCFResonanceCtrl.fvalue = resonance;
   
             FilterLeft.SetParameters(cutoff,  resonance, SampleRate);  
             FilterRight.SetParameters(cutoff, resonance, SampleRate);  
   
             FilterUpdateCounter = -1;  
511          }          }
512          else {          else {
513              VCFCutoffCtrl.controller    = 0;              VCFCutoffCtrl.controller    = 0;
514              VCFResonanceCtrl.controller = 0;              VCFResonanceCtrl.controller = 0;
515          }          }
     #endif // ENABLE_FILTER  
   
         // ************************************************  
         // TODO: ARTICULATION DATA HANDLING IS MISSING HERE  
         // ************************************************  
516    
517          return 0; // success          return 0; // success
518      }      }
# Line 509  namespace LinuxSampler { namespace gig { Line 530  namespace LinuxSampler { namespace gig {
530       */       */
531      void Voice::Render(uint Samples) {      void Voice::Render(uint Samples) {
532    
533          // Reset the synthesis parameter matrix          // select default values for synthesis mode bits
534          pEngine->ResetSynthesisParameters(Event::destination_vca, this->Volume);          SYNTHESIS_MODE_SET_LOOP(SynthesisMode, false);
         pEngine->ResetSynthesisParameters(Event::destination_vco, this->PitchBase);  
     #if ENABLE_FILTER  
         pEngine->ResetSynthesisParameters(Event::destination_vcfc, VCFCutoffCtrl.fvalue);  
         pEngine->ResetSynthesisParameters(Event::destination_vcfr, VCFResonanceCtrl.fvalue);  
     #endif // ENABLE_FILTER  
   
   
         // Apply events to the synthesis parameter matrix  
         ProcessEvents(Samples);  
   
   
         // Let all modulators write their parameter changes to the synthesis parameter matrix for the current audio fragment  
         pEG1->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, pTriggerEvent, this->Pos, this->PitchBase * this->PitchBend);  
     #if ENABLE_FILTER  
         pEG2->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, pTriggerEvent, this->Pos, this->PitchBase * this->PitchBend);  
     #endif // ENABLE_FILTER  
         pEG3->Process(Samples);  
         pLFO1->Process(Samples);  
     #if ENABLE_FILTER  
         pLFO2->Process(Samples);  
     #endif // ENABLE_FILTER  
         pLFO3->Process(Samples);  
   
535    
536          switch (this->PlaybackState) {          switch (this->PlaybackState) {
537    
538                case playback_state_init:
539                    this->PlaybackState = playback_state_ram; // we always start playback from RAM cache and switch then to disk if needed
540                    // no break - continue with playback_state_ram
541    
542              case playback_state_ram: {              case playback_state_ram: {
543                      if (RAMLoop) InterpolateAndLoop(Samples, (sample_t*) pSample->GetCache().pStart, Delay);                      if (RAMLoop) SYNTHESIS_MODE_SET_LOOP(SynthesisMode, true); // enable looping
544                      else         Interpolate(Samples, (sample_t*) pSample->GetCache().pStart, Delay);  
545                        // render current fragment
546                        Synthesize(Samples, (sample_t*) pSample->GetCache().pStart, Delay);
547    
548                      if (DiskVoice) {                      if (DiskVoice) {
549                          // check if we reached the allowed limit of the sample RAM cache                          // check if we reached the allowed limit of the sample RAM cache
550                          if (Pos > MaxRAMPos) {                          if (Pos > MaxRAMPos) {
# Line 559  namespace LinuxSampler { namespace gig { Line 564  namespace LinuxSampler { namespace gig {
564                          DiskStreamRef.pStream = pDiskThread->AskForCreatedStream(DiskStreamRef.OrderID);                          DiskStreamRef.pStream = pDiskThread->AskForCreatedStream(DiskStreamRef.OrderID);
565                          if (!DiskStreamRef.pStream) {                          if (!DiskStreamRef.pStream) {
566                              std::cout << stderr << "Disk stream not available in time!" << std::endl << std::flush;                              std::cout << stderr << "Disk stream not available in time!" << std::endl << std::flush;
567                              Kill();                              KillImmediately();
568                              return;                              return;
569                          }                          }
570                          DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (RTMath::DoubleToInt(Pos) - MaxRAMPos));                          DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (int(Pos) - MaxRAMPos));
571                          Pos -= RTMath::DoubleToInt(Pos);                          Pos -= int(Pos);
572                            RealSampleWordsLeftToRead = -1; // -1 means no silence has been added yet
573                      }                      }
574    
575                        const int sampleWordsLeftToRead = DiskStreamRef.pStream->GetReadSpace();
576    
577                      // add silence sample at the end if we reached the end of the stream (for the interpolator)                      // add silence sample at the end if we reached the end of the stream (for the interpolator)
578                      if (DiskStreamRef.State == Stream::state_end && DiskStreamRef.pStream->GetReadSpace() < (MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels) {                      if (DiskStreamRef.State == Stream::state_end) {
579                          DiskStreamRef.pStream->WriteSilence((MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels);                          const int maxSampleWordsPerCycle = (pEngine->MaxSamplesPerCycle << CONFIG_MAX_PITCH) * pSample->Channels + 6; // +6 for the interpolator algorithm
580                          this->PlaybackState = playback_state_end;                          if (sampleWordsLeftToRead <= maxSampleWordsPerCycle) {
581                                // remember how many sample words there are before any silence has been added
582                                if (RealSampleWordsLeftToRead < 0) RealSampleWordsLeftToRead = sampleWordsLeftToRead;
583                                DiskStreamRef.pStream->WriteSilence(maxSampleWordsPerCycle - sampleWordsLeftToRead);
584                            }
585                      }                      }
586    
587                      sample_t* ptr = DiskStreamRef.pStream->GetReadPtr(); // get the current read_ptr within the ringbuffer where we read the samples from                      sample_t* ptr = DiskStreamRef.pStream->GetReadPtr(); // get the current read_ptr within the ringbuffer where we read the samples from
588                      Interpolate(Samples, ptr, Delay);  
589                      DiskStreamRef.pStream->IncrementReadPos(RTMath::DoubleToInt(Pos) * pSample->Channels);                      // render current audio fragment
590                      Pos -= RTMath::DoubleToInt(Pos);                      Synthesize(Samples, ptr, Delay);
591    
592                        const int iPos = (int) Pos;
593                        const int readSampleWords = iPos * pSample->Channels; // amount of sample words actually been read
594                        DiskStreamRef.pStream->IncrementReadPos(readSampleWords);
595                        Pos -= iPos; // just keep fractional part of Pos
596    
597                        // change state of voice to 'end' if we really reached the end of the sample data
598                        if (RealSampleWordsLeftToRead >= 0) {
599                            RealSampleWordsLeftToRead -= readSampleWords;
600                            if (RealSampleWordsLeftToRead <= 0) this->PlaybackState = playback_state_end;
601                        }
602                  }                  }
603                  break;                  break;
604    
605              case playback_state_end:              case playback_state_end:
606                  Kill(); // free voice                  std::cerr << "gig::Voice::Render(): entered with playback_state_end, this is a bug!\n" << std::flush;
607                  break;                  break;
608          }          }
609    
610            // Reset synthesis event lists
611      #if ENABLE_FILTER          pEngineChannel->pEvents->clear();
         // Reset synthesis event lists (except VCO, as VCO events apply channel wide currently)  
         pEngine->pSynthesisEvents[Event::destination_vcfc]->clear();  
         pEngine->pSynthesisEvents[Event::destination_vcfr]->clear();  
     #endif // ENABLE_FILTER  
612    
613          // Reset delay          // Reset delay
614          Delay = 0;          Delay = 0;
615    
616          pTriggerEvent = NULL;          itTriggerEvent = Pool<Event>::Iterator();
617    
618          // If release stage finished, let the voice be killed          // If sample stream or release stage finished, kill the voice
619          if (pEG1->GetStage() == EGADSR::stage_end) this->PlaybackState = playback_state_end;          if (PlaybackState == playback_state_end || EG1.getSegmentType() == EGADSR::segment_end) KillImmediately();
620      }      }
621    
622      /**      /**
# Line 605  namespace LinuxSampler { namespace gig { Line 624  namespace LinuxSampler { namespace gig {
624       *  suspended / not running.       *  suspended / not running.
625       */       */
626      void Voice::Reset() {      void Voice::Reset() {
627          pLFO1->Reset();          FilterLeft.Reset();
628          pLFO2->Reset();          FilterRight.Reset();
         pLFO3->Reset();  
629          DiskStreamRef.pStream = NULL;          DiskStreamRef.pStream = NULL;
630          DiskStreamRef.hStream = 0;          DiskStreamRef.hStream = 0;
631          DiskStreamRef.State   = Stream::state_unused;          DiskStreamRef.State   = Stream::state_unused;
632          DiskStreamRef.OrderID = 0;          DiskStreamRef.OrderID = 0;
633          Active = false;          PlaybackState = playback_state_end;
634            itTriggerEvent = Pool<Event>::Iterator();
635            itKillEvent    = Pool<Event>::Iterator();
636      }      }
637    
638      /**      /**
639       *  Process the control change event lists of the engine for the current       * Process given list of MIDI note on, note off and sustain pedal events
640       *  audio fragment. Event values will be applied to the synthesis parameter       * for the given time.
      *  matrix.  
641       *       *
642       *  @param Samples - number of samples to be rendered in this audio fragment cycle       * @param itEvent - iterator pointing to the next event to be processed
643         * @param End     - youngest time stamp where processing should be stopped
644       */       */
645      void Voice::ProcessEvents(uint Samples) {      void Voice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) {
646            for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
647          // dispatch control change events              if (itEvent->Type == Event::type_release) {
648          Event* pCCEvent = pEngine->pCCEvents->first();                  EG1.update(EGADSR::event_release, this->Pos, fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
649          if (Delay) { // skip events that happened before this voice was triggered                  EG2.update(EGADSR::event_release, this->Pos, fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
650              while (pCCEvent && pCCEvent->FragmentPos() <= Delay) pCCEvent = pEngine->pCCEvents->next();              } else if (itEvent->Type == Event::type_cancel_release) {
651          }                  EG1.update(EGADSR::event_cancel_release, this->Pos, fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
652          while (pCCEvent) {                  EG2.update(EGADSR::event_cancel_release, this->Pos, fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
             if (pCCEvent->Controller) { // if valid MIDI controller  
                 #if ENABLE_FILTER  
                 if (pCCEvent->Controller == VCFCutoffCtrl.controller) {  
                     pEngine->pSynthesisEvents[Event::destination_vcfc]->alloc_assign(*pCCEvent);  
                 }  
                 if (pCCEvent->Controller == VCFResonanceCtrl.controller) {  
                     pEngine->pSynthesisEvents[Event::destination_vcfr]->alloc_assign(*pCCEvent);  
                 }  
                 #endif // ENABLE_FILTER  
                 if (pCCEvent->Controller == pLFO1->ExtController) {  
                     pLFO1->SendEvent(pCCEvent);  
                 }  
                 #if ENABLE_FILTER  
                 if (pCCEvent->Controller == pLFO2->ExtController) {  
                     pLFO2->SendEvent(pCCEvent);  
                 }  
                 #endif // ENABLE_FILTER  
                 if (pCCEvent->Controller == pLFO3->ExtController) {  
                     pLFO3->SendEvent(pCCEvent);  
                 }  
             }  
   
             pCCEvent = pEngine->pCCEvents->next();  
         }  
   
   
         // process pitch events  
         {  
             RTEList<Event>* pVCOEventList = pEngine->pSynthesisEvents[Event::destination_vco];  
             Event* pVCOEvent = pVCOEventList->first();  
             if (Delay) { // skip events that happened before this voice was triggered  
                 while (pVCOEvent && pVCOEvent->FragmentPos() <= Delay) pVCOEvent = pVCOEventList->next();  
             }  
             // apply old pitchbend value until first pitch event occurs  
             if (this->PitchBend != 1.0) {  
                 uint end = (pVCOEvent) ? pVCOEvent->FragmentPos() : Samples;  
                 for (uint i = Delay; i < end; i++) {  
                     pEngine->pSynthesisParameters[Event::destination_vco][i] *= this->PitchBend;  
                 }  
             }  
             float pitch;  
             while (pVCOEvent) {  
                 Event* pNextVCOEvent = pVCOEventList->next();  
   
                 // calculate the influence length of this event (in sample points)  
                 uint end = (pNextVCOEvent) ? pNextVCOEvent->FragmentPos() : Samples;  
   
                 pitch = RTMath::CentsToFreqRatio(((double) pVCOEvent->Pitch / 8192.0) * 200.0); // +-two semitones = +-200 cents  
   
                 // apply pitch value to the pitch parameter sequence  
                 for (uint i = pVCOEvent->FragmentPos(); i < end; i++) {  
                     pEngine->pSynthesisParameters[Event::destination_vco][i] *= pitch;  
                 }  
   
                 pVCOEvent = pNextVCOEvent;  
             }  
             if (pVCOEventList->last()) this->PitchBend = pitch;  
         }  
   
   
     #if ENABLE_FILTER  
         // process filter cutoff events  
         {  
             RTEList<Event>* pCutoffEventList = pEngine->pSynthesisEvents[Event::destination_vcfc];  
             Event* pCutoffEvent = pCutoffEventList->first();  
             if (Delay) { // skip events that happened before this voice was triggered  
                 while (pCutoffEvent && pCutoffEvent->FragmentPos() <= Delay) pCutoffEvent = pCutoffEventList->next();  
             }  
             float cutoff;  
             while (pCutoffEvent) {  
                 Event* pNextCutoffEvent = pCutoffEventList->next();  
   
                 // calculate the influence length of this event (in sample points)  
                 uint end = (pNextCutoffEvent) ? pNextCutoffEvent->FragmentPos() : Samples;  
   
                 cutoff = exp((float) pCutoffEvent->Value * 0.00787402f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX - FILTER_CUTOFF_MIN;  
   
                 // apply cutoff frequency to the cutoff parameter sequence  
                 for (uint i = pCutoffEvent->FragmentPos(); i < end; i++) {  
                     pEngine->pSynthesisParameters[Event::destination_vcfc][i] = cutoff;  
                 }  
   
                 pCutoffEvent = pNextCutoffEvent;  
             }  
             if (pCutoffEventList->last()) VCFCutoffCtrl.fvalue = cutoff; // needed for initialization of parameter matrix next time  
         }  
   
         // process filter resonance events  
         {  
             RTEList<Event>* pResonanceEventList = pEngine->pSynthesisEvents[Event::destination_vcfr];  
             Event* pResonanceEvent = pResonanceEventList->first();  
             if (Delay) { // skip events that happened before this voice was triggered  
                 while (pResonanceEvent && pResonanceEvent->FragmentPos() <= Delay) pResonanceEvent = pResonanceEventList->next();  
             }  
             while (pResonanceEvent) {  
                 Event* pNextResonanceEvent = pResonanceEventList->next();  
   
                 // calculate the influence length of this event (in sample points)  
                 uint end = (pNextResonanceEvent) ? pNextResonanceEvent->FragmentPos() : Samples;  
   
                 // convert absolute controller value to differential  
                 int ctrldelta = pResonanceEvent->Value - VCFResonanceCtrl.value;  
                 VCFResonanceCtrl.value = pResonanceEvent->Value;  
   
                 float resonancedelta = (float) ctrldelta * 0.00787f; // 0.0..1.0  
   
                 // apply cutoff frequency to the cutoff parameter sequence  
                 for (uint i = pResonanceEvent->FragmentPos(); i < end; i++) {  
                     pEngine->pSynthesisParameters[Event::destination_vcfr][i] += resonancedelta;  
                 }  
   
                 pResonanceEvent = pNextResonanceEvent;  
653              }              }
             if (pResonanceEventList->last()) VCFResonanceCtrl.fvalue = pResonanceEventList->last()->Value * 0.00787f; // needed for initialization of parameter matrix next time  
654          }          }
     #endif // ENABLE_FILTER  
655      }      }
656    
657      /**      /**
658       *  Interpolates the input audio data (no loop).       * Process given list of MIDI control change and pitch bend events for
659         * the given time.
660       *       *
661       *  @param Samples - number of sample points to be rendered in this audio       * @param itEvent - iterator pointing to the next event to be processed
662       *                   fragment cycle       * @param End     - youngest time stamp where processing should be stopped
      *  @param pSrc    - pointer to input sample data  
      *  @param Skip    - number of sample points to skip in output buffer  
663       */       */
664      void Voice::Interpolate(uint Samples, sample_t* pSrc, uint Skip) {      void Voice::processCCEvents(RTList<Event>::Iterator& itEvent, uint End) {
665          int i = Skip;          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
666                if (itEvent->Type == Event::type_control_change &&
667          // FIXME: assuming either mono or stereo                  itEvent->Param.CC.Controller) { // if (valid) MIDI control change event
668          if (this->pSample->Channels == 2) { // Stereo Sample                  if (itEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {
669              while (i < Samples) {                      processCutoffEvent(itEvent);
670                  InterpolateOneStep_Stereo(pSrc, i,                  }
671                                            pEngine->pSynthesisParameters[Event::destination_vca][i],                  if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {
672                                            pEngine->pSynthesisParameters[Event::destination_vco][i],                      processResonanceEvent(itEvent);
673                                            pEngine->pSynthesisParameters[Event::destination_vcfc][i],                  }
674                                            pEngine->pSynthesisParameters[Event::destination_vcfr][i]);                  if (itEvent->Param.CC.Controller == pLFO1->ExtController) {
675              }                      pLFO1->update(itEvent->Param.CC.Value);
676          }                  }
677          else { // Mono Sample                  if (itEvent->Param.CC.Controller == pLFO2->ExtController) {
678              while (i < Samples) {                      pLFO2->update(itEvent->Param.CC.Value);
679                  InterpolateOneStep_Mono(pSrc, i,                  }
680                                          pEngine->pSynthesisParameters[Event::destination_vca][i],                  if (itEvent->Param.CC.Controller == pLFO3->ExtController) {
681                                          pEngine->pSynthesisParameters[Event::destination_vco][i],                      pLFO3->update(itEvent->Param.CC.Value);
682                                          pEngine->pSynthesisParameters[Event::destination_vcfc][i],                  }
683                                          pEngine->pSynthesisParameters[Event::destination_vcfr][i]);                  if (pDimRgn->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange &&
684              }                      itEvent->Param.CC.Controller == pDimRgn->AttenuationController.controller_number) {
685          }                      processCrossFadeEvent(itEvent);
686                    }
687                } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event
688                    processPitchEvent(itEvent);
689                }
690            }
691        }
692    
693        void Voice::processPitchEvent(RTList<Event>::Iterator& itEvent) {
694            const float pitch = RTMath::CentsToFreqRatio(((double) itEvent->Param.Pitch.Pitch / 8192.0) * 200.0); // +-two semitones = +-200 cents
695            fFinalPitch *= pitch;
696            PitchBend = pitch;
697        }
698    
699        void Voice::processCrossFadeEvent(RTList<Event>::Iterator& itEvent) {
700            CrossfadeVolume = CrossfadeAttenuation(itEvent->Param.CC.Value);
701            #if CONFIG_PROCESS_MUTED_CHANNELS
702            const float effectiveVolume = CrossfadeVolume * Volume * (pEngineChannel->GetMute() ? 0 : pEngineChannel->GlobalVolume);
703            #else
704            const float effectiveVolume = CrossfadeVolume * Volume * pEngineChannel->GlobalVolume;
705            #endif
706            fFinalVolume = effectiveVolume;
707        }
708    
709        void Voice::processCutoffEvent(RTList<Event>::Iterator& itEvent) {
710            int ccvalue = itEvent->Param.CC.Value;
711            if (VCFCutoffCtrl.value == ccvalue) return;
712            VCFCutoffCtrl.value == ccvalue;
713            if (pDimRgn->VCFCutoffControllerInvert)  ccvalue = 127 - ccvalue;
714            if (ccvalue < pDimRgn->VCFVelocityScale) ccvalue = pDimRgn->VCFVelocityScale;
715            float cutoff = CutoffBase * float(ccvalue) * 0.00787402f; // (1 / 127)
716            if (cutoff > 1.0) cutoff = 1.0;
717            cutoff = exp(cutoff * FILTER_CUTOFF_COEFF) * CONFIG_FILTER_CUTOFF_MIN - CONFIG_FILTER_CUTOFF_MIN;
718            VCFCutoffCtrl.fvalue = cutoff; // needed for initialization of fFinalCutoff next time
719            fFinalCutoff = cutoff;
720        }
721    
722        void Voice::processResonanceEvent(RTList<Event>::Iterator& itEvent) {
723            // convert absolute controller value to differential
724            const int ctrldelta = itEvent->Param.CC.Value - VCFResonanceCtrl.value;
725            VCFResonanceCtrl.value = itEvent->Param.CC.Value;
726            const float resonancedelta = (float) ctrldelta * 0.00787f; // 0.0..1.0
727            fFinalResonance += resonancedelta;
728            // needed for initialization of parameter
729            VCFResonanceCtrl.fvalue = itEvent->Param.CC.Value * 0.00787f;
730      }      }
731    
732      /**      /**
733       *  Interpolates the input audio data, this method honors looping.       *  Synthesizes the current audio fragment for this voice.
734       *       *
735       *  @param Samples - number of sample points to be rendered in this audio       *  @param Samples - number of sample points to be rendered in this audio
736       *                   fragment cycle       *                   fragment cycle
737       *  @param pSrc    - pointer to input sample data       *  @param pSrc    - pointer to input sample data
738       *  @param Skip    - number of sample points to skip in output buffer       *  @param Skip    - number of sample points to skip in output buffer
739       */       */
740      void Voice::InterpolateAndLoop(uint Samples, sample_t* pSrc, uint Skip) {      void Voice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {
741          int i = Skip;          RTList<Event>::Iterator itCCEvent = pEngineChannel->pEvents->first();
742            RTList<Event>::Iterator itNoteEvent = pEngineChannel->pMIDIKeyInfo[MIDIKey].pEvents->first();
743    
744          // FIXME: assuming either mono or stereo          if (Skip) { // skip events that happened before this voice was triggered
745          if (pSample->Channels == 2) { // Stereo Sample              while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;
746              if (pSample->LoopPlayCount) {              while (itNoteEvent && itNoteEvent->FragmentPos() <= Skip) ++itNoteEvent;
747                  // render loop (loop count limited)          }
748                  while (i < Samples && LoopCyclesLeft) {  
749                      InterpolateOneStep_Stereo(pSrc, i,          uint i = Skip;
750                                                pEngine->pSynthesisParameters[Event::destination_vca][i],          while (i < Samples) {
751                                                pEngine->pSynthesisParameters[Event::destination_vco][i],              int iSubFragmentEnd = RTMath::Min(i + CONFIG_DEFAULT_SUBFRAGMENT_SIZE, Samples);
752                                                pEngine->pSynthesisParameters[Event::destination_vcfc][i],  
753                                                pEngine->pSynthesisParameters[Event::destination_vcfr][i]);              // initialize all final synthesis parameters
754                      if (Pos > pSample->LoopEnd) {              fFinalPitch = PitchBase * PitchBend;
755                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;              #if CONFIG_PROCESS_MUTED_CHANNELS
756                          LoopCyclesLeft--;              fFinalVolume = this->Volume * this->CrossfadeVolume * (pEngineChannel->GetMute() ? 0 : pEngineChannel->GlobalVolume);
757                      }              #else
758                  }              fFinalVolume = this->Volume * this->CrossfadeVolume * pEngineChannel->GlobalVolume;
759                  // render on without loop              #endif
760                  while (i < Samples) {              fFinalCutoff    = VCFCutoffCtrl.fvalue;
761                      InterpolateOneStep_Stereo(pSrc, i,              fFinalResonance = VCFResonanceCtrl.fvalue;
762                                                pEngine->pSynthesisParameters[Event::destination_vca][i],  
763                                                pEngine->pSynthesisParameters[Event::destination_vco][i],              // process MIDI control change and pitchbend events for this subfragment
764                                                pEngine->pSynthesisParameters[Event::destination_vcfc][i],              processCCEvents(itCCEvent, iSubFragmentEnd);
765                                                pEngine->pSynthesisParameters[Event::destination_vcfr][i]);  
766                  }              // process transition events (note on, note off & sustain pedal)
767                processTransitionEvents(itNoteEvent, iSubFragmentEnd);
768    
769                // process envelope generators
770                switch (EG1.getSegmentType()) {
771                    case EGADSR::segment_lin:
772                        fFinalVolume *= EG1.processLin();
773                        break;
774                    case EGADSR::segment_exp:
775                        fFinalVolume *= EG1.processExp();
776                        break;
777                    case EGADSR::segment_end:
778                        fFinalVolume *= EG1.getLevel();
779                        break; // noop
780              }              }
781              else { // render loop (endless loop)              switch (EG2.getSegmentType()) {
782                  while (i < Samples) {                  case EGADSR::segment_lin:
783                      InterpolateOneStep_Stereo(pSrc, i,                      fFinalCutoff *= EG2.processLin();
784                                                pEngine->pSynthesisParameters[Event::destination_vca][i],                      break;
785                                                pEngine->pSynthesisParameters[Event::destination_vco][i],                  case EGADSR::segment_exp:
786                                                pEngine->pSynthesisParameters[Event::destination_vcfc][i],                      fFinalCutoff *= EG2.processExp();
787                                                pEngine->pSynthesisParameters[Event::destination_vcfr][i]);                      break;
788                      if (Pos > pSample->LoopEnd) {                  case EGADSR::segment_end:
789                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);                      fFinalCutoff *= EG2.getLevel();
790                      }                      break; // noop
                 }  
791              }              }
792          }              fFinalPitch *= RTMath::CentsToFreqRatio(EG3.render());
793          else { // Mono Sample  
794              if (pSample->LoopPlayCount) {              // process low frequency oscillators
795                  // render loop (loop count limited)              if (bLFO1Enabled) fFinalVolume *= pLFO1->render();
796                  while (i < Samples && LoopCyclesLeft) {              if (bLFO2Enabled) fFinalCutoff *= pLFO2->render();
797                      InterpolateOneStep_Mono(pSrc, i,              if (bLFO3Enabled) fFinalPitch  *= RTMath::CentsToFreqRatio(pLFO3->render());
798                                              pEngine->pSynthesisParameters[Event::destination_vca][i],  
799                                              pEngine->pSynthesisParameters[Event::destination_vco][i],              // if filter enabled then update filter coefficients
800                                              pEngine->pSynthesisParameters[Event::destination_vcfc][i],              if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode)) {
801                                              pEngine->pSynthesisParameters[Event::destination_vcfr][i]);                  FilterLeft.SetParameters(fFinalCutoff, fFinalResonance, pEngine->SampleRate);
802                      if (Pos > pSample->LoopEnd) {                  FilterRight.SetParameters(fFinalCutoff, fFinalResonance, pEngine->SampleRate);
                         Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;  
                         LoopCyclesLeft--;  
                     }  
                 }  
                 // render on without loop  
                 while (i < Samples) {  
                     InterpolateOneStep_Mono(pSrc, i,  
                                             pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                             pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                             pEngine->pSynthesisParameters[Event::destination_vcfc][i],  
                                             pEngine->pSynthesisParameters[Event::destination_vcfr][i]);  
                 }  
803              }              }
804              else { // render loop (endless loop)  
805                  while (i < Samples) {              // how many steps do we calculate for this next subfragment
806                      InterpolateOneStep_Mono(pSrc, i,              const int steps = iSubFragmentEnd - i;
807                                              pEngine->pSynthesisParameters[Event::destination_vca][i],  
808                                              pEngine->pSynthesisParameters[Event::destination_vco][i],              // select the appropriate synthesis mode
809                                              pEngine->pSynthesisParameters[Event::destination_vcfc][i],              SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, fFinalPitch != 1.0f);
810                                              pEngine->pSynthesisParameters[Event::destination_vcfr][i]);  
811                      if (Pos > pSample->LoopEnd) {              // render audio for one subfragment
812                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;              RunSynthesisFunction(SynthesisMode, *this, iSubFragmentEnd, pSrc, i);
813                      }  
814                  }              // increment envelopes' positions
815                if (EG1.active()) {
816                    EG1.increment(1);
817                    if (!EG1.toStageEndLeft()) EG1.update(EGADSR::event_stage_end, this->Pos, fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
818              }              }
819                if (EG2.active()) {
820                    EG2.increment(1);
821                    if (!EG2.toStageEndLeft()) EG2.update(EGADSR::event_stage_end, this->Pos, fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
822                }
823                EG3.increment(1);
824                if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached
825    
826                i = iSubFragmentEnd;
827          }          }
828      }      }
829    
830      /**      /**
831       *  Immediately kill the voice.       *  Immediately kill the voice. This method should not be used to kill
832         *  a normal, active voice, because it doesn't take care of things like
833         *  fading down the volume level to avoid clicks and regular processing
834         *  until the kill event actually occured!
835         *
836         *  @see Kill()
837       */       */
838      void Voice::Kill() {      void Voice::KillImmediately() {
839          if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {          if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {
840              pDiskThread->OrderDeletionOfStream(&DiskStreamRef);              pDiskThread->OrderDeletionOfStream(&DiskStreamRef);
841          }          }
842          Reset();          Reset();
843      }      }
844    
845        /**
846         *  Kill the voice in regular sense. Let the voice render audio until
847         *  the kill event actually occured and then fade down the volume level
848         *  very quickly and let the voice die finally. Unlike a normal release
849         *  of a voice, a kill process cannot be cancalled and is therefore
850         *  usually used for voice stealing and key group conflicts.
851         *
852         *  @param itKillEvent - event which caused the voice to be killed
853         */
854        void Voice::Kill(Pool<Event>::Iterator& itKillEvent) {
855            #if CONFIG_DEVMODE
856            if (!itKillEvent) dmsg(1,("gig::Voice::Kill(): ERROR, !itKillEvent !!!\n"));
857            if (itKillEvent && !itKillEvent.isValid()) dmsg(1,("gig::Voice::Kill(): ERROR, itKillEvent invalid !!!\n"));
858            #endif // CONFIG_DEVMODE
859    
860            if (itTriggerEvent && itKillEvent->FragmentPos() <= itTriggerEvent->FragmentPos()) return;
861            this->itKillEvent = itKillEvent;
862        }
863    
864  }} // namespace LinuxSampler::gig  }} // namespace LinuxSampler::gig

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

  ViewVC Help
Powered by ViewVC