/[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 318 by schoenebeck, Sat Oct 16 17:38:03 2004 UTC revision 319 by schoenebeck, Mon Dec 13 00:46:42 2004 UTC
# Line 22  Line 22 
22    
23  #include "EGADSR.h"  #include "EGADSR.h"
24  #include "Manipulator.h"  #include "Manipulator.h"
25    #include "../../common/Features.h"
26    #include "Synthesizer.h"
27    
28  #include "Voice.h"  #include "Voice.h"
29    
# Line 56  namespace LinuxSampler { namespace gig { Line 58  namespace LinuxSampler { namespace gig {
58          pLFO2  = NULL;          pLFO2  = NULL;
59          pLFO3  = NULL;          pLFO3  = NULL;
60          KeyGroup = 0;          KeyGroup = 0;
61    
62            // select synthesis implementation (currently either pure C++ or MMX+SSE(1))
63            SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, Features::supportsMMX() && Features::supportsSSE());
64      }      }
65    
66      Voice::~Voice() {      Voice::~Voice() {
# Line 116  namespace LinuxSampler { namespace gig { Line 121  namespace LinuxSampler { namespace gig {
121             dmsg(1,("voice::trigger: !pInstrument\n"));             dmsg(1,("voice::trigger: !pInstrument\n"));
122             exit(EXIT_FAILURE);             exit(EXIT_FAILURE);
123          }          }
124            if (itNoteOnEvent->FragmentPos() > pEngine->MaxSamplesPerCycle) { // FIXME: should be removed before the final release (purpose: just a sanity check for debugging)
125                dmsg(1,("Voice::Trigger(): ERROR, TriggerDelay > Totalsamples\n"));
126            }
127    
128          Type            = type_normal;          Type            = type_normal;
129          MIDIKey         = itNoteOnEvent->Param.Note.Key;          MIDIKey         = itNoteOnEvent->Param.Note.Key;
# Line 240  namespace LinuxSampler { namespace gig { Line 248  namespace LinuxSampler { namespace gig {
248          }          }
249          pDimRgn = pRegion->GetDimensionRegionByValue(DimValues[4],DimValues[3],DimValues[2],DimValues[1],DimValues[0]);          pDimRgn = pRegion->GetDimensionRegionByValue(DimValues[4],DimValues[3],DimValues[2],DimValues[1],DimValues[0]);
250    
251            pSample = pDimRgn->pSample; // sample won't change until the voice is finished
252    
253            // select channel mode (mono or stereo)
254            SYNTHESIS_MODE_SET_CHANNELS(SynthesisMode, pSample->Channels == 2);
255    
256          // get starting crossfade volume level          // get starting crossfade volume level
257          switch (pDimRgn->AttenuationController.type) {          switch (pDimRgn->AttenuationController.type) {
258              case ::gig::attenuation_ctrl_t::type_channelaftertouch:              case ::gig::attenuation_ctrl_t::type_channelaftertouch:
# Line 259  namespace LinuxSampler { namespace gig { Line 272  namespace LinuxSampler { namespace gig {
272          PanLeft  = 1.0f - float(RTMath::Max(pDimRgn->Pan, 0)) /  63.0f;          PanLeft  = 1.0f - float(RTMath::Max(pDimRgn->Pan, 0)) /  63.0f;
273          PanRight = 1.0f - float(RTMath::Min(pDimRgn->Pan, 0)) / -64.0f;          PanRight = 1.0f - float(RTMath::Min(pDimRgn->Pan, 0)) / -64.0f;
274    
         pSample = pDimRgn->pSample; // sample won't change until the voice is finished  
   
275          Pos = pDimRgn->SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)          Pos = pDimRgn->SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)
276    
277          // Check if the sample needs disk streaming or is too short for that          // Check if the sample needs disk streaming or is too short for that
# Line 303  namespace LinuxSampler { namespace gig { Line 314  namespace LinuxSampler { namespace gig {
314              this->PitchBend = RTMath::CentsToFreqRatio(((double) PitchBend / 8192.0) * 200.0); // pitchbend wheel +-2 semitones = 200 cents              this->PitchBend = RTMath::CentsToFreqRatio(((double) PitchBend / 8192.0) * 200.0); // pitchbend wheel +-2 semitones = 200 cents
315          }          }
316    
   
