/[svn]/linuxsampler/trunk/src/engines/common/AbstractVoice.cpp
ViewVC logotype

Diff of /linuxsampler/trunk/src/engines/common/AbstractVoice.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 2205 by iliev, Mon Jul 11 17:52:01 2011 UTC revision 2219 by iliev, Thu Jul 28 12:35:49 2011 UTC
# Line 26  Line 26 
26    
27  namespace LinuxSampler {  namespace LinuxSampler {
28    
29      AbstractVoice::AbstractVoice() {      AbstractVoice::AbstractVoice(SignalUnitRack* pRack): pSignalUnitRack(pRack) {
30          pEngineChannel = NULL;          pEngineChannel = NULL;
31          pLFO1 = new LFOUnsigned(1.0f);  // amplitude LFO (0..1 range)          pLFO1 = new LFOUnsigned(1.0f);  // amplitude LFO (0..1 range)
32          pLFO2 = new LFOUnsigned(1.0f);  // filter LFO (0..1 range)          pLFO2 = new LFOUnsigned(1.0f);  // filter LFO (0..1 range)
# Line 99  namespace LinuxSampler { Line 99  namespace LinuxSampler {
99    
100          Type            = VoiceType;          Type            = VoiceType;
101          MIDIKey         = itNoteOnEvent->Param.Note.Key;          MIDIKey         = itNoteOnEvent->Param.Note.Key;
102            MIDIVelocity    = itNoteOnEvent->Param.Note.Velocity;
103            MIDIPan         = pEngineChannel->ControllerTable[10];
104            if (MIDIPan == 0 && pEngineChannel->GlobalPanRight == 1) MIDIPan = 64; // workaround used to determine whether the MIDI pan has not been set
105          PlaybackState   = playback_state_init; // mark voice as triggered, but no audio rendered yet          PlaybackState   = playback_state_init; // mark voice as triggered, but no audio rendered yet
106          Delay           = itNoteOnEvent->FragmentPos();          Delay           = itNoteOnEvent->FragmentPos();
107          itTriggerEvent  = itNoteOnEvent;          itTriggerEvent  = itNoteOnEvent;
# Line 135  namespace LinuxSampler { Line 138  namespace LinuxSampler {
138          PanLeftSmoother.trigger(pEngineChannel->GlobalPanLeft, subfragmentRate);          PanLeftSmoother.trigger(pEngineChannel->GlobalPanLeft, subfragmentRate);
139          PanRightSmoother.trigger(pEngineChannel->GlobalPanRight, subfragmentRate);          PanRightSmoother.trigger(pEngineChannel->GlobalPanRight, subfragmentRate);
140    
         finalSynthesisParameters.dPos = RgnInfo.SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)  
         Pos = RgnInfo.SampleStartOffset;  
   
141          // 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
142          long cachedsamples = GetSampleCacheSize() / SmplInfo.FrameSize;          long cachedsamples = GetSampleCacheSize() / SmplInfo.FrameSize;
143          DiskVoice          = cachedsamples < SmplInfo.TotalFrameCount;          DiskVoice          = cachedsamples < SmplInfo.TotalFrameCount;
144    
145            SetSampleStartOffset();
146    
147          if (DiskVoice) { // voice to be streamed from disk          if (DiskVoice) { // voice to be streamed from disk
148              if (cachedsamples > (GetEngine()->MaxSamplesPerCycle << CONFIG_MAX_PITCH)) {              if (cachedsamples > (GetEngine()->MaxSamplesPerCycle << CONFIG_MAX_PITCH)) {
149                  MaxRAMPos = cachedsamples - (GetEngine()->MaxSamplesPerCycle << CONFIG_MAX_PITCH) / SmplInfo.ChannelCount; //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 - (GetEngine()->MaxSamplesPerCycle << CONFIG_MAX_PITCH) / SmplInfo.ChannelCount; //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)
# Line 178  namespace LinuxSampler { Line 180  namespace LinuxSampler {
180          // the length of the decay and release curves are dependent on the velocity          // the length of the decay and release curves are dependent on the velocity
181          const double velrelease = 1 / GetVelocityRelease(itNoteOnEvent->Param.Note.Velocity);          const double velrelease = 1 / GetVelocityRelease(itNoteOnEvent->Param.Note.Velocity);
182    
183          if (GetSignalUnitRack() == NULL) { // setup EG 1 (VCA EG)          if (pSignalUnitRack == NULL) { // setup EG 1 (VCA EG)
184              // get current value of EG1 controller              // get current value of EG1 controller
185              double eg1controllervalue = GetEG1ControllerValue(itNoteOnEvent->Param.Note.Velocity);              double eg1controllervalue = GetEG1ControllerValue(itNoteOnEvent->Param.Note.Velocity);
186    
# Line 187  namespace LinuxSampler { Line 189  namespace LinuxSampler {
189    
190              TriggerEG1(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity);              TriggerEG1(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity);
191          } else {          } else {
192              GetSignalUnitRack()->Trigger();              pSignalUnitRack->Trigger();
193          }          }
194    
195  #ifdef CONFIG_INTERPOLATE_VOLUME  #ifdef CONFIG_INTERPOLATE_VOLUME
# Line 201  namespace LinuxSampler { Line 203  namespace LinuxSampler {
203      #else      #else
204          {          {
205              float finalVolume;              float finalVolume;
206              if (GetSignalUnitRack() == NULL) {              if (pSignalUnitRack == NULL) {
207                  finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pEG1->getLevel();                  finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pEG1->getLevel();
208              } else {              } else {
209                  finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * GetSignalUnitRack()->GetEndpointUnit()->GetVolume();                  finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pSignalUnitRack->GetEndpointUnit()->GetVolume();
210              }              }
211    
212              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * pEngineChannel->GlobalPanLeft;              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * pEngineChannel->GlobalPanLeft;
# Line 213  namespace LinuxSampler { Line 215  namespace LinuxSampler {
215      #endif      #endif
216  #endif  #endif
217    
218          if (GetSignalUnitRack() == NULL) {          if (pSignalUnitRack == NULL) {
219              // setup EG 2 (VCF Cutoff EG)              // setup EG 2 (VCF Cutoff EG)
220              {              {
221                  // get current value of EG2 controller                  // get current value of EG2 controller
# Line 295  namespace LinuxSampler { Line 297  namespace LinuxSampler {
297    
298          return 0; // success          return 0; // success
299      }      }
300        
301        void AbstractVoice::SetSampleStartOffset() {
302            finalSynthesisParameters.dPos = RgnInfo.SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)
303            Pos = RgnInfo.SampleStartOffset;
304        }
305    
306      /**      /**
307       *  Synthesizes the current audio fragment for this voice.       *  Synthesizes the current audio fragment for this voice.
# Line 352  namespace LinuxSampler { Line 359  namespace LinuxSampler {
359                  // drivers that use Samples < MaxSamplesPerCycle).                  // drivers that use Samples < MaxSamplesPerCycle).
360                  // End the EG1 here, at pos 0, with a shorter max fade                  // End the EG1 here, at pos 0, with a shorter max fade
361                  // out time.                  // out time.
362                  if (GetSignalUnitRack() == NULL) {                  if (pSignalUnitRack == NULL) {
363                      pEG1->enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                      pEG1->enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
364                  } else {                  } else {
365                      // TODO:                      // TODO:
# Line 373  namespace LinuxSampler { Line 380  namespace LinuxSampler {
380    
381              // process MIDI control change and pitchbend events for this subfragment              // process MIDI control change and pitchbend events for this subfragment
382              processCCEvents(itCCEvent, iSubFragmentEnd);              processCCEvents(itCCEvent, iSubFragmentEnd);
383                uint8_t pan = MIDIPan;
384                if (pSignalUnitRack != NULL) pan = pSignalUnitRack->GetEndpointUnit()->CaluclatePan(pan);
385                
386                PanLeftSmoother.update(AbstractEngine::PanCurve[128 - pan]);
387                PanRightSmoother.update(AbstractEngine::PanCurve[pan]);
388    
389              finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend;              finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend;
390              float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render();              float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render();
# Line 384  namespace LinuxSampler { Line 396  namespace LinuxSampler {
396              processTransitionEvents(itNoteEvent, iSubFragmentEnd);              processTransitionEvents(itNoteEvent, iSubFragmentEnd);
397              processGroupEvents(itGroupEvent, iSubFragmentEnd);              processGroupEvents(itGroupEvent, iSubFragmentEnd);
398    
399              if (GetSignalUnitRack() == NULL) {              if (pSignalUnitRack == NULL) {
400                  // if the voice was killed in this subfragment, or if the                  // if the voice was killed in this subfragment, or if the
401                  // filter EG is finished, switch EG1 to fade out stage                  // filter EG is finished, switch EG1 to fade out stage
402                  if ((itKillEvent && killPos <= iSubFragmentEnd) ||                  if ((itKillEvent && killPos <= iSubFragmentEnd) ||
# Line 440  namespace LinuxSampler { Line 452  namespace LinuxSampler {
452                  }*/                  }*/
453                  // TODO: ^^^                  // TODO: ^^^
454    
455                  fFinalVolume   *= GetSignalUnitRack()->GetEndpointUnit()->GetVolume();                  fFinalVolume   *= pSignalUnitRack->GetEndpointUnit()->GetVolume();
456                  fFinalCutoff    = GetSignalUnitRack()->GetEndpointUnit()->CalculateFilterCutoff(fFinalCutoff);                  fFinalCutoff    = pSignalUnitRack->GetEndpointUnit()->CalculateFilterCutoff(fFinalCutoff);
457                  fFinalResonance = GetSignalUnitRack()->GetEndpointUnit()->CalculateResonance(fFinalResonance);                  fFinalResonance = pSignalUnitRack->GetEndpointUnit()->CalculateResonance(fFinalResonance);
458                                    
459                  finalSynthesisParameters.fFinalPitch =                  finalSynthesisParameters.fFinalPitch =
460                      GetSignalUnitRack()->GetEndpointUnit()->CalculatePitch(finalSynthesisParameters.fFinalPitch);                      pSignalUnitRack->GetEndpointUnit()->CalculatePitch(finalSynthesisParameters.fFinalPitch);
461                                            
462              }              }
463                            
# Line 483  namespace LinuxSampler { Line 495  namespace LinuxSampler {
495              // render audio for one subfragment              // render audio for one subfragment
496              RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);              RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);
497    
498              if (GetSignalUnitRack() == NULL) {              if (pSignalUnitRack == NULL) {
499                  // stop the rendering if volume EG is finished                  // stop the rendering if volume EG is finished
500                  if (pEG1->getSegmentType() == EG::segment_end) break;                  if (pEG1->getSegmentType() == EG::segment_end) break;
501              } else {              } else {
502                  // stop the rendering if the endpoint unit is not active                  // stop the rendering if the endpoint unit is not active
503                  if (!GetSignalUnitRack()->GetEndpointUnit()->Active()) break;                  if (!pSignalUnitRack->GetEndpointUnit()->Active()) break;
504              }              }
505    
506              const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;              const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;
507    
508              if (GetSignalUnitRack() == NULL) {              if (pSignalUnitRack == NULL) {
509                  // increment envelopes' positions                  // increment envelopes' positions
510                  if (pEG1->active()) {                  if (pEG1->active()) {
511    
# Line 518  namespace LinuxSampler { Line 530  namespace LinuxSampler {
530                      }*/                      }*/
531                  // TODO: ^^^                  // TODO: ^^^
532                                    
533                  GetSignalUnitRack()->Increment();                  pSignalUnitRack->Increment();
534              }              }
535    
536              Pos = newPos;              Pos = newPos;
# Line 550  namespace LinuxSampler { Line 562  namespace LinuxSampler {
562                  if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {                  if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {
563                      processResonanceEvent(itEvent);                      processResonanceEvent(itEvent);
564                  }                  }
565                  if (GetSignalUnitRack() == NULL) {                  if (pSignalUnitRack == NULL) {
566                      if (itEvent->Param.CC.Controller == pLFO1->ExtController) {                      if (itEvent->Param.CC.Controller == pLFO1->ExtController) {
567                          pLFO1->update(itEvent->Param.CC.Value);                          pLFO1->update(itEvent->Param.CC.Value);
568                      }                      }
# Line 564  namespace LinuxSampler { Line 576  namespace LinuxSampler {
576                  if (itEvent->Param.CC.Controller == 7) { // volume                  if (itEvent->Param.CC.Controller == 7) { // volume
577                      VolumeSmoother.update(AbstractEngine::VolumeCurve[itEvent->Param.CC.Value]);                      VolumeSmoother.update(AbstractEngine::VolumeCurve[itEvent->Param.CC.Value]);
578                  } else if (itEvent->Param.CC.Controller == 10) { // panpot                  } else if (itEvent->Param.CC.Controller == 10) { // panpot
579                      PanLeftSmoother.update(AbstractEngine::PanCurve[128 - itEvent->Param.CC.Value]);                      MIDIPan = itEvent->Param.CC.Value;
                     PanRightSmoother.update(AbstractEngine::PanCurve[itEvent->Param.CC.Value]);  
580                  }                  }
581              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event
582                  processPitchEvent(itEvent);                  processPitchEvent(itEvent);
583              }              }
584    
585              ProcessCCEvent(itEvent);              ProcessCCEvent(itEvent);
586              if (GetSignalUnitRack() != NULL) {              if (pSignalUnitRack != NULL) {
587                  GetSignalUnitRack()->ProcessCCEvent(itEvent);                  pSignalUnitRack->ProcessCCEvent(itEvent);
588              }              }
589          }          }
590      }      }
# Line 606  namespace LinuxSampler { Line 617  namespace LinuxSampler {
617                  if (itEvent->Type == Event::type_release) {                  if (itEvent->Type == Event::type_release) {
618                      EnterReleaseStage();                      EnterReleaseStage();
619                  } else if (itEvent->Type == Event::type_cancel_release) {                  } else if (itEvent->Type == Event::type_cancel_release) {
620                      if (GetSignalUnitRack() == NULL) {                      if (pSignalUnitRack == NULL) {
621                          pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                          pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
622                          pEG2->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                          pEG2->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
623                      } else {                      } else {
624                          GetSignalUnitRack()->CancelRelease();                          pSignalUnitRack->CancelRelease();
625                      }                      }
626                  }                  }
627              }              }
# Line 638  namespace LinuxSampler { Line 649  namespace LinuxSampler {
649       * @param itNoteOffEvent - event which causes this voice to die soon       * @param itNoteOffEvent - event which causes this voice to die soon
650       */       */
651      void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {      void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {
652          if (GetSignalUnitRack() == NULL) {          if (pSignalUnitRack == NULL) {
653              const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());              const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());
654              pEngineChannel->PortamentoPos = (float) MIDIKey + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;              pEngineChannel->PortamentoPos = (float) MIDIKey + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;
655          } else {          } else {
# Line 705  namespace LinuxSampler { Line 716  namespace LinuxSampler {
716      }      }
717    
718      void AbstractVoice::EnterReleaseStage() {      void AbstractVoice::EnterReleaseStage() {
719          if (GetSignalUnitRack() == NULL) {          if (pSignalUnitRack == NULL) {
720              pEG1->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);              pEG1->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
721              pEG2->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);              pEG2->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
722          } else {          } else {
723              GetSignalUnitRack()->EnterReleaseStage();              pSignalUnitRack->EnterReleaseStage();
724          }          }
725      }      }
726    
727      bool AbstractVoice::EG1Finished() {      bool AbstractVoice::EG1Finished() {
728          if (GetSignalUnitRack() == NULL) {          if (pSignalUnitRack == NULL) {
729              return pEG1->getSegmentType() == EG::segment_end;              return pEG1->getSegmentType() == EG::segment_end;
730          } else {          } else {
731              return !GetSignalUnitRack()->GetEndpointUnit()->Active();              return !pSignalUnitRack->GetEndpointUnit()->Active();
732          }          }
733      }      }
734    

Legend:
Removed from v.2205  
changed lines
  Added in v.2219

  ViewVC Help
Powered by ViewVC