/[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 841 by persson, Sat Mar 4 16:23:53 2006 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, 2006 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 29  Line 29 
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 44  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);
# Line 85  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 104  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          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)          // 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 119  namespace LinuxSampler { namespace gig { Line 117  namespace LinuxSampler { namespace gig {
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;          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 = Engine::CrossfadeCurve[CrossfadeAttenuation(itNoteOnEvent->Param.Note.Velocity)];                  crossfadeVolume = Engine::CrossfadeCurve[CrossfadeAttenuation(itNoteOnEvent->Param.Note.Velocity)];
# Line 142  namespace LinuxSampler { namespace gig { Line 142  namespace LinuxSampler { namespace gig {
142    
143          float subfragmentRate = pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;          float subfragmentRate = pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;
144          CrossfadeSmoother.trigger(crossfadeVolume, subfragmentRate);          CrossfadeSmoother.trigger(crossfadeVolume, subfragmentRate);
145          VolumeSmoother.trigger(pEngineChannel->GlobalVolume, subfragmentRate);          VolumeSmoother.trigger(pEngineChannel->MidiVolume, subfragmentRate);
146          PanLeftSmoother.trigger(pEngineChannel->GlobalPanLeft, subfragmentRate);          PanLeftSmoother.trigger(pEngineChannel->GlobalPanLeft, subfragmentRate);
147          PanRightSmoother.trigger(pEngineChannel->GlobalPanRight, subfragmentRate);          PanRightSmoother.trigger(pEngineChannel->GlobalPanRight, subfragmentRate);
148    
# Line 153  namespace LinuxSampler { namespace gig { Line 153  namespace LinuxSampler { namespace gig {
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              RAMLoop = (pSample->Loops && pSample->LoopEnd <= MaxRAMPos);              RAMLoop = (pDimRgn->SampleLoops && (loopinfo.LoopStart + loopinfo.LoopLength) <= MaxRAMPos);
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 168  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              RAMLoop = (pSample->Loops != 0);              RAMLoop = (pDimRgn->SampleLoops != 0);
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) {          if (RAMLoop) {
177              loop.uiTotalCycles = pSample->LoopPlayCount;              loop.uiTotalCycles = pSample->LoopPlayCount;
178              loop.uiCyclesLeft  = pSample->LoopPlayCount;              loop.uiCyclesLeft  = pSample->LoopPlayCount;
179              loop.uiStart       = pSample->LoopStart;              loop.uiStart       = loopinfo.LoopStart;
180              loop.uiEnd         = pSample->LoopEnd;              loop.uiEnd         = loopinfo.LoopStart + loopinfo.LoopLength;
181              loop.uiSize        = pSample->LoopSize;              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 199  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 240  namespace LinuxSampler { namespace gig { Line 247  namespace LinuxSampler { namespace gig {
247          else          else
248  #else  #else
249          {          {
250              float finalVolume = pEngineChannel->GlobalVolume * crossfadeVolume * EG1.getLevel();              float finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * EG1.getLevel();
251    
252              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * pEngineChannel->GlobalPanLeft;              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * pEngineChannel->GlobalPanLeft;
253              finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * pEngineChannel->GlobalPanRight;              finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * pEngineChannel->GlobalPanRight;
# Line 257  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 337  namespace LinuxSampler { namespace gig { Line 344  namespace LinuxSampler { namespace gig {
344              }              }
345              if (bLFO1Enabled) {              if (bLFO1Enabled) {
346                  pLFO1->trigger(pDimRgn->LFO1Frequency,                  pLFO1->trigger(pDimRgn->LFO1Frequency,
347                                 start_level_max,                                 start_level_min,
348                                 lfo1_internal_depth,                                 lfo1_internal_depth,
349                                 pDimRgn->LFO1ControlDepth,                                 pDimRgn->LFO1ControlDepth,
350                                 pDimRgn->LFO1FlipPhase,                                 pDimRgn->LFO1FlipPhase,
# Line 409  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 419  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;
# Line 477  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 511  namespace LinuxSampler { namespace gig { Line 520  namespace LinuxSampler { namespace gig {
520              finalSynthesisParameters.filterLeft.SetType(pDimRgn->VCFType);              finalSynthesisParameters.filterLeft.SetType(pDimRgn->VCFType);
521              finalSynthesisParameters.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 535  namespace LinuxSampler { namespace gig { Line 544  namespace LinuxSampler { namespace gig {
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 = (cutoff < 0.5 ? cutoff * 4826 - 1 : cutoff * 5715 - 449);  
             if (cutoff < 1.0) cutoff = 1.0;  
549    
550              // calculate resonance              // calculate resonance
551              float resonance = (float) (VCFResonanceCtrl.controller ? VCFResonanceCtrl.value : pDimRgn->VCFResonance) * 0.00787f; // 0.0..1.0              float resonance = (float) (VCFResonanceCtrl.controller ? VCFResonanceCtrl.value : pDimRgn->VCFResonance);
552    
553              VCFCutoffCtrl.fvalue    = cutoff - 1.0;              VCFCutoffCtrl.fvalue    = cutoff;
554              VCFResonanceCtrl.fvalue = resonance;              VCFResonanceCtrl.fvalue = resonance;
555          }          }
556          else {          else {
# Line 620  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);
# Line 718  namespace LinuxSampler { namespace gig { Line 725  namespace LinuxSampler { namespace gig {
725                      CrossfadeSmoother.update(Engine::CrossfadeCurve[CrossfadeAttenuation(itEvent->Param.CC.Value)]);                      CrossfadeSmoother.update(Engine::CrossfadeCurve[CrossfadeAttenuation(itEvent->Param.CC.Value)]);
726                  }                  }
727                  if (itEvent->Param.CC.Controller == 7) { // volume                  if (itEvent->Param.CC.Controller == 7) { // volume
728                      VolumeSmoother.update(Engine::VolumeCurve[itEvent->Param.CC.Value] * CONFIG_GLOBAL_ATTENUATION);                      VolumeSmoother.update(Engine::VolumeCurve[itEvent->Param.CC.Value]);
729                  } else if (itEvent->Param.CC.Controller == 10) { // panpot                  } else if (itEvent->Param.CC.Controller == 10) { // panpot
730                      PanLeftSmoother.update(Engine::PanCurve[128 - itEvent->Param.CC.Value]);                      PanLeftSmoother.update(Engine::PanCurve[128 - itEvent->Param.CC.Value]);
731                      PanRightSmoother.update(Engine::PanCurve[itEvent->Param.CC.Value]);                      PanRightSmoother.update(Engine::PanCurve[itEvent->Param.CC.Value]);
# Line 730  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);
         finalSynthesisParameters.fFinalPitch *= pitch;  
         PitchBend = pitch;  
741      }      }
742    
743      void Voice::processCutoffEvent(RTList<Event>::Iterator& itEvent) {      void Voice::processCutoffEvent(RTList<Event>::Iterator& itEvent) {
# Line 741  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;
         cutoff = (cutoff < 0.5 ? cutoff * 4826 - 1 : cutoff * 5715 - 449);  
         if (cutoff < 1.0) cutoff = 1.0;  
751    
752          VCFCutoffCtrl.fvalue = cutoff - 1.0; // needed for initialization of fFinalCutoff next time          VCFCutoffCtrl.fvalue = cutoff; // needed for initialization of fFinalCutoff next time
753          fFinalCutoff = cutoff;          fFinalCutoff = cutoff;
754      }      }
755    
# Line 754  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 769  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->pOutputLeft[Skip];          finalSynthesisParameters.pOutLeft  = &pEngineChannel->pChannelLeft->Buffer()[Skip];
776          finalSynthesisParameters.pOutRight = &pEngineChannel->pOutputRight[Skip];          finalSynthesisParameters.pOutRight = &pEngineChannel->pChannelRight->Buffer()[Skip];
777          finalSynthesisParameters.pSrc      = pSrc;          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;          uint killPos;
796          if (itKillEvent) killPos = RTMath::Min(itKillEvent->FragmentPos(), pEngine->MaxFadeOutPos);          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
             finalSynthesisParameters.fFinalPitch = PitchBase * PitchBend;  
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();              float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render();
824  #ifdef CONFIG_PROCESS_MUTED_CHANNELS  #ifdef CONFIG_PROCESS_MUTED_CHANNELS
825              if (pEngineChannel->GetMute()) fFinalVolume = 0;              if (pEngineChannel->GetMute()) fFinalVolume = 0;
# Line 804  namespace LinuxSampler { namespace gig { Line 828  namespace LinuxSampler { namespace gig {
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 switch EG1 to fade out stage              // if the voice was killed in this subfragment, or if the
832              if (itKillEvent && killPos <= iSubFragmentEnd) {              // 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();                  EG1.enterFadeOutStage();
837                  itKillEvent = Pool<Event>::Iterator();                  itKillEvent = Pool<Event>::Iterator();
838              }              }
# Line 836  namespace LinuxSampler { namespace gig { Line 863  namespace LinuxSampler { namespace gig {
863              if (EG3.active()) finalSynthesisParameters.fFinalPitch *= 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) finalSynthesisParameters.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                  finalSynthesisParameters.filterLeft.SetParameters(fFinalCutoff + 1.0, fFinalResonance, pEngine->SampleRate);                  finalSynthesisParameters.filterLeft.SetParameters(fFinalCutoff, fFinalResonance, pEngine->SampleRate);
873                  finalSynthesisParameters.filterRight.SetParameters(fFinalCutoff + 1.0, fFinalResonance, pEngine->SampleRate);                  finalSynthesisParameters.filterRight.SetParameters(fFinalCutoff, fFinalResonance, pEngine->SampleRate);
874              }              }
875    
876              // do we need resampling?              // do we need resampling?
# Line 880  namespace LinuxSampler { namespace gig { Line 907  namespace LinuxSampler { namespace gig {
907              if (EG1.active()) {              if (EG1.active()) {
908    
909                  // 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                  // 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 (pSample->Loops && Pos <= pSample->LoopStart && pSample->LoopStart < newPos) {                  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);                      EG1.update(EGADSR::event_hold_end, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
912                  }                  }
913    
# Line 918  namespace LinuxSampler { namespace gig { Line 945  namespace LinuxSampler { namespace gig {
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.841  
changed lines
  Added in v.1858

  ViewVC Help
Powered by ViewVC