317          Volume = pDimRgn->GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity) / 32768.0f; // we downscale by 32768 to convert from int16 value range to DSP value range (which is -1.0..1.0)          Volume = pDimRgn->GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity) / 32768.0f; // we downscale by 32768 to convert from int16 value range to DSP value range (which is -1.0..1.0)
318    
   
319          // setup EG 1 (VCA EG)          // setup EG 1 (VCA EG)
320          {          {
321              // get current value of EG1 controller              // get current value of EG1 controller
# Line 345  namespace LinuxSampler { namespace gig { Line 354  namespace LinuxSampler { namespace gig {
354          }          }
355    
356    
     #if ENABLE_FILTER  
357          // setup EG 2 (VCF Cutoff EG)          // setup EG 2 (VCF Cutoff EG)
358          {          {
359              // get current value of EG2 controller              // get current value of EG2 controller
# Line 382  namespace LinuxSampler { namespace gig { Line 390  namespace LinuxSampler { namespace gig {
390                            pDimRgn->EG2Release + eg2release,                            pDimRgn->EG2Release + eg2release,
391                            Delay);                            Delay);
392          }          }
     #endif // ENABLE_FILTER  
393    
394    
395          // setup EG 3 (VCO EG)          // setup EG 3 (VCO EG)
# Line 429  namespace LinuxSampler { namespace gig { Line 436  namespace LinuxSampler { namespace gig {
436                            Delay);                            Delay);
437          }          }
438    
439      #if ENABLE_FILTER  
440          // setup LFO 2 (VCF Cutoff LFO)          // setup LFO 2 (VCF Cutoff LFO)
441          {          {
442              uint16_t lfo2_internal_depth;              uint16_t lfo2_internal_depth;
# Line 466  namespace LinuxSampler { namespace gig { Line 473  namespace LinuxSampler { namespace gig {
473                            pEngine->SampleRate,                            pEngine->SampleRate,
474                            Delay);                            Delay);
475          }          }
476      #endif // ENABLE_FILTER  
477    
478          // setup LFO 3 (VCO LFO)          // setup LFO 3 (VCO LFO)
479          {          {
# Line 505  namespace LinuxSampler { namespace gig { Line 512  namespace LinuxSampler { namespace gig {
512                            Delay);                            Delay);
513          }          }
514    
515      #if ENABLE_FILTER  
516          #if FORCE_FILTER_USAGE          #if FORCE_FILTER_USAGE
517          FilterLeft.Enabled = FilterRight.Enabled = true;          SYNTHESIS_MODE_SET_FILTER(SynthesisMode, true);
518          #else // use filter only if instrument file told so          #else // use filter only if instrument file told so
519          FilterLeft.Enabled = FilterRight.Enabled = pDimRgn->VCFEnabled;          SYNTHESIS_MODE_SET_FILTER(SynthesisMode, pDimRgn->VCFEnabled);
520          #endif // FORCE_FILTER_USAGE          #endif // FORCE_FILTER_USAGE
521          if (pDimRgn->VCFEnabled) {          if (pDimRgn->VCFEnabled) {
522              #ifdef OVERRIDE_FILTER_CUTOFF_CTRL              #ifdef OVERRIDE_FILTER_CUTOFF_CTRL
# Line 599  namespace LinuxSampler { namespace gig { Line 606  namespace LinuxSampler { namespace gig {
606              VCFCutoffCtrl.fvalue    = cutoff - FILTER_CUTOFF_MIN;              VCFCutoffCtrl.fvalue    = cutoff - FILTER_CUTOFF_MIN;
607              VCFResonanceCtrl.fvalue = resonance;              VCFResonanceCtrl.fvalue = resonance;
608    
             FilterLeft.SetParameters(cutoff,  resonance, pEngine->SampleRate);  
             FilterRight.SetParameters(cutoff, resonance, pEngine->SampleRate);  
   
609              FilterUpdateCounter = -1;              FilterUpdateCounter = -1;
610          }          }
611          else {          else {
612              VCFCutoffCtrl.controller    = 0;              VCFCutoffCtrl.controller    = 0;
613              VCFResonanceCtrl.controller = 0;              VCFResonanceCtrl.controller = 0;
614          }          }
     #endif // ENABLE_FILTER  
