/[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 322 by senkov, Mon Dec 13 03:33:59 2004 UTC revision 407 by persson, Wed Feb 23 19:14:14 2005 UTC
# Line 58  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            SynthesisMode = 0; // set all mode bits to 0 first
62          // select synthesis implementation (currently either pure C++ or MMX+SSE(1))          // select synthesis implementation (currently either pure C++ or MMX+SSE(1))
63            #if ARCH_X86
64          SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, Features::supportsMMX() && Features::supportsSSE());          SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, Features::supportsMMX() && Features::supportsSSE());
65            #else
66            SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, false);
67            #endif
68            SYNTHESIS_MODE_SET_PROFILING(SynthesisMode, true);
69    
70            FilterLeft.Reset();
71            FilterRight.Reset();
72      }      }
73    
74      Voice::~Voice() {      Voice::~Voice() {
# Line 114  namespace LinuxSampler { namespace gig { Line 122  namespace LinuxSampler { namespace gig {
122       *  @param iLayer              - layer number this voice refers to (only if this is a layered sound of course)       *  @param iLayer              - layer number this voice refers to (only if this is a layered sound of course)
123       *  @param ReleaseTriggerVoice - if this new voice is a release trigger voice (optional, default = false)       *  @param ReleaseTriggerVoice - if this new voice is a release trigger voice (optional, default = false)
124       *  @param VoiceStealing       - wether the voice is allowed to steal voices for further subvoices       *  @param VoiceStealing       - wether the voice is allowed to steal voices for further subvoices
125       *  @returns 0 on success, a value < 0 if something failed       *  @returns 0 on success, a value < 0 if the voice wasn't triggered
126         *           (either due to an error or e.g. because no region is
127         *           defined for the given key)
128       */       */
129      int Voice::Trigger(Pool<Event>::Iterator& itNoteOnEvent, int PitchBend, ::gig::Instrument* pInstrument, int iLayer, bool ReleaseTriggerVoice, bool VoiceStealing) {      int Voice::Trigger(Pool<Event>::Iterator& itNoteOnEvent, int PitchBend, ::gig::Instrument* pInstrument, int iLayer, bool ReleaseTriggerVoice, bool VoiceStealing) {
130          if (!pInstrument) {          if (!pInstrument) {
# Line 135  namespace LinuxSampler { namespace gig { Line 145  namespace LinuxSampler { namespace gig {
145          itChildVoice    = Pool<Voice>::Iterator();          itChildVoice    = Pool<Voice>::Iterator();
146    
147          if (!pRegion) {          if (!pRegion) {
148              std::cerr << "gig::Voice: No Region defined for MIDI key " << MIDIKey << std::endl << std::flush;              dmsg(4, ("gig::Voice: No Region defined for MIDI key %d\n", MIDIKey));
             KillImmediately();  
149              return -1;              return -1;
150          }          }
151    
# Line 144  namespace LinuxSampler { namespace gig { Line 153  namespace LinuxSampler { namespace gig {
153    
154          // get current dimension values to select the right dimension region          // get current dimension values to select the right dimension region
155          //FIXME: controller values for selecting the dimension region here are currently not sample accurate          //FIXME: controller values for selecting the dimension region here are currently not sample accurate
156          uint DimValues[5] = {0,0,0,0,0};          uint DimValues[8] = { 0 };
157          for (int i = pRegion->Dimensions - 1; i >= 0; i--) {          for (int i = pRegion->Dimensions - 1; i >= 0; i--) {
158              switch (pRegion->pDimensionDefinitions[i].dimension) {              switch (pRegion->pDimensionDefinitions[i].dimension) {
159                  case ::gig::dimension_samplechannel:                  case ::gig::dimension_samplechannel:
# Line 168  namespace LinuxSampler { namespace gig { Line 177  namespace LinuxSampler { namespace gig {
177                      DimValues[i] = (uint) ReleaseTriggerVoice;                      DimValues[i] = (uint) ReleaseTriggerVoice;
178                      break;                      break;
179                  case ::gig::dimension_keyboard:                  case ::gig::dimension_keyboard:
180                      DimValues[i] = (uint) itNoteOnEvent->Param.Note.Key;                      DimValues[i] = (uint) pEngine->CurrentKeyDimension;
181                      break;                      break;
182                  case ::gig::dimension_modwheel:                  case ::gig::dimension_modwheel:
183                      DimValues[i] = pEngine->ControllerTable[1];                      DimValues[i] = pEngine->ControllerTable[1];
# Line 246  namespace LinuxSampler { namespace gig { Line 255  namespace LinuxSampler { namespace gig {
255                      std::cerr << "gig::Voice::Trigger() Error: Unknown dimension\n" << std::flush;                      std::cerr << "gig::Voice::Trigger() Error: Unknown dimension\n" << std::flush;
256              }              }
257          }          }
258          pDimRgn = pRegion->GetDimensionRegionByValue(DimValues[4],DimValues[3],DimValues[2],DimValues[1],DimValues[0]);          pDimRgn = pRegion->GetDimensionRegionByValue(DimValues);
259    
260          pSample = pDimRgn->pSample; // sample won't change until the voice is finished          pSample = pDimRgn->pSample; // sample won't change until the voice is finished
261            if (!pSample || !pSample->SamplesTotal) return -1; // no need to continue if sample is silent
262    
263          // select channel mode (mono or stereo)          // select channel mode (mono or stereo)
264          SYNTHESIS_MODE_SET_CHANNELS(SynthesisMode, pSample->Channels == 2);          SYNTHESIS_MODE_SET_CHANNELS(SynthesisMode, pSample->Channels == 2);
# Line 308  namespace LinuxSampler { namespace gig { Line 318  namespace LinuxSampler { namespace gig {
318    
319          // calculate initial pitch value          // calculate initial pitch value
320          {          {
321              double pitchbasecents = pDimRgn->FineTune * 10 + (int) pEngine->ScaleTuning[MIDIKey % 12];              double pitchbasecents = pDimRgn->FineTune + (int) pEngine->ScaleTuning[MIDIKey % 12];
322              if (pDimRgn->PitchTrack) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;              if (pDimRgn->PitchTrack) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;
323              this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents) * (double(pSample->SamplesPerSecond) / double(pEngine->pAudioOutputDevice->SampleRate()));              this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents) * (double(pSample->SamplesPerSecond) / double(pEngine->pAudioOutputDevice->SampleRate()));
324              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
# Line 316  namespace LinuxSampler { namespace gig { Line 326  namespace LinuxSampler { namespace gig {
326    
327          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)
328    
329            Volume *= pDimRgn->SampleAttenuation;
330    
331          // setup EG 1 (VCA EG)          // setup EG 1 (VCA EG)
332          {          {
333              // get current value of EG1 controller              // get current value of EG1 controller
# Line 514  namespace LinuxSampler { namespace gig { Line 526  namespace LinuxSampler { namespace gig {
526    
527    
528          #if FORCE_FILTER_USAGE          #if FORCE_FILTER_USAGE
529          SYNTHESIS_MODE_SET_FILTER(SynthesisMode, true);          const bool bUseFilter = true;
530          #else // use filter only if instrument file told so          #else // use filter only if instrument file told so
531          SYNTHESIS_MODE_SET_FILTER(SynthesisMode, pDimRgn->VCFEnabled);          const bool bUseFilter = pDimRgn->VCFEnabled;
532          #endif // FORCE_FILTER_USAGE          #endif // FORCE_FILTER_USAGE
533          if (pDimRgn->VCFEnabled) {          SYNTHESIS_MODE_SET_FILTER(SynthesisMode, bUseFilter);
534            if (bUseFilter) {
535              #ifdef OVERRIDE_FILTER_CUTOFF_CTRL              #ifdef OVERRIDE_FILTER_CUTOFF_CTRL
536              VCFCutoffCtrl.controller = OVERRIDE_FILTER_CUTOFF_CTRL;              VCFCutoffCtrl.controller = OVERRIDE_FILTER_CUTOFF_CTRL;
537              #else // use the one defined in the instrument file              #else // use the one defined in the instrument file
# Line 693  namespace LinuxSampler { namespace gig { Line 706  namespace LinuxSampler { namespace gig {
706                          }                          }
707                          DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (int(Pos) - MaxRAMPos));                          DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (int(Pos) - MaxRAMPos));
708                          Pos -= int(Pos);                          Pos -= int(Pos);
709                            RealSampleWordsLeftToRead = -1; // -1 means no silence has been added yet
710                      }                      }
711    
712                        const int sampleWordsLeftToRead = DiskStreamRef.pStream->GetReadSpace();
713    
714                      // 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)
715                      if (DiskStreamRef.State == Stream::state_end && DiskStreamRef.pStream->GetReadSpace() < (pEngine->MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels) {                      if (DiskStreamRef.State == Stream::state_end) {
716                          DiskStreamRef.pStream->WriteSilence((pEngine->MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels);                          const int maxSampleWordsPerCycle = (pEngine->MaxSamplesPerCycle << MAX_PITCH) * pSample->Channels + 6; // +6 for the interpolator algorithm
717                          this->PlaybackState = playback_state_end;                          if (sampleWordsLeftToRead <= maxSampleWordsPerCycle) {
718                                // remember how many sample words there are before any silence has been added
719                                if (RealSampleWordsLeftToRead < 0) RealSampleWordsLeftToRead = sampleWordsLeftToRead;
720                                DiskStreamRef.pStream->WriteSilence(maxSampleWordsPerCycle - sampleWordsLeftToRead);
721                            }
722                      }                      }
723    
724                      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
# Line 706  namespace LinuxSampler { namespace gig { Line 726  namespace LinuxSampler { namespace gig {
726                      // render current audio fragment                      // render current audio fragment
727                      Synthesize(Samples, ptr, Delay);                      Synthesize(Samples, ptr, Delay);
728    
729                      DiskStreamRef.pStream->IncrementReadPos(int(Pos) * pSample->Channels);                      const int iPos = (int) Pos;
730                      Pos -= int(Pos);                      const int readSampleWords = iPos * pSample->Channels; // amount of sample words actually been read
731                        DiskStreamRef.pStream->IncrementReadPos(readSampleWords);
732                        Pos -= iPos; // just keep fractional part of Pos
733    
734                        // change state of voice to 'end' if we really reached the end of the sample data
735                        if (RealSampleWordsLeftToRead >= 0) {
736                            RealSampleWordsLeftToRead -= readSampleWords;
737                            if (RealSampleWordsLeftToRead <= 0) this->PlaybackState = playback_state_end;
738                        }
739                  }                  }
740                  break;                  break;
741    
# Line 925  namespace LinuxSampler { namespace gig { Line 953  namespace LinuxSampler { namespace gig {
953          biquad_param_t bqmain;          biquad_param_t bqmain;
954          float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0];          float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0];
955          float prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][0];          float prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][0];
956          FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);          FilterLeft.SetParameters( &bqbase, &bqmain, prev_cutoff + FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate);
957          FilterRight.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);          FilterRight.SetParameters(&bqbase, &bqmain, prev_cutoff + FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate);
958          pEngine->pBasicFilterParameters[0] = bqbase;          pEngine->pBasicFilterParameters[0] = bqbase;
959          pEngine->pMainFilterParameters[0]  = bqmain;          pEngine->pMainFilterParameters[0]  = bqmain;
960    
# Line 939  namespace LinuxSampler { namespace gig { Line 967  namespace LinuxSampler { namespace gig {
967                  {                  {
968                      prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][i];                      prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][i];
969                      prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][i];                      prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][i];
970                      FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);                      FilterLeft.SetParameters( &bqbase, &bqmain, prev_cutoff + FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate);
971                      FilterRight.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);                      FilterRight.SetParameters(&bqbase, &bqmain, prev_cutoff + FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate);
972                  }                  }
973              }              }
974    
975              //same as 'pEngine->pBasicFilterParameters[i] = bqbase;'              //same as 'pEngine->pBasicFilterParameters[i] = bqbase;'
976              bq    = (float*) &pEngine->pBasicFilterParameters[i];              bq    = (float*) &pEngine->pBasicFilterParameters[i];
977              bq[0] = bqbase.a1;              bq[0] = bqbase.b0;
978              bq[1] = bqbase.a2;              bq[1] = bqbase.b1;
979              bq[2] = bqbase.b0;              bq[2] = bqbase.b2;
980              bq[3] = bqbase.b1;              bq[3] = bqbase.a1;
981              bq[4] = bqbase.b2;              bq[4] = bqbase.a2;
982    
983              // same as 'pEngine->pMainFilterParameters[i] = bqmain;'              // same as 'pEngine->pMainFilterParameters[i] = bqmain;'
984              bq    = (float*) &pEngine->pMainFilterParameters[i];              bq    = (float*) &pEngine->pMainFilterParameters[i];
985              bq[0] = bqmain.a1;              bq[0] = bqmain.b0;
986              bq[1] = bqmain.a2;              bq[1] = bqmain.b1;
987              bq[2] = bqmain.b0;              bq[2] = bqmain.b2;
988              bq[3] = bqmain.b1;              bq[3] = bqmain.a1;
989              bq[4] = bqmain.b2;              bq[4] = bqmain.a2;
990          }          }
991      }      }
992    
# Line 970  namespace LinuxSampler { namespace gig { Line 998  namespace LinuxSampler { namespace gig {
998       *  @param pSrc    - pointer to input sample data       *  @param pSrc    - pointer to input sample data
999       *  @param Skip    - number of sample points to skip in output buffer       *  @param Skip    - number of sample points to skip in output buffer
1000       */       */
1001      void Voice::Synthesize(uint Samples, sample_t* pSrc, int Skip) {      void Voice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {
1002          UpdateSynthesisMode();          RunSynthesisFunction(SynthesisMode, *this, Samples, pSrc, Skip);
         SynthesizeFragment_Fn* f = (SynthesizeFragment_Fn*) SynthesizeFragmentFnPtr;  
         f(*this, Samples, pSrc, Skip);  
     }  
   
     /**  
      *  Determine the respective synthesis function for the given synthesis  
      *  mode.  
      */  
     void Voice::UpdateSynthesisMode() {  
         SynthesizeFragmentFnPtr = GetSynthesisFunction(SynthesisMode);  
1003      }      }
1004    
1005      /**      /**

Legend:
Removed from v.322  
changed lines
  Added in v.407

  ViewVC Help
Powered by ViewVC