/[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 796 by persson, Sun Oct 30 08:35:13 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 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 104  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 114  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            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)          finalSynthesisParameters.dPos = pDimRgn->SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)
144          Pos = pDimRgn->SampleStartOffset;          Pos = pDimRgn->SampleStartOffset;
# Line 146  namespace LinuxSampler { namespace gig { Line 147  namespace LinuxSampler { namespace gig {
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;  
                 loop.uiTotalCycles = pSample->LoopPlayCount;  
                 loop.uiCyclesLeft  = pSample->LoopPlayCount;  
                 loop.uiStart       = pSample->LoopStart;  
                 loop.uiEnd         = pSample->LoopEnd;  
                 loop.uiSize        = pSample->LoopSize;  
             }  
             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 169  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;  
                 loop.uiCyclesLeft = 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 229  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 270  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 309  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 352  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 395  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 500  namespace LinuxSampler { namespace gig { Line 531  namespace LinuxSampler { namespace gig {
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 = (cutoff < 0.5 ? cutoff * 4826 - 1 : cutoff * 5715 - 449);  
             if (cutoff < 1.0) cutoff = 1.0;  
536    
537              // calculate resonance              // calculate resonance
538              float resonance = (float) (VCFResonanceCtrl.controller ? VCFResonanceCtrl.value : pDimRgn->VCFResonance) * 0.00787f; // 0.0..1.0              float resonance = (float) (VCFResonanceCtrl.controller ? VCFResonanceCtrl.value : pDimRgn->VCFResonance);
539    
540              VCFCutoffCtrl.fvalue    = cutoff - 1.0;              VCFCutoffCtrl.fvalue    = cutoff;
541              VCFResonanceCtrl.fvalue = resonance;              VCFResonanceCtrl.fvalue = resonance;
542          }          }
543          else {          else {
# Line 638  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) {
# Line 657  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 680  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 694  namespace LinuxSampler { namespace gig { Line 729  namespace LinuxSampler { namespace gig {
729          PitchBend = pitch;          PitchBend = pitch;
730      }      }
731    
     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;  
     }  
   
732      void Voice::processCutoffEvent(RTList<Event>::Iterator& itEvent) {      void Voice::processCutoffEvent(RTList<Event>::Iterator& itEvent) {
733          int ccvalue = itEvent->Param.CC.Value;          int ccvalue = itEvent->Param.CC.Value;
734          if (VCFCutoffCtrl.value == ccvalue) return;          if (VCFCutoffCtrl.value == ccvalue) return;
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;
         cutoff = (cutoff < 0.5 ? cutoff * 4826 - 1 : cutoff * 5715 - 449);  
         if (cutoff < 1.0) cutoff = 1.0;  
740    
741          VCFCutoffCtrl.fvalue = cutoff - 1.0; // needed for initialization of fFinalCutoff next time          VCFCutoffCtrl.fvalue = cutoff; // needed for initialization of fFinalCutoff next time
742          fFinalCutoff = cutoff;          fFinalCutoff = cutoff;
743      }      }
744    
# Line 723  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 759  namespace LinuxSampler { namespace gig { Line 782  namespace LinuxSampler { namespace gig {
782    
783              // initialize all final synthesis parameters              // initialize all final synthesis parameters
784              finalSynthesisParameters.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    
# Line 802  namespace LinuxSampler { namespace gig { Line 825  namespace LinuxSampler { namespace gig {
825                      fFinalCutoff *= EG2.getLevel();                      fFinalCutoff *= EG2.getLevel();
826                      break; // noop                      break; // noop
827              }              }
828              if (EG3.active()) finalSynthesisParameters.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();
# Line 811  namespace LinuxSampler { namespace gig { Line 834  namespace LinuxSampler { namespace gig {
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                  finalSynthesisParameters.filterLeft.SetParameters(fFinalCutoff + 1.0, fFinalResonance, pEngine->SampleRate);                  finalSynthesisParameters.filterLeft.SetParameters(fFinalCutoff, fFinalResonance, pEngine->SampleRate);
838                  finalSynthesisParameters.filterRight.SetParameters(fFinalCutoff + 1.0, fFinalResonance, pEngine->SampleRate);                  finalSynthesisParameters.filterRight.SetParameters(fFinalCutoff, fFinalResonance, pEngine->SampleRate);
839              }              }
840    
841              // do we need resampling?              // do we need resampling?
# Line 823  namespace LinuxSampler { namespace gig { Line 846  namespace LinuxSampler { namespace gig {
846              SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, bResamplingRequired);              SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, bResamplingRequired);
847    
848              // prepare final synthesis parameters structure              // prepare final synthesis parameters structure
             finalSynthesisParameters.fFinalVolumeLeft  = fFinalVolume * PanLeft;  
             finalSynthesisParameters.fFinalVolumeRight = fFinalVolume * PanRight;  
849              finalSynthesisParameters.uiToGo            = iSubFragmentEnd - i;              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, &finalSynthesisParameters, &loop);              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;              const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;
870    
871              // increment envelopes' positions              // increment envelopes' positions
872              if (EG1.active()) {              if (EG1.active()) {
873    
874                  // 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
875                  if (pSample->Loops && Pos <= pSample->LoopStart && pSample->LoopStart < newPos) {                  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);                      EG1.update(EGADSR::event_hold_end, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
877                  }                  }
878    
# Line 855  namespace LinuxSampler { namespace gig { Line 891  namespace LinuxSampler { namespace gig {
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.796  
changed lines
  Added in v.877

  ViewVC Help
Powered by ViewVC