615    
616          return 0; // success          return 0; // success
617      }      }
# Line 626  namespace LinuxSampler { namespace gig { Line 629  namespace LinuxSampler { namespace gig {
629       */       */
630      void Voice::Render(uint Samples) {      void Voice::Render(uint Samples) {
631    
632            // select default values for synthesis mode bits
633            SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, (PitchBase * PitchBend) != 1.0f);
634            SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, true);
635            SYNTHESIS_MODE_SET_LOOP(SynthesisMode, false);
636    
637          // Reset the synthesis parameter matrix          // Reset the synthesis parameter matrix
638    
639          pEngine->ResetSynthesisParameters(Event::destination_vca, this->Volume * this->CrossfadeVolume * pEngine->GlobalVolume);          pEngine->ResetSynthesisParameters(Event::destination_vca, this->Volume * this->CrossfadeVolume * pEngine->GlobalVolume);
640          pEngine->ResetSynthesisParameters(Event::destination_vco, this->PitchBase);          pEngine->ResetSynthesisParameters(Event::destination_vco, this->PitchBase);
     #if ENABLE_FILTER  
641          pEngine->ResetSynthesisParameters(Event::destination_vcfc, VCFCutoffCtrl.fvalue);          pEngine->ResetSynthesisParameters(Event::destination_vcfc, VCFCutoffCtrl.fvalue);
642          pEngine->ResetSynthesisParameters(Event::destination_vcfr, VCFResonanceCtrl.fvalue);          pEngine->ResetSynthesisParameters(Event::destination_vcfr, VCFResonanceCtrl.fvalue);
     #endif // ENABLE_FILTER  
   
643    
644          // Apply events to the synthesis parameter matrix          // Apply events to the synthesis parameter matrix
645          ProcessEvents(Samples);          ProcessEvents(Samples);
646    
   
647          // Let all modulators write their parameter changes to the synthesis parameter matrix for the current audio fragment          // Let all modulators write their parameter changes to the synthesis parameter matrix for the current audio fragment
648          pEG1->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, itTriggerEvent, this->Pos, this->PitchBase * this->PitchBend, itKillEvent);          pEG1->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, itTriggerEvent, this->Pos, this->PitchBase * this->PitchBend, itKillEvent);
     #if ENABLE_FILTER  
649          pEG2->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, itTriggerEvent, this->Pos, this->PitchBase * this->PitchBend);          pEG2->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, itTriggerEvent, this->Pos, this->PitchBase * this->PitchBend);
650      #endif // ENABLE_FILTER          if (pEG3->Process(Samples)) { // if pitch EG is active
651          pEG3->Process(Samples);              SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, true);
652                SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, false);
653            }
654          pLFO1->Process(Samples);          pLFO1->Process(Samples);
     #if ENABLE_FILTER  
655          pLFO2->Process(Samples);          pLFO2->Process(Samples);
656      #endif // ENABLE_FILTER          if (pLFO3->Process(Samples)) { // if pitch LFO modulation is active
657          pLFO3->Process(Samples);              SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, true);
658                SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, false);
659            }
     #if ENABLE_FILTER  
         CalculateBiquadParameters(Samples); // calculate the final biquad filter parameters  
     #endif // ENABLE_FILTER  
