/[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 2296 by iliev, Thu Dec 8 20:03:47 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 177  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 186  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 200  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 212  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 315  namespace LinuxSampler { Line 318  namespace LinuxSampler {
318          const bool bVoiceRequiresDedicatedRouting =          const bool bVoiceRequiresDedicatedRouting =
319              pEngineChannel->GetFxSendCount() > 0 &&              pEngineChannel->GetFxSendCount() > 0 &&
320              (pMidiKeyInfo->ReverbSend || pMidiKeyInfo->ChorusSend);              (pMidiKeyInfo->ReverbSend || pMidiKeyInfo->ChorusSend);
321            
322            const bool bEq =
323                pSignalUnitRack != NULL && pSignalUnitRack->HasEq() && GetEngine()->pEq->HasSupport();
324    
325          if (bVoiceRequiresDedicatedRouting) {          if (bEq) {
326                GetEngine()->pEq->GetInChannelLeft()->Clear();
327                GetEngine()->pEq->GetInChannelRight()->Clear();
328                finalSynthesisParameters.pOutLeft  = &GetEngine()->pEq->GetInChannelLeft()->Buffer()[Skip];
329                finalSynthesisParameters.pOutRight = &GetEngine()->pEq->GetInChannelRight()->Buffer()[Skip];
330                pSignalUnitRack->UpdateEqSettings(GetEngine()->pEq);
331            } else if (bVoiceRequiresDedicatedRouting) {
332              finalSynthesisParameters.pOutLeft  = &GetEngine()->pDedicatedVoiceChannelLeft->Buffer()[Skip];              finalSynthesisParameters.pOutLeft  = &GetEngine()->pDedicatedVoiceChannelLeft->Buffer()[Skip];
333              finalSynthesisParameters.pOutRight = &GetEngine()->pDedicatedVoiceChannelRight->Buffer()[Skip];              finalSynthesisParameters.pOutRight = &GetEngine()->pDedicatedVoiceChannelRight->Buffer()[Skip];
334          } else {          } else {
# Line 356  namespace LinuxSampler { Line 368  namespace LinuxSampler {
368                  // drivers that use Samples < MaxSamplesPerCycle).                  // drivers that use Samples < MaxSamplesPerCycle).
369                  // End the EG1 here, at pos 0, with a shorter max fade                  // End the EG1 here, at pos 0, with a shorter max fade
370                  // out time.                  // out time.
371                  if (GetSignalUnitRack() == NULL) {                  if (pSignalUnitRack == NULL) {
372                      pEG1->enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                      pEG1->enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
373                  } else {                  } else {
374                      // TODO:                      // TODO:
# Line 377  namespace LinuxSampler { Line 389  namespace LinuxSampler {
389    
390              // process MIDI control change and pitchbend events for this subfragment              // process MIDI control change and pitchbend events for this subfragment
391              processCCEvents(itCCEvent, iSubFragmentEnd);              processCCEvents(itCCEvent, iSubFragmentEnd);
392                uint8_t pan = MIDIPan;
393                if (pSignalUnitRack != NULL) pan = pSignalUnitRack->GetEndpointUnit()->CaluclatePan(pan);
394                
395                PanLeftSmoother.update(AbstractEngine::PanCurve[128 - pan]);
396                PanRightSmoother.update(AbstractEngine::PanCurve[pan]);
397    
398              finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend;              finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend;
399              float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render();              float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render();
# Line 388  namespace LinuxSampler { Line 405  namespace LinuxSampler {
405              processTransitionEvents(itNoteEvent, iSubFragmentEnd);              processTransitionEvents(itNoteEvent, iSubFragmentEnd);
406              processGroupEvents(itGroupEvent, iSubFragmentEnd);              processGroupEvents(itGroupEvent, iSubFragmentEnd);
407    
408              if (GetSignalUnitRack() == NULL) {              if (pSignalUnitRack == NULL) {
409                  // if the voice was killed in this subfragment, or if the                  // if the voice was killed in this subfragment, or if the
410                  // filter EG is finished, switch EG1 to fade out stage                  // filter EG is finished, switch EG1 to fade out stage
411                  if ((itKillEvent && killPos <= iSubFragmentEnd) ||                  if ((itKillEvent && killPos <= iSubFragmentEnd) ||
# Line 444  namespace LinuxSampler { Line 461  namespace LinuxSampler {
461                  }*/                  }*/
462                  // TODO: ^^^                  // TODO: ^^^
463    
464                  fFinalVolume   *= GetSignalUnitRack()->GetEndpointUnit()->GetVolume();                  fFinalVolume   *= pSignalUnitRack->GetEndpointUnit()->GetVolume();
465                  fFinalCutoff    = GetSignalUnitRack()->GetEndpointUnit()->CalculateFilterCutoff(fFinalCutoff);                  fFinalCutoff    = pSignalUnitRack->GetEndpointUnit()->CalculateFilterCutoff(fFinalCutoff);
466                  fFinalResonance = GetSignalUnitRack()->GetEndpointUnit()->CalculateResonance(fFinalResonance);                  fFinalResonance = pSignalUnitRack->GetEndpointUnit()->CalculateResonance(fFinalResonance);
467                                    
468                  finalSynthesisParameters.fFinalPitch =                  finalSynthesisParameters.fFinalPitch =
469                      GetSignalUnitRack()->GetEndpointUnit()->CalculatePitch(finalSynthesisParameters.fFinalPitch);                      pSignalUnitRack->GetEndpointUnit()->CalculatePitch(finalSynthesisParameters.fFinalPitch);
470                                            
471              }              }
472                            
# Line 487  namespace LinuxSampler { Line 504  namespace LinuxSampler {
504              // render audio for one subfragment              // render audio for one subfragment
505              RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);              RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);
506    
507              if (GetSignalUnitRack() == NULL) {              if (pSignalUnitRack == NULL) {
508                  // stop the rendering if volume EG is finished                  // stop the rendering if volume EG is finished
509                  if (pEG1->getSegmentType() == EG::segment_end) break;                  if (pEG1->getSegmentType() == EG::segment_end) break;
510              } else {              } else {
511                  // stop the rendering if the endpoint unit is not active                  // stop the rendering if the endpoint unit is not active
512                  if (!GetSignalUnitRack()->GetEndpointUnit()->Active()) break;                  if (!pSignalUnitRack->GetEndpointUnit()->Active()) break;
513              }              }
514    
515              const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;              const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;
516    
517              if (GetSignalUnitRack() == NULL) {              if (pSignalUnitRack == NULL) {
518                  // increment envelopes' positions                  // increment envelopes' positions
519                  if (pEG1->active()) {                  if (pEG1->active()) {
520    
# Line 522  namespace LinuxSampler { Line 539  namespace LinuxSampler {
539                      }*/                      }*/
540                  // TODO: ^^^                  // TODO: ^^^
541                                    
542                  GetSignalUnitRack()->Increment();                  pSignalUnitRack->Increment();
543              }              }
544    
545              Pos = newPos;              Pos = newPos;
# Line 530  namespace LinuxSampler { Line 547  namespace LinuxSampler {
547          }          }
548    
549          if (bVoiceRequiresDedicatedRouting) {          if (bVoiceRequiresDedicatedRouting) {
550                if (bEq) {
551                    GetEngine()->pEq->RenderAudio(Samples);
552                    GetEngine()->pEq->GetOutChannelLeft()->CopyTo(GetEngine()->pDedicatedVoiceChannelLeft, Samples);
553                    GetEngine()->pEq->GetOutChannelRight()->CopyTo(GetEngine()->pDedicatedVoiceChannelRight, Samples);
554                }
555              optional<float> effectSendLevels[2] = {              optional<float> effectSendLevels[2] = {
556                  pMidiKeyInfo->ReverbSend,                  pMidiKeyInfo->ReverbSend,
557                  pMidiKeyInfo->ChorusSend                  pMidiKeyInfo->ChorusSend
558              };              };
559              GetEngine()->RouteDedicatedVoiceChannels(pEngineChannel, effectSendLevels, Samples);              GetEngine()->RouteDedicatedVoiceChannels(pEngineChannel, effectSendLevels, Samples);
560            } else if (bEq) {
561                GetEngine()->pEq->RenderAudio(Samples);
562                GetEngine()->pEq->GetOutChannelLeft()->CopyTo(pChannel->pChannelLeft, Samples);
563                GetEngine()->pEq->GetOutChannelRight()->CopyTo(pChannel->pChannelRight, Samples);
564          }          }
565      }      }
566    
# Line 554  namespace LinuxSampler { Line 580  namespace LinuxSampler {
580                  if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {                  if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {
581                      processResonanceEvent(itEvent);                      processResonanceEvent(itEvent);
582                  }                  }
583                  if (GetSignalUnitRack() == NULL) {                  if (pSignalUnitRack == NULL) {
584                      if (itEvent->Param.CC.Controller == pLFO1->ExtController) {                      if (itEvent->Param.CC.Controller == pLFO1->ExtController) {
585                          pLFO1->update(itEvent->Param.CC.Value);                          pLFO1->update(itEvent->Param.CC.Value);
586                      }                      }
# Line 568  namespace LinuxSampler { Line 594  namespace LinuxSampler {
594                  if (itEvent->Param.CC.Controller == 7) { // volume                  if (itEvent->Param.CC.Controller == 7) { // volume
595                      VolumeSmoother.update(AbstractEngine::VolumeCurve[itEvent->Param.CC.Value]);                      VolumeSmoother.update(AbstractEngine::VolumeCurve[itEvent->Param.CC.Value]);
596                  } else if (itEvent->Param.CC.Controller == 10) { // panpot                  } else if (itEvent->Param.CC.Controller == 10) { // panpot
597                      PanLeftSmoother.update(AbstractEngine::PanCurve[128 - itEvent->Param.CC.Value]);                      MIDIPan = itEvent->Param.CC.Value;
                     PanRightSmoother.update(AbstractEngine::PanCurve[itEvent->Param.CC.Value]);  
598                  }                  }
599              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event
600                  processPitchEvent(itEvent);                  processPitchEvent(itEvent);
601              }              }
602    
603              ProcessCCEvent(itEvent);              ProcessCCEvent(itEvent);
604              if (GetSignalUnitRack() != NULL) {              if (pSignalUnitRack != NULL) {
605                  GetSignalUnitRack()->ProcessCCEvent(itEvent);                  pSignalUnitRack->ProcessCCEvent(itEvent);
606              }              }
607          }          }
608      }      }
# Line 610  namespace LinuxSampler { Line 635  namespace LinuxSampler {
635                  if (itEvent->Type == Event::type_release) {                  if (itEvent->Type == Event::type_release) {
636                      EnterReleaseStage();                      EnterReleaseStage();
637                  } else if (itEvent->Type == Event::type_cancel_release) {                  } else if (itEvent->Type == Event::type_cancel_release) {
638                      if (GetSignalUnitRack() == NULL) {                      if (pSignalUnitRack == NULL) {
639                          pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                          pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
640                          pEG2->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                          pEG2->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
641                      } else {                      } else {
642                          GetSignalUnitRack()->CancelRelease();                          pSignalUnitRack->CancelRelease();
643                      }                      }
644                  }                  }
645              }              }
# Line 642  namespace LinuxSampler { Line 667  namespace LinuxSampler {
667       * @param itNoteOffEvent - event which causes this voice to die soon       * @param itNoteOffEvent - event which causes this voice to die soon
668       */       */
669      void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {      void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {
670          if (GetSignalUnitRack() == NULL) {          if (pSignalUnitRack == NULL) {
671              const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());              const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());
672              pEngineChannel->PortamentoPos = (float) MIDIKey + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;              pEngineChannel->PortamentoPos = (float) MIDIKey + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;
673          } else {          } else {
# Line 709  namespace LinuxSampler { Line 734  namespace LinuxSampler {
734      }      }
735    
736      void AbstractVoice::EnterReleaseStage() {      void AbstractVoice::EnterReleaseStage() {
737          if (GetSignalUnitRack() == NULL) {          if (pSignalUnitRack == NULL) {
738              pEG1->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);              pEG1->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
739              pEG2->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);              pEG2->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
740          } else {          } else {
741              GetSignalUnitRack()->EnterReleaseStage();              pSignalUnitRack->EnterReleaseStage();
742          }          }
743      }      }
744    
745      bool AbstractVoice::EG1Finished() {      bool AbstractVoice::EG1Finished() {
746          if (GetSignalUnitRack() == NULL) {          if (pSignalUnitRack == NULL) {
747              return pEG1->getSegmentType() == EG::segment_end;              return pEG1->getSegmentType() == EG::segment_end;
748          } else {          } else {
749              return !GetSignalUnitRack()->GetEndpointUnit()->Active();              return !pSignalUnitRack->GetEndpointUnit()->Active();
750          }          }
751      }      }
752    

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

  ViewVC Help
Powered by ViewVC