/[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 799 by persson, Sat Nov 5 10:59:37 2005 UTC revision 832 by persson, Sun Feb 5 10:24:05 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 104  namespace LinuxSampler { namespace gig { Line 104  namespace LinuxSampler { namespace gig {
104          // calculate volume          // calculate volume
105          const double velocityAttenuation = pDimRgn->GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity);          const double velocityAttenuation = pDimRgn->GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity);
106    
107          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)
108    
109          Volume *= pDimRgn->SampleAttenuation;          volume *= pDimRgn->SampleAttenuation;
110    
111          // the volume of release triggered samples depends on note length          // the volume of release triggered samples depends on note length
112          if (Type == type_release_trigger) {          if (Type == type_release_trigger) {
# Line 114  namespace LinuxSampler { namespace gig { Line 114  namespace LinuxSampler { namespace gig {
114                                       pEngineChannel->pMIDIKeyInfo[MIDIKey].NoteOnTime) / pEngine->SampleRate;                                       pEngineChannel->pMIDIKeyInfo[MIDIKey].NoteOnTime) / pEngine->SampleRate;
115              float attenuation = 1 - 0.01053 * (256 >> pDimRgn->ReleaseTriggerDecay) * noteLength;              float attenuation = 1 - 0.01053 * (256 >> pDimRgn->ReleaseTriggerDecay) * noteLength;
116              if (attenuation <= 0) return -1;              if (attenuation <= 0) return -1;
117              Volume *= attenuation;              volume *= attenuation;
118          }          }
119    
120          // select channel mode (mono or stereo)          // select channel mode (mono or stereo)
121          SYNTHESIS_MODE_SET_CHANNELS(SynthesisMode, pSample->Channels == 2);          SYNTHESIS_MODE_SET_CHANNELS(SynthesisMode, pSample->Channels == 2);
122    
123          // get starting crossfade volume level          // get starting crossfade volume level
124            float crossfadeVolume;
125          switch (pDimRgn->AttenuationController.type) {          switch (pDimRgn->AttenuationController.type) {
126              case ::gig::attenuation_ctrl_t::type_channelaftertouch:              case ::gig::attenuation_ctrl_t::type_channelaftertouch:
127                  CrossfadeVolume = 1.0f; //TODO: aftertouch not supported yet                  crossfadeVolume = 1.0f; //TODO: aftertouch not supported yet
128                  break;                  break;
129              case ::gig::attenuation_ctrl_t::type_velocity:              case ::gig::attenuation_ctrl_t::type_velocity:
130                  CrossfadeVolume = CrossfadeAttenuation(itNoteOnEvent->Param.Note.Velocity);                  crossfadeVolume = Engine::CrossfadeCurve[CrossfadeAttenuation(itNoteOnEvent->Param.Note.Velocity)];
131                  break;                  break;
132              case ::gig::attenuation_ctrl_t::type_controlchange: //FIXME: currently not sample accurate              case ::gig::attenuation_ctrl_t::type_controlchange: //FIXME: currently not sample accurate
133                  CrossfadeVolume = CrossfadeAttenuation(pEngineChannel->ControllerTable[pDimRgn->AttenuationController.controller_number]);                  crossfadeVolume = Engine::CrossfadeCurve[CrossfadeAttenuation(pEngineChannel->ControllerTable[pDimRgn->AttenuationController.controller_number])];
134                  break;                  break;
135              case ::gig::attenuation_ctrl_t::type_none: // no crossfade defined              case ::gig::attenuation_ctrl_t::type_none: // no crossfade defined
136              default:              default:
137                  CrossfadeVolume = 1.0f;                  crossfadeVolume = 1.0f;
138          }          }
139    
140          PanLeft  = 1.0f - float(RTMath::Max(pDimRgn->Pan, 0)) /  63.0f;          VolumeLeft  = volume * Engine::PanCurve[64 - pDimRgn->Pan];
141          PanRight = 1.0f - float(RTMath::Min(pDimRgn->Pan, 0)) / -64.0f;          VolumeRight = volume * Engine::PanCurve[64 + pDimRgn->Pan];
142    
143            float subfragmentRate = pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;
144            CrossfadeSmoother.trigger(crossfadeVolume, subfragmentRate);
145            VolumeSmoother.trigger(pEngineChannel->GlobalVolume, subfragmentRate);
146            PanLeftSmoother.trigger(pEngineChannel->GlobalPanLeft, subfragmentRate);
147            PanRightSmoother.trigger(pEngineChannel->GlobalPanRight, subfragmentRate);
148    
149          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)
150          Pos = pDimRgn->SampleStartOffset;          Pos = pDimRgn->SampleStartOffset;
# Line 223  namespace LinuxSampler { namespace gig { Line 230  namespace LinuxSampler { namespace gig {
230                          pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                          pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
231          }          }
232    
233    #ifdef CONFIG_INTERPOLATE_VOLUME
234            // setup initial volume in synthesis parameters
235    #ifdef CONFIG_PROCESS_MUTED_CHANNELS
236            if (pEngineChannel->GetMute()) {
237                finalSynthesisParameters.fFinalVolumeLeft  = 0;
238                finalSynthesisParameters.fFinalVolumeRight = 0;
239            }
240            else
241    #else
242            {
243                float finalVolume = pEngineChannel->GlobalVolume * crossfadeVolume * EG1.getLevel();
244    
245                finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * pEngineChannel->GlobalPanLeft;
246                finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * pEngineChannel->GlobalPanRight;
247            }
248    #endif
249    #endif
250    
251          // setup EG 2 (VCF Cutoff EG)          // setup EG 2 (VCF Cutoff EG)
252          {          {
# Line 264  namespace LinuxSampler { namespace gig { Line 288  namespace LinuxSampler { namespace gig {
288    
289          // setup EG 3 (VCO EG)          // setup EG 3 (VCO EG)
290          {          {
291            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
292            EG3.trigger(eg3depth, pDimRgn->EG3Attack, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);              bool  bPortamento = pEngineChannel->PortamentoMode && pEngineChannel->PortamentoPos >= 0.0f;
293                float eg3depth = (bPortamento)
294                                     ? RTMath::CentsToFreqRatio((pEngineChannel->PortamentoPos - (float) MIDIKey) * 100)
295                                     : RTMath::CentsToFreqRatio(pDimRgn->EG3Depth);
296                float eg3time = (bPortamento)
297                                    ? pEngineChannel->PortamentoTime
298                                    : pDimRgn->EG3Attack;
299                EG3.trigger(eg3depth, eg3time, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
300                dmsg(5,("PortamentoPos=%f, depth=%f, time=%f\n", pEngineChannel->PortamentoPos, eg3depth, eg3time));
301          }          }
302    
303    
# Line 632  namespace LinuxSampler { namespace gig { Line 664  namespace LinuxSampler { namespace gig {
664       * for the given time.       * for the given time.
665       *       *
666       * @param itEvent - iterator pointing to the next event to be processed       * @param itEvent - iterator pointing to the next event to be processed
667       * @param End     - youngest time stamp where processing should be stopped       * @param End     - youngest time stamp where processing should be stopped
668       */       */
669      void Voice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) {      void Voice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) {
670          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
# Line 651  namespace LinuxSampler { namespace gig { Line 683  namespace LinuxSampler { namespace gig {
683       * the given time.       * the given time.
684       *       *
685       * @param itEvent - iterator pointing to the next event to be processed       * @param itEvent - iterator pointing to the next event to be processed
686       * @param End     - youngest time stamp where processing should be stopped       * @param End     - youngest time stamp where processing should be stopped
687       */       */
688      void Voice::processCCEvents(RTList<Event>::Iterator& itEvent, uint End) {      void Voice::processCCEvents(RTList<Event>::Iterator& itEvent, uint End) {
689          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
# Line 674  namespace LinuxSampler { namespace gig { Line 706  namespace LinuxSampler { namespace gig {
706                  }                  }
707                  if (pDimRgn->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange &&                  if (pDimRgn->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange &&
708                      itEvent->Param.CC.Controller == pDimRgn->AttenuationController.controller_number) {                      itEvent->Param.CC.Controller == pDimRgn->AttenuationController.controller_number) {
709                      processCrossFadeEvent(itEvent);                      CrossfadeSmoother.update(Engine::CrossfadeCurve[CrossfadeAttenuation(itEvent->Param.CC.Value)]);
710                    }
711                    if (itEvent->Param.CC.Controller == 7) { // volume
712                        VolumeSmoother.update(Engine::VolumeCurve[itEvent->Param.CC.Value] * CONFIG_GLOBAL_ATTENUATION);
713                    } else if (itEvent->Param.CC.Controller == 10) { // panpot
714                        PanLeftSmoother.update(Engine::PanCurve[128 - itEvent->Param.CC.Value]);
715                        PanRightSmoother.update(Engine::PanCurve[itEvent->Param.CC.Value]);
716                  }                  }
717              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event
718                  processPitchEvent(itEvent);                  processPitchEvent(itEvent);
# Line 688  namespace LinuxSampler { namespace gig { Line 726  namespace LinuxSampler { namespace gig {
726          PitchBend = pitch;          PitchBend = pitch;
727      }      }
728    
     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;  
     }  
   
