/[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 2205 by iliev, Mon Jul 11 17:52:01 2011 UTC revision 2298 by iliev, Fri Dec 9 17:04:24 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 43  namespace LinuxSampler { Line 43  namespace LinuxSampler {
43    
44          finalSynthesisParameters.filterLeft.Reset();          finalSynthesisParameters.filterLeft.Reset();
45          finalSynthesisParameters.filterRight.Reset();          finalSynthesisParameters.filterRight.Reset();
46            
47            pEq          = NULL;
48            bEqSupport   = false;
49      }      }
50    
51      AbstractVoice::~AbstractVoice() {      AbstractVoice::~AbstractVoice() {
52          if (pLFO1) delete pLFO1;          if (pLFO1) delete pLFO1;
53          if (pLFO2) delete pLFO2;          if (pLFO2) delete pLFO2;
54          if (pLFO3) delete pLFO3;          if (pLFO3) delete pLFO3;
55            
56            if(pEq != NULL) delete pEq;
57        }
58                
59        void AbstractVoice::CreateEq() {
60            if(!bEqSupport) return;
61            if(pEq != NULL) delete pEq;
62            pEq = new EqSupport;
63            pEq->InitEffect(GetEngine()->pAudioOutputDevice);
64      }      }
65    
66      /**      /**
# Line 99  namespace LinuxSampler { Line 111  namespace LinuxSampler {
111    
112          Type            = VoiceType;          Type            = VoiceType;
113          MIDIKey         = itNoteOnEvent->Param.Note.Key;          MIDIKey         = itNoteOnEvent->Param.Note.Key;
114            MIDIVelocity    = itNoteOnEvent->Param.Note.Velocity;
115            MIDIPan         = pEngineChannel->ControllerTable[10];
116            if (MIDIPan == 0 && pEngineChannel->GlobalPanRight == 1) MIDIPan = 64; // workaround used to determine whether the MIDI pan has not been set
117          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
118          Delay           = itNoteOnEvent->FragmentPos();          Delay           = itNoteOnEvent->FragmentPos();
119          itTriggerEvent  = itNoteOnEvent;          itTriggerEvent  = itNoteOnEvent;
# Line 135  namespace LinuxSampler { Line 150  namespace LinuxSampler {
150          PanLeftSmoother.trigger(pEngineChannel->GlobalPanLeft, subfragmentRate);          PanLeftSmoother.trigger(pEngineChannel->GlobalPanLeft, subfragmentRate);
151          PanRightSmoother.trigger(pEngineChannel->GlobalPanRight, subfragmentRate);          PanRightSmoother.trigger(pEngineChannel->GlobalPanRight, subfragmentRate);
152    
         finalSynthesisParameters.dPos = RgnInfo.SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)  
         Pos = RgnInfo.SampleStartOffset;  
   
153          // 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
154          long cachedsamples = GetSampleCacheSize() / SmplInfo.FrameSize;          long cachedsamples = GetSampleCacheSize() / SmplInfo.FrameSize;
155          DiskVoice          = cachedsamples < SmplInfo.TotalFrameCount;          DiskVoice          = cachedsamples < SmplInfo.TotalFrameCount;
156    
157            SetSampleStartOffset();
158    
159          if (DiskVoice) { // voice to be streamed from disk          if (DiskVoice) { // voice to be streamed from disk
160              if (cachedsamples > (GetEngine()->MaxSamplesPerCycle << CONFIG_MAX_PITCH)) {              if (cachedsamples > (GetEngine()->MaxSamplesPerCycle << CONFIG_MAX_PITCH)) {
161                  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 178  namespace LinuxSampler { Line 192  namespace LinuxSampler {
192          // 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
193          const double velrelease = 1 / GetVelocityRelease(itNoteOnEvent->Param.Note.Velocity);          const double velrelease = 1 / GetVelocityRelease(itNoteOnEvent->Param.Note.Velocity);
194    
195          if (GetSignalUnitRack() == NULL) { // setup EG 1 (VCA EG)          if (pSignalUnitRack == NULL) { // setup EG 1 (VCA EG)
196              // get current value of EG1 controller              // get current value of EG1 controller
197              double eg1controllervalue = GetEG1ControllerValue(itNoteOnEvent->Param.Note.Velocity);              double eg1controllervalue = GetEG1ControllerValue(itNoteOnEvent->Param.Note.Velocity);
198    
# Line 187  namespace LinuxSampler { Line 201  namespace LinuxSampler {
201    
202              TriggerEG1(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity);              TriggerEG1(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity);
203          } else {          } else {
204              GetSignalUnitRack()->Trigger();              pSignalUnitRack->Trigger();
205          }          }
206    
207  #ifdef CONFIG_INTERPOLATE_VOLUME  #ifdef CONFIG_INTERPOLATE_VOLUME
# Line 201  namespace LinuxSampler { Line 215  namespace LinuxSampler {
215      #else      #else
216          {          {
217              float finalVolume;              float finalVolume;
218              if (GetSignalUnitRack() == NULL) {              if (pSignalUnitRack == NULL) {
219                  finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pEG1->getLevel();                  finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pEG1->getLevel();
220              } else {              } else {
221                  finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * GetSignalUnitRack()->GetEndpointUnit()->GetVolume();                  finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pSignalUnitRack->GetEndpointUnit()->GetVolume();
222              }              }
223    
224              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * pEngineChannel->GlobalPanLeft;              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * pEngineChannel->GlobalPanLeft;
# Line 213  namespace LinuxSampler { Line 227  namespace LinuxSampler {
227      #endif      #endif
228  #endif  #endif
229    
230          if (GetSignalUnitRack() == NULL) {          if (pSignalUnitRack == NULL) {
231              // setup EG 2 (VCF Cutoff EG)              // setup EG 2 (VCF Cutoff EG)
232              {              {
233                  // get current value of EG2 controller                  // get current value of EG2 controller
# Line 295  namespace LinuxSampler { Line 309  namespace LinuxSampler {
309    
310          return 0; // success          return 0; // success
311      }      }
312        
313        void AbstractVoice::SetSampleStartOffset() {
314            finalSynthesisParameters.dPos = RgnInfo.SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)
315            Pos = RgnInfo.SampleStartOffset;
316        }
317    
318      /**      /**
319       *  Synthesizes the current audio fragment for this voice.       *  Synthesizes the current audio fragment for this voice.
# Line 305  namespace LinuxSampler { Line 324  namespace LinuxSampler {
324       *  @param Skip    - number of sample points to skip in output buffer       *  @param Skip    - number of sample points to skip in output buffer
325       */       */
326      void AbstractVoice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {      void AbstractVoice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {
327            bool delay = false; // Whether the voice playback should be delayed for this call
328            
329            if (pSignalUnitRack != NULL) {
330                uint delaySteps = pSignalUnitRack->GetEndpointUnit()->DelayTrigger();
331                if (delaySteps > 0) { // delay on the endpoint unit means delay of the voice playback
332                    if (delaySteps >= Samples) {
333                        pSignalUnitRack->GetEndpointUnit()->DecreaseDelay(Samples);
334                        delay = true;
335                    } else {
336                        pSignalUnitRack->GetEndpointUnit()->DecreaseDelay(delaySteps);
337                        Samples -= delaySteps;
338                        Skip += delaySteps;
339                    }
340                }
341            }
342            
343          AbstractEngineChannel* pChannel = pEngineChannel;          AbstractEngineChannel* pChannel = pEngineChannel;
344          MidiKeyBase* pMidiKeyInfo = GetMidiKeyInfo(MIDIKey);          MidiKeyBase* pMidiKeyInfo = GetMidiKeyInfo(MIDIKey);
345    
346          const bool bVoiceRequiresDedicatedRouting =          const bool bVoiceRequiresDedicatedRouting =
347              pEngineChannel->GetFxSendCount() > 0 &&              pEngineChannel->GetFxSendCount() > 0 &&
348              (pMidiKeyInfo->ReverbSend || pMidiKeyInfo->ChorusSend);              (pMidiKeyInfo->ReverbSend || pMidiKeyInfo->ChorusSend);
349            
350            const bool bEq =
351                pSignalUnitRack != NULL && pSignalUnitRack->HasEq() && pEq->HasSupport();
352    
353          if (bVoiceRequiresDedicatedRouting) {          if (bEq) {
354                pEq->GetInChannelLeft()->Clear();
355                pEq->GetInChannelRight()->Clear();
356                finalSynthesisParameters.pOutLeft  = &pEq->GetInChannelLeft()->Buffer()[Skip];
357                finalSynthesisParameters.pOutRight = &pEq->GetInChannelRight()->Buffer()[Skip];
358                pSignalUnitRack->UpdateEqSettings(pEq);
359            } else if (bVoiceRequiresDedicatedRouting) {
360              finalSynthesisParameters.pOutLeft  = &GetEngine()->pDedicatedVoiceChannelLeft->Buffer()[Skip];              finalSynthesisParameters.pOutLeft  = &GetEngine()->pDedicatedVoiceChannelLeft->Buffer()[Skip];
361              finalSynthesisParameters.pOutRight = &GetEngine()->pDedicatedVoiceChannelRight->Buffer()[Skip];              finalSynthesisParameters.pOutRight = &GetEngine()->pDedicatedVoiceChannelRight->Buffer()[Skip];
362          } else {          } else {
# Line 352  namespace LinuxSampler { Line 396  namespace LinuxSampler {
396                  // drivers that use Samples < MaxSamplesPerCycle).                  // drivers that use Samples < MaxSamplesPerCycle).
397                  // End the EG1 here, at pos 0, with a shorter max fade                  // End the EG1 here, at pos 0, with a shorter max fade
398                  // out time.                  // out time.
399                  if (GetSignalUnitRack() == NULL) {                  if (pSignalUnitRack == NULL) {
400                      pEG1->enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                      pEG1->enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
401                  } else {                  } else {
402                      // TODO:                      // TODO:
# Line 373  namespace LinuxSampler { Line 417  namespace LinuxSampler {
417    
418              // process MIDI control change and pitchbend events for this subfragment              // process MIDI control change and pitchbend events for this subfragment
419              processCCEvents(itCCEvent, iSubFragmentEnd);              processCCEvents(itCCEvent, iSubFragmentEnd);
420                uint8_t pan = MIDIPan;
421                if (pSignalUnitRack != NULL) pan = pSignalUnitRack->GetEndpointUnit()->CaluclatePan(pan);
422                
423                PanLeftSmoother.update(AbstractEngine::PanCurve[128 - pan]);
424                PanRightSmoother.update(AbstractEngine::PanCurve[pan]);
425    
426              finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend;              finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend;
427              float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render();              float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render();
# Line 383  namespace LinuxSampler { Line 432  namespace LinuxSampler {
432              // process transition events (note on, note off & sustain pedal)              // process transition events (note on, note off & sustain pedal)
433              processTransitionEvents(itNoteEvent, iSubFragmentEnd);              processTransitionEvents(itNoteEvent, iSubFragmentEnd);
434              processGroupEvents(itGroupEvent, iSubFragmentEnd);              processGroupEvents(itGroupEvent, iSubFragmentEnd);
435                
436              if (GetSignalUnitRack() == NULL) {              if (pSignalUnitRack == NULL) {
437                  // if the voice was killed in this subfragment, or if the                  // if the voice was killed in this subfragment, or if the
438                  // filter EG is finished, switch EG1 to fade out stage                  // filter EG is finished, switch EG1 to fade out stage
439                  if ((itKillEvent && killPos <= iSubFragmentEnd) ||                  if ((itKillEvent && killPos <= iSubFragmentEnd) ||
# Line 440  namespace LinuxSampler { Line 489  namespace LinuxSampler {
489                  }*/                  }*/
490                  // TODO: ^^^                  // TODO: ^^^
491    
492                  fFinalVolume   *= GetSignalUnitRack()->GetEndpointUnit()->GetVolume();                  fFinalVolume   *= pSignalUnitRack->GetEndpointUnit()->GetVolume();
493                  fFinalCutoff    = GetSignalUnitRack()->GetEndpointUnit()->CalculateFilterCutoff(fFinalCutoff);                  fFinalCutoff    = pSignalUnitRack->GetEndpointUnit()->CalculateFilterCutoff(fFinalCutoff);
494                  fFinalResonance = GetSignalUnitRack()->GetEndpointUnit()->CalculateResonance(fFinalResonance);                  fFinalResonance = pSignalUnitRack->GetEndpointUnit()->CalculateResonance(fFinalResonance);
495                                    
496                  finalSynthesisParameters.fFinalPitch =                  finalSynthesisParameters.fFinalPitch =
497                      GetSignalUnitRack()->GetEndpointUnit()->CalculatePitch(finalSynthesisParameters.fFinalPitch);                      pSignalUnitRack->GetEndpointUnit()->CalculatePitch(finalSynthesisParameters.fFinalPitch);
498                                            
499              }              }
500                            
# Line 481  namespace LinuxSampler { Line 530  namespace LinuxSampler {
530                  fFinalVolume * VolumeRight * PanRightSmoother.render();                  fFinalVolume * VolumeRight * PanRightSmoother.render();
531  #endif  #endif
532              // render audio for one subfragment              // render audio for one subfragment
533              RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);              if (!delay) RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);
534    
535              if (GetSignalUnitRack() == NULL) {              if (pSignalUnitRack == NULL) {
536                  // stop the rendering if volume EG is finished                  // stop the rendering if volume EG is finished
537                  if (pEG1->getSegmentType() == EG::segment_end) break;                  if (pEG1->getSegmentType() == EG::segment_end) break;
538              } else {              } else {
539                  // stop the rendering if the endpoint unit is not active                  // stop the rendering if the endpoint unit is not active
540                  if (!GetSignalUnitRack()->GetEndpointUnit()->Active()) break;                  if (!pSignalUnitRack->GetEndpointUnit()->Active()) break;
541              }              }
542    
543              const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;              const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;
544    
545              if (GetSignalUnitRack() == NULL) {              if (pSignalUnitRack == NULL) {
546                  // increment envelopes' positions                  // increment envelopes' positions
547                  if (pEG1->active()) {                  if (pEG1->active()) {
548    
# Line 518  namespace LinuxSampler { Line 567  namespace LinuxSampler {
567                      }*/                      }*/
568                  // TODO: ^^^                  // TODO: ^^^
569                                    
570                  GetSignalUnitRack()->Increment();                  if (!delay) pSignalUnitRack->Increment();
571              }              }
572    
573              Pos = newPos;              Pos = newPos;
574              i = iSubFragmentEnd;              i = iSubFragmentEnd;
575          }          }
576            
577            if (delay) return;
578    
579          if (bVoiceRequiresDedicatedRouting) {          if (bVoiceRequiresDedicatedRouting) {
580                if (bEq) {
581                    pEq->RenderAudio(Samples);
582                    pEq->GetOutChannelLeft()->CopyTo(GetEngine()->pDedicatedVoiceChannelLeft, Samples);
583                    pEq->GetOutChannelRight()->CopyTo(GetEngine()->pDedicatedVoiceChannelRight, Samples);
584                }
585              optional<float> effectSendLevels[2] = {              optional<float> effectSendLevels[2] = {
586                  pMidiKeyInfo->ReverbSend,                  pMidiKeyInfo->ReverbSend,
587                  pMidiKeyInfo->ChorusSend                  pMidiKeyInfo->ChorusSend
588              };              };
589              GetEngine()->RouteDedicatedVoiceChannels(pEngineChannel, effectSendLevels, Samples);              GetEngine()->RouteDedicatedVoiceChannels(pEngineChannel, effectSendLevels, Samples);
590            } else if (bEq) {
591                pEq->RenderAudio(Samples);
592                pEq->GetOutChannelLeft()->MixTo(pChannel->pChannelLeft, Samples);
593                pEq->GetOutChannelRight()->MixTo(pChannel->pChannelRight, Samples);
594          }          }
595      }      }
596    
# Line 550  namespace LinuxSampler { Line 610  namespace LinuxSampler {
610                  if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {                  if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {
611                      processResonanceEvent(itEvent);                      processResonanceEvent(itEvent);
612                  }                  }
613                  if (GetSignalUnitRack() == NULL) {                  if (pSignalUnitRack == NULL) {
614                      if (itEvent->Param.CC.Controller == pLFO1->ExtController) {                      if (itEvent->Param.CC.Controller == pLFO1->ExtController) {
615                          pLFO1->update(itEvent->Param.CC.Value);                          pLFO1->update(itEvent->Param.CC.Value);
616                      }                      }
# Line 564  namespace LinuxSampler { Line 624  namespace LinuxSampler {
624                  if (itEvent->Param.CC.Controller == 7) { // volume                  if (itEvent->Param.CC.Controller == 7) { // volume
625                      VolumeSmoother.update(AbstractEngine::VolumeCurve[itEvent->Param.CC.Value]);                      VolumeSmoother.update(AbstractEngine::VolumeCurve[itEvent->Param.CC.Value]);
626                  } else if (itEvent->Param.CC.Controller == 10) { // panpot                  } else if (itEvent->Param.CC.Controller == 10) { // panpot
627                      PanLeftSmoother.update(AbstractEngine::PanCurve[128 - itEvent->Param.CC.Value]);                      MIDIPan = itEvent->Param.CC.Value;
                     PanRightSmoother.update(AbstractEngine::PanCurve[itEvent->Param.CC.Value]);  
628                  }                  }
629              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event
630                  processPitchEvent(itEvent);                  processPitchEvent(itEvent);
631              }              }
632    
633              ProcessCCEvent(itEvent);              ProcessCCEvent(itEvent);
634              if (GetSignalUnitRack() != NULL) {              if (pSignalUnitRack != NULL) {
635                  GetSignalUnitRack()->ProcessCCEvent(itEvent);                  pSignalUnitRack->ProcessCCEvent(itEvent);
636              }              }
637          }          }
638      }      }
# Line 606  namespace LinuxSampler { Line 665  namespace LinuxSampler {
665                  if (itEvent->Type == Event::type_release) {                  if (itEvent->Type == Event::type_release) {
666                      EnterReleaseStage();                      EnterReleaseStage();
667                  } else if (itEvent->Type == Event::type_cancel_release) {                  } else if (itEvent->Type == Event::type_cancel_release) {
668                      if (GetSignalUnitRack() == NULL) {                      if (pSignalUnitRack == NULL) {
669                          pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                          pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
670                          pEG2->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                          pEG2->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
671                      } else {                      } else {
672                          GetSignalUnitRack()->CancelRelease();                          pSignalUnitRack->CancelRelease();
673                      }                      }
674                  }                  }
675              }              }
# Line 638  namespace LinuxSampler { Line 697  namespace LinuxSampler {
697       * @param itNoteOffEvent - event which causes this voice to die soon       * @param itNoteOffEvent - event which causes this voice to die soon
698       */       */
699      void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {      void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {
700          if (GetSignalUnitRack() == NULL) {          if (pSignalUnitRack == NULL) {
701              const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());              const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());
702              pEngineChannel->PortamentoPos = (float) MIDIKey + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;              pEngineChannel->PortamentoPos = (float) MIDIKey + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;
703          } else {          } else {
# Line 705  namespace LinuxSampler { Line 764  namespace LinuxSampler {
764      }      }
765    
766      void AbstractVoice::EnterReleaseStage() {      void AbstractVoice::EnterReleaseStage() {
767          if (GetSignalUnitRack() == NULL) {          if (pSignalUnitRack == NULL) {
768              pEG1->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);              pEG1->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
769              pEG2->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);              pEG2->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
770          } else {          } else {
771              GetSignalUnitRack()->EnterReleaseStage();              pSignalUnitRack->EnterReleaseStage();
772          }          }
773      }      }
774    
775      bool AbstractVoice::EG1Finished() {      bool AbstractVoice::EG1Finished() {
776          if (GetSignalUnitRack() == NULL) {          if (pSignalUnitRack == NULL) {
777              return pEG1->getSegmentType() == EG::segment_end;              return pEG1->getSegmentType() == EG::segment_end;
778          } else {          } else {
779              return !GetSignalUnitRack()->GetEndpointUnit()->Active();              return !pSignalUnitRack->GetEndpointUnit()->Active();
780          }          }
781      }      }
782    

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

  ViewVC Help
Powered by ViewVC