/[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 769 by schoenebeck, Sat Sep 3 11:14:30 2005 UTC revision 1857 by schoenebeck, Sat Mar 7 19:23:10 2009 UTC
# Line 3  Line 3 
3   *   LinuxSampler - modular, streaming capable sampler                     *   *   LinuxSampler - modular, streaming capable sampler                     *
4   *                                                                         *   *                                                                         *
5   *   Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck   *   *   Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck   *
6   *   Copyright (C) 2005 Christian Schoenebeck                              *   *   Copyright (C) 2005 - 2009 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 23  Line 23 
23    
24  #include "../../common/Features.h"  #include "../../common/Features.h"
25  #include "Synthesizer.h"  #include "Synthesizer.h"
26    #include "Profiler.h"
27    
28  #include "Voice.h"  #include "Voice.h"
29    
30  namespace LinuxSampler { namespace gig {  namespace LinuxSampler { namespace gig {
31    
     const float Voice::FILTER_CUTOFF_COEFF(CalculateFilterCutoffCoeff());  
   
     float Voice::CalculateFilterCutoffCoeff() {  
         return log(CONFIG_FILTER_CUTOFF_MAX / CONFIG_FILTER_CUTOFF_MIN);  
     }  
   
32      Voice::Voice() {      Voice::Voice() {
33          pEngine     = NULL;          pEngine     = NULL;
34          pDiskThread = NULL;          pDiskThread = NULL;
# Line 43  namespace LinuxSampler { namespace gig { Line 38  namespace LinuxSampler { namespace gig {
38          pLFO3 = new LFOSigned(1200.0f); // pitch EG (-1200..+1200 range)          pLFO3 = new LFOSigned(1200.0f); // pitch EG (-1200..+1200 range)
39          KeyGroup = 0;          KeyGroup = 0;
40          SynthesisMode = 0; // set all mode bits to 0 first          SynthesisMode = 0; // set all mode bits to 0 first
41          // select synthesis implementation (currently either pure C++ or MMX+SSE(1))          // select synthesis implementation (asm core is not supported ATM)
42          #if CONFIG_ASM && ARCH_X86          #if 0 // CONFIG_ASM && ARCH_X86
43          SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, Features::supportsMMX() && Features::supportsSSE());          SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, Features::supportsMMX() && Features::supportsSSE());
44          #else          #else
45          SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, false);          SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, false);
46          #endif          #endif
47          SYNTHESIS_MODE_SET_PROFILING(SynthesisMode, true);          SYNTHESIS_MODE_SET_PROFILING(SynthesisMode, Profiler::isEnabled());
48    
49          FilterLeft.Reset();          finalSynthesisParameters.filterLeft.Reset();
50          FilterRight.Reset();          finalSynthesisParameters.filterRight.Reset();
51      }      }
52    
53      Voice::~Voice() {      Voice::~Voice() {
# Line 84  namespace LinuxSampler { namespace gig { Line 79  namespace LinuxSampler { namespace gig {
79      int Voice::Trigger(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent, int PitchBend, ::gig::DimensionRegion* pDimRgn, type_t VoiceType, int iKeyGroup) {      int Voice::Trigger(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent, int PitchBend, ::gig::DimensionRegion* pDimRgn, type_t VoiceType, int iKeyGroup) {
80          this->pEngineChannel = pEngineChannel;          this->pEngineChannel = pEngineChannel;
81          this->pDimRgn        = pDimRgn;          this->pDimRgn        = pDimRgn;
82            Orphan = false;
83    
84          #if CONFIG_DEVMODE          #if CONFIG_DEVMODE
85          if (itNoteOnEvent->FragmentPos() > pEngine->MaxSamplesPerCycle) { // just a sanity check for debugging          if (itNoteOnEvent->FragmentPos() > pEngine->MaxSamplesPerCycle) { // just a sanity check for debugging
# Line 103  namespace LinuxSampler { namespace gig { Line 99  namespace LinuxSampler { namespace gig {
99          // calculate volume          // calculate volume
100          const double velocityAttenuation = pDimRgn->GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity);          const double velocityAttenuation = pDimRgn->GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity);
101    
102          Volume = velocityAttenuation / 32768.0f; // we downscale by 32768 to convert from int16 value range to DSP value range (which is -1.0..1.0)          // For 16 bit samples, we downscale by 32768 to convert from
103            // int16 value range to DSP value range (which is
104            // -1.0..1.0). For 24 bit, we downscale from int32.
105            float volume = velocityAttenuation / (pSample->BitDepth == 16 ? 32768.0f : 32768.0f * 65536.0f);
106    
107          Volume *= pDimRgn->SampleAttenuation;          volume *= pDimRgn->SampleAttenuation * pEngineChannel->GlobalVolume * GLOBAL_VOLUME;
108    
109          // the volume of release triggered samples depends on note length          // the volume of release triggered samples depends on note length
110          if (Type == type_release_trigger) {          if (Type == type_release_trigger) {
# Line 113  namespace LinuxSampler { namespace gig { Line 112  namespace LinuxSampler { namespace gig {
112                                       pEngineChannel->pMIDIKeyInfo[MIDIKey].NoteOnTime) / pEngine->SampleRate;                                       pEngineChannel->pMIDIKeyInfo[MIDIKey].NoteOnTime) / pEngine->SampleRate;
113              float attenuation = 1 - 0.01053 * (256 >> pDimRgn->ReleaseTriggerDecay) * noteLength;              float attenuation = 1 - 0.01053 * (256 >> pDimRgn->ReleaseTriggerDecay) * noteLength;
114              if (attenuation <= 0) return -1;              if (attenuation <= 0) return -1;
115              Volume *= attenuation;              volume *= attenuation;
116          }          }
117    
118          // select channel mode (mono or stereo)          // select channel mode (mono or stereo)
119          SYNTHESIS_MODE_SET_CHANNELS(SynthesisMode, pSample->Channels == 2);          SYNTHESIS_MODE_SET_CHANNELS(SynthesisMode, pSample->Channels == 2);
120            // select bit depth (16 or 24)
121            SYNTHESIS_MODE_SET_BITDEPTH24(SynthesisMode, pSample->BitDepth == 24);
122    
123          // get starting crossfade volume level          // get starting crossfade volume level
124            float crossfadeVolume;
125          switch (pDimRgn->AttenuationController.type) {          switch (pDimRgn->AttenuationController.type) {
126              case ::gig::attenuation_ctrl_t::type_channelaftertouch:              case ::gig::attenuation_ctrl_t::type_channelaftertouch:
127                  CrossfadeVolume = 1.0f; //TODO: aftertouch not supported yet                  crossfadeVolume = Engine::CrossfadeCurve[CrossfadeAttenuation(pEngineChannel->ControllerTable[128])];
128                  break;                  break;
129              case ::gig::attenuation_ctrl_t::type_velocity:              case ::gig::attenuation_ctrl_t::type_velocity:
130                  CrossfadeVolume = CrossfadeAttenuation(itNoteOnEvent->Param.Note.Velocity);                  crossfadeVolume = Engine::CrossfadeCurve[CrossfadeAttenuation(itNoteOnEvent->Param.Note.Velocity)];
131                  break;                  break;
132              case ::gig::attenuation_ctrl_t::type_controlchange: //FIXME: currently not sample accurate              case ::gig::attenuation_ctrl_t::type_controlchange: //FIXME: currently not sample accurate
133                  CrossfadeVolume = CrossfadeAttenuation(pEngineChannel->ControllerTable[pDimRgn->AttenuationController.controller_number]);                  crossfadeVolume = Engine::CrossfadeCurve[CrossfadeAttenuation(pEngineChannel->ControllerTable[pDimRgn->AttenuationController.controller_number])];
134                  break;                  break;
135              case ::gig::attenuation_ctrl_t::type_none: // no crossfade defined              case ::gig::attenuation_ctrl_t::type_none: // no crossfade defined
136              default:              default:
137                  CrossfadeVolume = 1.0f;                  crossfadeVolume = 1.0f;
138          }          }
139    
140          PanLeft  = 1.0f - float(RTMath::Max(pDimRgn->Pan, 0)) /  63.0f;          VolumeLeft  = volume * Engine::PanCurve[64 - pDimRgn->Pan];
141          PanRight = 1.0f - float(RTMath::Min(pDimRgn->Pan, 0)) / -64.0f;          VolumeRight = volume * Engine::PanCurve[64 + pDimRgn->Pan];
142    
143            float subfragmentRate = pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;
144            CrossfadeSmoother.trigger(crossfadeVolume, subfragmentRate);
145            VolumeSmoother.trigger(pEngineChannel->MidiVolume, subfragmentRate);
146            PanLeftSmoother.trigger(pEngineChannel->GlobalPanLeft, subfragmentRate);
147            PanRightSmoother.trigger(pEngineChannel->GlobalPanRight, subfragmentRate);
148    
149          Pos = pDimRgn->SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)          finalSynthesisParameters.dPos = pDimRgn->SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)
150            Pos = pDimRgn->SampleStartOffset;
151    
152          // 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
153          long cachedsamples = pSample->GetCache().Size / pSample->FrameSize;          long cachedsamples = pSample->GetCache().Size / pSample->FrameSize;
154          DiskVoice          = cachedsamples < pSample->SamplesTotal;          DiskVoice          = cachedsamples < pSample->SamplesTotal;
155    
156            const DLS::sample_loop_t& loopinfo = pDimRgn->pSampleLoops[0];
157    
158          if (DiskVoice) { // voice to be streamed from disk          if (DiskVoice) { // voice to be streamed from disk
159              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)              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)
160    
161              // 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
162              if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) {              RAMLoop = (pDimRgn->SampleLoops && (loopinfo.LoopStart + loopinfo.LoopLength) <= MaxRAMPos);
                 RAMLoop        = true;  
                 LoopCyclesLeft = pSample->LoopPlayCount;  
             }  
             else RAMLoop = false;  
