/[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 830 by persson, Sun Jan 15 18:23:11 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 150  namespace LinuxSampler { namespace gig { Line 150  namespace LinuxSampler { namespace gig {
150              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)
151    
152              // 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
153              if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) {              RAMLoop = (pSample->Loops && pSample->LoopEnd <= 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;  
154    
155              if (pDiskThread->OrderNewStream(&DiskStreamRef, pSample, MaxRAMPos, !RAMLoop) < 0) {              if (pDiskThread->OrderNewStream(&DiskStreamRef, pSample, MaxRAMPos, !RAMLoop) < 0) {
156                  dmsg(1,("Disk stream order failed!\n"));                  dmsg(1,("Disk stream order failed!\n"));
# Line 169  namespace LinuxSampler { namespace gig { Line 161  namespace LinuxSampler { namespace gig {
161          }          }
162          else { // RAM only voice          else { // RAM only voice
163              MaxRAMPos = cachedsamples;              MaxRAMPos = cachedsamples;
164              if (pSample->Loops) {              RAMLoop = (pSample->Loops != 0);
                 RAMLoop           = true;  
                 loop.uiCyclesLeft = pSample->LoopPlayCount;  
             }  
             else RAMLoop = false;  
165              dmsg(4,("RAM only voice launched (Looping: %s)\n", (RAMLoop) ? "yes" : "no"));              dmsg(4,("RAM only voice launched (Looping: %s)\n", (RAMLoop) ? "yes" : "no"));
166          }          }
167            if (RAMLoop) {
168                loop.uiTotalCycles = pSample->LoopPlayCount;
169                loop.uiCyclesLeft  = pSample->LoopPlayCount;
170                loop.uiStart       = pSample->LoopStart;
171                loop.uiEnd         = pSample->LoopEnd;
172                loop.uiSize        = pSample->LoopSize;
173            }
174    
175          // calculate initial pitch value          // calculate initial pitch value
176          {          {
# Line 229  namespace LinuxSampler { namespace gig { Line 223  namespace LinuxSampler { namespace gig {
223                          pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                          pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
224          }          }
225    
226            // setup initial volume in synthesis parameters
227            fFinalVolume = getVolume() * EG1.getLevel();
228            finalSynthesisParameters.fFinalVolumeLeft  = fFinalVolume * PanLeft;
229            finalSynthesisParameters.fFinalVolumeRight = fFinalVolume * PanRight;
230    
231    
232          // setup EG 2 (VCF Cutoff EG)          // setup EG 2 (VCF Cutoff EG)
233          {          {
# Line 270  namespace LinuxSampler { namespace gig { Line 269  namespace LinuxSampler { namespace gig {
269    
270          // setup EG 3 (VCO EG)          // setup EG 3 (VCO EG)
271          {          {
272            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
273            EG3.trigger(eg3depth, pDimRgn->EG3Attack, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);              bool  bPortamento = pEngineChannel->PortamentoMode && pEngineChannel->PortamentoPos >= 0.0f;
274                float eg3depth = (bPortamento)
275                                     ? RTMath::CentsToFreqRatio((pEngineChannel->PortamentoPos - (float) MIDIKey) * 100)
276                                     : RTMath::CentsToFreqRatio(pDimRgn->EG3Depth);
277                float eg3time = (bPortamento)
278                                    ? pEngineChannel->PortamentoTime
279                                    : pDimRgn->EG3Attack;
280                EG3.trigger(eg3depth, eg3time, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
281                dmsg(5,("PortamentoPos=%f, depth=%f, time=%f\n", pEngineChannel->PortamentoPos, eg3depth, eg3time));
282          }          }
283    
284    
# Line 696  namespace LinuxSampler { namespace gig { Line 703  namespace LinuxSampler { namespace gig {
703    
704      void Voice::processCrossFadeEvent(RTList<Event>::Iterator& itEvent) {      void Voice::processCrossFadeEvent(RTList<Event>::Iterator& itEvent) {
705          CrossfadeVolume = CrossfadeAttenuation(itEvent->Param.CC.Value);          CrossfadeVolume = CrossfadeAttenuation(itEvent->Param.CC.Value);
706            fFinalVolume = getVolume();
707        }
708    
709        float Voice::getVolume() {
710          #if CONFIG_PROCESS_MUTED_CHANNELS          #if CONFIG_PROCESS_MUTED_CHANNELS
711          const float effectiveVolume = CrossfadeVolume * Volume * (pEngineChannel->GetMute() ? 0 : pEngineChannel->GlobalVolume);          return pEngineChannel->GetMute() ? 0 : (Volume * CrossfadeVolume * pEngineChannel->GlobalVolume);
712          #else          #else
713          const float effectiveVolume = CrossfadeVolume * Volume * pEngineChannel->GlobalVolume;          return Volume * CrossfadeVolume * pEngineChannel->GlobalVolume;
714          #endif          #endif
         fFinalVolume = effectiveVolume;  
715      }      }
716    
717      void Voice::processCutoffEvent(RTList<Event>::Iterator& itEvent) {      void Voice::processCutoffEvent(RTList<Event>::Iterator& itEvent) {
# Line 759  namespace LinuxSampler { namespace gig { Line 769  namespace LinuxSampler { namespace gig {
769    
770              // initialize all final synthesis parameters              // initialize all final synthesis parameters
771              finalSynthesisParameters.fFinalPitch = PitchBase * PitchBend;              finalSynthesisParameters.fFinalPitch = PitchBase * PitchBend;
772              #if CONFIG_PROCESS_MUTED_CHANNELS              fFinalVolume    = getVolume();
             fFinalVolume = this->Volume * this->CrossfadeVolume * (pEngineChannel->GetMute() ? 0 : pEngineChannel->GlobalVolume);  
             #else  
             fFinalVolume = this->Volume * this->CrossfadeVolume * pEngineChannel->GlobalVolume;  
             #endif  
773              fFinalCutoff    = VCFCutoffCtrl.fvalue;              fFinalCutoff    = VCFCutoffCtrl.fvalue;
774              fFinalResonance = VCFResonanceCtrl.fvalue;              fFinalResonance = VCFResonanceCtrl.fvalue;
775    
# Line 802  namespace LinuxSampler { namespace gig { Line 808  namespace LinuxSampler { namespace gig {
808                      fFinalCutoff *= EG2.getLevel();                      fFinalCutoff *= EG2.getLevel();
809                      break; // noop                      break; // noop
810              }              }
811              if (EG3.active()) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(EG3.render());              if (EG3.active()) finalSynthesisParameters.fFinalPitch *= EG3.render();
812    
813              // process low frequency oscillators              // process low frequency oscillators
814              if (bLFO1Enabled) fFinalVolume *= pLFO1->render();              if (bLFO1Enabled) fFinalVolume *= pLFO1->render();
# Line 823  namespace LinuxSampler { namespace gig { Line 829  namespace LinuxSampler { namespace gig {
829              SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, bResamplingRequired);              SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, bResamplingRequired);
830    
831              // prepare final synthesis parameters structure              // prepare final synthesis parameters structure
832                finalSynthesisParameters.uiToGo            = iSubFragmentEnd - i;
833    #ifdef CONFIG_INTERPOLATE_VOLUME
834                finalSynthesisParameters.fFinalVolumeDeltaLeft  =
835                    (fFinalVolume * PanLeft - finalSynthesisParameters.fFinalVolumeLeft) / finalSynthesisParameters.uiToGo;
836                finalSynthesisParameters.fFinalVolumeDeltaRight =
837                    (fFinalVolume * PanRight - finalSynthesisParameters.fFinalVolumeRight) / finalSynthesisParameters.uiToGo;
838    #else
839              finalSynthesisParameters.fFinalVolumeLeft  = fFinalVolume * PanLeft;              finalSynthesisParameters.fFinalVolumeLeft  = fFinalVolume * PanLeft;
840              finalSynthesisParameters.fFinalVolumeRight = fFinalVolume * PanRight;              finalSynthesisParameters.fFinalVolumeRight = fFinalVolume * PanRight;
841              finalSynthesisParameters.uiToGo            = iSubFragmentEnd - i;  #endif
   
842              // render audio for one subfragment              // render audio for one subfragment
843              RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);              RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);
844    
845                // stop the rendering if volume EG is finished
846                if (EG1.getSegmentType() == EGADSR::segment_end) break;
847    
848              const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;              const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;
849    
850              // increment envelopes' positions              // increment envelopes' positions
# Line 855  namespace LinuxSampler { namespace gig { Line 870  namespace LinuxSampler { namespace gig {
870          }          }
871      }      }
872    
873        /** @brief Update current portamento position.
874         *
875         * Will be called when portamento mode is enabled to get the final
876         * portamento position of this active voice from where the next voice(s)
877         * might continue to slide on.
878         *
879         * @param itNoteOffEvent - event which causes this voice to die soon
880         */
881        void Voice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {
882            const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());
883            pEngineChannel->PortamentoPos = (float) MIDIKey + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;
884        }
885    
886      /**      /**
887       *  Immediately kill the voice. This method should not be used to kill       *  Immediately kill the voice. This method should not be used to kill
888       *  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.830

  ViewVC Help
Powered by ViewVC