660    
661            if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode))
662                    CalculateBiquadParameters(Samples); // calculate the final biquad filter parameters
663    
664          switch (this->PlaybackState) {          switch (this->PlaybackState) {
665    
666              case playback_state_ram: {              case playback_state_ram: {
667                      if (RAMLoop) InterpolateAndLoop(Samples, (sample_t*) pSample->GetCache().pStart, Delay);                      if (RAMLoop) SYNTHESIS_MODE_SET_LOOP(SynthesisMode, true); // enable looping
668                      else         InterpolateNoLoop(Samples, (sample_t*) pSample->GetCache().pStart, Delay);  
669                        // render current fragment
670                        Synthesize(Samples, (sample_t*) pSample->GetCache().pStart, Delay);
671    
672                      if (DiskVoice) {                      if (DiskVoice) {
673                          // check if we reached the allowed limit of the sample RAM cache                          // check if we reached the allowed limit of the sample RAM cache
674                          if (Pos > MaxRAMPos) {                          if (Pos > MaxRAMPos) {
# Line 684  namespace LinuxSampler { namespace gig { Line 691  namespace LinuxSampler { namespace gig {
691                              KillImmediately();                              KillImmediately();
692                              return;                              return;
693                          }                          }
694                          DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (RTMath::DoubleToInt(Pos) - MaxRAMPos));                          DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (int(Pos) - MaxRAMPos));
695                          Pos -= RTMath::DoubleToInt(Pos);                          Pos -= int(Pos);
696                      }                      }
697    
698                      // add silence sample at the end if we reached the end of the stream (for the interpolator)                      // add silence sample at the end if we reached the end of the stream (for the interpolator)
# Line 695  namespace LinuxSampler { namespace gig { Line 702  namespace LinuxSampler { namespace gig {
702                      }                      }
703    
704                      sample_t* ptr = DiskStreamRef.pStream->GetReadPtr(); // get the current read_ptr within the ringbuffer where we read the samples from                      sample_t* ptr = DiskStreamRef.pStream->GetReadPtr(); // get the current read_ptr within the ringbuffer where we read the samples from
705                      InterpolateNoLoop(Samples, ptr, Delay);  
706                      DiskStreamRef.pStream->IncrementReadPos(RTMath::DoubleToInt(Pos) * pSample->Channels);                      // render current audio fragment
707                      Pos -= RTMath::DoubleToInt(Pos);                      Synthesize(Samples, ptr, Delay);
708    
709                        DiskStreamRef.pStream->IncrementReadPos(int(Pos) * pSample->Channels);
710                        Pos -= int(Pos);
711                  }                  }
712                  break;                  break;
713    
# Line 706  namespace LinuxSampler { namespace gig { Line 716  namespace LinuxSampler { namespace gig {
716                  break;                  break;
717          }          }
718    
   
719          // Reset synthesis event lists (except VCO, as VCO events apply channel wide currently)          // Reset synthesis event lists (except VCO, as VCO events apply channel wide currently)
720          pEngine->pSynthesisEvents[Event::destination_vca]->clear();          pEngine->pSynthesisEvents[Event::destination_vca]->clear();
     #if ENABLE_FILTER  
721          pEngine->pSynthesisEvents[Event::destination_vcfc]->clear();          pEngine->pSynthesisEvents[Event::destination_vcfc]->clear();
722          pEngine->pSynthesisEvents[Event::destination_vcfr]->clear();          pEngine->pSynthesisEvents[Event::destination_vcfr]->clear();
     #endif // ENABLE_FILTER  
723    
724          // Reset delay          // Reset delay
725          Delay = 0;          Delay = 0;
# Line 731  namespace LinuxSampler { namespace gig { Line 738  namespace LinuxSampler { namespace gig {
738          pLFO1->Reset();          pLFO1->Reset();
739          pLFO2->Reset();          pLFO2->Reset();
740          pLFO3->Reset();          pLFO3->Reset();
741            FilterLeft.Reset();
742            FilterRight.Reset();
743          DiskStreamRef.pStream = NULL;          DiskStreamRef.pStream = NULL;
744          DiskStreamRef.hStream = 0;          DiskStreamRef.hStream = 0;
745          DiskStreamRef.State   = Stream::state_unused;          DiskStreamRef.State   = Stream::state_unused;
# Line 756  namespace LinuxSampler { namespace gig { Line 765  namespace LinuxSampler { namespace gig {
765          }          }
766          while (itCCEvent) {          while (itCCEvent) {
767              if (itCCEvent->Param.CC.Controller) { // if valid MIDI controller              if (itCCEvent->Param.CC.Controller) { // if valid MIDI controller
                 #if ENABLE_FILTER  
768                  if (itCCEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {                  if (itCCEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {
769                      *pEngine->pSynthesisEvents[Event::destination_vcfc]->allocAppend() = *itCCEvent;                      *pEngine->pSynthesisEvents[Event::destination_vcfc]->allocAppend() = *itCCEvent;
770                  }                  }
771                  if (itCCEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {                  if (itCCEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {
772                      *pEngine->pSynthesisEvents[Event::destination_vcfr]->allocAppend() = *itCCEvent;                      *pEngine->pSynthesisEvents[Event::destination_vcfr]->allocAppend() = *itCCEvent;
773                  }                  }
                 #endif // ENABLE_FILTER  
774                  if (itCCEvent->Param.CC.Controller == pLFO1->ExtController) {                  if (itCCEvent->Param.CC.Controller == pLFO1->ExtController) {
775                      pLFO1->SendEvent(itCCEvent);                      pLFO1->SendEvent(itCCEvent);
776                  }                  }
                 #if ENABLE_FILTER  
777                  if (itCCEvent->Param.CC.Controller == pLFO2->ExtController) {                  if (itCCEvent->Param.CC.Controller == pLFO2->ExtController) {
778                      pLFO2->SendEvent(itCCEvent);                      pLFO2->SendEvent(itCCEvent);
779                  }                  }
                 #endif // ENABLE_FILTER  
780                  if (itCCEvent->Param.CC.Controller == pLFO3->ExtController) {                  if (itCCEvent->Param.CC.Controller == pLFO3->ExtController) {
781                      pLFO3->SendEvent(itCCEvent);                      pLFO3->SendEvent(itCCEvent);
782                  }                  }
# Line 816  namespace LinuxSampler { namespace gig { Line 821  namespace LinuxSampler { namespace gig {
821    
822                  itVCOEvent = itNextVCOEvent;                  itVCOEvent = itNextVCOEvent;
823              }              }
824              if (!pVCOEventList->isEmpty()) this->PitchBend = pitch;              if (!pVCOEventList->isEmpty()) {
825                    this->PitchBend = pitch;
826                    SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, true);
827                    SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, false);
828                }
829          }          }
830    
831          // process volume / attenuation events (TODO: we only handle and _expect_ crossfade events here ATM !)          // process volume / attenuation events (TODO: we only handle and _expect_ crossfade events here ATM !)
# Line 848  namespace LinuxSampler { namespace gig { Line 857  namespace LinuxSampler { namespace gig {
857              if (!pVCAEventList->isEmpty()) this->CrossfadeVolume = crossfadevolume;              if (!pVCAEventList->isEmpty()) this->CrossfadeVolume = crossfadevolume;
858          }          }
859    
     #if ENABLE_FILTER  