163    
164              if (pDiskThread->OrderNewStream(&DiskStreamRef, pSample, MaxRAMPos, !RAMLoop) < 0) {              if (pDiskThread->OrderNewStream(&DiskStreamRef, pDimRgn, MaxRAMPos, !RAMLoop) < 0) {
165                  dmsg(1,("Disk stream order failed!\n"));                  dmsg(1,("Disk stream order failed!\n"));
166                  KillImmediately();                  KillImmediately();
167                  return -1;                  return -1;
# Line 163  namespace LinuxSampler { namespace gig { Line 170  namespace LinuxSampler { namespace gig {
170          }          }
171          else { // RAM only voice          else { // RAM only voice
172              MaxRAMPos = cachedsamples;              MaxRAMPos = cachedsamples;
173              if (pSample->Loops) {              RAMLoop = (pDimRgn->SampleLoops != 0);
                 RAMLoop        = true;  
                 LoopCyclesLeft = pSample->LoopPlayCount;  
             }  
             else RAMLoop = false;  
174              dmsg(4,("RAM only voice launched (Looping: %s)\n", (RAMLoop) ? "yes" : "no"));              dmsg(4,("RAM only voice launched (Looping: %s)\n", (RAMLoop) ? "yes" : "no"));
175          }          }
176            if (RAMLoop) {
177                loop.uiTotalCycles = pSample->LoopPlayCount;
178                loop.uiCyclesLeft  = pSample->LoopPlayCount;
179                loop.uiStart       = loopinfo.LoopStart;
180                loop.uiEnd         = loopinfo.LoopStart + loopinfo.LoopLength;
181                loop.uiSize        = loopinfo.LoopLength;
182            }
183    
184          // calculate initial pitch value          // calculate initial pitch value
185          {          {
186              double pitchbasecents = pDimRgn->FineTune + (int) pEngine->ScaleTuning[MIDIKey % 12];              double pitchbasecents = pDimRgn->FineTune + (int) pEngine->ScaleTuning[MIDIKey % 12];
187              if (pDimRgn->PitchTrack) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;  
188                // GSt behaviour: maximum transpose up is 40 semitones. If
189                // MIDI key is more than 40 semitones above unity note,
190                // the transpose is not done.
191                if (pDimRgn->PitchTrack && (MIDIKey - (int) pDimRgn->UnityNote) < 40) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;
192    
193              this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents) * (double(pSample->SamplesPerSecond) / double(pEngine->SampleRate));              this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents) * (double(pSample->SamplesPerSecond) / double(pEngine->SampleRate));
194              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
195          }          }
# Line 192  namespace LinuxSampler { namespace gig { Line 206  namespace LinuxSampler { namespace gig {
206                      eg1controllervalue = 0;                      eg1controllervalue = 0;
207                      break;                      break;
208                  case ::gig::eg1_ctrl_t::type_channelaftertouch:                  case ::gig::eg1_ctrl_t::type_channelaftertouch:
209                      eg1controllervalue = 0; // TODO: aftertouch not yet supported                      eg1controllervalue = pEngineChannel->ControllerTable[128];
210                      break;                      break;
211                  case ::gig::eg1_ctrl_t::type_velocity:                  case ::gig::eg1_ctrl_t::type_velocity:
212                      eg1controllervalue = itNoteOnEvent->Param.Note.Velocity;                      eg1controllervalue = itNoteOnEvent->Param.Note.Velocity;
# Line 214  namespace LinuxSampler { namespace gig { Line 228  namespace LinuxSampler { namespace gig {
228              EG1.trigger(pDimRgn->EG1PreAttack,              EG1.trigger(pDimRgn->EG1PreAttack,
229                          pDimRgn->EG1Attack * eg1attack,                          pDimRgn->EG1Attack * eg1attack,
230                          pDimRgn->EG1Hold,                          pDimRgn->EG1Hold,
                         pSample->LoopStart,  
231                          pDimRgn->EG1Decay1 * eg1decay * velrelease,                          pDimRgn->EG1Decay1 * eg1decay * velrelease,
232                          pDimRgn->EG1Decay2 * eg1decay * velrelease,                          pDimRgn->EG1Decay2 * eg1decay * velrelease,
233                          pDimRgn->EG1InfiniteSustain,                          pDimRgn->EG1InfiniteSustain,
# Line 224  namespace LinuxSampler { namespace gig { Line 237  namespace LinuxSampler { namespace gig {
237                          pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                          pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
238          }          }
239    
240    #ifdef CONFIG_INTERPOLATE_VOLUME
241            // setup initial volume in synthesis parameters
242    #ifdef CONFIG_PROCESS_MUTED_CHANNELS
243            if (pEngineChannel->GetMute()) {
244                finalSynthesisParameters.fFinalVolumeLeft  = 0;
245                finalSynthesisParameters.fFinalVolumeRight = 0;
246            }
247            else
248    #else
249            {
250                float finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * EG1.getLevel();
251    
252                finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * pEngineChannel->GlobalPanLeft;
253                finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * pEngineChannel->GlobalPanRight;
254            }
255    #endif
256    #endif
257    
258          // setup EG 2 (VCF Cutoff EG)          // setup EG 2 (VCF Cutoff EG)
259          {          {
# Line 234  namespace LinuxSampler { namespace gig { Line 264  namespace LinuxSampler { namespace gig {
264                      eg2controllervalue = 0;                      eg2controllervalue = 0;
265                      break;                      break;
266                  case ::gig::eg2_ctrl_t::type_channelaftertouch:                  case ::gig::eg2_ctrl_t::type_channelaftertouch:
267                      eg2controllervalue = 0; // TODO: aftertouch not yet supported                      eg2controllervalue = pEngineChannel->ControllerTable[128];
268                      break;                      break;
269                  case ::gig::eg2_ctrl_t::type_velocity:                  case ::gig::eg2_ctrl_t::type_velocity:
270                      eg2controllervalue = itNoteOnEvent->Param.Note.Velocity;                      eg2controllervalue = itNoteOnEvent->Param.Note.Velocity;
# Line 253  namespace LinuxSampler { namespace gig { Line 283  namespace LinuxSampler { namespace gig {
283              EG2.trigger(pDimRgn->EG2PreAttack,              EG2.trigger(pDimRgn->EG2PreAttack,
284                          pDimRgn->EG2Attack * eg2attack,                          pDimRgn->EG2Attack * eg2attack,
285                          false,                          false,
                         pSample->LoopStart,  
286                          pDimRgn->EG2Decay1 * eg2decay * velrelease,                          pDimRgn->EG2Decay1 * eg2decay * velrelease,
287                          pDimRgn->EG2Decay2 * eg2decay * velrelease,                          pDimRgn->EG2Decay2 * eg2decay * velrelease,
288                          pDimRgn->EG2InfiniteSustain,                          pDimRgn->EG2InfiniteSustain,
# Line 266  namespace LinuxSampler { namespace gig { Line 295  namespace LinuxSampler { namespace gig {
295    
296          // setup EG 3 (VCO EG)          // setup EG 3 (VCO EG)
297          {          {
298            double eg3depth = RTMath::CentsToFreqRatio(pDimRgn->EG3Depth);              // if portamento mode is on, we dedicate EG3 purely for portamento, otherwise if portamento is off we do as told by the patch
299            EG3.trigger(eg3depth, pDimRgn->EG3Attack, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);              bool  bPortamento = pEngineChannel->PortamentoMode && pEngineChannel->PortamentoPos >= 0.0f;
300                float eg3depth = (bPortamento)
301                                     ? RTMath::CentsToFreqRatio((pEngineChannel->PortamentoPos - (float) MIDIKey) * 100)
302                                     : RTMath::CentsToFreqRatio(pDimRgn->EG3Depth);
303                float eg3time = (bPortamento)
304                                    ? pEngineChannel->PortamentoTime
305                                    : pDimRgn->EG3Attack;
306                EG3.trigger(eg3depth, eg3time, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
307                dmsg(5,("PortamentoPos=%f, depth=%f, time=%f\n", pEngineChannel->PortamentoPos, eg3depth, eg3time));
308          }          }
309    
310    
# Line 305  namespace LinuxSampler { namespace gig { Line 342  namespace LinuxSampler { namespace gig {
342                      pLFO1->ExtController = 0; // no external controller                      pLFO1->ExtController = 0; // no external controller
343                      bLFO1Enabled         = false;                      bLFO1Enabled         = false;
344              }              }
345              if (bLFO1Enabled) pLFO1->trigger(pDimRgn->LFO1Frequency,              if (bLFO1Enabled) {
346                                               start_level_max,                  pLFO1->trigger(pDimRgn->LFO1Frequency,
347                                               lfo1_internal_depth,                                 start_level_min,
348                                               pDimRgn->LFO1ControlDepth,                                 lfo1_internal_depth,
349                                               pDimRgn->LFO1FlipPhase,                                 pDimRgn->LFO1ControlDepth,
350                                               pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                                 pDimRgn->LFO1FlipPhase,
351                                   pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
352                    pLFO1->update(pLFO1->ExtController ? pEngineChannel->ControllerTable[pLFO1->ExtController] : 0);
353                }
354          }          }
355    
356    
# Line 348  namespace LinuxSampler { namespace gig { Line 388  namespace LinuxSampler { namespace gig {
388                      pLFO2->ExtController = 0; // no external controller                      pLFO2->ExtController = 0; // no external controller
389                      bLFO2Enabled         = false;                      bLFO2Enabled         = false;
390              }              }
391              if (bLFO2Enabled) pLFO2->trigger(pDimRgn->LFO2Frequency,              if (bLFO2Enabled) {
392                                               start_level_max,                  pLFO2->trigger(pDimRgn->LFO2Frequency,
393                                               lfo2_internal_depth,                                 start_level_max,
394                                               pDimRgn->LFO2ControlDepth,                                 lfo2_internal_depth,
395                                               pDimRgn->LFO2FlipPhase,                                 pDimRgn->LFO2ControlDepth,
396                                               pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                                 pDimRgn->LFO2FlipPhase,
397                                   pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
398                    pLFO2->update(pLFO2->ExtController ? pEngineChannel->ControllerTable[pLFO2->ExtController] : 0);
399                }
400          }          }
401    
402    
# Line 373  namespace LinuxSampler { namespace gig { Line 416  namespace LinuxSampler { namespace gig {
416                      break;                      break;
417                  case ::gig::lfo3_ctrl_aftertouch:                  case ::gig::lfo3_ctrl_aftertouch:
418                      lfo3_internal_depth  = 0;                      lfo3_internal_depth  = 0;
419                      pLFO3->ExtController = 0; // TODO: aftertouch not implemented yet                      pLFO3->ExtController = 128;
420                      bLFO3Enabled         = false; // see TODO comment in line above                      bLFO3Enabled         = true;
421                      break;                      break;
422                  case ::gig::lfo3_ctrl_internal_modwheel:                  case ::gig::lfo3_ctrl_internal_modwheel:
423                      lfo3_internal_depth  = pDimRgn->LFO3InternalDepth;                      lfo3_internal_depth  = pDimRgn->LFO3InternalDepth;
# Line 383  namespace LinuxSampler { namespace gig { Line 426  namespace LinuxSampler { namespace gig {
426                      break;                      break;
427                  case ::gig::lfo3_ctrl_internal_aftertouch:                  case ::gig::lfo3_ctrl_internal_aftertouch:
428                      lfo3_internal_depth  = pDimRgn->LFO3InternalDepth;                      lfo3_internal_depth  = pDimRgn->LFO3InternalDepth;
429                      pLFO1->ExtController = 0; // TODO: aftertouch not implemented yet                      pLFO1->ExtController = 128;
430                      bLFO3Enabled         = (lfo3_internal_depth > 0 /*|| pDimRgn->LFO3ControlDepth > 0*/); // see TODO comment in line above                      bLFO3Enabled         = (lfo3_internal_depth > 0 || pDimRgn->LFO3ControlDepth > 0);
431                      break;                      break;
432                  default:                  default:
433                      lfo3_internal_depth  = 0;                      lfo3_internal_depth  = 0;
434                      pLFO3->ExtController = 0; // no external controller                      pLFO3->ExtController = 0; // no external controller
435                      bLFO3Enabled         = false;                      bLFO3Enabled         = false;
436              }              }
437              if (bLFO3Enabled) pLFO3->trigger(pDimRgn->LFO3Frequency,              if (bLFO3Enabled) {
438                                               start_level_mid,                  pLFO3->trigger(pDimRgn->LFO3Frequency,
439                                               lfo3_internal_depth,                                 start_level_mid,
440                                               pDimRgn->LFO3ControlDepth,                                 lfo3_internal_depth,
441                                               false,                                 pDimRgn->LFO3ControlDepth,
442                                               pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                                 false,
443                                   pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
444                    pLFO3->update(pLFO3->ExtController ? pEngineChannel->ControllerTable[pLFO3->ExtController] : 0);
445                }
446          }          }
447    
448    
# Line 438  namespace LinuxSampler { namespace gig { Line 484  namespace LinuxSampler { namespace gig {
484                  case ::gig::vcf_cutoff_ctrl_genpurpose8:                  case ::gig::vcf_cutoff_ctrl_genpurpose8:
485                      VCFCutoffCtrl.controller = 83;                      VCFCutoffCtrl.controller = 83;
486                      break;                      break;
487                  case ::gig::vcf_cutoff_ctrl_aftertouch: //TODO: not implemented yet                  case ::gig::vcf_cutoff_ctrl_aftertouch:
488                        VCFCutoffCtrl.controller = 128;
489                        break;
490                  case ::gig::vcf_cutoff_ctrl_none:                  case ::gig::vcf_cutoff_ctrl_none:
491                  default:                  default:
492                      VCFCutoffCtrl.controller = 0;                      VCFCutoffCtrl.controller = 0;
# Line 469  namespace LinuxSampler { namespace gig { Line 517  namespace LinuxSampler { namespace gig {
517              #endif // CONFIG_OVERRIDE_RESONANCE_CTRL              #endif // CONFIG_OVERRIDE_RESONANCE_CTRL
518    
519              #ifndef CONFIG_OVERRIDE_FILTER_TYPE              #ifndef CONFIG_OVERRIDE_FILTER_TYPE
520              FilterLeft.SetType(pDimRgn->VCFType);              finalSynthesisParameters.filterLeft.SetType(pDimRgn->VCFType);
521              FilterRight.SetType(pDimRgn->VCFType);              finalSynthesisParameters.filterRight.SetType(pDimRgn->VCFType);
522              #else // override filter type              #else // override filter type
523              FilterLeft.SetType(CONFIG_OVERRIDE_FILTER_TYPE);              finalSynthesisParameters.filterLeft.SetType(CONFIG_OVERRIDE_FILTER_TYPE);
524              FilterRight.SetType(CONFIG_OVERRIDE_FILTER_TYPE);              finalSynthesisParameters.filterRight.SetType(CONFIG_OVERRIDE_FILTER_TYPE);
525              #endif // CONFIG_OVERRIDE_FILTER_TYPE              #endif // CONFIG_OVERRIDE_FILTER_TYPE
526    
527              VCFCutoffCtrl.value    = pEngineChannel->ControllerTable[VCFCutoffCtrl.controller];              VCFCutoffCtrl.value    = pEngineChannel->ControllerTable[VCFCutoffCtrl.controller];
# Line 490  namespace LinuxSampler { namespace gig { Line 538  namespace LinuxSampler { namespace gig {
538              if (VCFCutoffCtrl.controller) {              if (VCFCutoffCtrl.controller) {
539                  cvalue = pEngineChannel->ControllerTable[VCFCutoffCtrl.controller];                  cvalue = pEngineChannel->ControllerTable[VCFCutoffCtrl.controller];
540                  if (pDimRgn->VCFCutoffControllerInvert) cvalue = 127 - cvalue;                  if (pDimRgn->VCFCutoffControllerInvert) cvalue = 127 - cvalue;
541                    // VCFVelocityScale in this case means Minimum cutoff
542                  if (cvalue < pDimRgn->VCFVelocityScale) cvalue = pDimRgn->VCFVelocityScale;                  if (cvalue < pDimRgn->VCFVelocityScale) cvalue = pDimRgn->VCFVelocityScale;
543              }              }
544              else {              else {
545                  cvalue = pDimRgn->VCFCutoff;                  cvalue = pDimRgn->VCFCutoff;
546              }              }
547              cutoff *= float(cvalue) * 0.00787402f; // (1 / 127)              cutoff *= float(cvalue);
548              if (cutoff > 1.0) cutoff = 1.0;              if (cutoff > 127.0f) cutoff = 127.0f;
             cutoff = exp(cutoff * FILTER_CUTOFF_COEFF) * CONFIG_FILTER_CUTOFF_MIN;  
