/[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 2015 by iliev, Sun Oct 25 22:22:52 2009 UTC revision 2205 by iliev, Mon Jul 11 17:52:01 2011 UTC
# Line 3  Line 3 
3   *   LinuxSampler - modular, streaming capable sampler                     *   *   LinuxSampler - modular, streaming capable sampler                     *
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-2009 Christian Schoenebeck                         *   *   Copyright (C) 2005-2008 Christian Schoenebeck                         *
7   *   Copyright (C) 2009 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;
         KeyGroup = 0;  
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)
37          #if 0 // CONFIG_ASM && ARCH_X86          #if 0 // CONFIG_ASM && ARCH_X86
# Line 51  namespace LinuxSampler { Line 50  namespace LinuxSampler {
50          if (pLFO2) delete pLFO2;          if (pLFO2) delete pLFO2;
51          if (pLFO3) delete pLFO3;          if (pLFO3) delete pLFO3;
52      }      }
53        
54      /**      /**
55       *  Resets voice variables. Should only be called if rendering process is       *  Resets voice variables. Should only be called if rendering process is
56       *  suspended / not running.       *  suspended / not running.
# Line 104  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          KeyGroup        = iKeyGroup;          MidiKeyBase* pKeyInfo = GetMidiKeyInfo(MIDIKey);
107    
108            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;
120    
121          // select channel mode (mono or stereo)          // select channel mode (mono or stereo)
122          SYNTHESIS_MODE_SET_CHANNELS(SynthesisMode, SmplInfo.ChannelCount == 2);          SYNTHESIS_MODE_SET_CHANNELS(SynthesisMode, SmplInfo.ChannelCount == 2);
# Line 122  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 174  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    
185              // calculate influence of EG1 controller on EG1's parameters              // calculate influence of EG1 controller on EG1's parameters
186              EGInfo egInfo = CalculateEG1ControllerInfluence(eg1controllervalue);              EGInfo egInfo = CalculateEG1ControllerInfluence(eg1controllervalue);
187    
188              EG1.trigger (              TriggerEG1(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity);
189                  RgnInfo.EG1PreAttack,          } else {
190                  RgnInfo.EG1Attack * egInfo.Attack,              GetSignalUnitRack()->Trigger();
                 RgnInfo.EG1Hold,  
                 RgnInfo.EG1Decay1 * egInfo.Decay * velrelease,  
                 RgnInfo.EG1Decay2 * egInfo.Decay * velrelease,  
                 RgnInfo.EG1InfiniteSustain,  
                 RgnInfo.EG1Sustain,  
                 RgnInfo.EG1Release * egInfo.Release * velrelease,  
                 velocityAttenuation,  
                 GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE  
             );  
191          }          }
192    
193  #ifdef CONFIG_INTERPOLATE_VOLUME  #ifdef CONFIG_INTERPOLATE_VOLUME
# Line 206  namespace LinuxSampler { Line 200  namespace LinuxSampler {
200          else          else
201      #else      #else
202          {          {
203              float finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * EG1.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 214  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                  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                  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 316  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;
326          GetFirstEventOnKey(MIDIKey, itNoteEvent);          GetFirstEventOnKey(MIDIKey, itNoteEvent);
327    
328            RTList<Event>::Iterator itGroupEvent;
329            if (pGroupEvents) itGroupEvent = pGroupEvents->first();
330    
331          if (itTriggerEvent) { // skip events that happened before this voice was triggered          if (itTriggerEvent) { // skip events that happened before this voice was triggered
332              while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;              while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;
333                while (itGroupEvent && itGroupEvent->FragmentPos() <= Skip) ++itGroupEvent;
334    
335              // we can't simply compare the timestamp here, because note events              // we can't simply compare the timestamp here, because note events
336              // might happen on the same time stamp, so we have to deal on the              // might happen on the same time stamp, so we have to deal on the
337              // actual sequence the note events arrived instead (see bug #112)              // actual sequence the note events arrived instead (see bug #112)
# Line 346  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                  EG1.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 372  namespace LinuxSampler { Line 382  namespace LinuxSampler {
382    
383              // process transition events (note on, note off & sustain pedal)              // process transition events (note on, note off & sustain pedal)
384              processTransitionEvents(itNoteEvent, iSubFragmentEnd);              processTransitionEvents(itNoteEvent, iSubFragmentEnd);
385                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                  EG1.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 (EG1.getSegmentType()) {                  switch (pEG1->getSegmentType()) {
399                  case gig::EGADSR::segment_lin:                      case EG::segment_lin:
400                      fFinalVolume *= EG1.processLin();                          fFinalVolume *= pEG1->processLin();
401                      break;                          break;
402                  case gig::EGADSR::segment_exp:                      case EG::segment_exp:
403                      fFinalVolume *= EG1.processExp();                          fFinalVolume *= pEG1->processExp();
404                      break;                          break;
405                  case gig::EGADSR::segment_end:                      case EG::segment_end:
406                      fFinalVolume *= EG1.getLevel();                          fFinalVolume *= pEG1->getLevel();
407                      break; // noop                          break; // noop
408              }                      case EG::segment_pow:
409              switch (EG2.getSegmentType()) {                          fFinalVolume *= pEG1->processPow();
410                  case gig::EGADSR::segment_lin:                          break;
411                      fFinalCutoff *= EG2.processLin();                  }
412                      break;                  switch (pEG2->getSegmentType()) {
413                  case gig::EGADSR::segment_exp:                      case EG::segment_lin:
414                      fFinalCutoff *= EG2.processExp();                          fFinalCutoff *= pEG2->processLin();
415                      break;                          break;
416                  case gig::EGADSR::segment_end:                      case EG::segment_exp:
417                      fFinalCutoff *= EG2.getLevel();                          fFinalCutoff *= pEG2->processExp();
418                      break; // noop                          break;
419              }                      case EG::segment_end:
420              if (EG3.active()) finalSynthesisParameters.fFinalPitch *= EG3.render();                          fFinalCutoff *= pEG2->getLevel();
421                            break; // noop
422              // process low frequency oscillators                      case EG::segment_pow:
423              if (bLFO1Enabled) fFinalVolume *= (1.0f - pLFO1->render());                          fFinalCutoff *= pEG2->processPow();
424              if (bLFO2Enabled) fFinalCutoff *= pLFO2->render();                          break;
425              if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());                  }
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 446  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 (EG1.getSegmentType() == gig::EGADSR::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 (EG1.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);
                     EG1.update(gig::EGADSR::event_hold_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);  
507                  }                  }
508                    if (pEG2->active()) {
509                  EG1.increment(1);                      pEG2->increment(1);
510                  if (!EG1.toStageEndLeft()) EG1.update(gig::EGADSR::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      /**      /**
538       * Process given list of MIDI control change and pitch bend events for       * Process given list of MIDI control change and pitch bend events for
539       * the given time.       * the given time.
# Line 490  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 510  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 536  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 (itEvent->Type == Event::type_release) {              // some voice types ignore note off
605                  EG1.update(gig::EGADSR::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);              if (!(Type & (Voice::type_one_shot | Voice::type_release_trigger | Voice::type_controller_triggered))) {
606                  EG2.update(gig::EGADSR::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  if (itEvent->Type == Event::type_release) {
607              } else if (itEvent->Type == Event::type_cancel_release) {                      EnterReleaseStage();
608                  EG1.update(gig::EGADSR::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  } else if (itEvent->Type == Event::type_cancel_release) {
609                  EG2.update(gig::EGADSR::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                      if (GetSignalUnitRack() == NULL) {
610                            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          }          }
618      }      }
619    
620        /**
621         * Process given list of events aimed at all voices in a key group.
622         *
623         * @param itEvent - iterator pointing to the next event to be processed
624         * @param End     - youngest time stamp where processing should be stopped
625         */
626        void AbstractVoice::processGroupEvents(RTList<Event>::Iterator& itEvent, uint End) {
627            for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
628                ProcessGroupEvent(itEvent);
629            }
630        }
631    
632      /** @brief Update current portamento position.      /** @brief Update current portamento position.
633       *       *
634       * Will be called when portamento mode is enabled to get the final       * Will be called when portamento mode is enabled to get the final
# Line 555  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 603  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    
697              float attenuation = 1 - 0.01053 * (256 >> RgnInfo.ReleaseTriggerDecay) * noteLength;              volume *= GetReleaseTriggerAttenuation(noteLength);
             if (attenuation <= 0) return -1;  
             volume *= attenuation;  
698          }          }
699    
700          return volume;          return volume;
701      }      }
702    
703        float AbstractVoice::GetReleaseTriggerAttenuation(float noteLength) {
704            return 1 - RgnInfo.ReleaseTriggerDecay * noteLength;
705        }
706    
707        void AbstractVoice::EnterReleaseStage() {
708            if (GetSignalUnitRack() == NULL) {
709                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.2015  
changed lines
  Added in v.2205

  ViewVC Help
Powered by ViewVC