/[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 53 by schoenebeck, Mon Apr 26 17:15:51 2004 UTC revision 738 by schoenebeck, Tue Aug 16 17:14:25 2005 UTC
# Line 2  Line 2 
2   *                                                                         *   *                                                                         *
3   *   LinuxSampler - modular, streaming capable sampler                     *   *   LinuxSampler - modular, streaming capable sampler                     *
4   *                                                                         *   *                                                                         *
5   *   Copyright (C) 2003 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        }
697    
698        void Voice::processCrossFadeEvent(RTList<Event>::Iterator& itEvent) {
699            CrossfadeVolume = CrossfadeAttenuation(itEvent->Param.CC.Value);
700            #if CONFIG_PROCESS_MUTED_CHANNELS
701            const float effectiveVolume = CrossfadeVolume * Volume * (pEngineChannel->GetMute() ? 0 : pEngineChannel->GlobalVolume);
702            #else
703            const float effectiveVolume = CrossfadeVolume * Volume * pEngineChannel->GlobalVolume;
704            #endif
705            fFinalVolume = effectiveVolume;
706        }
707    
708        void Voice::processCutoffEvent(RTList<Event>::Iterator& itEvent) {
709            int ccvalue = itEvent->Param.CC.Value;
710            if (VCFCutoffCtrl.value == ccvalue) return;
711            VCFCutoffCtrl.value == ccvalue;
712            if (pDimRgn->VCFCutoffControllerInvert)  ccvalue = 127 - ccvalue;
713            if (ccvalue < pDimRgn->VCFVelocityScale) ccvalue = pDimRgn->VCFVelocityScale;
714            float cutoff = CutoffBase * float(ccvalue) * 0.00787402f; // (1 / 127)
715            if (cutoff > 1.0) cutoff = 1.0;
716            cutoff = exp(cutoff * FILTER_CUTOFF_COEFF) * CONFIG_FILTER_CUTOFF_MIN - CONFIG_FILTER_CUTOFF_MIN;
717            VCFCutoffCtrl.fvalue = cutoff; // needed for initialization of fFinalCutoff next time
718            fFinalCutoff = cutoff;
719        }
720    
721        void Voice::processResonanceEvent(RTList<Event>::Iterator& itEvent) {
722            // convert absolute controller value to differential
723            const int ctrldelta = itEvent->Param.CC.Value - VCFResonanceCtrl.value;
724            VCFResonanceCtrl.value = itEvent->Param.CC.Value;
725            const float resonancedelta = (float) ctrldelta * 0.00787f; // 0.0..1.0
726            fFinalResonance += resonancedelta;
727            // needed for initialization of parameter
728            VCFResonanceCtrl.fvalue = itEvent->Param.CC.Value * 0.00787f;
729      }      }
730    
731      /**      /**
732       *  Interpolates the input audio data, this method honors looping.       *  Synthesizes the current audio fragment for this voice.
733       *       *
734       *  @param Samples - number of sample points to be rendered in this audio       *  @param Samples - number of sample points to be rendered in this audio
735       *                   fragment cycle       *                   fragment cycle
736       *  @param pSrc    - pointer to input sample data       *  @param pSrc    - pointer to input sample data
737       *  @param Skip    - number of sample points to skip in output buffer       *  @param Skip    - number of sample points to skip in output buffer
738       */       */
739      void Voice::InterpolateAndLoop(uint Samples, sample_t* pSrc, uint Skip) {      void Voice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {
740          int i = Skip;          RTList<Event>::Iterator itCCEvent = pEngineChannel->pEvents->first();
741            RTList<Event>::Iterator itNoteEvent = pEngineChannel->pMIDIKeyInfo[MIDIKey].pEvents->first();
742          // FIXME: assuming either mono or stereo                  
743          if (pSample->Channels == 2) { // Stereo Sample          if (Skip) { // skip events that happened before this voice was triggered
744              if (pSample->LoopPlayCount) {              while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;
745                  // render loop (loop count limited)              while (itNoteEvent && itNoteEvent->FragmentPos() <= Skip) ++itNoteEvent;
746                  while (i < Samples && LoopCyclesLeft) {          }
747                      InterpolateOneStep_Stereo(pSrc, i,          
748                                                pEngine->pSynthesisParameters[Event::destination_vca][i],          uint i = Skip;
749                                                pEngine->pSynthesisParameters[Event::destination_vco][i],          while (i < Samples) {
750                                                pEngine->pSynthesisParameters[Event::destination_vcfc][i],              int iSubFragmentEnd = RTMath::Min(i + CONFIG_DEFAULT_SUBFRAGMENT_SIZE, Samples);
751                                                pEngine->pSynthesisParameters[Event::destination_vcfr][i]);              
752                      if (Pos > pSample->LoopEnd) {              // initialize all final synthesis parameters
753                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;              fFinalPitch = PitchBase * PitchBend;
754                          LoopCyclesLeft--;              #if CONFIG_PROCESS_MUTED_CHANNELS
755                      }              fFinalVolume = this->Volume * this->CrossfadeVolume * (pEngineChannel->GetMute() ? 0 : pEngineChannel->GlobalVolume));
756                  }              #else
757                  // render on without loop              fFinalVolume = this->Volume * this->CrossfadeVolume * pEngineChannel->GlobalVolume;
758                  while (i < Samples) {              #endif
759                      InterpolateOneStep_Stereo(pSrc, i,              fFinalCutoff    = VCFCutoffCtrl.fvalue;
760                                                pEngine->pSynthesisParameters[Event::destination_vca][i],              fFinalResonance = VCFResonanceCtrl.fvalue;
761                                                pEngine->pSynthesisParameters[Event::destination_vco][i],              
762                                                pEngine->pSynthesisParameters[Event::destination_vcfc][i],              // process MIDI control change and pitchbend events for this subfragment
763                                                pEngine->pSynthesisParameters[Event::destination_vcfr][i]);              processCCEvents(itCCEvent, iSubFragmentEnd);
764                  }  
765              }              // process transition events (note on, note off & sustain pedal)
766              else { // render loop (endless loop)              processTransitionEvents(itNoteEvent, iSubFragmentEnd);
767                  while (i < Samples) {              
768                      InterpolateOneStep_Stereo(pSrc, i,              // process envelope generators
769                                                pEngine->pSynthesisParameters[Event::destination_vca][i],              switch (EG1.getSegmentType()) {
770                                                pEngine->pSynthesisParameters[Event::destination_vco][i],                  case EGADSR::segment_lin:
771                                                pEngine->pSynthesisParameters[Event::destination_vcfc][i],                      fFinalVolume *= EG1.processLin();
772                                                pEngine->pSynthesisParameters[Event::destination_vcfr][i]);                      break;
773                      if (Pos > pSample->LoopEnd) {                  case EGADSR::segment_exp:
774                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);                      fFinalVolume *= EG1.processExp();
775                      }                      break;
776                  }                  case EGADSR::segment_end:
777              }                      fFinalVolume *= EG1.getLevel();
778          }                      break; // noop
779          else { // Mono Sample              }
780              if (pSample->LoopPlayCount) {              switch (EG2.getSegmentType()) {
781                  // render loop (loop count limited)                  case EGADSR::segment_lin:
782                  while (i < Samples && LoopCyclesLeft) {                      fFinalCutoff *= EG2.processLin();
783                      InterpolateOneStep_Mono(pSrc, i,                      break;
784                                              pEngine->pSynthesisParameters[Event::destination_vca][i],                  case EGADSR::segment_exp:
785                                              pEngine->pSynthesisParameters[Event::destination_vco][i],                      fFinalCutoff *= EG2.processExp();
786                                              pEngine->pSynthesisParameters[Event::destination_vcfc][i],                      break;
787                                              pEngine->pSynthesisParameters[Event::destination_vcfr][i]);                  case EGADSR::segment_end:
788                      if (Pos > pSample->LoopEnd) {                      fFinalCutoff *= EG2.getLevel();
789                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;                      break; // noop
790                          LoopCyclesLeft--;              }
791                      }              fFinalPitch *= RTMath::CentsToFreqRatio(EG3.render());
792                  }              
793                  // render on without loop              // process low frequency oscillators
794                  while (i < Samples) {              if (bLFO1Enabled) fFinalVolume *= pLFO1->render();
795                      InterpolateOneStep_Mono(pSrc, i,              if (bLFO2Enabled) fFinalCutoff *= pLFO2->render();
796                                              pEngine->pSynthesisParameters[Event::destination_vca][i],              if (bLFO3Enabled) fFinalPitch  *= RTMath::CentsToFreqRatio(pLFO3->render());
797                                              pEngine->pSynthesisParameters[Event::destination_vco][i],  
798                                              pEngine->pSynthesisParameters[Event::destination_vcfc][i],              // if filter enabled then update filter coefficients
799                                              pEngine->pSynthesisParameters[Event::destination_vcfr][i]);              if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode)) {
800                  }                  FilterLeft.SetParameters(fFinalCutoff, fFinalResonance, pEngine->SampleRate);
801              }                  FilterRight.SetParameters(fFinalCutoff, fFinalResonance, pEngine->SampleRate);
802              else { // render loop (endless loop)              }
803                  while (i < Samples) {  
804                      InterpolateOneStep_Mono(pSrc, i,              // how many steps do we calculate for this next subfragment
805                                              pEngine->pSynthesisParameters[Event::destination_vca][i],              const int steps = iSubFragmentEnd - i;
806                                              pEngine->pSynthesisParameters[Event::destination_vco][i],              
807                                              pEngine->pSynthesisParameters[Event::destination_vcfc][i],              // select the appropriate synthesis mode
808                                              pEngine->pSynthesisParameters[Event::destination_vcfr][i]);              SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, fFinalPitch != 1.0f);
809                      if (Pos > pSample->LoopEnd) {              
810                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;              // render audio for one subfragment
811                      }              RunSynthesisFunction(SynthesisMode, *this, iSubFragmentEnd, pSrc, i);
812                  }  
813                // increment envelopes' positions            
814                if (EG1.active()) {
815                    EG1.increment(steps);
816                    if (!EG1.toStageEndLeft()) EG1.update(EGADSR::event_stage_end, this->Pos, fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
817                }
818                if (EG2.active()) {
819                    EG2.increment(steps);
820                    if (!EG2.toStageEndLeft()) EG2.update(EGADSR::event_stage_end, this->Pos, fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
821              }              }
822                EG3.increment(steps);
823                if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached
824          }          }
825      }      }
826    
827      /**      /**
828       *  Immediately kill the voice.       *  Immediately kill the voice. This method should not be used to kill
829         *  a normal, active voice, because it doesn't take care of things like
830         *  fading down the volume level to avoid clicks and regular processing
831         *  until the kill event actually occured!
832         *
833         *  @see Kill()
834       */       */
835      void Voice::Kill() {      void Voice::KillImmediately() {
836          if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {          if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {
837              pDiskThread->OrderDeletionOfStream(&DiskStreamRef);              pDiskThread->OrderDeletionOfStream(&DiskStreamRef);
838          }          }
839          Reset();          Reset();
840      }      }
841    
842        /**
843         *  Kill the voice in regular sense. Let the voice render audio until
844         *  the kill event actually occured and then fade down the volume level
845         *  very quickly and let the voice die finally. Unlike a normal release
846         *  of a voice, a kill process cannot be cancalled and is therefore
847         *  usually used for voice stealing and key group conflicts.
848         *
849         *  @param itKillEvent - event which caused the voice to be killed
850         */
851        void Voice::Kill(Pool<Event>::Iterator& itKillEvent) {
852            #if CONFIG_DEVMODE
853            if (!itKillEvent) dmsg(1,("gig::Voice::Kill(): ERROR, !itKillEvent !!!\n"));
854            if (itKillEvent && !itKillEvent.isValid()) dmsg(1,("gig::Voice::Kill(): ERROR, itKillEvent invalid !!!\n"));
855            #endif // CONFIG_DEVMODE
856    
857            if (itTriggerEvent && itKillEvent->FragmentPos() <= itTriggerEvent->FragmentPos()) return;
858            this->itKillEvent = itKillEvent;
859        }
860    
861  }} // namespace LinuxSampler::gig  }} // namespace LinuxSampler::gig

Legend:
Removed from v.53  
changed lines
  Added in v.738

  ViewVC Help
Powered by ViewVC