549    
550              // calculate resonance              // calculate resonance
551              float resonance = (float) VCFResonanceCtrl.value * 0.00787f;   // 0.0..1.0              float resonance = (float) (VCFResonanceCtrl.controller ? VCFResonanceCtrl.value : pDimRgn->VCFResonance);
             if (pDimRgn->VCFKeyboardTracking) {  
                 resonance += (float) (itNoteOnEvent->Param.Note.Key - pDimRgn->VCFKeyboardTrackingBreakpoint) * 0.00787f;  
             }  
             Constrain(resonance, 0.0, 1.0); // correct resonance if outside allowed value range (0.0..1.0)  
552    
553              VCFCutoffCtrl.fvalue    = cutoff - CONFIG_FILTER_CUTOFF_MIN;              VCFCutoffCtrl.fvalue    = cutoff;
554              VCFResonanceCtrl.fvalue = resonance;              VCFResonanceCtrl.fvalue = resonance;
555          }          }
556          else {          else {
# Line 547  namespace LinuxSampler { namespace gig { Line 591  namespace LinuxSampler { namespace gig {
591    
592                      if (DiskVoice) {                      if (DiskVoice) {
593                          // check if we reached the allowed limit of the sample RAM cache                          // check if we reached the allowed limit of the sample RAM cache
594                          if (Pos > MaxRAMPos) {                          if (finalSynthesisParameters.dPos > MaxRAMPos) {
595                              dmsg(5,("Voice: switching to disk playback (Pos=%f)\n", Pos));                              dmsg(5,("Voice: switching to disk playback (Pos=%f)\n", finalSynthesisParameters.dPos));
596                              this->PlaybackState = playback_state_disk;                              this->PlaybackState = playback_state_disk;
597                          }                          }
598                      }                      } else if (finalSynthesisParameters.dPos >= pSample->GetCache().Size / pSample->FrameSize) {
                     else if (Pos >= pSample->GetCache().Size / pSample->FrameSize) {  
599                          this->PlaybackState = playback_state_end;                          this->PlaybackState = playback_state_end;
600                      }                      }
601                  }                  }
# Line 567  namespace LinuxSampler { namespace gig { Line 610  namespace LinuxSampler { namespace gig {
610                              KillImmediately();                              KillImmediately();
611                              return;                              return;
612                          }                          }
613                          DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (int(Pos) - MaxRAMPos));                          DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (int(finalSynthesisParameters.dPos) - MaxRAMPos));
614                          Pos -= int(Pos);                          finalSynthesisParameters.dPos -= int(finalSynthesisParameters.dPos);
615                          RealSampleWordsLeftToRead = -1; // -1 means no silence has been added yet                          RealSampleWordsLeftToRead = -1; // -1 means no silence has been added yet
616                      }                      }
617    
# Line 584  namespace LinuxSampler { namespace gig { Line 627  namespace LinuxSampler { namespace gig {
627                          }                          }
628                      }                      }
629    
630                      sample_t* ptr = DiskStreamRef.pStream->GetReadPtr(); // get the current read_ptr within the ringbuffer where we read the samples from                      sample_t* ptr = (sample_t*)DiskStreamRef.pStream->GetReadPtr(); // get the current read_ptr within the ringbuffer where we read the samples from
631    
632                      // render current audio fragment                      // render current audio fragment
633                      Synthesize(Samples, ptr, Delay);                      Synthesize(Samples, ptr, Delay);
634    
635                      const int iPos = (int) Pos;                      const int iPos = (int) finalSynthesisParameters.dPos;
636                      const int readSampleWords = iPos * pSample->Channels; // amount of sample words actually been read                      const int readSampleWords = iPos * pSample->Channels; // amount of sample words actually been read
637                      DiskStreamRef.pStream->IncrementReadPos(readSampleWords);                      DiskStreamRef.pStream->IncrementReadPos(readSampleWords);
638                      Pos -= iPos; // just keep fractional part of Pos                      finalSynthesisParameters.dPos -= iPos; // just keep fractional part of playback position
639    
640                      // change state of voice to 'end' if we really reached the end of the sample data                      // change state of voice to 'end' if we really reached the end of the sample data
641                      if (RealSampleWordsLeftToRead >= 0) {                      if (RealSampleWordsLeftToRead >= 0) {
# Line 607  namespace LinuxSampler { namespace gig { Line 650  namespace LinuxSampler { namespace gig {
650                  break;                  break;
651          }          }
652    
         // Reset synthesis event lists  
         pEngineChannel->pEvents->clear();  
   
