/[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 769 by schoenebeck, Sat Sep 3 11:14:30 2005 UTC revision 770 by schoenebeck, Sun Sep 11 15:56:29 2005 UTC
# Line 23  Line 23 
23    
24  #include "../../common/Features.h"  #include "../../common/Features.h"
25  #include "Synthesizer.h"  #include "Synthesizer.h"
26    #include "Profiler.h"
27    
28  #include "Voice.h"  #include "Voice.h"
29    
# Line 49  namespace LinuxSampler { namespace gig { Line 50  namespace LinuxSampler { namespace gig {
50          #else          #else
51          SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, false);          SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, false);
52          #endif          #endif
53          SYNTHESIS_MODE_SET_PROFILING(SynthesisMode, true);          SYNTHESIS_MODE_SET_PROFILING(SynthesisMode, Profiler::isEnabled());
54    
55          FilterLeft.Reset();          finalSynthesisParameters.filterLeft.Reset();
56          FilterRight.Reset();          finalSynthesisParameters.filterRight.Reset();
57      }      }
58    
59      Voice::~Voice() {      Voice::~Voice() {
# Line 138  namespace LinuxSampler { namespace gig { Line 139  namespace LinuxSampler { namespace gig {
139          PanLeft  = 1.0f - float(RTMath::Max(pDimRgn->Pan, 0)) /  63.0f;          PanLeft  = 1.0f - float(RTMath::Max(pDimRgn->Pan, 0)) /  63.0f;
140          PanRight = 1.0f - float(RTMath::Min(pDimRgn->Pan, 0)) / -64.0f;          PanRight = 1.0f - float(RTMath::Min(pDimRgn->Pan, 0)) / -64.0f;
141    
142          Pos = 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)
143    
144          // 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
145          long cachedsamples = pSample->GetCache().Size / pSample->FrameSize;          long cachedsamples = pSample->GetCache().Size / pSample->FrameSize;
# Line 149  namespace LinuxSampler { namespace gig { Line 150  namespace LinuxSampler { namespace gig {
150    
151              // 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
152              if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) {              if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) {
153                  RAMLoop        = true;                  RAMLoop            = true;
154                  LoopCyclesLeft = pSample->LoopPlayCount;                  loop.uiTotalCycles = pSample->LoopPlayCount;
155                    loop.uiCyclesLeft  = pSample->LoopPlayCount;
156                    loop.uiStart       = pSample->LoopStart;
157                    loop.uiEnd         = pSample->LoopEnd;
158                    loop.uiSize        = pSample->LoopSize;
159              }              }
160              else RAMLoop = false;              else RAMLoop = false;
161    
# Line 164  namespace LinuxSampler { namespace gig { Line 169  namespace LinuxSampler { namespace gig {
169          else { // RAM only voice          else { // RAM only voice
170              MaxRAMPos = cachedsamples;              MaxRAMPos = cachedsamples;
171              if (pSample->Loops) {              if (pSample->Loops) {
172                  RAMLoop        = true;                  RAMLoop           = true;
173                  LoopCyclesLeft = pSample->LoopPlayCount;                  loop.uiCyclesLeft = pSample->LoopPlayCount;
174              }              }
175              else RAMLoop = false;              else RAMLoop = false;
176              dmsg(4,("RAM only voice launched (Looping: %s)\n", (RAMLoop) ? "yes" : "no"));              dmsg(4,("RAM only voice launched (Looping: %s)\n", (RAMLoop) ? "yes" : "no"));
# Line 469  namespace LinuxSampler { namespace gig { Line 474  namespace LinuxSampler { namespace gig {
474              #endif // CONFIG_OVERRIDE_RESONANCE_CTRL              #endif // CONFIG_OVERRIDE_RESONANCE_CTRL
475    
476              #ifndef CONFIG_OVERRIDE_FILTER_TYPE              #ifndef CONFIG_OVERRIDE_FILTER_TYPE
477              FilterLeft.SetType(pDimRgn->VCFType);              finalSynthesisParameters.filterLeft.SetType(pDimRgn->VCFType);
478              FilterRight.SetType(pDimRgn->VCFType);              finalSynthesisParameters.filterRight.SetType(pDimRgn->VCFType);
479              #else // override filter type              #else // override filter type
480              FilterLeft.SetType(CONFIG_OVERRIDE_FILTER_TYPE);              FilterLeft.SetType(CONFIG_OVERRIDE_FILTER_TYPE);
481              FilterRight.SetType(CONFIG_OVERRIDE_FILTER_TYPE);              FilterRight.SetType(CONFIG_OVERRIDE_FILTER_TYPE);
# Line 547  namespace LinuxSampler { namespace gig { Line 552  namespace LinuxSampler { namespace gig {
552    
553                      if (DiskVoice) {                      if (DiskVoice) {
554                          // check if we reached the allowed limit of the sample RAM cache                          // check if we reached the allowed limit of the sample RAM cache
555                          if (Pos > MaxRAMPos) {                          if (finalSynthesisParameters.dPos > MaxRAMPos) {
556                              dmsg(5,("Voice: switching to disk playback (Pos=%f)\n", Pos));                              dmsg(5,("Voice: switching to disk playback (Pos=%f)\n", finalSynthesisParameters.dPos));
557                              this->PlaybackState = playback_state_disk;                              this->PlaybackState = playback_state_disk;
558                          }                          }
559                      }                      } else if (finalSynthesisParameters.dPos >= pSample->GetCache().Size / pSample->FrameSize) {
                     else if (Pos >= pSample->GetCache().Size / pSample->FrameSize) {  
560                          this->PlaybackState = playback_state_end;                          this->PlaybackState = playback_state_end;
561                      }                      }
562                  }                  }
# Line 567  namespace LinuxSampler { namespace gig { Line 571  namespace LinuxSampler { namespace gig {
571                              KillImmediately();                              KillImmediately();
572                              return;                              return;
573                          }                          }
574                          DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (int(Pos) - MaxRAMPos));                          DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (int(finalSynthesisParameters.dPos) - MaxRAMPos));
575                          Pos -= int(Pos);                          finalSynthesisParameters.dPos -= int(finalSynthesisParameters.dPos);
576                          RealSampleWordsLeftToRead = -1; // -1 means no silence has been added yet                          RealSampleWordsLeftToRead = -1; // -1 means no silence has been added yet
577                      }                      }
578    
# Line 589  namespace LinuxSampler { namespace gig { Line 593  namespace LinuxSampler { namespace gig {
593                      // render current audio fragment                      // render current audio fragment
594                      Synthesize(Samples, ptr, Delay);                      Synthesize(Samples, ptr, Delay);
595    
596                      const int iPos = (int) Pos;                      const int iPos = (int) finalSynthesisParameters.dPos;
597                      const int readSampleWords = iPos * pSample->Channels; // amount of sample words actually been read                      const int readSampleWords = iPos * pSample->Channels; // amount of sample words actually been read
598                      DiskStreamRef.pStream->IncrementReadPos(readSampleWords);                      DiskStreamRef.pStream->IncrementReadPos(readSampleWords);
599                      Pos -= iPos; // just keep fractional part of Pos                      finalSynthesisParameters.dPos -= iPos; // just keep fractional part of playback position
600    
601                      // change state of voice to 'end' if we really reached the end of the sample data                      // change state of voice to 'end' if we really reached the end of the sample data
602                      if (RealSampleWordsLeftToRead >= 0) {                      if (RealSampleWordsLeftToRead >= 0) {
# Line 624  namespace LinuxSampler { namespace gig { Line 628  namespace LinuxSampler { namespace gig {
628       *  suspended / not running.       *  suspended / not running.
629       */       */
630      void Voice::Reset() {      void Voice::Reset() {
631          FilterLeft.Reset();          finalSynthesisParameters.filterLeft.Reset();
632          FilterRight.Reset();          finalSynthesisParameters.filterRight.Reset();
633          DiskStreamRef.pStream = NULL;          DiskStreamRef.pStream = NULL;
634          DiskStreamRef.hStream = 0;          DiskStreamRef.hStream = 0;
635          DiskStreamRef.State   = Stream::state_unused;          DiskStreamRef.State   = Stream::state_unused;
# Line 645  namespace LinuxSampler { namespace gig { Line 649  namespace LinuxSampler { namespace gig {
649      void Voice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) {      void Voice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) {
650          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
651              if (itEvent->Type == Event::type_release) {              if (itEvent->Type == Event::type_release) {
652                  EG1.update(EGADSR::event_release, this->Pos, fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  EG1.update(EGADSR::event_release, finalSynthesisParameters.dPos, finalSynthesisParameters.fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
653                  EG2.update(EGADSR::event_release, this->Pos, fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  EG2.update(EGADSR::event_release, finalSynthesisParameters.dPos, finalSynthesisParameters.fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
654              } else if (itEvent->Type == Event::type_cancel_release) {              } else if (itEvent->Type == Event::type_cancel_release) {
655                  EG1.update(EGADSR::event_cancel_release, this->Pos, fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  EG1.update(EGADSR::event_cancel_release, finalSynthesisParameters.dPos, finalSynthesisParameters.fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
656                  EG2.update(EGADSR::event_cancel_release, this->Pos, fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  EG2.update(EGADSR::event_cancel_release, finalSynthesisParameters.dPos, finalSynthesisParameters.fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
657              }              }
658          }          }
659      }      }
# Line 692  namespace LinuxSampler { namespace gig { Line 696  namespace LinuxSampler { namespace gig {
696    
697      void Voice::processPitchEvent(RTList<Event>::Iterator& itEvent) {      void Voice::processPitchEvent(RTList<Event>::Iterator& itEvent) {
698          const float pitch = RTMath::CentsToFreqRatio(((double) itEvent->Param.Pitch.Pitch / 8192.0) * 200.0); // +-two semitones = +-200 cents          const float pitch = RTMath::CentsToFreqRatio(((double) itEvent->Param.Pitch.Pitch / 8192.0) * 200.0); // +-two semitones = +-200 cents
699          fFinalPitch *= pitch;          finalSynthesisParameters.fFinalPitch *= pitch;
700          PitchBend = pitch;          PitchBend = pitch;
701      }      }
702    
# Line 738  namespace LinuxSampler { namespace gig { Line 742  namespace LinuxSampler { namespace gig {
742       *  @param Skip    - number of sample points to skip in output buffer       *  @param Skip    - number of sample points to skip in output buffer
743       */       */
744      void Voice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {      void Voice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {
745            finalSynthesisParameters.pOutLeft  = &pEngineChannel->pOutputLeft[Skip];
746            finalSynthesisParameters.pOutRight = &pEngineChannel->pOutputRight[Skip];
747            finalSynthesisParameters.pSrc      = pSrc;
748    
749          RTList<Event>::Iterator itCCEvent = pEngineChannel->pEvents->first();          RTList<Event>::Iterator itCCEvent = pEngineChannel->pEvents->first();
750          RTList<Event>::Iterator itNoteEvent = pEngineChannel->pMIDIKeyInfo[MIDIKey].pEvents->first();          RTList<Event>::Iterator itNoteEvent = pEngineChannel->pMIDIKeyInfo[MIDIKey].pEvents->first();
751    
# Line 751  namespace LinuxSampler { namespace gig { Line 759  namespace LinuxSampler { namespace gig {
759              int iSubFragmentEnd = RTMath::Min(i + CONFIG_DEFAULT_SUBFRAGMENT_SIZE, Samples);              int iSubFragmentEnd = RTMath::Min(i + CONFIG_DEFAULT_SUBFRAGMENT_SIZE, Samples);
760    
761              // initialize all final synthesis parameters              // initialize all final synthesis parameters
762              fFinalPitch = PitchBase * PitchBend;              finalSynthesisParameters.fFinalPitch = PitchBase * PitchBend;
763              #if CONFIG_PROCESS_MUTED_CHANNELS              #if CONFIG_PROCESS_MUTED_CHANNELS
764              fFinalVolume = this->Volume * this->CrossfadeVolume * (pEngineChannel->GetMute() ? 0 : pEngineChannel->GlobalVolume);              fFinalVolume = this->Volume * this->CrossfadeVolume * (pEngineChannel->GetMute() ? 0 : pEngineChannel->GlobalVolume);
765              #else              #else
# Line 789  namespace LinuxSampler { namespace gig { Line 797  namespace LinuxSampler { namespace gig {
797                      fFinalCutoff *= EG2.getLevel();                      fFinalCutoff *= EG2.getLevel();
798                      break; // noop                      break; // noop
799              }              }
800              fFinalPitch *= RTMath::CentsToFreqRatio(EG3.render());              if (EG3.active()) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(EG3.render());
801    
802              // process low frequency oscillators              // process low frequency oscillators
803              if (bLFO1Enabled) fFinalVolume *= pLFO1->render();              if (bLFO1Enabled) fFinalVolume *= pLFO1->render();
804              if (bLFO2Enabled) fFinalCutoff *= pLFO2->render();              if (bLFO2Enabled) fFinalCutoff *= pLFO2->render();
805              if (bLFO3Enabled) fFinalPitch  *= RTMath::CentsToFreqRatio(pLFO3->render());              if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());
806    
807              // if filter enabled then update filter coefficients              // if filter enabled then update filter coefficients
808              if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode)) {              if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode)) {
809                  FilterLeft.SetParameters(fFinalCutoff, fFinalResonance, pEngine->SampleRate);                  finalSynthesisParameters.filterLeft.SetParameters(fFinalCutoff, fFinalResonance, pEngine->SampleRate);
810                  FilterRight.SetParameters(fFinalCutoff, fFinalResonance, pEngine->SampleRate);                  finalSynthesisParameters.filterRight.SetParameters(fFinalCutoff, fFinalResonance, pEngine->SampleRate);
811              }              }
812    
813              // how many steps do we calculate for this next subfragment              // do we need resampling?
814              const int steps = iSubFragmentEnd - i;              const float __PLUS_ONE_CENT  = 1.000577789506554859250142541782224725466f;
815                const float __MINUS_ONE_CENT = 0.9994225441413807496009516495583113737666f;
816              // select the appropriate synthesis mode              const bool bResamplingRequired = !(finalSynthesisParameters.fFinalPitch <= __PLUS_ONE_CENT &&
817              SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, fFinalPitch != 1.0f);                                                 finalSynthesisParameters.fFinalPitch >= __MINUS_ONE_CENT);
818                SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, bResamplingRequired);
819    
820                // prepare final synthesis parameters structure
821                finalSynthesisParameters.fFinalVolumeLeft  = fFinalVolume * PanLeft;
822                finalSynthesisParameters.fFinalVolumeRight = fFinalVolume * PanRight;
823                finalSynthesisParameters.uiToGo            = iSubFragmentEnd - i;
824    
825              // render audio for one subfragment              // render audio for one subfragment
826              RunSynthesisFunction(SynthesisMode, *this, iSubFragmentEnd, pSrc, i);              RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);
827    
828              // increment envelopes' positions              // increment envelopes' positions
829              if (EG1.active()) {              if (EG1.active()) {
830                  EG1.increment(1);                  EG1.increment(1);
831                  if (!EG1.toStageEndLeft()) EG1.update(EGADSR::event_stage_end, this->Pos, fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  if (!EG1.toStageEndLeft()) EG1.update(EGADSR::event_stage_end, finalSynthesisParameters.dPos, finalSynthesisParameters.fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
832              }              }
833              if (EG2.active()) {              if (EG2.active()) {
834                  EG2.increment(1);                  EG2.increment(1);
835                  if (!EG2.toStageEndLeft()) EG2.update(EGADSR::event_stage_end, this->Pos, fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  if (!EG2.toStageEndLeft()) EG2.update(EGADSR::event_stage_end, finalSynthesisParameters.dPos, finalSynthesisParameters.fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
836              }              }
837              EG3.increment(1);              EG3.increment(1);
838              if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached              if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached

Legend:
Removed from v.769  
changed lines
  Added in v.770

  ViewVC Help
Powered by ViewVC