729      void Voice::processCutoffEvent(RTList<Event>::Iterator& itEvent) {      void Voice::processCutoffEvent(RTList<Event>::Iterator& itEvent) {
730          int ccvalue = itEvent->Param.CC.Value;          int ccvalue = itEvent->Param.CC.Value;
731          if (VCFCutoffCtrl.value == ccvalue) return;          if (VCFCutoffCtrl.value == ccvalue) return;
# Line 753  namespace LinuxSampler { namespace gig { Line 781  namespace LinuxSampler { namespace gig {
781    
782              // initialize all final synthesis parameters              // initialize all final synthesis parameters
783              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  
784              fFinalCutoff    = VCFCutoffCtrl.fvalue;              fFinalCutoff    = VCFCutoffCtrl.fvalue;
785              fFinalResonance = VCFResonanceCtrl.fvalue;              fFinalResonance = VCFResonanceCtrl.fvalue;
786    
787              // process MIDI control change and pitchbend events for this subfragment              // process MIDI control change and pitchbend events for this subfragment
788              processCCEvents(itCCEvent, iSubFragmentEnd);              processCCEvents(itCCEvent, iSubFragmentEnd);
789    
790                float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render();
791    #ifdef CONFIG_PROCESS_MUTED_CHANNELS
792                if (pEngineChannel->GetMute()) fFinalVolume = 0;
793    #endif
794    
795              // process transition events (note on, note off & sustain pedal)              // process transition events (note on, note off & sustain pedal)
796              processTransitionEvents(itNoteEvent, iSubFragmentEnd);              processTransitionEvents(itNoteEvent, iSubFragmentEnd);
797    
# Line 796  namespace LinuxSampler { namespace gig { Line 824  namespace LinuxSampler { namespace gig {
824                      fFinalCutoff *= EG2.getLevel();                      fFinalCutoff *= EG2.getLevel();
825                      break; // noop                      break; // noop
826              }              }
827              if (EG3.active()) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(EG3.render());              if (EG3.active()) finalSynthesisParameters.fFinalPitch *= EG3.render();
828    
829              // process low frequency oscillators              // process low frequency oscillators
830              if (bLFO1Enabled) fFinalVolume *= pLFO1->render();              if (bLFO1Enabled) fFinalVolume *= pLFO1->render();
# Line 817  namespace LinuxSampler { namespace gig { Line 845  namespace LinuxSampler { namespace gig {
845              SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, bResamplingRequired);              SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, bResamplingRequired);
846    
847              // prepare final synthesis parameters structure              // prepare final synthesis parameters structure
             finalSynthesisParameters.fFinalVolumeLeft  = fFinalVolume * PanLeft;  
             finalSynthesisParameters.fFinalVolumeRight = fFinalVolume * PanRight;  
