/[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 2216 by iliev, Mon Jul 25 17:21:16 2011 UTC revision 2298 by iliev, Fri Dec 9 17:04:24 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 43  namespace LinuxSampler { Line 43  namespace LinuxSampler {
43    
44          finalSynthesisParameters.filterLeft.Reset();          finalSynthesisParameters.filterLeft.Reset();
45          finalSynthesisParameters.filterRight.Reset();          finalSynthesisParameters.filterRight.Reset();
46            
47            pEq          = NULL;
48            bEqSupport   = false;
49      }      }
50    
51      AbstractVoice::~AbstractVoice() {      AbstractVoice::~AbstractVoice() {
52          if (pLFO1) delete pLFO1;          if (pLFO1) delete pLFO1;
53          if (pLFO2) delete pLFO2;          if (pLFO2) delete pLFO2;
54          if (pLFO3) delete pLFO3;          if (pLFO3) delete pLFO3;
55            
56            if(pEq != NULL) delete pEq;
57        }
58                
59        void AbstractVoice::CreateEq() {
60            if(!bEqSupport) return;
61            if(pEq != NULL) delete pEq;
62            pEq = new EqSupport;
63            pEq->InitEffect(GetEngine()->pAudioOutputDevice);
64      }      }
65    
66      /**      /**
# Line 99  namespace LinuxSampler { Line 111  namespace LinuxSampler {
111    
112          Type            = VoiceType;          Type            = VoiceType;
113          MIDIKey         = itNoteOnEvent->Param.Note.Key;          MIDIKey         = itNoteOnEvent->Param.Note.Key;
114            MIDIVelocity    = itNoteOnEvent->Param.Note.Velocity;
115            MIDIPan         = pEngineChannel->ControllerTable[10];
116            if (MIDIPan == 0 && pEngineChannel->GlobalPanRight == 1) MIDIPan = 64; // workaround used to determine whether the MIDI pan has not been set
117          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
118          Delay           = itNoteOnEvent->FragmentPos();          Delay           = itNoteOnEvent->FragmentPos();
119          itTriggerEvent  = itNoteOnEvent;          itTriggerEvent  = itNoteOnEvent;
# Line 177  namespace LinuxSampler { Line 192  namespace LinuxSampler {
192          // 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
193          const double velrelease = 1 / GetVelocityRelease(itNoteOnEvent->Param.Note.Velocity);          const double velrelease = 1 / GetVelocityRelease(itNoteOnEvent->Param.Note.Velocity);
194    
195          if (GetSignalUnitRack() == NULL) { // setup EG 1 (VCA EG)          if (pSignalUnitRack == NULL) { // setup EG 1 (VCA EG)
196              // get current value of EG1 controller              // get current value of EG1 controller
197              double eg1controllervalue = GetEG1ControllerValue(itNoteOnEvent->Param.Note.Velocity);              double eg1controllervalue = GetEG1ControllerValue(itNoteOnEvent->Param.Note.Velocity);
198    
# Line 186  namespace LinuxSampler { Line 201  namespace LinuxSampler {
201    
202              TriggerEG1(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity);              TriggerEG1(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity);
203          } else {          } else {
204              GetSignalUnitRack()->Trigger();              pSignalUnitRack->Trigger();
205          }          }
206    
207  #ifdef CONFIG_INTERPOLATE_VOLUME  #ifdef CONFIG_INTERPOLATE_VOLUME
# Line 200  namespace LinuxSampler { Line 215  namespace LinuxSampler {
215      #else      #else
216          {          {
217              float finalVolume;              float finalVolume;
218              if (GetSignalUnitRack() == NULL) {              if (pSignalUnitRack == NULL) {
219                  finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pEG1->getLevel();                  finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pEG1->getLevel();
220              } else {              } else {
221                  finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * GetSignalUnitRack()->GetEndpointUnit()->GetVolume();                  finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pSignalUnitRack->GetEndpointUnit()->GetVolume();
222              }              }
223    
224              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * pEngineChannel->GlobalPanLeft;              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * pEngineChannel->GlobalPanLeft;
# Line 212  namespace LinuxSampler { Line 227  namespace LinuxSampler {
227      #endif      #endif
228  #endif  #endif
229    
230          if (GetSignalUnitRack() == NULL) {          if (pSignalUnitRack == NULL) {
231              // setup EG 2 (VCF Cutoff EG)              // setup EG 2 (VCF Cutoff EG)
232              {              {
233                  // get current value of EG2 controller                  // get current value of EG2 controller
# Line 309  namespace LinuxSampler { Line 324  namespace LinuxSampler {
324       *  @param Skip    - number of sample points to skip in output buffer       *  @param Skip    - number of sample points to skip in output buffer
325       */       */
326      void AbstractVoice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {      void AbstractVoice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {
327            bool delay = false; // Whether the voice playback should be delayed for this call
328            
329            if (pSignalUnitRack != NULL) {
330                uint delaySteps = pSignalUnitRack->GetEndpointUnit()->DelayTrigger();
331                if (delaySteps > 0) { // delay on the endpoint unit means delay of the voice playback
332                    if (delaySteps >= Samples) {
333                        pSignalUnitRack->GetEndpointUnit()->DecreaseDelay(Samples);
334                        delay = true;
335                    } else {
336                        pSignalUnitRack->GetEndpointUnit()->DecreaseDelay(delaySteps);
337                        Samples -= delaySteps;
338                        Skip += delaySteps;
339                    }
340                }
341            }
342            
343          AbstractEngineChannel* pChannel = pEngineChannel;          AbstractEngineChannel* pChannel = pEngineChannel;
344          MidiKeyBase* pMidiKeyInfo = GetMidiKeyInfo(MIDIKey);          MidiKeyBase* pMidiKeyInfo = GetMidiKeyInfo(MIDIKey);
345    
346          const bool bVoiceRequiresDedicatedRouting =          const bool bVoiceRequiresDedicatedRouting =
347              pEngineChannel->GetFxSendCount() > 0 &&              pEngineChannel->GetFxSendCount() > 0 &&
348              (pMidiKeyInfo->ReverbSend || pMidiKeyInfo->ChorusSend);              (pMidiKeyInfo->ReverbSend || pMidiKeyInfo->ChorusSend);
349            
350            const bool bEq =
351                pSignalUnitRack != NULL && pSignalUnitRack->HasEq() && pEq->HasSupport();
352    
353          if (bVoiceRequiresDedicatedRouting) {          if (bEq) {
354                pEq->GetInChannelLeft()->Clear();
355                pEq->GetInChannelRight()->Clear();
356                finalSynthesisParameters.pOutLeft  = &pEq->GetInChannelLeft()->Buffer()[Skip];
357                finalSynthesisParameters.pOutRight = &pEq->GetInChannelRight()->Buffer()[Skip];
358                pSignalUnitRack->UpdateEqSettings(pEq);
359            } else if (bVoiceRequiresDedicatedRouting) {
360              finalSynthesisParameters.pOutLeft  = &GetEngine()->pDedicatedVoiceChannelLeft->Buffer()[Skip];              finalSynthesisParameters.pOutLeft  = &GetEngine()->pDedicatedVoiceChannelLeft->Buffer()[Skip];
361              finalSynthesisParameters.pOutRight = &GetEngine()->pDedicatedVoiceChannelRight->Buffer()[Skip];              finalSynthesisParameters.pOutRight = &GetEngine()->pDedicatedVoiceChannelRight->Buffer()[Skip];
362          } else {          } else {
# Line 356  namespace LinuxSampler { Line 396  namespace LinuxSampler {
396                  // drivers that use Samples < MaxSamplesPerCycle).                  // drivers that use Samples < MaxSamplesPerCycle).
397                  // End the EG1 here, at pos 0, with a shorter max fade                  // End the EG1 here, at pos 0, with a shorter max fade
398                  // out time.                  // out time.
399                  if (GetSignalUnitRack() == NULL) {                  if (pSignalUnitRack == NULL) {
400                      pEG1->enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                      pEG1->enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
401                  } else {                  } else {
402                      // TODO:                      // TODO:
# Line 377  namespace LinuxSampler { Line 417  namespace LinuxSampler {
417    
418              // process MIDI control change and pitchbend events for this subfragment              // process MIDI control change and pitchbend events for this subfragment
419              processCCEvents(itCCEvent, iSubFragmentEnd);              processCCEvents(itCCEvent, iSubFragmentEnd);
420                uint8_t pan = MIDIPan;
421                if (pSignalUnitRack != NULL) pan = pSignalUnitRack->GetEndpointUnit()->CaluclatePan(pan);
422                
423                PanLeftSmoother.update(AbstractEngine::PanCurve[128 - pan]);
424                PanRightSmoother.update(AbstractEngine::PanCurve[pan]);
425    
426              finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend;              finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend;
427              float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render();              float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render();
# Line 387  namespace LinuxSampler { Line 432  namespace LinuxSampler {
432              // process transition events (note on, note off & sustain pedal)              // process transition events (note on, note off & sustain pedal)
433              processTransitionEvents(itNoteEvent, iSubFragmentEnd);              processTransitionEvents(itNoteEvent, iSubFragmentEnd);
434              processGroupEvents(itGroupEvent, iSubFragmentEnd);              processGroupEvents(itGroupEvent, iSubFragmentEnd);
435                
436              if (GetSignalUnitRack() == NULL) {              if (pSignalUnitRack == NULL) {
437                  // if the voice was killed in this subfragment, or if the                  // if the voice was killed in this subfragment, or if the
438                  // filter EG is finished, switch EG1 to fade out stage                  // filter EG is finished, switch EG1 to fade out stage
439                  if ((itKillEvent && killPos <= iSubFragmentEnd) ||                  if ((itKillEvent && killPos <= iSubFragmentEnd) ||
# Line 444  namespace LinuxSampler { Line 489  namespace LinuxSampler {
489                  }*/                  }*/
490                  // TODO: ^^^                  // TODO: ^^^
491    
492                  fFinalVolume   *= GetSignalUnitRack()->GetEndpointUnit()->GetVolume();                  fFinalVolume   *= pSignalUnitRack->GetEndpointUnit()->GetVolume();
493                  fFinalCutoff    = GetSignalUnitRack()->GetEndpointUnit()->CalculateFilterCutoff(fFinalCutoff);                  fFinalCutoff    = pSignalUnitRack->GetEndpointUnit()->CalculateFilterCutoff(fFinalCutoff);
494                  fFinalResonance = GetSignalUnitRack()->GetEndpointUnit()->CalculateResonance(fFinalResonance);                  fFinalResonance = pSignalUnitRack->GetEndpointUnit()->CalculateResonance(fFinalResonance);
495                                    
496                  finalSynthesisParameters.fFinalPitch =                  finalSynthesisParameters.fFinalPitch =
497                      GetSignalUnitRack()->GetEndpointUnit()->CalculatePitch(finalSynthesisParameters.fFinalPitch);                      pSignalUnitRack->GetEndpointUnit()->CalculatePitch(finalSynthesisParameters.fFinalPitch);
498                                            
499              }              }
500                            
# Line 485  namespace LinuxSampler { Line 530  namespace LinuxSampler {
530                  fFinalVolume * VolumeRight * PanRightSmoother.render();                  fFinalVolume * VolumeRight * PanRightSmoother.render();
531  #endif  #endif
532              // render audio for one subfragment              // render audio for one subfragment
533              RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);              if (!delay) RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);
534    
535              if (GetSignalUnitRack() == NULL) {              if (pSignalUnitRack == NULL) {
536                  // stop the rendering if volume EG is finished                  // stop the rendering if volume EG is finished
537                  if (pEG1->getSegmentType() == EG::segment_end) break;                  if (pEG1->getSegmentType() == EG::segment_end) break;
538              } else {              } else {
539                  // stop the rendering if the endpoint unit is not active                  // stop the rendering if the endpoint unit is not active
540                  if (!GetSignalUnitRack()->GetEndpointUnit()->Active()) break;                  if (!pSignalUnitRack->GetEndpointUnit()->Active()) break;
541              }              }
542    
543              const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;              const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;
544    
545              if (GetSignalUnitRack() == NULL) {              if (pSignalUnitRack == NULL) {
546                  // increment envelopes' positions                  // increment envelopes' positions
547                  if (pEG1->active()) {                  if (pEG1->active()) {
548    
# Line 522  namespace LinuxSampler { Line 567  namespace LinuxSampler {
567                      }*/                      }*/
568                  // TODO: ^^^                  // TODO: ^^^
569                                    
570                  GetSignalUnitRack()->Increment();                  if (!delay) pSignalUnitRack->Increment();
571              }              }
572    
573              Pos = newPos;              Pos = newPos;
574              i = iSubFragmentEnd;              i = iSubFragmentEnd;
575          }          }
576            
577            if (delay) return;
578    
579          if (bVoiceRequiresDedicatedRouting) {          if (bVoiceRequiresDedicatedRouting) {
580                if (bEq) {
581                    pEq->RenderAudio(Samples);
582                    pEq->GetOutChannelLeft()->CopyTo(GetEngine()->pDedicatedVoiceChannelLeft, Samples);
583                    pEq->GetOutChannelRight()->CopyTo(GetEngine()->pDedicatedVoiceChannelRight, Samples);
584                }
585              optional<float> effectSendLevels[2] = {              optional<float> effectSendLevels[2] = {
586                  pMidiKeyInfo->ReverbSend,                  pMidiKeyInfo->ReverbSend,
587                  pMidiKeyInfo->ChorusSend                  pMidiKeyInfo->ChorusSend
588              };              };
589              GetEngine()->RouteDedicatedVoiceChannels(pEngineChannel, effectSendLevels, Samples);              GetEngine()->RouteDedicatedVoiceChannels(pEngineChannel, effectSendLevels, Samples);
590            } else if (bEq) {
591                pEq->RenderAudio(Samples);
592                pEq->GetOutChannelLeft()->MixTo(pChannel->pChannelLeft, Samples);
593                pEq->GetOutChannelRight()->MixTo(pChannel->pChannelRight, Samples);
594          }          }
595      }      }
596    
# Line 554  namespace LinuxSampler { Line 610  namespace LinuxSampler {
610                  if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {                  if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {
611                      processResonanceEvent(itEvent);                      processResonanceEvent(itEvent);
612                  }                  }
613                  if (GetSignalUnitRack() == NULL) {                  if (pSignalUnitRack == NULL) {
614                      if (itEvent->Param.CC.Controller == pLFO1->ExtController) {                      if (itEvent->Param.CC.Controller == pLFO1->ExtController) {
615                          pLFO1->update(itEvent->Param.CC.Value);                          pLFO1->update(itEvent->Param.CC.Value);
616                      }                      }
# Line 568  namespace LinuxSampler { Line 624  namespace LinuxSampler {
624                  if (itEvent->Param.CC.Controller == 7) { // volume                  if (itEvent->Param.CC.Controller == 7) { // volume
625                      VolumeSmoother.update(AbstractEngine::VolumeCurve[itEvent->Param.CC.Value]);                      VolumeSmoother.update(AbstractEngine::VolumeCurve[itEvent->Param.CC.Value]);
626                  } else if (itEvent->Param.CC.Controller == 10) { // panpot                  } else if (itEvent->Param.CC.Controller == 10) { // panpot
627                      PanLeftSmoother.update(AbstractEngine::PanCurve[128 - itEvent->Param.CC.Value]);                      MIDIPan = itEvent->Param.CC.Value;
                     PanRightSmoother.update(AbstractEngine::PanCurve[itEvent->Param.CC.Value]);  
628                  }                  }
629              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event
630                  processPitchEvent(itEvent);                  processPitchEvent(itEvent);
631              }              }
632    
633              ProcessCCEvent(itEvent);              ProcessCCEvent(itEvent);
634              if (GetSignalUnitRack() != NULL) {              if (pSignalUnitRack != NULL) {
635                  GetSignalUnitRack()->ProcessCCEvent(itEvent);                  pSignalUnitRack->ProcessCCEvent(itEvent);
636              }              }
637          }          }
638      }      }
# Line 610  namespace LinuxSampler { Line 665  namespace LinuxSampler {
665                  if (itEvent->Type == Event::type_release) {                  if (itEvent->Type == Event::type_release) {
666                      EnterReleaseStage();                      EnterReleaseStage();
667                  } else if (itEvent->Type == Event::type_cancel_release) {                  } else if (itEvent->Type == Event::type_cancel_release) {
668                      if (GetSignalUnitRack() == NULL) {                      if (pSignalUnitRack == NULL) {
669                          pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                          pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
670                          pEG2->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                          pEG2->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
671                      } else {                      } else {
672                          GetSignalUnitRack()->CancelRelease();                          pSignalUnitRack->CancelRelease();
673                      }                      }
674                  }                  }
675              }              }
# Line 642  namespace LinuxSampler { Line 697  namespace LinuxSampler {
697       * @param itNoteOffEvent - event which causes this voice to die soon       * @param itNoteOffEvent - event which causes this voice to die soon
698       */       */
699      void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {      void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {
700          if (GetSignalUnitRack() == NULL) {          if (pSignalUnitRack == NULL) {
701              const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());              const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());
702              pEngineChannel->PortamentoPos = (float) MIDIKey + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;              pEngineChannel->PortamentoPos = (float) MIDIKey + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;
703          } else {          } else {
# Line 709  namespace LinuxSampler { Line 764  namespace LinuxSampler {
764      }      }
765    
766      void AbstractVoice::EnterReleaseStage() {      void AbstractVoice::EnterReleaseStage() {
767          if (GetSignalUnitRack() == NULL) {          if (pSignalUnitRack == NULL) {
768              pEG1->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);              pEG1->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
769              pEG2->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);              pEG2->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
770          } else {          } else {
771              GetSignalUnitRack()->EnterReleaseStage();              pSignalUnitRack->EnterReleaseStage();
772          }          }
773      }      }
774    
775      bool AbstractVoice::EG1Finished() {      bool AbstractVoice::EG1Finished() {
776          if (GetSignalUnitRack() == NULL) {          if (pSignalUnitRack == NULL) {
777              return pEG1->getSegmentType() == EG::segment_end;              return pEG1->getSegmentType() == EG::segment_end;
778          } else {          } else {
779              return !GetSignalUnitRack()->GetEndpointUnit()->Active();              return !pSignalUnitRack->GetEndpointUnit()->Active();
780          }          }
781      }      }
782    

Legend:
Removed from v.2216  
changed lines
  Added in v.2298

  ViewVC Help
Powered by ViewVC