860          // process filter cutoff events          // process filter cutoff events
861          {          {
862              RTList<Event>* pCutoffEventList = pEngine->pSynthesisEvents[Event::destination_vcfc];              RTList<Event>* pCutoffEventList = pEngine->pSynthesisEvents[Event::destination_vcfc];
# Line 905  namespace LinuxSampler { namespace gig { Line 913  namespace LinuxSampler { namespace gig {
913              }              }
914              if (!pResonanceEventList->isEmpty()) VCFResonanceCtrl.fvalue = pResonanceEventList->last()->Param.CC.Value * 0.00787f; // needed for initialization of parameter matrix next time              if (!pResonanceEventList->isEmpty()) VCFResonanceCtrl.fvalue = pResonanceEventList->last()->Param.CC.Value * 0.00787f; // needed for initialization of parameter matrix next time
915          }          }
     #endif // ENABLE_FILTER  
916      }      }
917    
     #if ENABLE_FILTER  
918      /**      /**
919       * Calculate all necessary, final biquad filter parameters.       * Calculate all necessary, final biquad filter parameters.
920       *       *
921       * @param Samples - number of samples to be rendered in this audio fragment cycle       * @param Samples - number of samples to be rendered in this audio fragment cycle
922       */       */
923      void Voice::CalculateBiquadParameters(uint Samples) {      void Voice::CalculateBiquadParameters(uint Samples) {
         if (!FilterLeft.Enabled) return;  
   
924          biquad_param_t bqbase;          biquad_param_t bqbase;
925          biquad_param_t bqmain;          biquad_param_t bqmain;
926          float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0];          float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0];
# Line 928  namespace LinuxSampler { namespace gig { Line 932  namespace LinuxSampler { namespace gig {
932          float* bq;          float* bq;
933          for (int i = 1; i < Samples; i++) {          for (int i = 1; i < Samples; i++) {
934              // recalculate biquad parameters if cutoff or resonance differ from previous sample point              // recalculate biquad parameters if cutoff or resonance differ from previous sample point
935              if (!(i & FILTER_UPDATE_MASK)) if (pEngine->pSynthesisParameters[Event::destination_vcfr][i] != prev_res ||              if (!(i & FILTER_UPDATE_MASK)) {
936                                                 pEngine->pSynthesisParameters[Event::destination_vcfc][i] != prev_cutoff) {                  if (pEngine->pSynthesisParameters[Event::destination_vcfr][i] != prev_res ||
937                  prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][i];                      pEngine->pSynthesisParameters[Event::destination_vcfc][i] != prev_cutoff)
938                  prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][i];                  {
939                  FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);                      prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][i];
940                        prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][i];
941                        FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);
942                    }
943              }              }
944    
945              //same as 'pEngine->pBasicFilterParameters[i] = bqbase;'              //same as 'pEngine->pBasicFilterParameters[i] = bqbase;'
# Line 952  namespace LinuxSampler { namespace gig { Line 959  namespace LinuxSampler { namespace gig {
959              bq[4] = bqmain.b2;              bq[4] = bqmain.b2;
960          }          }
961      }      }
     #endif // ENABLE_FILTER  
