/[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 738 by schoenebeck, Tue Aug 16 17:14:25 2005 UTC revision 1858 by persson, Sun Mar 8 09:57:19 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 = pEngineChannel->pInstrument->FineTune + pDimRgn->FineTune + 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(PitchBend / 8192.0 * 100.0 * pEngineChannel->pInstrument->PitchbendRange);
195          }          }
196    
197          // the length of the decay and release curves are dependent on the velocity          // the length of the decay and release curves are dependent on the velocity
# 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 691  namespace LinuxSampler { namespace gig { Line 737  namespace LinuxSampler { namespace gig {
737      }      }
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          PitchBend = RTMath::CentsToFreqRatio(itEvent->Param.Pitch.Pitch / 8192.0 * 100.0 * pEngineChannel->pInstrument->PitchbendRange);
         fFinalPitch *= pitch;  
     }  
   
     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;  
741      }      }
742    
743      void Voice::processCutoffEvent(RTList<Event>::Iterator& itEvent) {      void Voice::processCutoffEvent(RTList<Event>::Iterator& itEvent) {
# Line 711  namespace LinuxSampler { namespace gig { Line 746  namespace LinuxSampler { namespace gig {
746          VCFCutoffCtrl.value == ccvalue;          VCFCutoffCtrl.value == ccvalue;
747          if (pDimRgn->VCFCutoffControllerInvert)  ccvalue = 127 - ccvalue;          if (pDimRgn->VCFCutoffControllerInvert)  ccvalue = 127 - ccvalue;
748          if (ccvalue < pDimRgn->VCFVelocityScale) ccvalue = pDimRgn->VCFVelocityScale;          if (ccvalue < pDimRgn->VCFVelocityScale) ccvalue = pDimRgn->VCFVelocityScale;
749          float cutoff = CutoffBase * float(ccvalue) * 0.00787402f; // (1 / 127)          float cutoff = CutoffBase * float(ccvalue);
750          if (cutoff > 1.0) cutoff = 1.0;          if (cutoff > 127.0f) cutoff = 127.0f;
751          cutoff = exp(cutoff * FILTER_CUTOFF_COEFF) * CONFIG_FILTER_CUTOFF_MIN - CONFIG_FILTER_CUTOFF_MIN;  
752          VCFCutoffCtrl.fvalue = cutoff; // needed for initialization of fFinalCutoff next time          VCFCutoffCtrl.fvalue = cutoff; // needed for initialization of fFinalCutoff next time
753          fFinalCutoff = cutoff;          fFinalCutoff = cutoff;
754      }      }
# Line 722  namespace LinuxSampler { namespace gig { Line 757  namespace LinuxSampler { namespace gig {
757          // convert absolute controller value to differential          // convert absolute controller value to differential
758          const int ctrldelta = itEvent->Param.CC.Value - VCFResonanceCtrl.value;          const int ctrldelta = itEvent->Param.CC.Value - VCFResonanceCtrl.value;
759          VCFResonanceCtrl.value = itEvent->Param.CC.Value;          VCFResonanceCtrl.value = itEvent->Param.CC.Value;
760          const float resonancedelta = (float) ctrldelta * 0.00787f; // 0.0..1.0          const float resonancedelta = (float) ctrldelta;
761          fFinalResonance += resonancedelta;          fFinalResonance += resonancedelta;
762          // needed for initialization of parameter          // needed for initialization of parameter
763          VCFResonanceCtrl.fvalue = itEvent->Param.CC.Value * 0.00787f;          VCFResonanceCtrl.fvalue = itEvent->Param.CC.Value;
764      }      }
765    
766      /**      /**
# Line 737  namespace LinuxSampler { namespace gig { Line 772  namespace LinuxSampler { namespace gig {
772       *  @param Skip    - number of sample points to skip in output buffer       *  @param Skip    - number of sample points to skip in output buffer
773       */       */
774      void Voice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {      void Voice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {
775            finalSynthesisParameters.pOutLeft  = &pEngineChannel->pChannelLeft->Buffer()[Skip];
776            finalSynthesisParameters.pOutRight = &pEngineChannel->pChannelRight->Buffer()[Skip];
777            finalSynthesisParameters.pSrc      = pSrc;
778    
779          RTList<Event>::Iterator itCCEvent = pEngineChannel->pEvents->first();          RTList<Event>::Iterator itCCEvent = pEngineChannel->pEvents->first();
780          RTList<Event>::Iterator itNoteEvent = pEngineChannel->pMIDIKeyInfo[MIDIKey].pEvents->first();          RTList<Event>::Iterator itNoteEvent = pEngineChannel->pMIDIKeyInfo[MIDIKey].pEvents->first();
781                    
782          if (Skip) { // skip events that happened before this voice was triggered          if (itTriggerEvent) { // skip events that happened before this voice was triggered
783              while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;              while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;
784              while (itNoteEvent && itNoteEvent->FragmentPos() <= Skip) ++itNoteEvent;              // we can't simply compare the timestamp here, because note events
785                // might happen on the same time stamp, so we have to deal on the
786                // actual sequence the note events arrived instead (see bug #112)
787                for (; itNoteEvent; ++itNoteEvent) {
788                    if (itTriggerEvent == itNoteEvent) {
789                        ++itNoteEvent;
790                        break;
791                    }
792                }
793          }          }
794            
795            uint killPos;
796            if (itKillEvent) {
797                int maxFadeOutPos = Samples - pEngine->MinFadeOutSamples;
798                if (maxFadeOutPos < 0) {
799                    // There's not enough space in buffer to do a fade out
800                    // from max volume (this can only happen for audio
801                    // drivers that use Samples < MaxSamplesPerCycle).
802                    // End the EG1 here, at pos 0, with a shorter max fade
803                    // out time.
804                    EG1.enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
805                    itKillEvent = Pool<Event>::Iterator();
806                } else {
807                    killPos = RTMath::Min(itKillEvent->FragmentPos(), maxFadeOutPos);
808                }
809            }
810    
811          uint i = Skip;          uint i = Skip;
812          while (i < Samples) {          while (i < Samples) {
813              int iSubFragmentEnd = RTMath::Min(i + CONFIG_DEFAULT_SUBFRAGMENT_SIZE, Samples);              int iSubFragmentEnd = RTMath::Min(i + CONFIG_DEFAULT_SUBFRAGMENT_SIZE, Samples);
814                
815              // initialize all final synthesis parameters              // initialize all final synthesis parameters
             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  
816              fFinalCutoff    = VCFCutoffCtrl.fvalue;              fFinalCutoff    = VCFCutoffCtrl.fvalue;
817              fFinalResonance = VCFResonanceCtrl.fvalue;              fFinalResonance = VCFResonanceCtrl.fvalue;
818                
819              // process MIDI control change and pitchbend events for this subfragment              // process MIDI control change and pitchbend events for this subfragment
820              processCCEvents(itCCEvent, iSubFragmentEnd);              processCCEvents(itCCEvent, iSubFragmentEnd);
821    
822                finalSynthesisParameters.fFinalPitch = PitchBase * PitchBend;
823                float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render();
824    #ifdef CONFIG_PROCESS_MUTED_CHANNELS
825                if (pEngineChannel->GetMute()) fFinalVolume = 0;
826    #endif
827    
828              // process transition events (note on, note off & sustain pedal)              // process transition events (note on, note off & sustain pedal)
829              processTransitionEvents(itNoteEvent, iSubFragmentEnd);              processTransitionEvents(itNoteEvent, iSubFragmentEnd);
830                
831                // if the voice was killed in this subfragment, or if the
832                // filter EG is finished, switch EG1 to fade out stage
833                if ((itKillEvent && killPos <= iSubFragmentEnd) ||
834                    (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&
835                     EG2.getSegmentType() == EGADSR::segment_end)) {
836                    EG1.enterFadeOutStage();
837                    itKillEvent = Pool<Event>::Iterator();
838                }
839    
840              // process envelope generators              // process envelope generators
841              switch (EG1.getSegmentType()) {              switch (EG1.getSegmentType()) {
842                  case EGADSR::segment_lin:                  case EGADSR::segment_lin:
# Line 788  namespace LinuxSampler { namespace gig { Line 860  namespace LinuxSampler { namespace gig {
860                      fFinalCutoff *= EG2.getLevel();                      fFinalCutoff *= EG2.getLevel();
861                      break; // noop                      break; // noop
862              }              }
863              fFinalPitch *= RTMath::CentsToFreqRatio(EG3.render());              if (EG3.active()) finalSynthesisParameters.fFinalPitch *= EG3.render();
864                
865              // process low frequency oscillators              // process low frequency oscillators
866              if (bLFO1Enabled) fFinalVolume *= pLFO1->render();              if (bLFO1Enabled) fFinalVolume *= (1.0f - pLFO1->render());
867              if (bLFO2Enabled) fFinalCutoff *= pLFO2->render();              if (bLFO2Enabled) fFinalCutoff *= pLFO2->render();
868              if (bLFO3Enabled) fFinalPitch  *= RTMath::CentsToFreqRatio(pLFO3->render());              if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());
869    
870              // if filter enabled then update filter coefficients              // if filter enabled then update filter coefficients
871              if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode)) {              if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode)) {
872                  FilterLeft.SetParameters(fFinalCutoff, fFinalResonance, pEngine->SampleRate);                  finalSynthesisParameters.filterLeft.SetParameters(fFinalCutoff, fFinalResonance, pEngine->SampleRate);
873                  FilterRight.SetParameters(fFinalCutoff, fFinalResonance, pEngine->SampleRate);                  finalSynthesisParameters.filterRight.SetParameters(fFinalCutoff, fFinalResonance, pEngine->SampleRate);
874              }              }
875    
876              // how many steps do we calculate for this next subfragment              // do we need resampling?
877              const int steps = iSubFragmentEnd - i;              const float __PLUS_ONE_CENT  = 1.000577789506554859250142541782224725466f;
878                            const float __MINUS_ONE_CENT = 0.9994225441413807496009516495583113737666f;
879              // select the appropriate synthesis mode              const bool bResamplingRequired = !(finalSynthesisParameters.fFinalPitch <= __PLUS_ONE_CENT &&
880              SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, fFinalPitch != 1.0f);                                                 finalSynthesisParameters.fFinalPitch >= __MINUS_ONE_CENT);
881                            SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, bResamplingRequired);
882    
883                // prepare final synthesis parameters structure
884                finalSynthesisParameters.uiToGo            = iSubFragmentEnd - i;
885    #ifdef CONFIG_INTERPOLATE_VOLUME
886                finalSynthesisParameters.fFinalVolumeDeltaLeft  =
887                    (fFinalVolume * VolumeLeft  * PanLeftSmoother.render() -
888                     finalSynthesisParameters.fFinalVolumeLeft) / finalSynthesisParameters.uiToGo;
889                finalSynthesisParameters.fFinalVolumeDeltaRight =
890                    (fFinalVolume * VolumeRight * PanRightSmoother.render() -
891                     finalSynthesisParameters.fFinalVolumeRight) / finalSynthesisParameters.uiToGo;
892    #else
893                finalSynthesisParameters.fFinalVolumeLeft  =
894                    fFinalVolume * VolumeLeft  * PanLeftSmoother.render();
895                finalSynthesisParameters.fFinalVolumeRight =
896                    fFinalVolume * VolumeRight * PanRightSmoother.render();
897    #endif
898              // render audio for one subfragment              // render audio for one subfragment
899              RunSynthesisFunction(SynthesisMode, *this, iSubFragmentEnd, pSrc, i);              RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);
900    
901                // stop the rendering if volume EG is finished
902                if (EG1.getSegmentType() == EGADSR::segment_end) break;
903    
904                const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;
905    
906              // increment envelopes' positions                          // increment envelopes' positions
907              if (EG1.active()) {              if (EG1.active()) {
908                  EG1.increment(steps);  
909                  if (!EG1.toStageEndLeft()) EG1.update(EGADSR::event_stage_end, this->Pos, fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  // 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
910                    if (pDimRgn->SampleLoops && Pos <= pDimRgn->pSampleLoops[0].LoopStart && pDimRgn->pSampleLoops[0].LoopStart < newPos) {
911                        EG1.update(EGADSR::event_hold_end, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
912                    }
913    
914                    EG1.increment(1);
915                    if (!EG1.toStageEndLeft()) EG1.update(EGADSR::event_stage_end, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
916              }              }
917              if (EG2.active()) {              if (EG2.active()) {
918                  EG2.increment(steps);                  EG2.increment(1);
919                  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);
920              }              }
921              EG3.increment(steps);              EG3.increment(1);
922              if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached              if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached
923    
924                Pos = newPos;
925                i = iSubFragmentEnd;
926          }          }
927      }      }
928    
929        /** @brief Update current portamento position.
930         *
931         * Will be called when portamento mode is enabled to get the final
932         * portamento position of this active voice from where the next voice(s)
933         * might continue to slide on.
934         *
935         * @param itNoteOffEvent - event which causes this voice to die soon
936         */
937        void Voice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {
938            const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());
939            pEngineChannel->PortamentoPos = (float) MIDIKey + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;
940        }
941    
942      /**      /**
943       *  Immediately kill the voice. This method should not be used to kill       *  Immediately kill the voice. This method should not be used to kill
944       *  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
945       *  fading down the volume level to avoid clicks and regular processing       *  fading down the volume level to avoid clicks and regular processing
946       *  until the kill event actually occured!       *  until the kill event actually occured!
947       *       *
948       *  @see Kill()       * If it's necessary to know when the voice's disk stream was actually
949         * deleted, then one can set the optional @a bRequestNotification
950         * parameter and this method will then return the handle of the disk
951         * stream (unique identifier) and one can use this handle to poll the
952         * disk thread if this stream has been deleted. In any case this method
953         * will return immediately and will not block until the stream actually
954         * was deleted.
955         *
956         * @param bRequestNotification - (optional) whether the disk thread shall
957         *                                provide a notification once it deleted
958         *                               the respective disk stream
959         *                               (default=false)
960         * @returns handle to the voice's disk stream or @c Stream::INVALID_HANDLE
961         *          if the voice did not use a disk stream at all
962         * @see Kill()
963       */       */
964      void Voice::KillImmediately() {      Stream::Handle Voice::KillImmediately(bool bRequestNotification) {
965            Stream::Handle hStream = Stream::INVALID_HANDLE;
966          if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {          if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {
967              pDiskThread->OrderDeletionOfStream(&DiskStreamRef);              pDiskThread->OrderDeletionOfStream(&DiskStreamRef, bRequestNotification);
968                hStream = DiskStreamRef.hStream;
969          }          }
970          Reset();          Reset();
971            return hStream;
972      }      }
973    
974      /**      /**

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

  ViewVC Help
Powered by ViewVC