/[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 2218 by iliev, Thu Jul 28 08:05:57 2011 UTC
# Line 26  Line 26 
26    
27  namespace LinuxSampler {  namespace LinuxSampler {
28    
29      AbstractVoice::AbstractVoice() {      AbstractVoice::AbstractVoice(SignalUnitRack* pRack): pSignalUnitRack(pRack) {
30          pEngineChannel = NULL;          pEngineChannel = NULL;
31          pLFO1 = new LFOUnsigned(1.0f);  // amplitude LFO (0..1 range)          pLFO1 = new LFOUnsigned(1.0f);  // amplitude LFO (0..1 range)
32          pLFO2 = new LFOUnsigned(1.0f);  // filter LFO (0..1 range)          pLFO2 = new LFOUnsigned(1.0f);  // filter LFO (0..1 range)
# Line 99  namespace LinuxSampler { Line 99  namespace LinuxSampler {
99    
100          Type            = VoiceType;          Type            = VoiceType;
101          MIDIKey         = itNoteOnEvent->Param.Note.Key;          MIDIKey         = itNoteOnEvent->Param.Note.Key;
102            MIDIVelocity    = itNoteOnEvent->Param.Note.Velocity;
103          PlaybackState   = playback_state_init; // mark voice as triggered, but no audio rendered yet          PlaybackState   = playback_state_init; // mark voice as triggered, but no audio rendered yet
104          Delay           = itNoteOnEvent->FragmentPos();          Delay           = itNoteOnEvent->FragmentPos();
105          itTriggerEvent  = itNoteOnEvent;          itTriggerEvent  = itNoteOnEvent;
# Line 110  namespace LinuxSampler { Line 111  namespace LinuxSampler {
111          SmplInfo   = GetSampleInfo();          SmplInfo   = GetSampleInfo();
112          RgnInfo    = GetRegionInfo();          RgnInfo    = GetRegionInfo();
113          InstrInfo  = GetInstrumentInfo();          InstrInfo  = GetInstrumentInfo();
114            
115            AboutToTrigger();
116    
117          // calculate volume          // calculate volume
118          const double velocityAttenuation = GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity);          const double velocityAttenuation = GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity);
# Line 133  namespace LinuxSampler { Line 136  namespace LinuxSampler {
136          PanLeftSmoother.trigger(pEngineChannel->GlobalPanLeft, subfragmentRate);          PanLeftSmoother.trigger(pEngineChannel->GlobalPanLeft, subfragmentRate);
137          PanRightSmoother.trigger(pEngineChannel->GlobalPanRight, subfragmentRate);          PanRightSmoother.trigger(pEngineChannel->GlobalPanRight, subfragmentRate);
138    
         finalSynthesisParameters.dPos = RgnInfo.SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)  
         Pos = RgnInfo.SampleStartOffset;  
   
139          // Check if the sample needs disk streaming or is too short for that          // Check if the sample needs disk streaming or is too short for that
140          long cachedsamples = GetSampleCacheSize() / SmplInfo.FrameSize;          long cachedsamples = GetSampleCacheSize() / SmplInfo.FrameSize;
141          DiskVoice          = cachedsamples < SmplInfo.TotalFrameCount;          DiskVoice          = cachedsamples < SmplInfo.TotalFrameCount;
142    
143            SetSampleStartOffset();
144    
145          if (DiskVoice) { // voice to be streamed from disk          if (DiskVoice) { // voice to be streamed from disk
146              if (cachedsamples > (GetEngine()->MaxSamplesPerCycle << CONFIG_MAX_PITCH)) {              if (cachedsamples > (GetEngine()->MaxSamplesPerCycle << CONFIG_MAX_PITCH)) {
147                  MaxRAMPos = cachedsamples - (GetEngine()->MaxSamplesPerCycle << CONFIG_MAX_PITCH) / SmplInfo.ChannelCount; //TODO: this calculation is too pessimistic and may better be moved to Render() method, so it calculates MaxRAMPos dependent to the current demand of sample points to be rendered (e.g. in case of JACK)                  MaxRAMPos = cachedsamples - (GetEngine()->MaxSamplesPerCycle << CONFIG_MAX_PITCH) / SmplInfo.ChannelCount; //TODO: this calculation is too pessimistic and may better be moved to Render() method, so it calculates MaxRAMPos dependent to the current demand of sample points to be rendered (e.g. in case of JACK)
# 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 (pSignalUnitRack == 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                pSignalUnitRack->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 (pSignalUnitRack == NULL) {
205                    finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pEG1->getLevel();
206                } else {
207                    finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pSignalUnitRack->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 (pSignalUnitRack == 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 285  namespace LinuxSampler { Line 295  namespace LinuxSampler {
295    
296          return 0; // success          return 0; // success
297      }      }
298        
299        void AbstractVoice::SetSampleStartOffset() {
300            finalSynthesisParameters.dPos = RgnInfo.SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)
301            Pos = RgnInfo.SampleStartOffset;
302        }
303    
304      /**      /**
305       *  Synthesizes the current audio fragment for this voice.       *  Synthesizes the current audio fragment for this voice.
# Line 342  namespace LinuxSampler { Line 357  namespace LinuxSampler {
357                  // drivers that use Samples < MaxSamplesPerCycle).                  // drivers that use Samples < MaxSamplesPerCycle).
358                  // End the EG1 here, at pos 0, with a shorter max fade                  // End the EG1 here, at pos 0, with a shorter max fade
359                  // out time.                  // out time.
360                  pEG1->enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  if (pSignalUnitRack == NULL) {
361                        pEG1->enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
362                    } else {
363                        // TODO:
364                    }
365                  itKillEvent = Pool<Event>::Iterator();                  itKillEvent = Pool<Event>::Iterator();
366              } else {              } else {
367                  killPos = RTMath::Min(itKillEvent->FragmentPos(), maxFadeOutPos);                  killPos = RTMath::Min(itKillEvent->FragmentPos(), maxFadeOutPos);
# Line 370  namespace LinuxSampler { Line 389  namespace LinuxSampler {
389              processTransitionEvents(itNoteEvent, iSubFragmentEnd);              processTransitionEvents(itNoteEvent, iSubFragmentEnd);
390              processGroupEvents(itGroupEvent, iSubFragmentEnd);              processGroupEvents(itGroupEvent, iSubFragmentEnd);
391    
392              // if the voice was killed in this subfragment, or if the              if (pSignalUnitRack == NULL) {
393              // filter EG is finished, switch EG1 to fade out stage                  // if the voice was killed in this subfragment, or if the
394              if ((itKillEvent && killPos <= iSubFragmentEnd) ||                  // filter EG is finished, switch EG1 to fade out stage
395                  (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&                  if ((itKillEvent && killPos <= iSubFragmentEnd) ||
396                   pEG2->getSegmentType() == EG::segment_end)) {                      (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&
397                  pEG1->enterFadeOutStage();                      pEG2->getSegmentType() == EG::segment_end)) {
398                  itKillEvent = Pool<Event>::Iterator();                      pEG1->enterFadeOutStage();
399              }                      itKillEvent = Pool<Event>::Iterator();
400                    }
             // 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();  
401    
402              // process low frequency oscillators                  // process envelope generators
403              if (bLFO1Enabled) fFinalVolume *= (1.0f - pLFO1->render());                  switch (pEG1->getSegmentType()) {
404              if (bLFO2Enabled) fFinalCutoff *= pLFO2->render();                      case EG::segment_lin:
405              if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());                          fFinalVolume *= pEG1->processLin();
406                            break;
407                        case EG::segment_exp:
408                            fFinalVolume *= pEG1->processExp();
409                            break;
410                        case EG::segment_end:
411                            fFinalVolume *= pEG1->getLevel();
412                            break; // noop
413                        case EG::segment_pow:
414                            fFinalVolume *= pEG1->processPow();
415                            break;
416                    }
417                    switch (pEG2->getSegmentType()) {
418                        case EG::segment_lin:
419                            fFinalCutoff *= pEG2->processLin();
420                            break;
421                        case EG::segment_exp:
422                            fFinalCutoff *= pEG2->processExp();
423                            break;
424                        case EG::segment_end:
425                            fFinalCutoff *= pEG2->getLevel();
426                            break; // noop
427                        case EG::segment_pow:
428                            fFinalCutoff *= pEG2->processPow();
429                            break;
430                    }
431                    if (EG3.active()) finalSynthesisParameters.fFinalPitch *= EG3.render();
432    
433                    // process low frequency oscillators
434                    if (bLFO1Enabled) fFinalVolume *= (1.0f - pLFO1->render());
435                    if (bLFO2Enabled) fFinalCutoff *= pLFO2->render();
436                    if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());
437                } else {
438                    // if the voice was killed in this subfragment, or if the
439                    // filter EG is finished, switch EG1 to fade out stage
440                    /*if ((itKillEvent && killPos <= iSubFragmentEnd) ||
441                        (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&
442                        pEG2->getSegmentType() == EG::segment_end)) {
443                        pEG1->enterFadeOutStage();
444                        itKillEvent = Pool<Event>::Iterator();
445                    }*/
446                    // TODO: ^^^
447    
448                    fFinalVolume   *= pSignalUnitRack->GetEndpointUnit()->GetVolume();
449                    fFinalCutoff    = pSignalUnitRack->GetEndpointUnit()->CalculateFilterCutoff(fFinalCutoff);
450                    fFinalResonance = pSignalUnitRack->GetEndpointUnit()->CalculateResonance(fFinalResonance);
451                    
452                    finalSynthesisParameters.fFinalPitch =
453                        pSignalUnitRack->GetEndpointUnit()->CalculatePitch(finalSynthesisParameters.fFinalPitch);
454                        
455                }
456                
457              // limit the pitch so we don't read outside the buffer              // limit the pitch so we don't read outside the buffer
458              finalSynthesisParameters.fFinalPitch = RTMath::Min(finalSynthesisParameters.fFinalPitch, float(1 << CONFIG_MAX_PITCH));              finalSynthesisParameters.fFinalPitch = RTMath::Min(finalSynthesisParameters.fFinalPitch, float(1 << CONFIG_MAX_PITCH));
459    
# Line 449  namespace LinuxSampler { Line 488  namespace LinuxSampler {
488              // render audio for one subfragment              // render audio for one subfragment
489              RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);              RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);
490    
491              // stop the rendering if volume EG is finished              if (pSignalUnitRack == NULL) {
492              if (pEG1->getSegmentType() == EG::segment_end) break;                  // stop the rendering if volume EG is finished
493                    if (pEG1->getSegmentType() == EG::segment_end) break;
494                } else {
495                    // stop the rendering if the endpoint unit is not active
496                    if (!pSignalUnitRack->GetEndpointUnit()->Active()) break;
497                }
498    
499              const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;              const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;
500    
501              // increment envelopes' positions              if (pSignalUnitRack == NULL) {
502              if (pEG1->active()) {                  // increment envelopes' positions
503                    if (pEG1->active()) {
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
506                        if (SmplInfo.HasLoops && Pos <= SmplInfo.LoopStart && SmplInfo.LoopStart < newPos) {
507                            pEG1->update(EG::event_hold_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
508                        }
509    
510                  // 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);
511                  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);  
512                  }                  }
513                    if (pEG2->active()) {
514                  pEG1->increment(1);                      pEG2->increment(1);
515                  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);
516              }                  }
517              if (pEG2->active()) {                  EG3.increment(1);
518                  pEG2->increment(1);                  if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached
519                  if (!pEG2->toStageEndLeft()) pEG2->update(EG::event_stage_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);              } else {
520                        // 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
521                        /*if (SmplInfo.HasLoops && Pos <= SmplInfo.LoopStart && SmplInfo.LoopStart < newPos) {
522                            pEG1->update(EG::event_hold_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
523                        }*/
524                    // TODO: ^^^
525                    
526                    pSignalUnitRack->Increment();
527              }              }
             EG3.increment(1);  
             if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached  