962    
963      /**      /**
964       *  Interpolates the input audio data (without looping).       *  Synthesizes the current audio fragment for this voice.
965       *       *
966       *  @param Samples - number of sample points to be rendered in this audio       *  @param Samples - number of sample points to be rendered in this audio
967       *                   fragment cycle       *                   fragment cycle
968       *  @param pSrc    - pointer to input sample data       *  @param pSrc    - pointer to input sample data
969       *  @param Skip    - number of sample points to skip in output buffer       *  @param Skip    - number of sample points to skip in output buffer
970       */       */
971      void Voice::InterpolateNoLoop(uint Samples, sample_t* pSrc, uint Skip) {      void Voice::Synthesize(uint Samples, sample_t* pSrc, int Skip) {
972          int i = Skip;          UpdateSynthesisMode();
973            SynthesizeFragment_Fn* f = (SynthesizeFragment_Fn*) SynthesizeFragmentFnPtr;
974          // FIXME: assuming either mono or stereo          f(*this, Samples, pSrc, Skip);
         if (this->pSample->Channels == 2) { // Stereo Sample  
             while (i < Samples) InterpolateStereo(pSrc, i);  
         }  
         else { // Mono Sample  
             while (i < Samples) InterpolateMono(pSrc, i);  
         }  
975      }      }
976    
977      /**      /**
978       *  Interpolates the input audio data, this method honors looping.       *  Determine the respective synthesis function for the given synthesis
979       *       *  mode.
      *  @param Samples - number of sample points to be rendered in this audio  
      *                   fragment cycle  
      *  @param pSrc    - pointer to input sample data  
      *  @param Skip    - number of sample points to skip in output buffer  
980       */       */
981      void Voice::InterpolateAndLoop(uint Samples, sample_t* pSrc, uint Skip) {      void Voice::UpdateSynthesisMode() {
982          int i = Skip;          SynthesizeFragmentFnPtr = GetSynthesisFunction(SynthesisMode);
   
         // FIXME: assuming either mono or stereo  
         if (pSample->Channels == 2) { // Stereo Sample  
             if (pSample->LoopPlayCount) {  
                 // render loop (loop count limited)  
                 while (i < Samples && LoopCyclesLeft) {  
                     InterpolateStereo(pSrc, i);  
                     if (Pos > pSample->LoopEnd) {  
                         Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;  
                         LoopCyclesLeft--;  
                     }  
                 }  
                 // render on without loop  
                 while (i < Samples) InterpolateStereo(pSrc, i);  
             }  
             else { // render loop (endless loop)  
                 while (i < Samples) {  
                     InterpolateStereo(pSrc, i);  
                     if (Pos > pSample->LoopEnd) {  
                         Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);  
                     }  
                 }  
             }  
         }  
         else { // Mono Sample  
             if (pSample->LoopPlayCount) {  
                 // render loop (loop count limited)  
                 while (i < Samples && LoopCyclesLeft) {  
                     InterpolateMono(pSrc, i);  
                     if (Pos > pSample->LoopEnd) {  
                         Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;  
                         LoopCyclesLeft--;  
                     }  
                 }  
                 // render on without loop  
                 while (i < Samples) InterpolateMono(pSrc, i);  
             }  
             else { // render loop (endless loop)  
                 while (i < Samples) {  
                     InterpolateMono(pSrc, i);  
                     if (Pos > pSample->LoopEnd) {  
                         Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;  
                     }  
                 }  
             }  
         }  
983      }      }
984    
985      /**      /**

Legend:
Removed from v.318  
changed lines
  Added in v.319

  ViewVC Help
Powered by ViewVC