/[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 877 by persson, Sun Jun 25 13:54:17 2006 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, 2006 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 49  namespace LinuxSampler { namespace gig { Line 44  namespace LinuxSampler { namespace gig {
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 103  namespace LinuxSampler { namespace gig { Line 98  namespace LinuxSampler { namespace gig {
98          // calculate volume          // calculate volume
99          const double velocityAttenuation = pDimRgn->GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity);          const double velocityAttenuation = pDimRgn->GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity);
100    
101          Volume = velocityAttenuation / 32768.0f; // we downscale by 32768 to convert from int16 value range to DSP value range (which is -1.0..1.0)          float volume = velocityAttenuation / 32768.0f; // we downscale by 32768 to convert from int16 value range to DSP value range (which is -1.0..1.0)
102    
103          Volume *= pDimRgn->SampleAttenuation;          volume *= pDimRgn->SampleAttenuation;
104    
105          // the volume of release triggered samples depends on note length          // the volume of release triggered samples depends on note length
106          if (Type == type_release_trigger) {          if (Type == type_release_trigger) {
# Line 113  namespace LinuxSampler { namespace gig { Line 108  namespace LinuxSampler { namespace gig {
108                                       pEngineChannel->pMIDIKeyInfo[MIDIKey].NoteOnTime) / pEngine->SampleRate;                                       pEngineChannel->pMIDIKeyInfo[MIDIKey].NoteOnTime) / pEngine->SampleRate;
109              float attenuation = 1 - 0.01053 * (256 >> pDimRgn->ReleaseTriggerDecay) * noteLength;              float attenuation = 1 - 0.01053 * (256 >> pDimRgn->ReleaseTriggerDecay) * noteLength;
110              if (attenuation <= 0) return -1;              if (attenuation <= 0) return -1;
111              Volume *= attenuation;              volume *= attenuation;
112          }          }
113    
114          // select channel mode (mono or stereo)          // select channel mode (mono or stereo)
115          SYNTHESIS_MODE_SET_CHANNELS(SynthesisMode, pSample->Channels == 2);          SYNTHESIS_MODE_SET_CHANNELS(SynthesisMode, pSample->Channels == 2);
116    
117          // get starting crossfade volume level          // get starting crossfade volume level
118            float crossfadeVolume;
119          switch (pDimRgn->AttenuationController.type) {          switch (pDimRgn->AttenuationController.type) {
120              case ::gig::attenuation_ctrl_t::type_channelaftertouch:              case ::gig::attenuation_ctrl_t::type_channelaftertouch:
121                  CrossfadeVolume = 1.0f; //TODO: aftertouch not supported yet                  crossfadeVolume = 1.0f; //TODO: aftertouch not supported yet
122                  break;                  break;
123              case ::gig::attenuation_ctrl_t::type_velocity:              case ::gig::attenuation_ctrl_t::type_velocity:
124                  CrossfadeVolume = CrossfadeAttenuation(itNoteOnEvent->Param.Note.Velocity);                  crossfadeVolume = Engine::CrossfadeCurve[CrossfadeAttenuation(itNoteOnEvent->Param.Note.Velocity)];
125                  break;                  break;
126              case ::gig::attenuation_ctrl_t::type_controlchange: //FIXME: currently not sample accurate              case ::gig::attenuation_ctrl_t::type_controlchange: //FIXME: currently not sample accurate
127                  CrossfadeVolume = CrossfadeAttenuation(pEngineChannel->ControllerTable[pDimRgn->AttenuationController.controller_number]);                  crossfadeVolume = Engine::CrossfadeCurve[CrossfadeAttenuation(pEngineChannel->ControllerTable[pDimRgn->AttenuationController.controller_number])];
128                  break;                  break;
129              case ::gig::attenuation_ctrl_t::type_none: // no crossfade defined              case ::gig::attenuation_ctrl_t::type_none: // no crossfade defined
130              default:              default:
131                  CrossfadeVolume = 1.0f;                  crossfadeVolume = 1.0f;
132          }          }
133    
134          PanLeft  = 1.0f - float(RTMath::Max(pDimRgn->Pan, 0)) /  63.0f;          VolumeLeft  = volume * Engine::PanCurve[64 - pDimRgn->Pan];
135          PanRight = 1.0f - float(RTMath::Min(pDimRgn->Pan, 0)) / -64.0f;          VolumeRight = volume * Engine::PanCurve[64 + pDimRgn->Pan];
136    
137          Pos = pDimRgn->SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)          float subfragmentRate = pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;
138            CrossfadeSmoother.trigger(crossfadeVolume, subfragmentRate);
139            VolumeSmoother.trigger(pEngineChannel->GlobalVolume, subfragmentRate);
140            PanLeftSmoother.trigger(pEngineChannel->GlobalPanLeft, subfragmentRate);
141            PanRightSmoother.trigger(pEngineChannel->GlobalPanRight, subfragmentRate);
142    
143            finalSynthesisParameters.dPos = pDimRgn->SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)
144            Pos = pDimRgn->SampleStartOffset;
145    
146          // 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
147          long cachedsamples = pSample->GetCache().Size / pSample->FrameSize;          long cachedsamples = pSample->GetCache().Size / pSample->FrameSize;
148          DiskVoice          = cachedsamples < pSample->SamplesTotal;          DiskVoice          = cachedsamples < pSample->SamplesTotal;
149    
150            const DLS::sample_loop_t& loopinfo = pDimRgn->pSampleLoops[0];
151    
152          if (DiskVoice) { // voice to be streamed from disk          if (DiskVoice) { // voice to be streamed from disk
153              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)
154    
155              // 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
156              if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) {              RAMLoop = (pDimRgn->SampleLoops && (loopinfo.LoopStart + loopinfo.LoopLength) <= MaxRAMPos);
                 RAMLoop        = true;  
                 LoopCyclesLeft = pSample->LoopPlayCount;  
             }  
             else RAMLoop = false;  
157    
158              if (pDiskThread->OrderNewStream(&DiskStreamRef, pSample, MaxRAMPos, !RAMLoop) < 0) {              if (pDiskThread->OrderNewStream(&DiskStreamRef, pDimRgn, MaxRAMPos, !RAMLoop) < 0) {
159                  dmsg(1,("Disk stream order failed!\n"));                  dmsg(1,("Disk stream order failed!\n"));
160                  KillImmediately();                  KillImmediately();
161                  return -1;                  return -1;
# Line 163  namespace LinuxSampler { namespace gig { Line 164  namespace LinuxSampler { namespace gig {
164          }          }
165          else { // RAM only voice          else { // RAM only voice
166              MaxRAMPos = cachedsamples;              MaxRAMPos = cachedsamples;
167              if (pSample->Loops) {              RAMLoop = (pDimRgn->SampleLoops != 0);
                 RAMLoop        = true;  
                 LoopCyclesLeft = pSample->LoopPlayCount;  
             }  
             else RAMLoop = false;  
168              dmsg(4,("RAM only voice launched (Looping: %s)\n", (RAMLoop) ? "yes" : "no"));              dmsg(4,("RAM only voice launched (Looping: %s)\n", (RAMLoop) ? "yes" : "no"));
169          }          }
170            if (RAMLoop) {
171                loop.uiTotalCycles = pSample->LoopPlayCount;
172                loop.uiCyclesLeft  = pSample->LoopPlayCount;
173                loop.uiStart       = loopinfo.LoopStart;
174                loop.uiEnd         = loopinfo.LoopStart + loopinfo.LoopLength;
175                loop.uiSize        = loopinfo.LoopLength;
176            }
177    
178          // calculate initial pitch value          // calculate initial pitch value
179          {          {
# Line 214  namespace LinuxSampler { namespace gig { Line 217  namespace LinuxSampler { namespace gig {
217              EG1.trigger(pDimRgn->EG1PreAttack,              EG1.trigger(pDimRgn->EG1PreAttack,
218                          pDimRgn->EG1Attack * eg1attack,                          pDimRgn->EG1Attack * eg1attack,
219                          pDimRgn->EG1Hold,                          pDimRgn->EG1Hold,
                         pSample->LoopStart,  
220                          pDimRgn->EG1Decay1 * eg1decay * velrelease,                          pDimRgn->EG1Decay1 * eg1decay * velrelease,
221                          pDimRgn->EG1Decay2 * eg1decay * velrelease,                          pDimRgn->EG1Decay2 * eg1decay * velrelease,
222                          pDimRgn->EG1InfiniteSustain,                          pDimRgn->EG1InfiniteSustain,
# Line 224  namespace LinuxSampler { namespace gig { Line 226  namespace LinuxSampler { namespace gig {
226                          pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                          pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
227          }          }
228    
229    #ifdef CONFIG_INTERPOLATE_VOLUME
230            // setup initial volume in synthesis parameters
231    #ifdef CONFIG_PROCESS_MUTED_CHANNELS
232            if (pEngineChannel->GetMute()) {
233                finalSynthesisParameters.fFinalVolumeLeft  = 0;
234                finalSynthesisParameters.fFinalVolumeRight = 0;
235            }
236            else
237    #else
238            {
239                float finalVolume = pEngineChannel->GlobalVolume * crossfadeVolume * EG1.getLevel();
240    
241                finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * pEngineChannel->GlobalPanLeft;
242                finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * pEngineChannel->GlobalPanRight;
243            }
244    #endif
245    #endif
246    
247          // setup EG 2 (VCF Cutoff EG)          // setup EG 2 (VCF Cutoff EG)
248          {          {
# Line 253  namespace LinuxSampler { namespace gig { Line 272  namespace LinuxSampler { namespace gig {
272              EG2.trigger(pDimRgn->EG2PreAttack,              EG2.trigger(pDimRgn->EG2PreAttack,
273                          pDimRgn->EG2Attack * eg2attack,                          pDimRgn->EG2Attack * eg2attack,
274                          false,                          false,
                         pSample->LoopStart,  
275                          pDimRgn->EG2Decay1 * eg2decay * velrelease,                          pDimRgn->EG2Decay1 * eg2decay * velrelease,
276                          pDimRgn->EG2Decay2 * eg2decay * velrelease,                          pDimRgn->EG2Decay2 * eg2decay * velrelease,
277                          pDimRgn->EG2InfiniteSustain,                          pDimRgn->EG2InfiniteSustain,
# Line 266  namespace LinuxSampler { namespace gig { Line 284  namespace LinuxSampler { namespace gig {
284    
285          // setup EG 3 (VCO EG)          // setup EG 3 (VCO EG)
286          {          {
287            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
288            EG3.trigger(eg3depth, pDimRgn->EG3Attack, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);              bool  bPortamento = pEngineChannel->PortamentoMode && pEngineChannel->PortamentoPos >= 0.0f;
289                float eg3depth = (bPortamento)
290                                     ? RTMath::CentsToFreqRatio((pEngineChannel->PortamentoPos - (float) MIDIKey) * 100)
291                                     : RTMath::CentsToFreqRatio(pDimRgn->EG3Depth);
292                float eg3time = (bPortamento)
293                                    ? pEngineChannel->PortamentoTime
294                                    : pDimRgn->EG3Attack;
295                EG3.trigger(eg3depth, eg3time, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
296                dmsg(5,("PortamentoPos=%f, depth=%f, time=%f\n", pEngineChannel->PortamentoPos, eg3depth, eg3time));
297          }          }
298    
299    
# Line 305  namespace LinuxSampler { namespace gig { Line 331  namespace LinuxSampler { namespace gig {
331                      pLFO1->ExtController = 0; // no external controller                      pLFO1->ExtController = 0; // no external controller
332                      bLFO1Enabled         = false;                      bLFO1Enabled         = false;
333              }              }
334              if (bLFO1Enabled) pLFO1->trigger(pDimRgn->LFO1Frequency,              if (bLFO1Enabled) {
335                                               start_level_max,                  pLFO1->trigger(pDimRgn->LFO1Frequency,
336                                               lfo1_internal_depth,                                 start_level_max,
337                                               pDimRgn->LFO1ControlDepth,                                 lfo1_internal_depth,
338                                               pDimRgn->LFO1FlipPhase,                                 pDimRgn->LFO1ControlDepth,
339                                               pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                                 pDimRgn->LFO1FlipPhase,
340                                   pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
341                    pLFO1->update(pLFO1->ExtController ? pEngineChannel->ControllerTable[pLFO1->ExtController] : 0);
342                }
343          }          }
344    
345    
# Line 348  namespace LinuxSampler { namespace gig { Line 377  namespace LinuxSampler { namespace gig {
377                      pLFO2->ExtController = 0; // no external controller                      pLFO2->ExtController = 0; // no external controller
378                      bLFO2Enabled         = false;                      bLFO2Enabled         = false;
379              }              }
380              if (bLFO2Enabled) pLFO2->trigger(pDimRgn->LFO2Frequency,              if (bLFO2Enabled) {
381                                               start_level_max,                  pLFO2->trigger(pDimRgn->LFO2Frequency,
382                                               lfo2_internal_depth,                                 start_level_max,
383                                               pDimRgn->LFO2ControlDepth,                                 lfo2_internal_depth,
384                                               pDimRgn->LFO2FlipPhase,                                 pDimRgn->LFO2ControlDepth,
385                                               pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                                 pDimRgn->LFO2FlipPhase,
386                                   pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
387                    pLFO2->update(pLFO2->ExtController ? pEngineChannel->ControllerTable[pLFO2->ExtController] : 0);
388                }
389          }          }
390    
391    
# Line 391  namespace LinuxSampler { namespace gig { Line 423  namespace LinuxSampler { namespace gig {
423                      pLFO3->ExtController = 0; // no external controller                      pLFO3->ExtController = 0; // no external controller
424                      bLFO3Enabled         = false;                      bLFO3Enabled         = false;
425              }              }
426              if (bLFO3Enabled) pLFO3->trigger(pDimRgn->LFO3Frequency,              if (bLFO3Enabled) {
427                                               start_level_mid,                  pLFO3->trigger(pDimRgn->LFO3Frequency,
428                                               lfo3_internal_depth,                                 start_level_mid,
429                                               pDimRgn->LFO3ControlDepth,                                 lfo3_internal_depth,
430                                               false,                                 pDimRgn->LFO3ControlDepth,
431                                               pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                                 false,
432                                   pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
433                    pLFO3->update(pLFO3->ExtController ? pEngineChannel->ControllerTable[pLFO3->ExtController] : 0);
434                }
435          }          }
436    
437    
# Line 469  namespace LinuxSampler { namespace gig { Line 504  namespace LinuxSampler { namespace gig {
504              #endif // CONFIG_OVERRIDE_RESONANCE_CTRL              #endif // CONFIG_OVERRIDE_RESONANCE_CTRL
505    
506              #ifndef CONFIG_OVERRIDE_FILTER_TYPE              #ifndef CONFIG_OVERRIDE_FILTER_TYPE
507              FilterLeft.SetType(pDimRgn->VCFType);              finalSynthesisParameters.filterLeft.SetType(pDimRgn->VCFType);
508              FilterRight.SetType(pDimRgn->VCFType);              finalSynthesisParameters.filterRight.SetType(pDimRgn->VCFType);
509              #else // override filter type              #else // override filter type
510              FilterLeft.SetType(CONFIG_OVERRIDE_FILTER_TYPE);              FilterLeft.SetType(CONFIG_OVERRIDE_FILTER_TYPE);
511              FilterRight.SetType(CONFIG_OVERRIDE_FILTER_TYPE);              FilterRight.SetType(CONFIG_OVERRIDE_FILTER_TYPE);
# Line 490  namespace LinuxSampler { namespace gig { Line 525  namespace LinuxSampler { namespace gig {
525              if (VCFCutoffCtrl.controller) {              if (VCFCutoffCtrl.controller) {
526                  cvalue = pEngineChannel->ControllerTable[VCFCutoffCtrl.controller];                  cvalue = pEngineChannel->ControllerTable[VCFCutoffCtrl.controller];
527                  if (pDimRgn->VCFCutoffControllerInvert) cvalue = 127 - cvalue;                  if (pDimRgn->VCFCutoffControllerInvert) cvalue = 127 - cvalue;
528                    // VCFVelocityScale in this case means Minimum cutoff
529                  if (cvalue < pDimRgn->VCFVelocityScale) cvalue = pDimRgn->VCFVelocityScale;                  if (cvalue < pDimRgn->VCFVelocityScale) cvalue = pDimRgn->VCFVelocityScale;
530              }              }
531              else {              else {
532                  cvalue = pDimRgn->VCFCutoff;                  cvalue = pDimRgn->VCFCutoff;
533              }              }
534              cutoff *= float(cvalue) * 0.00787402f; // (1 / 127)              cutoff *= float(cvalue);
535              if (cutoff > 1.0) cutoff = 1.0;              if (cutoff > 127.0f) cutoff = 127.0f;
             cutoff = exp(cutoff * FILTER_CUTOFF_COEFF) * CONFIG_FILTER_CUTOFF_MIN;  
536    
537              // calculate resonance              // calculate resonance
538              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)  
539    
540              VCFCutoffCtrl.fvalue    = cutoff - CONFIG_FILTER_CUTOFF_MIN;              VCFCutoffCtrl.fvalue    = cutoff;
541              VCFResonanceCtrl.fvalue = resonance;              VCFResonanceCtrl.fvalue = resonance;
542          }          }
543          else {          else {
# Line 547  namespace LinuxSampler { namespace gig { Line 578  namespace LinuxSampler { namespace gig {
578    
579                      if (DiskVoice) {                      if (DiskVoice) {
580                          // check if we reached the allowed limit of the sample RAM cache                          // check if we reached the allowed limit of the sample RAM cache
581                          if (Pos > MaxRAMPos) {                          if (finalSynthesisParameters.dPos > MaxRAMPos) {
582                              dmsg(5,("Voice: switching to disk playback (Pos=%f)\n", Pos));                              dmsg(5,("Voice: switching to disk playback (Pos=%f)\n", finalSynthesisParameters.dPos));
583                              this->PlaybackState = playback_state_disk;                              this->PlaybackState = playback_state_disk;
584                          }                          }
585                      }                      } else if (finalSynthesisParameters.dPos >= pSample->GetCache().Size / pSample->FrameSize) {
                     else if (Pos >= pSample->GetCache().Size / pSample->FrameSize) {  
586                          this->PlaybackState = playback_state_end;                          this->PlaybackState = playback_state_end;
587                      }                      }
588                  }                  }
# Line 567  namespace LinuxSampler { namespace gig { Line 597  namespace LinuxSampler { namespace gig {
597                              KillImmediately();                              KillImmediately();
598                              return;                              return;
599                          }                          }
600                          DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (int(Pos) - MaxRAMPos));                          DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (int(finalSynthesisParameters.dPos) - MaxRAMPos));
601                          Pos -= int(Pos);                          finalSynthesisParameters.dPos -= int(finalSynthesisParameters.dPos);
602                          RealSampleWordsLeftToRead = -1; // -1 means no silence has been added yet                          RealSampleWordsLeftToRead = -1; // -1 means no silence has been added yet
603                      }                      }
604    
# Line 589  namespace LinuxSampler { namespace gig { Line 619  namespace LinuxSampler { namespace gig {
619                      // render current audio fragment                      // render current audio fragment
620                      Synthesize(Samples, ptr, Delay);                      Synthesize(Samples, ptr, Delay);
621    
622                      const int iPos = (int) Pos;                      const int iPos = (int) finalSynthesisParameters.dPos;
623                      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
624                      DiskStreamRef.pStream->IncrementReadPos(readSampleWords);                      DiskStreamRef.pStream->IncrementReadPos(readSampleWords);
625                      Pos -= iPos; // just keep fractional part of Pos                      finalSynthesisParameters.dPos -= iPos; // just keep fractional part of playback position
626    
627                      // 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
628                      if (RealSampleWordsLeftToRead >= 0) {                      if (RealSampleWordsLeftToRead >= 0) {
# Line 607  namespace LinuxSampler { namespace gig { Line 637  namespace LinuxSampler { namespace gig {
637                  break;                  break;
638          }          }
639    
         // Reset synthesis event lists  
         pEngineChannel->pEvents->clear();  
   