653          // Reset delay          // Reset delay
654          Delay = 0;          Delay = 0;
655    
# Line 624  namespace LinuxSampler { namespace gig { Line 664  namespace LinuxSampler { namespace gig {
664       *  suspended / not running.       *  suspended / not running.
665       */       */
666      void Voice::Reset() {      void Voice::Reset() {
667          FilterLeft.Reset();          finalSynthesisParameters.filterLeft.Reset();
668          FilterRight.Reset();          finalSynthesisParameters.filterRight.Reset();
669          DiskStreamRef.pStream = NULL;          DiskStreamRef.pStream = NULL;
670          DiskStreamRef.hStream = 0;          DiskStreamRef.hStream = 0;
671          DiskStreamRef.State   = Stream::state_unused;          DiskStreamRef.State   = Stream::state_unused;
# Line 640  namespace LinuxSampler { namespace gig { Line 680  namespace LinuxSampler { namespace gig {
680       * for the given time.       * for the given time.
681       *       *
682       * @param itEvent - iterator pointing to the next event to be processed       * @param itEvent - iterator pointing to the next event to be processed
683       * @param End     - youngest time stamp where processing should be stopped       * @param End     - youngest time stamp where processing should be stopped
684       */       */
685      void Voice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) {      void Voice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) {
686          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
687              if (itEvent->Type == Event::type_release) {              if (itEvent->Type == Event::type_release) {
688                  EG1.update(EGADSR::event_release, this->Pos, fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  EG1.update(EGADSR::event_release, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
689                  EG2.update(EGADSR::event_release, this->Pos, fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  EG2.update(EGADSR::event_release, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
690              } else if (itEvent->Type == Event::type_cancel_release) {              } else if (itEvent->Type == Event::type_cancel_release) {
691                  EG1.update(EGADSR::event_cancel_release, this->Pos, fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  EG1.update(EGADSR::event_cancel_release, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
692                  EG2.update(EGADSR::event_cancel_release, this->Pos, fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  EG2.update(EGADSR::event_cancel_release, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
693              }              }
694          }          }
695      }      }
# Line 659  namespace LinuxSampler { namespace gig { Line 699  namespace LinuxSampler { namespace gig {
699       * the given time.       * the given time.
700       *       *
701       * @param itEvent - iterator pointing to the next event to be processed       * @param itEvent - iterator pointing to the next event to be processed
702       * @param End     - youngest time stamp where processing should be stopped       * @param End     - youngest time stamp where processing should be stopped
703       */       */
704      void Voice::processCCEvents(RTList<Event>::Iterator& itEvent, uint End) {      void Voice::processCCEvents(RTList<Event>::Iterator& itEvent, uint End) {
705          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
# Line 682  namespace LinuxSampler { namespace gig { Line 722  namespace LinuxSampler { namespace gig {
722                  }                  }
723                  if (pDimRgn->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange &&                  if (pDimRgn->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange &&
724                      itEvent->Param.CC.Controller == pDimRgn->AttenuationController.controller_number) {                      itEvent->Param.CC.Controller == pDimRgn->AttenuationController.controller_number) {
725                      processCrossFadeEvent(itEvent);                      CrossfadeSmoother.update(Engine::CrossfadeCurve[CrossfadeAttenuation(itEvent->Param.CC.Value)]);
726                    }
727                    if (itEvent->Param.CC.Controller == 7) { // volume
728                        VolumeSmoother.update(Engine::VolumeCurve[itEvent->Param.CC.Value]);
729                    } else if (itEvent->Param.CC.Controller == 10) { // panpot
730                        PanLeftSmoother.update(Engine::PanCurve[128 - itEvent->Param.CC.Value]);
731                        PanRightSmoother.update(Engine::PanCurve[itEvent->Param.CC.Value]);
732                  }                  }
733              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event
734                  processPitchEvent(itEvent);                  processPitchEvent(itEvent);
# Line 692  namespace LinuxSampler { namespace gig { Line 738  namespace LinuxSampler { namespace gig {
738    
739      void Voice::processPitchEvent(RTList<Event>::Iterator& itEvent) {      void Voice::processPitchEvent(RTList<Event>::Iterator& itEvent) {
740          const float pitch = RTMath::CentsToFreqRatio(((double) itEvent->Param.Pitch.Pitch / 8192.0) * 200.0); // +-two semitones = +-200 cents          const float pitch = RTMath::CentsToFreqRatio(((double) itEvent->Param.Pitch.Pitch / 8192.0) * 200.0); // +-two semitones = +-200 cents
741          fFinalPitch *= pitch;          finalSynthesisParameters.fFinalPitch *= pitch;
742          PitchBend = pitch;          PitchBend = pitch;
743      }      }
744    
     void Voice::processCrossFadeEvent(RTList<Event>::Iterator& itEvent) {  
         CrossfadeVolume = CrossfadeAttenuation(itEvent->Param.CC.Value);  
         #if CONFIG_PROCESS_MUTED_CHANNELS  
         const float effectiveVolume = CrossfadeVolume * Volume * (pEngineChannel->GetMute() ? 0 : pEngineChannel->GlobalVolume);  
         #else  
         const float effectiveVolume = CrossfadeVolume * Volume * pEngineChannel->GlobalVolume;  
         #endif  
         fFinalVolume = effectiveVolume;  
     }  
   
745      void Voice::processCutoffEvent(RTList<Event>::Iterator& itEvent) {      void Voice::processCutoffEvent(RTList<Event>::Iterator& itEvent) {
746          int ccvalue = itEvent->Param.CC.Value;          int ccvalue = itEvent->Param.CC.Value;
747          if (VCFCutoffCtrl.value == ccvalue) return;          if (VCFCutoffCtrl.value == ccvalue) return;
748          VCFCutoffCtrl.value == ccvalue;          VCFCutoffCtrl.value == ccvalue;
749          if (pDimRgn->VCFCutoffControllerInvert)  ccvalue = 127 - ccvalue;          if (pDimRgn->VCFCutoffControllerInvert)  ccvalue = 127 - ccvalue;
750          if (ccvalue < pDimRgn->VCFVelocityScale) ccvalue = pDimRgn->VCFVelocityScale;          if (ccvalue < pDimRgn->VCFVelocityScale) ccvalue = pDimRgn->VCFVelocityScale;
751          float cutoff = CutoffBase * float(ccvalue) * 0.00787402f; // (1 / 127)          float cutoff = CutoffBase * float(ccvalue);
752          if (cutoff > 1.0) cutoff = 1.0;          if (cutoff > 127.0f) cutoff = 127.0f;
753          cutoff = exp(cutoff * FILTER_CUTOFF_COEFF) * CONFIG_FILTER_CUTOFF_MIN - CONFIG_FILTER_CUTOFF_MIN;  
754          VCFCutoffCtrl.fvalue = cutoff; // needed for initialization of fFinalCutoff next time          VCFCutoffCtrl.fvalue = cutoff; // needed for initialization of fFinalCutoff next time
755          fFinalCutoff = cutoff;          fFinalCutoff = cutoff;
756      }      }
# Line 723  namespace LinuxSampler { namespace gig { Line 759  namespace LinuxSampler { namespace gig {
759          // convert absolute controller value to differential          // convert absolute controller value to differential
760          const int ctrldelta = itEvent->Param.CC.Value - VCFResonanceCtrl.value;          const int ctrldelta = itEvent->Param.CC.Value - VCFResonanceCtrl.value;
761          VCFResonanceCtrl.value = itEvent->Param.CC.Value;          VCFResonanceCtrl.value = itEvent->Param.CC.Value;
762          const float resonancedelta = (float) ctrldelta * 0.00787f; // 0.0..1.0          const float resonancedelta = (float) ctrldelta;
763          fFinalResonance += resonancedelta;          fFinalResonance += resonancedelta;
764          // needed for initialization of parameter          // needed for initialization of parameter
765          VCFResonanceCtrl.fvalue = itEvent->Param.CC.Value * 0.00787f;          VCFResonanceCtrl.fvalue = itEvent->Param.CC.Value;
766      }      }
767    
768      /**      /**
# Line 738  namespace LinuxSampler { namespace gig { Line 774  namespace LinuxSampler { namespace gig {
774       *  @param Skip    - number of sample points to skip in output buffer       *  @param Skip    - number of sample points to skip in output buffer
775       */       */
776      void Voice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {      void Voice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {
777            finalSynthesisParameters.pOutLeft  = &pEngineChannel->pChannelLeft->Buffer()[Skip];
778            finalSynthesisParameters.pOutRight = &pEngineChannel->pChannelRight->Buffer()[Skip];
779            finalSynthesisParameters.pSrc      = pSrc;
780    
781          RTList<Event>::Iterator itCCEvent = pEngineChannel->pEvents->first();          RTList<Event>::Iterator itCCEvent = pEngineChannel->pEvents->first();
782          RTList<Event>::Iterator itNoteEvent = pEngineChannel->pMIDIKeyInfo[MIDIKey].pEvents->first();          RTList<Event>::Iterator itNoteEvent = pEngineChannel->pMIDIKeyInfo[MIDIKey].pEvents->first();
783    
784          if (Skip) { // skip events that happened before this voice was triggered          if (itTriggerEvent) { // skip events that happened before this voice was triggered
785              while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;              while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;
786              while (itNoteEvent && itNoteEvent->FragmentPos() <= Skip) ++itNoteEvent;              // we can't simply compare the timestamp here, because note events
787                // might happen on the same time stamp, so we have to deal on the
788                // actual sequence the note events arrived instead (see bug #112)
789                for (; itNoteEvent; ++itNoteEvent) {
790                    if (itTriggerEvent == itNoteEvent) {
791                        ++itNoteEvent;
792                        break;
793                    }
794                }
795            }
796    
797            uint killPos;
798            if (itKillEvent) {
799                int maxFadeOutPos = Samples - pEngine->MinFadeOutSamples;
800                if (maxFadeOutPos < 0) {
801                    // There's not enough space in buffer to do a fade out
802                    // from max volume (this can only happen for audio
803                    // drivers that use Samples < MaxSamplesPerCycle).
804                    // End the EG1 here, at pos 0, with a shorter max fade
805                    // out time.
806                    EG1.enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
807                    itKillEvent = Pool<Event>::Iterator();
808                } else {
809                    killPos = RTMath::Min(itKillEvent->FragmentPos(), maxFadeOutPos);
810                }
811          }          }
812    
813          uint i = Skip;          uint i = Skip;
# Line 751  namespace LinuxSampler { namespace gig { Line 815  namespace LinuxSampler { namespace gig {
815              int iSubFragmentEnd = RTMath::Min(i + CONFIG_DEFAULT_SUBFRAGMENT_SIZE, Samples);              int iSubFragmentEnd = RTMath::Min(i + CONFIG_DEFAULT_SUBFRAGMENT_SIZE, Samples);
816    
817              // initialize all final synthesis parameters              // initialize all final synthesis parameters
818              fFinalPitch = PitchBase * PitchBend;              finalSynthesisParameters.fFinalPitch = PitchBase * PitchBend;
             #if CONFIG_PROCESS_MUTED_CHANNELS  
             fFinalVolume = this->Volume * this->CrossfadeVolume * (pEngineChannel->GetMute() ? 0 : pEngineChannel->GlobalVolume);  
             #else  
             fFinalVolume = this->Volume * this->CrossfadeVolume * pEngineChannel->GlobalVolume;  
             #endif  
819              fFinalCutoff    = VCFCutoffCtrl.fvalue;              fFinalCutoff    = VCFCutoffCtrl.fvalue;
820              fFinalResonance = VCFResonanceCtrl.fvalue;              fFinalResonance = VCFResonanceCtrl.fvalue;
821    
822              // process MIDI control change and pitchbend events for this subfragment              // process MIDI control change and pitchbend events for this subfragment
823              processCCEvents(itCCEvent, iSubFragmentEnd);              processCCEvents(itCCEvent, iSubFragmentEnd);
824    
825                float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render();
826    #ifdef CONFIG_PROCESS_MUTED_CHANNELS
827                if (pEngineChannel->GetMute()) fFinalVolume = 0;
828    #endif
829    
830              // process transition events (note on, note off & sustain pedal)              // process transition events (note on, note off & sustain pedal)
831              processTransitionEvents(itNoteEvent, iSubFragmentEnd);              processTransitionEvents(itNoteEvent, iSubFragmentEnd);
832    
833                // if the voice was killed in this subfragment, or if the
834                // filter EG is finished, switch EG1 to fade out stage
835                if ((itKillEvent && killPos <= iSubFragmentEnd) ||
836                    (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&
837                     EG2.getSegmentType() == EGADSR::segment_end)) {
838                    EG1.enterFadeOutStage();
839                    itKillEvent = Pool<Event>::Iterator();
840                }
841    
842              // process envelope generators              // process envelope generators
843              switch (EG1.getSegmentType()) {              switch (EG1.getSegmentType()) {
844                  case EGADSR::segment_lin:                  case EGADSR::segment_lin:
# Line 789  namespace LinuxSampler { namespace gig { Line 862  namespace LinuxSampler { namespace gig {
862                      fFinalCutoff *= EG2.getLevel();                      fFinalCutoff *= EG2.getLevel();
863                      break; // noop                      break; // noop
864              }              }
865              fFinalPitch *= RTMath::CentsToFreqRatio(EG3.render());              if (EG3.active()) finalSynthesisParameters.fFinalPitch *= EG3.render();
866    
867              // process low frequency oscillators              // process low frequency oscillators
868              if (bLFO1Enabled) fFinalVolume *= pLFO1->render();              if (bLFO1Enabled) fFinalVolume *= (1.0f - pLFO1->render());
869              if (bLFO2Enabled) fFinalCutoff *= pLFO2->render();              if (bLFO2Enabled) fFinalCutoff *= pLFO2->render();
870              if (bLFO3Enabled) fFinalPitch  *= RTMath::CentsToFreqRatio(pLFO3->render());              if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());
871    
872              // if filter enabled then update filter coefficients              // if filter enabled then update filter coefficients
873              if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode)) {              if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode)) {
874                  FilterLeft.SetParameters(fFinalCutoff, fFinalResonance, pEngine->SampleRate);                  finalSynthesisParameters.filterLeft.SetParameters(fFinalCutoff, fFinalResonance, pEngine->SampleRate);
875                  FilterRight.SetParameters(fFinalCutoff, fFinalResonance, pEngine->SampleRate);                  finalSynthesisParameters.filterRight.SetParameters(fFinalCutoff, fFinalResonance, pEngine->SampleRate);
876              }              }
877    
878              // how many steps do we calculate for this next subfragment              // do we need resampling?
879              const int steps = iSubFragmentEnd - i;              const float __PLUS_ONE_CENT  = 1.000577789506554859250142541782224725466f;
880                const float __MINUS_ONE_CENT = 0.9994225441413807496009516495583113737666f;
881                const bool bResamplingRequired = !(finalSynthesisParameters.fFinalPitch <= __PLUS_ONE_CENT &&
882                                                   finalSynthesisParameters.fFinalPitch >= __MINUS_ONE_CENT);
883                SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, bResamplingRequired);
884    
885                // prepare final synthesis parameters structure
886                finalSynthesisParameters.uiToGo            = iSubFragmentEnd - i;
887    #ifdef CONFIG_INTERPOLATE_VOLUME
888                finalSynthesisParameters.fFinalVolumeDeltaLeft  =
889                    (fFinalVolume * VolumeLeft  * PanLeftSmoother.render() -
890                     finalSynthesisParameters.fFinalVolumeLeft) / finalSynthesisParameters.uiToGo;
891                finalSynthesisParameters.fFinalVolumeDeltaRight =
892                    (fFinalVolume * VolumeRight * PanRightSmoother.render() -
893                     finalSynthesisParameters.fFinalVolumeRight) / finalSynthesisParameters.uiToGo;
894    #else
895                finalSynthesisParameters.fFinalVolumeLeft  =
896                    fFinalVolume * VolumeLeft  * PanLeftSmoother.render();
897                finalSynthesisParameters.fFinalVolumeRight =
898                    fFinalVolume * VolumeRight * PanRightSmoother.render();
899    #endif
900                // render audio for one subfragment
901                RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);
902    
903              // select the appropriate synthesis mode              // stop the rendering if volume EG is finished
904              SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, fFinalPitch != 1.0f);              if (EG1.getSegmentType() == EGADSR::segment_end) break;
905    
906              // render audio for one subfragment              const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;
             RunSynthesisFunction(SynthesisMode, *this, iSubFragmentEnd, pSrc, i);  