528    
529              Pos = newPos;              Pos = newPos;
530              i = iSubFragmentEnd;              i = iSubFragmentEnd;
# Line 501  namespace LinuxSampler { Line 555  namespace LinuxSampler {
555                  if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {                  if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {
556                      processResonanceEvent(itEvent);                      processResonanceEvent(itEvent);
557                  }                  }
558                  if (itEvent->Param.CC.Controller == pLFO1->ExtController) {                  if (pSignalUnitRack == NULL) {
559                      pLFO1->update(itEvent->Param.CC.Value);                      if (itEvent->Param.CC.Controller == pLFO1->ExtController) {
560                  }                          pLFO1->update(itEvent->Param.CC.Value);
561                  if (itEvent->Param.CC.Controller == pLFO2->ExtController) {                      }
562                      pLFO2->update(itEvent->Param.CC.Value);                      if (itEvent->Param.CC.Controller == pLFO2->ExtController) {
563                  }                          pLFO2->update(itEvent->Param.CC.Value);
564                  if (itEvent->Param.CC.Controller == pLFO3->ExtController) {                      }
565                      pLFO3->update(itEvent->Param.CC.Value);                      if (itEvent->Param.CC.Controller == pLFO3->ExtController) {
566                            pLFO3->update(itEvent->Param.CC.Value);
567                        }
568                  }                  }
569                  if (itEvent->Param.CC.Controller == 7) { // volume                  if (itEvent->Param.CC.Controller == 7) { // volume
570                      VolumeSmoother.update(AbstractEngine::VolumeCurve[itEvent->Param.CC.Value]);                      VolumeSmoother.update(AbstractEngine::VolumeCurve[itEvent->Param.CC.Value]);
# Line 521  namespace LinuxSampler { Line 577  namespace LinuxSampler {
577              }              }
578    
579              ProcessCCEvent(itEvent);              ProcessCCEvent(itEvent);
580                if (pSignalUnitRack != NULL) {
581                    pSignalUnitRack->ProcessCCEvent(itEvent);
582                }
583          }          }
584      }      }
585    
# Line 552  namespace LinuxSampler { Line 611  namespace LinuxSampler {
611                  if (itEvent->Type == Event::type_release) {                  if (itEvent->Type == Event::type_release) {
612                      EnterReleaseStage();                      EnterReleaseStage();
613                  } else if (itEvent->Type == Event::type_cancel_release) {                  } else if (itEvent->Type == Event::type_cancel_release) {
614                      pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                      if (pSignalUnitRack == NULL) {
615                      pEG2->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                          pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
616                            pEG2->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
617                        } else {
618                            pSignalUnitRack->CancelRelease();
619                        }
620                  }                  }
621              }              }
622          }          }
# Line 580  namespace LinuxSampler { Line 643  namespace LinuxSampler {
643       * @param itNoteOffEvent - event which causes this voice to die soon       * @param itNoteOffEvent - event which causes this voice to die soon
644       */       */
645      void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {      void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {
646          const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());          if (pSignalUnitRack == NULL) {
647          pEngineChannel->PortamentoPos = (float) MIDIKey + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;              const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());
648                pEngineChannel->PortamentoPos = (float) MIDIKey + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;
649            } else {
650                // TODO:
651            }
652      }      }
653    
654      /**      /**
# Line 643  namespace LinuxSampler { Line 710  namespace LinuxSampler {
710      }      }
711    
712      void AbstractVoice::EnterReleaseStage() {      void AbstractVoice::EnterReleaseStage() {
713          pEG1->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);          if (pSignalUnitRack == NULL) {
714          pEG2->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);              pEG1->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
715                pEG2->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
716            } else {
717                pSignalUnitRack->EnterReleaseStage();
718            }
719        }
720    
721        bool AbstractVoice::EG1Finished() {
722            if (pSignalUnitRack == NULL) {
723                return pEG1->getSegmentType() == EG::segment_end;
724            } else {
725                return !pSignalUnitRack->GetEndpointUnit()->Active();
726            }
727      }      }
728    
729  } // namespace LinuxSampler  } // namespace LinuxSampler

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

  ViewVC Help
Powered by ViewVC