848              finalSynthesisParameters.uiToGo            = iSubFragmentEnd - i;              finalSynthesisParameters.uiToGo            = iSubFragmentEnd - i;
849    #ifdef CONFIG_INTERPOLATE_VOLUME
850                finalSynthesisParameters.fFinalVolumeDeltaLeft  =
851                    (fFinalVolume * VolumeLeft  * PanLeftSmoother.render() -
852                     finalSynthesisParameters.fFinalVolumeLeft) / finalSynthesisParameters.uiToGo;
853                finalSynthesisParameters.fFinalVolumeDeltaRight =
854                    (fFinalVolume * VolumeRight * PanRightSmoother.render() -
855                     finalSynthesisParameters.fFinalVolumeRight) / finalSynthesisParameters.uiToGo;
856    #else
857                finalSynthesisParameters.fFinalVolumeLeft  =
858                    fFinalVolume * VolumeLeft  * PanLeftSmoother.render();
859                finalSynthesisParameters.fFinalVolumeRight =
860                    fFinalVolume * VolumeRight * PanRightSmoother.render();
861    #endif
862              // render audio for one subfragment              // render audio for one subfragment
863              RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);              RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);
864    
865                // stop the rendering if volume EG is finished
866                if (EG1.getSegmentType() == EGADSR::segment_end) break;
867    
868              const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;              const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;
869    
870              // increment envelopes' positions              // increment envelopes' positions
# Line 849  namespace LinuxSampler { namespace gig { Line 890  namespace LinuxSampler { namespace gig {
890          }          }
891      }      }
892    
893        /** @brief Update current portamento position.
894         *
895         * Will be called when portamento mode is enabled to get the final
896         * portamento position of this active voice from where the next voice(s)
897         * might continue to slide on.
898         *
899         * @param itNoteOffEvent - event which causes this voice to die soon
900         */
901        void Voice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {
902            const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());
903            pEngineChannel->PortamentoPos = (float) MIDIKey + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;
904        }
905    
906      /**      /**
907       *  Immediately kill the voice. This method should not be used to kill       *  Immediately kill the voice. This method should not be used to kill
908       *  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.799  
changed lines
  Added in v.832

  ViewVC Help
Powered by ViewVC