907    
908              // increment envelopes' positions              // increment envelopes' positions
909              if (EG1.active()) {              if (EG1.active()) {
910    
911                    // if sample has a loop and loop start has been reached in this subfragment, send a special event to EG1 to let it finish the attack hold stage
912                    if (pDimRgn->SampleLoops && Pos <= pDimRgn->pSampleLoops[0].LoopStart && pDimRgn->pSampleLoops[0].LoopStart < newPos) {
913                        EG1.update(EGADSR::event_hold_end, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
914                    }
915    
916                  EG1.increment(1);                  EG1.increment(1);
917                  if (!EG1.toStageEndLeft()) EG1.update(EGADSR::event_stage_end, this->Pos, fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  if (!EG1.toStageEndLeft()) EG1.update(EGADSR::event_stage_end, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
918              }              }
919              if (EG2.active()) {              if (EG2.active()) {
920                  EG2.increment(1);                  EG2.increment(1);
921                  if (!EG2.toStageEndLeft()) EG2.update(EGADSR::event_stage_end, this->Pos, fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  if (!EG2.toStageEndLeft()) EG2.update(EGADSR::event_stage_end, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
922              }              }
923              EG3.increment(1);              EG3.increment(1);
924              if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached              if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached
925    
926                Pos = newPos;
927              i = iSubFragmentEnd;              i = iSubFragmentEnd;
928          }          }
929      }      }
930    
931        /** @brief Update current portamento position.
932         *
933         * Will be called when portamento mode is enabled to get the final
934         * portamento position of this active voice from where the next voice(s)
935         * might continue to slide on.
936         *
937         * @param itNoteOffEvent - event which causes this voice to die soon
938         */
939        void Voice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {
940            const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());
941            pEngineChannel->PortamentoPos = (float) MIDIKey + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;
942        }
943    
944      /**      /**
945       *  Immediately kill the voice. This method should not be used to kill       *  Immediately kill the voice. This method should not be used to kill
946       *  a normal, active voice, because it doesn't take care of things like       *  a normal, active voice, because it doesn't take care of things like
947       *  fading down the volume level to avoid clicks and regular processing       *  fading down the volume level to avoid clicks and regular processing
948       *  until the kill event actually occured!       *  until the kill event actually occured!
949       *       *
950       *  @see Kill()       * If it's necessary to know when the voice's disk stream was actually
951         * deleted, then one can set the optional @a bRequestNotification
952         * parameter and this method will then return the handle of the disk
953         * stream (unique identifier) and one can use this handle to poll the
954         * disk thread if this stream has been deleted. In any case this method
955         * will return immediately and will not block until the stream actually
956         * was deleted.
957         *
958         * @param bRequestNotification - (optional) whether the disk thread shall
959         *                                provide a notification once it deleted
960         *                               the respective disk stream
961         *                               (default=false)
962         * @returns handle to the voice's disk stream or @c Stream::INVALID_HANDLE
963         *          if the voice did not use a disk stream at all
964         * @see Kill()
965       */       */
966      void Voice::KillImmediately() {      Stream::Handle Voice::KillImmediately(bool bRequestNotification) {
967            Stream::Handle hStream = Stream::INVALID_HANDLE;
968          if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {          if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {
969              pDiskThread->OrderDeletionOfStream(&DiskStreamRef);              pDiskThread->OrderDeletionOfStream(&DiskStreamRef, bRequestNotification);
970                hStream = DiskStreamRef.hStream;
971          }          }
972          Reset();          Reset();
973            return hStream;
974      }      }
975    
976      /**      /**

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

  ViewVC Help
Powered by ViewVC