/[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 2175 by persson, Mon Apr 25 08:12:36 2011 UTC revision 2205 by iliev, Mon Jul 11 17:52:01 2011 UTC
# Line 110  namespace LinuxSampler { Line 110  namespace LinuxSampler {
110          SmplInfo   = GetSampleInfo();          SmplInfo   = GetSampleInfo();
111          RgnInfo    = GetRegionInfo();          RgnInfo    = GetRegionInfo();
112          InstrInfo  = GetInstrumentInfo();          InstrInfo  = GetInstrumentInfo();
113            
114            AboutToTrigger();
115    
116          // calculate volume          // calculate volume
117          const double velocityAttenuation = GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity);          const double velocityAttenuation = GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity);
# Line 176  namespace LinuxSampler { Line 178  namespace LinuxSampler {
178          // 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
179          const double velrelease = 1 / GetVelocityRelease(itNoteOnEvent->Param.Note.Velocity);          const double velrelease = 1 / GetVelocityRelease(itNoteOnEvent->Param.Note.Velocity);
180    
181          // setup EG 1 (VCA EG)          if (GetSignalUnitRack() == NULL) { // setup EG 1 (VCA EG)
         {  
182              // get current value of EG1 controller              // get current value of EG1 controller
183              double eg1controllervalue = GetEG1ControllerValue(itNoteOnEvent->Param.Note.Velocity);              double eg1controllervalue = GetEG1ControllerValue(itNoteOnEvent->Param.Note.Velocity);
184    
# Line 185  namespace LinuxSampler { Line 186  namespace LinuxSampler {
186              EGInfo egInfo = CalculateEG1ControllerInfluence(eg1controllervalue);              EGInfo egInfo = CalculateEG1ControllerInfluence(eg1controllervalue);
187    
188              TriggerEG1(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity);              TriggerEG1(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity);
189            } else {
190                GetSignalUnitRack()->Trigger();
191          }          }
192    
193  #ifdef CONFIG_INTERPOLATE_VOLUME  #ifdef CONFIG_INTERPOLATE_VOLUME
# Line 197  namespace LinuxSampler { Line 200  namespace LinuxSampler {
200          else          else
201      #else      #else
202          {          {
203              float finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pEG1->getLevel();              float finalVolume;
204                if (GetSignalUnitRack() == NULL) {
205                    finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pEG1->getLevel();
206                } else {
207                    finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * GetSignalUnitRack()->GetEndpointUnit()->GetVolume();
208                }
209    
210              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * pEngineChannel->GlobalPanLeft;              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * pEngineChannel->GlobalPanLeft;
211              finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * pEngineChannel->GlobalPanRight;              finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * pEngineChannel->GlobalPanRight;
# Line 205  namespace LinuxSampler { Line 213  namespace LinuxSampler {
213      #endif      #endif
214  #endif  #endif
215    
216          // setup EG 2 (VCF Cutoff EG)          if (GetSignalUnitRack() == NULL) {
217          {              // setup EG 2 (VCF Cutoff EG)
218              // get current value of EG2 controller              {
219              double eg2controllervalue = GetEG2ControllerValue(itNoteOnEvent->Param.Note.Velocity);                  // get current value of EG2 controller
220                    double eg2controllervalue = GetEG2ControllerValue(itNoteOnEvent->Param.Note.Velocity);
221    
222                    // calculate influence of EG2 controller on EG2's parameters
223                    EGInfo egInfo = CalculateEG2ControllerInfluence(eg2controllervalue);
224    
225                    TriggerEG2(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity);
226                }
227    
             // calculate influence of EG2 controller on EG2's parameters  
             EGInfo egInfo = CalculateEG2ControllerInfluence(eg2controllervalue);  
228    
229              TriggerEG2(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity);              // setup EG 3 (VCO EG)
230          }              {
231                    // if portamento mode is on, we dedicate EG3 purely for portamento, otherwise if portamento is off we do as told by the patch
232                    bool  bPortamento = pEngineChannel->PortamentoMode && pEngineChannel->PortamentoPos >= 0.0f;
233                    float eg3depth = (bPortamento)
234                                 ? RTMath::CentsToFreqRatio((pEngineChannel->PortamentoPos - (float) MIDIKey) * 100)
235                                 : RTMath::CentsToFreqRatio(RgnInfo.EG3Depth);
236                    float eg3time = (bPortamento)
237                                ? pEngineChannel->PortamentoTime
238                                : RgnInfo.EG3Attack;
239                    EG3.trigger(eg3depth, eg3time, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
240                    dmsg(5,("PortamentoPos=%f, depth=%f, time=%f\n", pEngineChannel->PortamentoPos, eg3depth, eg3time));
241                }
242    
243    
244          // setup EG 3 (VCO EG)              // setup LFO 1 (VCA LFO)
245          {              InitLFO1();
246              // if portamento mode is on, we dedicate EG3 purely for portamento, otherwise if portamento is off we do as told by the patch              // setup LFO 2 (VCF Cutoff LFO)
247              bool  bPortamento = pEngineChannel->PortamentoMode && pEngineChannel->PortamentoPos >= 0.0f;              InitLFO2();
248              float eg3depth = (bPortamento)              // setup LFO 3 (VCO LFO)
249                           ? RTMath::CentsToFreqRatio((pEngineChannel->PortamentoPos - (float) MIDIKey) * 100)              InitLFO3();
                          : RTMath::CentsToFreqRatio(RgnInfo.EG3Depth);  
             float eg3time = (bPortamento)  
                         ? pEngineChannel->PortamentoTime  
                         : RgnInfo.EG3Attack;  
             EG3.trigger(eg3depth, eg3time, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);  
             dmsg(5,("PortamentoPos=%f, depth=%f, time=%f\n", pEngineChannel->PortamentoPos, eg3depth, eg3time));  
250          }          }
251    
252    
         // setup LFO 1 (VCA LFO)  
         InitLFO1();  
         // setup LFO 2 (VCF Cutoff LFO)  
         InitLFO2();  
         // setup LFO 3 (VCO LFO)  
         InitLFO3();  
   
   
253          #if CONFIG_FORCE_FILTER          #if CONFIG_FORCE_FILTER
254          const bool bUseFilter = true;          const bool bUseFilter = true;
255          #else // use filter only if instrument file told so          #else // use filter only if instrument file told so
# Line 342  namespace LinuxSampler { Line 352  namespace LinuxSampler {
352                  // drivers that use Samples < MaxSamplesPerCycle).                  // drivers that use Samples < MaxSamplesPerCycle).
353                  // End the EG1 here, at pos 0, with a shorter max fade                  // End the EG1 here, at pos 0, with a shorter max fade
354                  // out time.                  // out time.
355                  pEG1->enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  if (GetSignalUnitRack() == NULL) {
356                        pEG1->enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
357                    } else {
358                        // TODO:
359                    }
360                  itKillEvent = Pool<Event>::Iterator();                  itKillEvent = Pool<Event>::Iterator();
361              } else {              } else {
362                  killPos = RTMath::Min(itKillEvent->FragmentPos(), maxFadeOutPos);                  killPos = RTMath::Min(itKillEvent->FragmentPos(), maxFadeOutPos);
# Line 370  namespace LinuxSampler { Line 384  namespace LinuxSampler {
384              processTransitionEvents(itNoteEvent, iSubFragmentEnd);              processTransitionEvents(itNoteEvent, iSubFragmentEnd);
385              processGroupEvents(itGroupEvent, iSubFragmentEnd);              processGroupEvents(itGroupEvent, iSubFragmentEnd);
386    
387              // if the voice was killed in this subfragment, or if the              if (GetSignalUnitRack() == NULL) {
388              // filter EG is finished, switch EG1 to fade out stage                  // if the voice was killed in this subfragment, or if the
389              if ((itKillEvent && killPos <= iSubFragmentEnd) ||                  // filter EG is finished, switch EG1 to fade out stage
390                  (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&                  if ((itKillEvent && killPos <= iSubFragmentEnd) ||
391                   pEG2->getSegmentType() == EG::segment_end)) {                      (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&
392                  pEG1->enterFadeOutStage();                      pEG2->getSegmentType() == EG::segment_end)) {
393                  itKillEvent = Pool<Event>::Iterator();                      pEG1->enterFadeOutStage();
394              }                      itKillEvent = Pool<Event>::Iterator();
395                    }
             // process envelope generators  
             switch (pEG1->getSegmentType()) {  
                 case EG::segment_lin:  
                     fFinalVolume *= pEG1->processLin();  
                     break;  
                 case EG::segment_exp:  
                     fFinalVolume *= pEG1->processExp();  
                     break;  
                 case EG::segment_end:  
                     fFinalVolume *= pEG1->getLevel();  
                     break; // noop  
                 case EG::segment_pow:  
                     fFinalVolume *= pEG1->processPow();  
                     break;  
             }  
             switch (pEG2->getSegmentType()) {  
                 case EG::segment_lin:  
                     fFinalCutoff *= pEG2->processLin();  
                     break;  
                 case EG::segment_exp:  
                     fFinalCutoff *= pEG2->processExp();  
                     break;  
                 case EG::segment_end:  
                     fFinalCutoff *= pEG2->getLevel();  
                     break; // noop  
                 case EG::segment_pow:  
                     fFinalCutoff *= pEG2->processPow();  
                     break;  
             }  
             if (EG3.active()) finalSynthesisParameters.fFinalPitch *= EG3.render();  
396    
397              // process low frequency oscillators                  // process envelope generators
398              if (bLFO1Enabled) fFinalVolume *= (1.0f - pLFO1->render());                  switch (pEG1->getSegmentType()) {
399              if (bLFO2Enabled) fFinalCutoff *= pLFO2->render();                      case EG::segment_lin:
400              if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());                          fFinalVolume *= pEG1->processLin();
401                            break;
402                        case EG::segment_exp:
403                            fFinalVolume *= pEG1->processExp();
404                            break;
405                        case EG::segment_end:
406                            fFinalVolume *= pEG1->getLevel();
407                            break; // noop
408                        case EG::segment_pow:
409                            fFinalVolume *= pEG1->processPow();
410                            break;
411                    }
412                    switch (pEG2->getSegmentType()) {
413                        case EG::segment_lin:
414                            fFinalCutoff *= pEG2->processLin();
415                            break;
416                        case EG::segment_exp:
417                            fFinalCutoff *= pEG2->processExp();
418                            break;
419                        case EG::segment_end:
420                            fFinalCutoff *= pEG2->getLevel();
421                            break; // noop
422                        case EG::segment_pow:
423                            fFinalCutoff *= pEG2->processPow();
424                            break;
425                    }
426                    if (EG3.active()) finalSynthesisParameters.fFinalPitch *= EG3.render();
427    
428                    // process low frequency oscillators
429                    if (bLFO1Enabled) fFinalVolume *= (1.0f - pLFO1->render());
430                    if (bLFO2Enabled) fFinalCutoff *= pLFO2->render();
431                    if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());
432                } else {
433                    // if the voice was killed in this subfragment, or if the
434                    // filter EG is finished, switch EG1 to fade out stage
435                    /*if ((itKillEvent && killPos <= iSubFragmentEnd) ||
436                        (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&
437                        pEG2->getSegmentType() == EG::segment_end)) {
438                        pEG1->enterFadeOutStage();
439                        itKillEvent = Pool<Event>::Iterator();
440                    }*/
441                    // TODO: ^^^
442    
443                    fFinalVolume   *= GetSignalUnitRack()->GetEndpointUnit()->GetVolume();
444                    fFinalCutoff    = GetSignalUnitRack()->GetEndpointUnit()->CalculateFilterCutoff(fFinalCutoff);
445                    fFinalResonance = GetSignalUnitRack()->GetEndpointUnit()->CalculateResonance(fFinalResonance);
446                    
447                    finalSynthesisParameters.fFinalPitch =
448                        GetSignalUnitRack()->GetEndpointUnit()->CalculatePitch(finalSynthesisParameters.fFinalPitch);
449                        
450                }
451                
452              // limit the pitch so we don't read outside the buffer              // limit the pitch so we don't read outside the buffer
453              finalSynthesisParameters.fFinalPitch = RTMath::Min(finalSynthesisParameters.fFinalPitch, float(1 << CONFIG_MAX_PITCH));              finalSynthesisParameters.fFinalPitch = RTMath::Min(finalSynthesisParameters.fFinalPitch, float(1 << CONFIG_MAX_PITCH));
454    
# Line 449  namespace LinuxSampler { Line 483  namespace LinuxSampler {
483              // render audio for one subfragment              // render audio for one subfragment
484              RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);              RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);
485    
486              // stop the rendering if volume EG is finished              if (GetSignalUnitRack() == NULL) {
487              if (pEG1->getSegmentType() == EG::segment_end) break;                  // stop the rendering if volume EG is finished
488                    if (pEG1->getSegmentType() == EG::segment_end) break;
489                } else {
490                    // stop the rendering if the endpoint unit is not active
491                    if (!GetSignalUnitRack()->GetEndpointUnit()->Active()) break;
492                }
493    
494              const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;              const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;
495    
496              // increment envelopes' positions              if (GetSignalUnitRack() == NULL) {
497              if (pEG1->active()) {                  // increment envelopes' positions
498                    if (pEG1->active()) {
499    
500                        // if sample has a loop and loop start has been reached in this subfragment, send a special event to EG1 to let it finish the attack hold stage
501                        if (SmplInfo.HasLoops && Pos <= SmplInfo.LoopStart && SmplInfo.LoopStart < newPos) {
502                            pEG1->update(EG::event_hold_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
503                        }
504    
505                  // if sample has a loop and loop start has been reached in this subfragment, send a special event to EG1 to let it finish the attack hold stage                      pEG1->increment(1);
506                  if (SmplInfo.HasLoops && Pos <= SmplInfo.LoopStart && SmplInfo.LoopStart < newPos) {                      if (!pEG1->toStageEndLeft()) pEG1->update(EG::event_stage_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
                     pEG1->update(EG::event_hold_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);  
507                  }                  }
508                    if (pEG2->active()) {
509                  pEG1->increment(1);                      pEG2->increment(1);
510                  if (!pEG1->toStageEndLeft()) pEG1->update(EG::event_stage_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                      if (!pEG2->toStageEndLeft()) pEG2->update(EG::event_stage_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
511              }                  }
512              if (pEG2->active()) {                  EG3.increment(1);
513                  pEG2->increment(1);                  if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached
514                  if (!pEG2->toStageEndLeft()) pEG2->update(EG::event_stage_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);              } else {
515                        // if sample has a loop and loop start has been reached in this subfragment, send a special event to EG1 to let it finish the attack hold stage
516                        /*if (SmplInfo.HasLoops && Pos <= SmplInfo.LoopStart && SmplInfo.LoopStart < newPos) {
517                            pEG1->update(EG::event_hold_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
518                        }*/
519                    // TODO: ^^^
520                    
521                    GetSignalUnitRack()->Increment();
522              }              }
             EG3.increment(1);  
             if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached  
523    
524              Pos = newPos;              Pos = newPos;
525              i = iSubFragmentEnd;              i = iSubFragmentEnd;
# Line 501  namespace LinuxSampler { Line 550  namespace LinuxSampler {
550                  if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {                  if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {
551                      processResonanceEvent(itEvent);                      processResonanceEvent(itEvent);
552                  }                  }
553                  if (itEvent->Param.CC.Controller == pLFO1->ExtController) {                  if (GetSignalUnitRack() == NULL) {
554                      pLFO1->update(itEvent->Param.CC.Value);                      if (itEvent->Param.CC.Controller == pLFO1->ExtController) {
555                  }                          pLFO1->update(itEvent->Param.CC.Value);
556                  if (itEvent->Param.CC.Controller == pLFO2->ExtController) {                      }
557                      pLFO2->update(itEvent->Param.CC.Value);                      if (itEvent->Param.CC.Controller == pLFO2->ExtController) {
558                  }                          pLFO2->update(itEvent->Param.CC.Value);
559                  if (itEvent->Param.CC.Controller == pLFO3->ExtController) {                      }
560                      pLFO3->update(itEvent->Param.CC.Value);                      if (itEvent->Param.CC.Controller == pLFO3->ExtController) {
561                            pLFO3->update(itEvent->Param.CC.Value);
562                        }
563                  }                  }
564                  if (itEvent->Param.CC.Controller == 7) { // volume                  if (itEvent->Param.CC.Controller == 7) { // volume
565                      VolumeSmoother.update(AbstractEngine::VolumeCurve[itEvent->Param.CC.Value]);                      VolumeSmoother.update(AbstractEngine::VolumeCurve[itEvent->Param.CC.Value]);
# Line 521  namespace LinuxSampler { Line 572  namespace LinuxSampler {
572              }              }
573    
574              ProcessCCEvent(itEvent);              ProcessCCEvent(itEvent);
575                if (GetSignalUnitRack() != NULL) {
576                    GetSignalUnitRack()->ProcessCCEvent(itEvent);
577                }
578          }          }
579      }      }
580    
# Line 552  namespace LinuxSampler { Line 606  namespace LinuxSampler {
606                  if (itEvent->Type == Event::type_release) {                  if (itEvent->Type == Event::type_release) {
607                      EnterReleaseStage();                      EnterReleaseStage();
608                  } else if (itEvent->Type == Event::type_cancel_release) {                  } else if (itEvent->Type == Event::type_cancel_release) {
609                      pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                      if (GetSignalUnitRack() == NULL) {
610                      pEG2->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                          pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
611                            pEG2->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
612                        } else {
613                            GetSignalUnitRack()->CancelRelease();
614                        }
615                  }                  }
616              }              }
617          }          }
# Line 580  namespace LinuxSampler { Line 638  namespace LinuxSampler {
638       * @param itNoteOffEvent - event which causes this voice to die soon       * @param itNoteOffEvent - event which causes this voice to die soon
639       */       */
640      void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {      void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {
641          const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());          if (GetSignalUnitRack() == NULL) {
642          pEngineChannel->PortamentoPos = (float) MIDIKey + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;              const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());
643                pEngineChannel->PortamentoPos = (float) MIDIKey + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;
644            } else {
645                // TODO:
646            }
647      }      }
648    
649      /**      /**
# Line 643  namespace LinuxSampler { Line 705  namespace LinuxSampler {
705      }      }
706    
707      void AbstractVoice::EnterReleaseStage() {      void AbstractVoice::EnterReleaseStage() {
708          pEG1->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);          if (GetSignalUnitRack() == NULL) {
709          pEG2->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);              pEG1->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
710                pEG2->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
711            } else {
712                GetSignalUnitRack()->EnterReleaseStage();
713            }
714        }
715    
716        bool AbstractVoice::EG1Finished() {
717            if (GetSignalUnitRack() == NULL) {
718                return pEG1->getSegmentType() == EG::segment_end;
719            } else {
720                return !GetSignalUnitRack()->GetEndpointUnit()->Active();
721            }
722      }      }
723    
724  } // namespace LinuxSampler  } // namespace LinuxSampler

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

  ViewVC Help
Powered by ViewVC