640          // Reset delay          // Reset delay
641          Delay = 0;          Delay = 0;
642    
# Line 624  namespace LinuxSampler { namespace gig { Line 651  namespace LinuxSampler { namespace gig {
651       *  suspended / not running.       *  suspended / not running.
652       */       */
653      void Voice::Reset() {      void Voice::Reset() {
654          FilterLeft.Reset();          finalSynthesisParameters.filterLeft.Reset();
655          FilterRight.Reset();          finalSynthesisParameters.filterRight.Reset();
656          DiskStreamRef.pStream = NULL;          DiskStreamRef.pStream = NULL;
657          DiskStreamRef.hStream = 0;          DiskStreamRef.hStream = 0;
658          DiskStreamRef.State   = Stream::state_unused;          DiskStreamRef.State   = Stream::state_unused;
# Line 640  namespace LinuxSampler { namespace gig { Line 667  namespace LinuxSampler { namespace gig {
667       * for the given time.       * for the given time.
668       *       *
669       * @param itEvent - iterator pointing to the next event to be processed       * @param itEvent - iterator pointing to the next event to be processed
670       * @param End     - youngest time stamp where processing should be stopped       * @param End     - youngest time stamp where processing should be stopped
671       */       */
672      void Voice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) {      void Voice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) {
673          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
674              if (itEvent->Type == Event::type_release) {              if (itEvent->Type == Event::type_release) {
675                  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);
676                  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);
677              } else if (itEvent->Type == Event::type_cancel_release) {              } else if (itEvent->Type == Event::type_cancel_release) {
678                  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);
679                  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);
680              }              }
681          }          }
682      }      }
# Line 659  namespace LinuxSampler { namespace gig { Line 686  namespace LinuxSampler { namespace gig {
686       * the given time.       * the given time.
687       *       *
688       * @param itEvent - iterator pointing to the next event to be processed       * @param itEvent - iterator pointing to the next event to be processed
689       * @param End     - youngest time stamp where processing should be stopped       * @param End     - youngest time stamp where processing should be stopped
690       */       */
691      void Voice::processCCEvents(RTList<Event>::Iterator& itEvent, uint End) {      void Voice::processCCEvents(RTList<Event>::Iterator& itEvent, uint End) {
692          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
# Line 682  namespace LinuxSampler { namespace gig { Line 709  namespace LinuxSampler { namespace gig {
709                  }                  }
710                  if (pDimRgn->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange &&                  if (pDimRgn->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange &&
711                      itEvent->Param.CC.Controller == pDimRgn->AttenuationController.controller_number) {                      itEvent->Param.CC.Controller == pDimRgn->AttenuationController.controller_number) {
712                      processCrossFadeEvent(itEvent);                      CrossfadeSmoother.update(Engine::CrossfadeCurve[CrossfadeAttenuation(itEvent->Param.CC.Value)]);
713                    }
714                    if (itEvent->Param.CC.Controller == 7) { // volume
715                        VolumeSmoother.update(Engine::VolumeCurve[itEvent->Param.CC.Value] * CONFIG_GLOBAL_ATTENUATION);
716                    } else if (itEvent->Param.CC.Controller == 10) { // panpot
717                        PanLeftSmoother.update(Engine::PanCurve[128 - itEvent->Param.CC.Value]);
718                        PanRightSmoother.update(Engine::PanCurve[itEvent->Param.CC.Value]);
719                  }                  }
720              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event
721                  processPitchEvent(itEvent);                  processPitchEvent(itEvent);
# Line 692  namespace LinuxSampler { namespace gig { Line 725  namespace LinuxSampler { namespace gig {
725    
726      void Voice::processPitchEvent(RTList<Event>::Iterator& itEvent) {      void Voice::processPitchEvent(RTList<Event>::Iterator& itEvent) {
727          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
728          fFinalPitch *= pitch;          finalSynthesisParameters.fFinalPitch *= pitch;
729      }          PitchBend = 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;  
730      }      }
731    
732      void Voice::processCutoffEvent(RTList<Event>::Iterator& itEvent) {      void Voice::processCutoffEvent(RTList<Event>::Iterator& itEvent) {
# Line 711  namespace LinuxSampler { namespace gig { Line 735  namespace LinuxSampler { namespace gig {
735          VCFCutoffCtrl.value == ccvalue;          VCFCutoffCtrl.value == ccvalue;
736          if (pDimRgn->VCFCutoffControllerInvert)  ccvalue = 127 - ccvalue;          if (pDimRgn->VCFCutoffControllerInvert)  ccvalue = 127 - ccvalue;
737          if (ccvalue < pDimRgn->VCFVelocityScale) ccvalue = pDimRgn->VCFVelocityScale;          if (ccvalue < pDimRgn->VCFVelocityScale) ccvalue = pDimRgn->VCFVelocityScale;
738          float cutoff = CutoffBase * float(ccvalue) * 0.00787402f; // (1 / 127)          float cutoff = CutoffBase * float(ccvalue);
739          if (cutoff > 1.0) cutoff = 1.0;          if (cutoff > 127.0f) cutoff = 127.0f;
740          cutoff = exp(cutoff * FILTER_CUTOFF_COEFF) * CONFIG_FILTER_CUTOFF_MIN - CONFIG_FILTER_CUTOFF_MIN;  
741          VCFCutoffCtrl.fvalue = cutoff; // needed for initialization of fFinalCutoff next time          VCFCutoffCtrl.fvalue = cutoff; // needed for initialization of fFinalCutoff next time
742          fFinalCutoff = cutoff;          fFinalCutoff = cutoff;
743      }      }
# Line 722  namespace LinuxSampler { namespace gig { Line 746  namespace LinuxSampler { namespace gig {
746          // convert absolute controller value to differential          // convert absolute controller value to differential
747          const int ctrldelta = itEvent->Param.CC.Value - VCFResonanceCtrl.value;          const int ctrldelta = itEvent->Param.CC.Value - VCFResonanceCtrl.value;
748          VCFResonanceCtrl.value = itEvent->Param.CC.Value;          VCFResonanceCtrl.value = itEvent->Param.CC.Value;
749          const float resonancedelta = (float) ctrldelta * 0.00787f; // 0.0..1.0          const float resonancedelta = (float) ctrldelta;
750          fFinalResonance += resonancedelta;          fFinalResonance += resonancedelta;
751          // needed for initialization of parameter          // needed for initialization of parameter
752          VCFResonanceCtrl.fvalue = itEvent->Param.CC.Value * 0.00787f;          VCFResonanceCtrl.fvalue = itEvent->Param.CC.Value;
753      }      }
754    
755      /**      /**
# Line 737  namespace LinuxSampler { namespace gig { Line 761  namespace LinuxSampler { namespace gig {
761       *  @param Skip    - number of sample points to skip in output buffer       *  @param Skip    - number of sample points to skip in output buffer
762       */       */
763      void Voice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {      void Voice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {
764            finalSynthesisParameters.pOutLeft  = &pEngineChannel->pOutputLeft[Skip];
765            finalSynthesisParameters.pOutRight = &pEngineChannel->pOutputRight[Skip];
766            finalSynthesisParameters.pSrc      = pSrc;
767    
768          RTList<Event>::Iterator itCCEvent = pEngineChannel->pEvents->first();          RTList<Event>::Iterator itCCEvent = pEngineChannel->pEvents->first();
769          RTList<Event>::Iterator itNoteEvent = pEngineChannel->pMIDIKeyInfo[MIDIKey].pEvents->first();          RTList<Event>::Iterator itNoteEvent = pEngineChannel->pMIDIKeyInfo[MIDIKey].pEvents->first();
770                    
771          if (Skip) { // skip events that happened before this voice was triggered          if (Skip) { // skip events that happened before this voice was triggered
772              while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;              while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;
773              while (itNoteEvent && itNoteEvent->FragmentPos() <= Skip) ++itNoteEvent;              while (itNoteEvent && itNoteEvent->FragmentPos() <= Skip) ++itNoteEvent;
774          }          }
775            
776            uint killPos;
777            if (itKillEvent) killPos = RTMath::Min(itKillEvent->FragmentPos(), pEngine->MaxFadeOutPos);
778    
779          uint i = Skip;          uint i = Skip;
780          while (i < Samples) {          while (i < Samples) {
781              int iSubFragmentEnd = RTMath::Min(i + CONFIG_DEFAULT_SUBFRAGMENT_SIZE, Samples);              int iSubFragmentEnd = RTMath::Min(i + CONFIG_DEFAULT_SUBFRAGMENT_SIZE, Samples);
782                
783              // initialize all final synthesis parameters              // initialize all final synthesis parameters
784              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  
785              fFinalCutoff    = VCFCutoffCtrl.fvalue;              fFinalCutoff    = VCFCutoffCtrl.fvalue;
786              fFinalResonance = VCFResonanceCtrl.fvalue;              fFinalResonance = VCFResonanceCtrl.fvalue;
787                
788              // process MIDI control change and pitchbend events for this subfragment              // process MIDI control change and pitchbend events for this subfragment
789              processCCEvents(itCCEvent, iSubFragmentEnd);              processCCEvents(itCCEvent, iSubFragmentEnd);
790    
791                float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render();
792    #ifdef CONFIG_PROCESS_MUTED_CHANNELS
793                if (pEngineChannel->GetMute()) fFinalVolume = 0;
794    #endif
795    
796              // process transition events (note on, note off & sustain pedal)              // process transition events (note on, note off & sustain pedal)
797              processTransitionEvents(itNoteEvent, iSubFragmentEnd);              processTransitionEvents(itNoteEvent, iSubFragmentEnd);
798                
799                // if the voice was killed in this subfragment switch EG1 to fade out stage
800                if (itKillEvent && killPos <= iSubFragmentEnd) {
801                    EG1.enterFadeOutStage();
802                    itKillEvent = Pool<Event>::Iterator();
803                }
804    
805              // process envelope generators              // process envelope generators
806              switch (EG1.getSegmentType()) {              switch (EG1.getSegmentType()) {
807                  case EGADSR::segment_lin:                  case EGADSR::segment_lin:
# Line 788  namespace LinuxSampler { namespace gig { Line 825  namespace LinuxSampler { namespace gig {
825                      fFinalCutoff *= EG2.getLevel();                      fFinalCutoff *= EG2.getLevel();
826                      break; // noop                      break; // noop
827              }              }
828              fFinalPitch *= RTMath::CentsToFreqRatio(EG3.render());              if (EG3.active()) finalSynthesisParameters.fFinalPitch *= EG3.render();
829                
830              // process low frequency oscillators              // process low frequency oscillators
831              if (bLFO1Enabled) fFinalVolume *= pLFO1->render();              if (bLFO1Enabled) fFinalVolume *= pLFO1->render();
832              if (bLFO2Enabled) fFinalCutoff *= pLFO2->render();              if (bLFO2Enabled) fFinalCutoff *= pLFO2->render();
833              if (bLFO3Enabled) fFinalPitch  *= RTMath::CentsToFreqRatio(pLFO3->render());              if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());
834    
835              // if filter enabled then update filter coefficients              // if filter enabled then update filter coefficients
836              if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode)) {              if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode)) {
837                  FilterLeft.SetParameters(fFinalCutoff, fFinalResonance, pEngine->SampleRate);                  finalSynthesisParameters.filterLeft.SetParameters(fFinalCutoff, fFinalResonance, pEngine->SampleRate);
838                  FilterRight.SetParameters(fFinalCutoff, fFinalResonance, pEngine->SampleRate);                  finalSynthesisParameters.filterRight.SetParameters(fFinalCutoff, fFinalResonance, pEngine->SampleRate);
839              }              }
840    
841              // how many steps do we calculate for this next subfragment              // do we need resampling?
842              const int steps = iSubFragmentEnd - i;              const float __PLUS_ONE_CENT  = 1.000577789506554859250142541782224725466f;
843                            const float __MINUS_ONE_CENT = 0.9994225441413807496009516495583113737666f;
844              // select the appropriate synthesis mode              const bool bResamplingRequired = !(finalSynthesisParameters.fFinalPitch <= __PLUS_ONE_CENT &&
845              SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, fFinalPitch != 1.0f);                                                 finalSynthesisParameters.fFinalPitch >= __MINUS_ONE_CENT);
846                            SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, bResamplingRequired);
847    
848                // prepare final synthesis parameters structure
849                finalSynthesisParameters.uiToGo            = iSubFragmentEnd - i;
850    #ifdef CONFIG_INTERPOLATE_VOLUME
851                finalSynthesisParameters.fFinalVolumeDeltaLeft  =
852                    (fFinalVolume * VolumeLeft  * PanLeftSmoother.render() -
853                     finalSynthesisParameters.fFinalVolumeLeft) / finalSynthesisParameters.uiToGo;
854                finalSynthesisParameters.fFinalVolumeDeltaRight =
855                    (fFinalVolume * VolumeRight * PanRightSmoother.render() -
856                     finalSynthesisParameters.fFinalVolumeRight) / finalSynthesisParameters.uiToGo;
857    #else
858                finalSynthesisParameters.fFinalVolumeLeft  =
859                    fFinalVolume * VolumeLeft  * PanLeftSmoother.render();
860                finalSynthesisParameters.fFinalVolumeRight =
861                    fFinalVolume * VolumeRight * PanRightSmoother.render();
862    #endif
863              // render audio for one subfragment              // render audio for one subfragment
864              RunSynthesisFunction(SynthesisMode, *this, iSubFragmentEnd, pSrc, i);              RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);
865    
866                // stop the rendering if volume EG is finished
867                if (EG1.getSegmentType() == EGADSR::segment_end) break;
868    
869                const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;
870    
871              // increment envelopes' positions                          // increment envelopes' positions
872              if (EG1.active()) {              if (EG1.active()) {
873                  EG1.increment(steps);  
874                  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
875                    if (pDimRgn->SampleLoops && Pos <= pDimRgn->pSampleLoops[0].LoopStart && pDimRgn->pSampleLoops[0].LoopStart < newPos) {
876                        EG1.update(EGADSR::event_hold_end, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
877                    }
878    
879                    EG1.increment(1);
880                    if (!EG1.toStageEndLeft()) EG1.update(EGADSR::event_stage_end, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
881              }              }
882              if (EG2.active()) {              if (EG2.active()) {
883                  EG2.increment(steps);                  EG2.increment(1);
884                  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);
885              }              }
886              EG3.increment(steps);              EG3.increment(1);
887              if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached              if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached
888    
889                Pos = newPos;
890                i = iSubFragmentEnd;
891          }          }
892      }      }
893    
894        /** @brief Update current portamento position.
895         *
896         * Will be called when portamento mode is enabled to get the final
897         * portamento position of this active voice from where the next voice(s)
898         * might continue to slide on.
899         *
900         * @param itNoteOffEvent - event which causes this voice to die soon
901         */
902        void Voice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {
903            const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());
904            pEngineChannel->PortamentoPos = (float) MIDIKey + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;
905        }
906    
907      /**      /**
908       *  Immediately kill the voice. This method should not be used to kill       *  Immediately kill the voice. This method should not be used to kill
909       *  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

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

  ViewVC Help
Powered by ViewVC