/[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 2114 by persson, Tue Aug 10 12:05:19 2010 UTC revision 2205 by iliev, Mon Jul 11 17:52:01 2011 UTC
# Line 4  Line 4 
4   *                                                                         *   *                                                                         *
5   *   Copyright (C) 2003,2004 by Benno Senoner and Christian Schoenebeck    *   *   Copyright (C) 2003,2004 by Benno Senoner and Christian Schoenebeck    *
6   *   Copyright (C) 2005-2008 Christian Schoenebeck                         *   *   Copyright (C) 2005-2008 Christian Schoenebeck                         *
7   *   Copyright (C) 2009-2010 Christian Schoenebeck and Grigor Iliev        *   *   Copyright (C) 2009-2011 Christian Schoenebeck and Grigor Iliev        *
8   *                                                                         *   *                                                                         *
9   *   This program is free software; you can redistribute it and/or modify  *   *   This program is free software; you can redistribute it and/or modify  *
10   *   it under the terms of the GNU General Public License as published by  *   *   it under the terms of the GNU General Public License as published by  *
# Line 28  namespace LinuxSampler { Line 28  namespace LinuxSampler {
28    
29      AbstractVoice::AbstractVoice() {      AbstractVoice::AbstractVoice() {
30          pEngineChannel = NULL;          pEngineChannel = NULL;
31          pLFO1 = new LFOUnsigned(1.0f);  // amplitude EG (0..1 range)          pLFO1 = new LFOUnsigned(1.0f);  // amplitude LFO (0..1 range)
32          pLFO2 = new LFOUnsigned(1.0f);  // filter EG (0..1 range)          pLFO2 = new LFOUnsigned(1.0f);  // filter LFO (0..1 range)
33          pLFO3 = new LFOSigned(1200.0f); // pitch EG (-1200..+1200 range)          pLFO3 = new LFOSigned(1200.0f); // pitch LFO (-1200..+1200 range)
34          PlaybackState = playback_state_end;          PlaybackState = playback_state_end;
35          SynthesisMode = 0; // set all mode bits to 0 first          SynthesisMode = 0; // set all mode bits to 0 first
36          // select synthesis implementation (asm core is not supported ATM)          // select synthesis implementation (asm core is not supported ATM)
# Line 103  namespace LinuxSampler { Line 103  namespace LinuxSampler {
103          Delay           = itNoteOnEvent->FragmentPos();          Delay           = itNoteOnEvent->FragmentPos();
104          itTriggerEvent  = itNoteOnEvent;          itTriggerEvent  = itNoteOnEvent;
105          itKillEvent     = Pool<Event>::Iterator();          itKillEvent     = Pool<Event>::Iterator();
106            MidiKeyBase* pKeyInfo = GetMidiKeyInfo(MIDIKey);
107    
108          pGroupEvents = iKeyGroup ? pEngineChannel->ActiveKeyGroups[iKeyGroup] : 0;          pGroupEvents = iKeyGroup ? pEngineChannel->ActiveKeyGroups[iKeyGroup] : 0;
109    
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);
118          float volume = CalculateVolume(velocityAttenuation);          float volume = CalculateVolume(velocityAttenuation) * pKeyInfo->Volume;
119          if (volume <= 0) return -1;          if (volume <= 0) return -1;
120    
121          // select channel mode (mono or stereo)          // select channel mode (mono or stereo)
# Line 123  namespace LinuxSampler { Line 126  namespace LinuxSampler {
126          // get starting crossfade volume level          // get starting crossfade volume level
127          float crossfadeVolume = CalculateCrossfadeVolume(itNoteOnEvent->Param.Note.Velocity);          float crossfadeVolume = CalculateCrossfadeVolume(itNoteOnEvent->Param.Note.Velocity);
128    
129          VolumeLeft  = volume * AbstractEngine::PanCurve[64 - RgnInfo.Pan];          VolumeLeft  = volume * pKeyInfo->PanLeft  * AbstractEngine::PanCurve[64 - RgnInfo.Pan];
130          VolumeRight = volume * AbstractEngine::PanCurve[64 + RgnInfo.Pan];          VolumeRight = volume * pKeyInfo->PanRight * AbstractEngine::PanCurve[64 + RgnInfo.Pan];
131    
132          float subfragmentRate = GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;          float subfragmentRate = GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;
133          CrossfadeSmoother.trigger(crossfadeVolume, subfragmentRate);          CrossfadeSmoother.trigger(crossfadeVolume, subfragmentRate);
# Line 175  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 184  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 196  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 204  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              EG2.trigger (              // setup EG 3 (VCO EG)
230                  uint(RgnInfo.EG2PreAttack),              {
231                  RgnInfo.EG2Attack * egInfo.Attack,                  // if portamento mode is on, we dedicate EG3 purely for portamento, otherwise if portamento is off we do as told by the patch
232                  false,                  bool  bPortamento = pEngineChannel->PortamentoMode && pEngineChannel->PortamentoPos >= 0.0f;
233                  RgnInfo.EG2Decay1 * egInfo.Decay * velrelease,                  float eg3depth = (bPortamento)
234                  RgnInfo.EG2Decay2 * egInfo.Decay * velrelease,                               ? RTMath::CentsToFreqRatio((pEngineChannel->PortamentoPos - (float) MIDIKey) * 100)
235                  RgnInfo.EG2InfiniteSustain,                               : RTMath::CentsToFreqRatio(RgnInfo.EG3Depth);
236                  uint(RgnInfo.EG2Sustain),                  float eg3time = (bPortamento)
237                  RgnInfo.EG2Release * egInfo.Release * velrelease,                              ? pEngineChannel->PortamentoTime
238                  velocityAttenuation,                              : RgnInfo.EG3Attack;
239                  GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE                  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 306  namespace LinuxSampler { Line 306  namespace LinuxSampler {
306       */       */
307      void AbstractVoice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {      void AbstractVoice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {
308          AbstractEngineChannel* pChannel = pEngineChannel;          AbstractEngineChannel* pChannel = pEngineChannel;
309          finalSynthesisParameters.pOutLeft  = &pChannel->pChannelLeft->Buffer()[Skip];          MidiKeyBase* pMidiKeyInfo = GetMidiKeyInfo(MIDIKey);
310          finalSynthesisParameters.pOutRight = &pChannel->pChannelRight->Buffer()[Skip];  
311          finalSynthesisParameters.pSrc      = pSrc;          const bool bVoiceRequiresDedicatedRouting =
312                pEngineChannel->GetFxSendCount() > 0 &&
313                (pMidiKeyInfo->ReverbSend || pMidiKeyInfo->ChorusSend);
314    
315            if (bVoiceRequiresDedicatedRouting) {
316                finalSynthesisParameters.pOutLeft  = &GetEngine()->pDedicatedVoiceChannelLeft->Buffer()[Skip];
317                finalSynthesisParameters.pOutRight = &GetEngine()->pDedicatedVoiceChannelRight->Buffer()[Skip];
318            } else {
319                finalSynthesisParameters.pOutLeft  = &pChannel->pChannelLeft->Buffer()[Skip];
320                finalSynthesisParameters.pOutRight = &pChannel->pChannelRight->Buffer()[Skip];
321            }
322            finalSynthesisParameters.pSrc = pSrc;
323    
324          RTList<Event>::Iterator itCCEvent = pChannel->pEvents->first();          RTList<Event>::Iterator itCCEvent = pChannel->pEvents->first();
325          RTList<Event>::Iterator itNoteEvent;          RTList<Event>::Iterator itNoteEvent;
# Line 341  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 369  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                   EG2.getSegmentType() == gig::EGADSR::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                    }
396    
397              // process envelope generators                  // process envelope generators
398              switch (pEG1->getSegmentType()) {                  switch (pEG1->getSegmentType()) {
399                  case EG::segment_lin:                      case EG::segment_lin:
400                      fFinalVolume *= pEG1->processLin();                          fFinalVolume *= pEG1->processLin();
401                      break;                          break;
402                  case EG::segment_exp:                      case EG::segment_exp:
403                      fFinalVolume *= pEG1->processExp();                          fFinalVolume *= pEG1->processExp();
404                      break;                          break;
405                  case EG::segment_end:                      case EG::segment_end:
406                      fFinalVolume *= pEG1->getLevel();                          fFinalVolume *= pEG1->getLevel();
407                      break; // noop                          break; // noop
408                  case EG::segment_pow:                      case EG::segment_pow:
409                      fFinalVolume *= pEG1->processPow();                          fFinalVolume *= pEG1->processPow();
410                      break;                          break;
411              }                  }
412              switch (EG2.getSegmentType()) {                  switch (pEG2->getSegmentType()) {
413                  case gig::EGADSR::segment_lin:                      case EG::segment_lin:
414                      fFinalCutoff *= EG2.processLin();                          fFinalCutoff *= pEG2->processLin();
415                      break;                          break;
416                  case gig::EGADSR::segment_exp:                      case EG::segment_exp:
417                      fFinalCutoff *= EG2.processExp();                          fFinalCutoff *= pEG2->processExp();
418                      break;                          break;
419                  case gig::EGADSR::segment_end:                      case EG::segment_end:
420                      fFinalCutoff *= EG2.getLevel();                          fFinalCutoff *= pEG2->getLevel();
421                      break; // noop                          break; // noop
422              }                      case EG::segment_pow:
423              if (EG3.active()) finalSynthesisParameters.fFinalPitch *= EG3.render();                          fFinalCutoff *= pEG2->processPow();
424                            break;
425              // process low frequency oscillators                  }
426              if (bLFO1Enabled) fFinalVolume *= (1.0f - pLFO1->render());                  if (EG3.active()) finalSynthesisParameters.fFinalPitch *= EG3.render();
             if (bLFO2Enabled) fFinalCutoff *= pLFO2->render();  
             if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->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 445  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 (EG2.active()) {                  EG3.increment(1);
513                  EG2.increment(1);                  if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached
514                  if (!EG2.toStageEndLeft()) EG2.update(gig::EGADSR::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;
526          }          }
527    
528            if (bVoiceRequiresDedicatedRouting) {
529                optional<float> effectSendLevels[2] = {
530                    pMidiKeyInfo->ReverbSend,
531                    pMidiKeyInfo->ChorusSend
532                };
533                GetEngine()->RouteDedicatedVoiceChannels(pEngineChannel, effectSendLevels, Samples);
534            }
535      }      }
536    
537      /**      /**
# Line 489  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 509  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 535  namespace LinuxSampler { Line 601  namespace LinuxSampler {
601       */       */
602      void AbstractVoice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) {      void AbstractVoice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) {
603          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
604              if (Type != Voice::type_release_trigger) {              // some voice types ignore note off
605                if (!(Type & (Voice::type_one_shot | Voice::type_release_trigger | Voice::type_controller_triggered))) {
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                      EG2.update(gig::EGADSR::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 568  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 616  namespace LinuxSampler { Line 690  namespace LinuxSampler {
690          volume *= GetSampleAttenuation() * pEngineChannel->GlobalVolume * GLOBAL_VOLUME;          volume *= GetSampleAttenuation() * pEngineChannel->GlobalVolume * GLOBAL_VOLUME;
691    
692          // the volume of release triggered samples depends on note length          // the volume of release triggered samples depends on note length
693          if (Type == Voice::type_release_trigger) {          if (Type & Voice::type_release_trigger) {
694              float noteLength = float(GetEngine()->FrameTime + Delay -              float noteLength = float(GetEngine()->FrameTime + Delay -
695                  GetNoteOnTime(MIDIKey) ) / GetEngine()->SampleRate;                  GetNoteOnTime(MIDIKey) ) / GetEngine()->SampleRate;
696    
# Line 631  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          EG2.update(gig::EGADSR::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.2114  
changed lines
  Added in v.2205

  ViewVC Help
Powered by ViewVC