/[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 2382 by persson, Sun Dec 2 16:30:42 2012 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-2011 Christian Schoenebeck and Grigor Iliev        *   *   Copyright (C) 2009-2012 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 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          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
116          Delay           = itNoteOnEvent->FragmentPos();          Delay           = itNoteOnEvent->FragmentPos();
117          itTriggerEvent  = itNoteOnEvent;          itTriggerEvent  = itNoteOnEvent;
# Line 111  namespace LinuxSampler { Line 124  namespace LinuxSampler {
124          RgnInfo    = GetRegionInfo();          RgnInfo    = GetRegionInfo();
125          InstrInfo  = GetInstrumentInfo();          InstrInfo  = GetInstrumentInfo();
126                    
127            MIDIPan    = CalculatePan(pEngineChannel->iLastPanRequest);
128    
129          AboutToTrigger();          AboutToTrigger();
130    
131          // calculate volume          // calculate volume
# Line 126  namespace LinuxSampler { Line 141  namespace LinuxSampler {
141          // get starting crossfade volume level          // get starting crossfade volume level
142          float crossfadeVolume = CalculateCrossfadeVolume(itNoteOnEvent->Param.Note.Velocity);          float crossfadeVolume = CalculateCrossfadeVolume(itNoteOnEvent->Param.Note.Velocity);
143    
144          VolumeLeft  = volume * pKeyInfo->PanLeft  * AbstractEngine::PanCurve[64 - RgnInfo.Pan];          VolumeLeft  = volume * pKeyInfo->PanLeft;
145          VolumeRight = volume * pKeyInfo->PanRight * AbstractEngine::PanCurve[64 + RgnInfo.Pan];          VolumeRight = volume * pKeyInfo->PanRight;
146    
147          float subfragmentRate = GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;          float subfragmentRate = GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;
148          CrossfadeSmoother.trigger(crossfadeVolume, subfragmentRate);          CrossfadeSmoother.trigger(crossfadeVolume, subfragmentRate);
149          VolumeSmoother.trigger(pEngineChannel->MidiVolume, subfragmentRate);          VolumeSmoother.trigger(pEngineChannel->MidiVolume, subfragmentRate);
         PanLeftSmoother.trigger(pEngineChannel->GlobalPanLeft, subfragmentRate);  
         PanRightSmoother.trigger(pEngineChannel->GlobalPanRight, subfragmentRate);  
   
         finalSynthesisParameters.dPos = RgnInfo.SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)  
         Pos = RgnInfo.SampleStartOffset;  
150    
151          // 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
152          long cachedsamples = GetSampleCacheSize() / SmplInfo.FrameSize;          long cachedsamples = GetSampleCacheSize() / SmplInfo.FrameSize;
153          DiskVoice          = cachedsamples < SmplInfo.TotalFrameCount;          DiskVoice          = cachedsamples < SmplInfo.TotalFrameCount;
154    
155            SetSampleStartOffset();
156    
157          if (DiskVoice) { // voice to be streamed from disk          if (DiskVoice) { // voice to be streamed from disk
158              if (cachedsamples > (GetEngine()->MaxSamplesPerCycle << CONFIG_MAX_PITCH)) {              if (cachedsamples > (GetEngine()->MaxSamplesPerCycle << CONFIG_MAX_PITCH)) {
159                  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 190  namespace LinuxSampler {
190          // 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
191          const double velrelease = 1 / GetVelocityRelease(itNoteOnEvent->Param.Note.Velocity);          const double velrelease = 1 / GetVelocityRelease(itNoteOnEvent->Param.Note.Velocity);
192    
193          if (GetSignalUnitRack() == NULL) { // setup EG 1 (VCA EG)          if (pSignalUnitRack == NULL) { // setup EG 1 (VCA EG)
194              // get current value of EG1 controller              // get current value of EG1 controller
195              double eg1controllervalue = GetEG1ControllerValue(itNoteOnEvent->Param.Note.Velocity);              double eg1controllervalue = GetEG1ControllerValue(itNoteOnEvent->Param.Note.Velocity);
196    
# Line 187  namespace LinuxSampler { Line 199  namespace LinuxSampler {
199    
200              TriggerEG1(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity);              TriggerEG1(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity);
201          } else {          } else {
202              GetSignalUnitRack()->Trigger();              pSignalUnitRack->Trigger();
203          }          }
204    
205            uint8_t pan = MIDIPan;
206            if (pSignalUnitRack) pan = pSignalUnitRack->GetEndpointUnit()->CalculatePan(MIDIPan);
207            PanLeftSmoother.trigger(AbstractEngine::PanCurve[128 - pan], subfragmentRate);
208            PanRightSmoother.trigger(AbstractEngine::PanCurve[pan], subfragmentRate);
209    
210  #ifdef CONFIG_INTERPOLATE_VOLUME  #ifdef CONFIG_INTERPOLATE_VOLUME
211          // setup initial volume in synthesis parameters          // setup initial volume in synthesis parameters
212      #ifdef CONFIG_PROCESS_MUTED_CHANNELS      #ifdef CONFIG_PROCESS_MUTED_CHANNELS
# Line 201  namespace LinuxSampler { Line 218  namespace LinuxSampler {
218      #else      #else
219          {          {
220              float finalVolume;              float finalVolume;
221              if (GetSignalUnitRack() == NULL) {              if (pSignalUnitRack == NULL) {
222                  finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pEG1->getLevel();                  finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pEG1->getLevel();
223              } else {              } else {
224                  finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * GetSignalUnitRack()->GetEndpointUnit()->GetVolume();                  finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pSignalUnitRack->GetEndpointUnit()->GetVolume();
225              }              }
226    
227              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * pEngineChannel->GlobalPanLeft;              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * PanLeftSmoother.render();
228              finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * pEngineChannel->GlobalPanRight;              finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * PanRightSmoother.render();
229          }          }
230      #endif      #endif
231  #endif  #endif
232    
233          if (GetSignalUnitRack() == NULL) {          if (pSignalUnitRack == NULL) {
234              // setup EG 2 (VCF Cutoff EG)              // setup EG 2 (VCF Cutoff EG)
235              {              {
236                  // get current value of EG2 controller                  // get current value of EG2 controller
# Line 292  namespace LinuxSampler { Line 309  namespace LinuxSampler {
309              VCFCutoffCtrl.controller    = 0;              VCFCutoffCtrl.controller    = 0;
310              VCFResonanceCtrl.controller = 0;              VCFResonanceCtrl.controller = 0;
311          }          }
312            
313            const bool bEq =
314                pSignalUnitRack != NULL && pSignalUnitRack->HasEq() && pEq->HasSupport();
315    
316            if (bEq) {
317                pEq->GetInChannelLeft()->Clear();
318                pEq->GetInChannelRight()->Clear();
319                pEq->RenderAudio(GetEngine()->pAudioOutputDevice->MaxSamplesPerCycle());
320            }
321    
322          return 0; // success          return 0; // success
323      }      }
324        
325        void AbstractVoice::SetSampleStartOffset() {
326            finalSynthesisParameters.dPos = RgnInfo.SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)
327            Pos = RgnInfo.SampleStartOffset;
328        }
329    
330      /**      /**
331       *  Synthesizes the current audio fragment for this voice.       *  Synthesizes the current audio fragment for this voice.
# Line 305  namespace LinuxSampler { Line 336  namespace LinuxSampler {
336       *  @param Skip    - number of sample points to skip in output buffer       *  @param Skip    - number of sample points to skip in output buffer
337       */       */
338      void AbstractVoice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {      void AbstractVoice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {
339            bool delay = false; // Whether the voice playback should be delayed for this call
340            
341            if (pSignalUnitRack != NULL) {
342                uint delaySteps = pSignalUnitRack->GetEndpointUnit()->DelayTrigger();
343                if (delaySteps > 0) { // delay on the endpoint unit means delay of the voice playback
344                    if (delaySteps >= Samples) {
345                        pSignalUnitRack->GetEndpointUnit()->DecreaseDelay(Samples);
346                        delay = true;
347                    } else {
348                        pSignalUnitRack->GetEndpointUnit()->DecreaseDelay(delaySteps);
349                        Samples -= delaySteps;
350                        Skip += delaySteps;
351                    }
352                }
353            }
354            
355          AbstractEngineChannel* pChannel = pEngineChannel;          AbstractEngineChannel* pChannel = pEngineChannel;
356          MidiKeyBase* pMidiKeyInfo = GetMidiKeyInfo(MIDIKey);          MidiKeyBase* pMidiKeyInfo = GetMidiKeyInfo(MIDIKey);
357    
358          const bool bVoiceRequiresDedicatedRouting =          const bool bVoiceRequiresDedicatedRouting =
359              pEngineChannel->GetFxSendCount() > 0 &&              pEngineChannel->GetFxSendCount() > 0 &&
360              (pMidiKeyInfo->ReverbSend || pMidiKeyInfo->ChorusSend);              (pMidiKeyInfo->ReverbSend || pMidiKeyInfo->ChorusSend);
361            
362            const bool bEq =
363                pSignalUnitRack != NULL && pSignalUnitRack->HasEq() && pEq->HasSupport();
364    
365          if (bVoiceRequiresDedicatedRouting) {          if (bEq) {
366                pEq->GetInChannelLeft()->Clear();
367                pEq->GetInChannelRight()->Clear();
368                finalSynthesisParameters.pOutLeft  = &pEq->GetInChannelLeft()->Buffer()[Skip];
369                finalSynthesisParameters.pOutRight = &pEq->GetInChannelRight()->Buffer()[Skip];
370                pSignalUnitRack->UpdateEqSettings(pEq);
371            } else if (bVoiceRequiresDedicatedRouting) {
372              finalSynthesisParameters.pOutLeft  = &GetEngine()->pDedicatedVoiceChannelLeft->Buffer()[Skip];              finalSynthesisParameters.pOutLeft  = &GetEngine()->pDedicatedVoiceChannelLeft->Buffer()[Skip];
373              finalSynthesisParameters.pOutRight = &GetEngine()->pDedicatedVoiceChannelRight->Buffer()[Skip];              finalSynthesisParameters.pOutRight = &GetEngine()->pDedicatedVoiceChannelRight->Buffer()[Skip];
374          } else {          } else {
# Line 326  namespace LinuxSampler { Line 382  namespace LinuxSampler {
382          GetFirstEventOnKey(MIDIKey, itNoteEvent);          GetFirstEventOnKey(MIDIKey, itNoteEvent);
383    
384          RTList<Event>::Iterator itGroupEvent;          RTList<Event>::Iterator itGroupEvent;
385          if (pGroupEvents) itGroupEvent = pGroupEvents->first();          if (pGroupEvents && !Orphan) itGroupEvent = pGroupEvents->first();
386    
387          if (itTriggerEvent) { // skip events that happened before this voice was triggered          if (itTriggerEvent) { // skip events that happened before this voice was triggered
388              while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;              while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;
# Line 352  namespace LinuxSampler { Line 408  namespace LinuxSampler {
408                  // drivers that use Samples < MaxSamplesPerCycle).                  // drivers that use Samples < MaxSamplesPerCycle).
409                  // End the EG1 here, at pos 0, with a shorter max fade                  // End the EG1 here, at pos 0, with a shorter max fade
410                  // out time.                  // out time.
411                  if (GetSignalUnitRack() == NULL) {                  if (pSignalUnitRack == NULL) {
412                      pEG1->enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                      pEG1->enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
413                  } else {                  } else {
414                      // TODO:                      pSignalUnitRack->EnterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
415                  }                  }
416                  itKillEvent = Pool<Event>::Iterator();                  itKillEvent = Pool<Event>::Iterator();
417              } else {              } else {
# Line 373  namespace LinuxSampler { Line 429  namespace LinuxSampler {
429    
430              // process MIDI control change and pitchbend events for this subfragment              // process MIDI control change and pitchbend events for this subfragment
431              processCCEvents(itCCEvent, iSubFragmentEnd);              processCCEvents(itCCEvent, iSubFragmentEnd);
432                uint8_t pan = MIDIPan;
433                if (pSignalUnitRack != NULL) pan = pSignalUnitRack->GetEndpointUnit()->CalculatePan(MIDIPan);
434                
435                PanLeftSmoother.update(AbstractEngine::PanCurve[128 - pan]);
436                PanRightSmoother.update(AbstractEngine::PanCurve[pan]);
437    
438              finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend;              finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend;
439              float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render();              float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render();
# Line 383  namespace LinuxSampler { Line 444  namespace LinuxSampler {
444              // process transition events (note on, note off & sustain pedal)              // process transition events (note on, note off & sustain pedal)
445              processTransitionEvents(itNoteEvent, iSubFragmentEnd);              processTransitionEvents(itNoteEvent, iSubFragmentEnd);
446              processGroupEvents(itGroupEvent, iSubFragmentEnd);              processGroupEvents(itGroupEvent, iSubFragmentEnd);
447                
448              if (GetSignalUnitRack() == NULL) {              if (pSignalUnitRack == NULL) {
449                  // if the voice was killed in this subfragment, or if the                  // if the voice was killed in this subfragment, or if the
450                  // filter EG is finished, switch EG1 to fade out stage                  // filter EG is finished, switch EG1 to fade out stage
451                  if ((itKillEvent && killPos <= iSubFragmentEnd) ||                  if ((itKillEvent && killPos <= iSubFragmentEnd) ||
# Line 430  namespace LinuxSampler { Line 491  namespace LinuxSampler {
491                  if (bLFO2Enabled) fFinalCutoff *= pLFO2->render();                  if (bLFO2Enabled) fFinalCutoff *= pLFO2->render();
492                  if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());                  if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());
493              } else {              } else {
494                  // if the voice was killed in this subfragment, or if the                  // if the voice was killed in this subfragment, enter fade out stage
495                  // filter EG is finished, switch EG1 to fade out stage                  if (itKillEvent && killPos <= iSubFragmentEnd) {
496                  /*if ((itKillEvent && killPos <= iSubFragmentEnd) ||                      pSignalUnitRack->EnterFadeOutStage();
497                      (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&                      itKillEvent = Pool<Event>::Iterator();
498                      pEG2->getSegmentType() == EG::segment_end)) {                  }
499                    
500                    // if the filter EG is finished, switch EG1 to fade out stage
501                    /*if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&
502                        pEG2->getSegmentType() == EG::segment_end) {
503                      pEG1->enterFadeOutStage();                      pEG1->enterFadeOutStage();
504                      itKillEvent = Pool<Event>::Iterator();                      itKillEvent = Pool<Event>::Iterator();
505                  }*/                  }*/
506                  // TODO: ^^^                  // TODO: ^^^
507    
508                  fFinalVolume   *= GetSignalUnitRack()->GetEndpointUnit()->GetVolume();                  fFinalVolume   *= pSignalUnitRack->GetEndpointUnit()->GetVolume();
509                  fFinalCutoff    = GetSignalUnitRack()->GetEndpointUnit()->CalculateFilterCutoff(fFinalCutoff);                  fFinalCutoff    = pSignalUnitRack->GetEndpointUnit()->CalculateFilterCutoff(fFinalCutoff);
510                  fFinalResonance = GetSignalUnitRack()->GetEndpointUnit()->CalculateResonance(fFinalResonance);                  fFinalResonance = pSignalUnitRack->GetEndpointUnit()->CalculateResonance(fFinalResonance);
511                                    
512                  finalSynthesisParameters.fFinalPitch =                  finalSynthesisParameters.fFinalPitch =
513                      GetSignalUnitRack()->GetEndpointUnit()->CalculatePitch(finalSynthesisParameters.fFinalPitch);                      pSignalUnitRack->GetEndpointUnit()->CalculatePitch(finalSynthesisParameters.fFinalPitch);
514                                            
515              }              }
516                            
# Line 481  namespace LinuxSampler { Line 546  namespace LinuxSampler {
546                  fFinalVolume * VolumeRight * PanRightSmoother.render();                  fFinalVolume * VolumeRight * PanRightSmoother.render();
547  #endif  #endif
548              // render audio for one subfragment              // render audio for one subfragment
549              RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);              if (!delay) RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);
550    
551              if (GetSignalUnitRack() == NULL) {              if (pSignalUnitRack == NULL) {
552                  // stop the rendering if volume EG is finished                  // stop the rendering if volume EG is finished
553                  if (pEG1->getSegmentType() == EG::segment_end) break;                  if (pEG1->getSegmentType() == EG::segment_end) break;
554              } else {              } else {
555                  // stop the rendering if the endpoint unit is not active                  // stop the rendering if the endpoint unit is not active
556                  if (!GetSignalUnitRack()->GetEndpointUnit()->Active()) break;                  if (!pSignalUnitRack->GetEndpointUnit()->Active()) break;
557              }              }
558    
559              const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;              const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;
560    
561              if (GetSignalUnitRack() == NULL) {              if (pSignalUnitRack == NULL) {
562                  // increment envelopes' positions                  // increment envelopes' positions
563                  if (pEG1->active()) {                  if (pEG1->active()) {
564    
# Line 518  namespace LinuxSampler { Line 583  namespace LinuxSampler {
583                      }*/                      }*/
584                  // TODO: ^^^                  // TODO: ^^^
585                                    
586                  GetSignalUnitRack()->Increment();                  if (!delay) pSignalUnitRack->Increment();
587              }              }
588    
589              Pos = newPos;              Pos = newPos;
590              i = iSubFragmentEnd;              i = iSubFragmentEnd;
591          }          }
592            
593            if (delay) return;
594    
595          if (bVoiceRequiresDedicatedRouting) {          if (bVoiceRequiresDedicatedRouting) {
596                if (bEq) {
597                    pEq->RenderAudio(Samples);
598                    pEq->GetOutChannelLeft()->CopyTo(GetEngine()->pDedicatedVoiceChannelLeft, Samples);
599                    pEq->GetOutChannelRight()->CopyTo(GetEngine()->pDedicatedVoiceChannelRight, Samples);
600                }
601              optional<float> effectSendLevels[2] = {              optional<float> effectSendLevels[2] = {
602                  pMidiKeyInfo->ReverbSend,                  pMidiKeyInfo->ReverbSend,
603                  pMidiKeyInfo->ChorusSend                  pMidiKeyInfo->ChorusSend
604              };              };
605              GetEngine()->RouteDedicatedVoiceChannels(pEngineChannel, effectSendLevels, Samples);              GetEngine()->RouteDedicatedVoiceChannels(pEngineChannel, effectSendLevels, Samples);
606            } else if (bEq) {
607                pEq->RenderAudio(Samples);
608                pEq->GetOutChannelLeft()->MixTo(pChannel->pChannelLeft, Samples);
609                pEq->GetOutChannelRight()->MixTo(pChannel->pChannelRight, Samples);
610          }          }
611      }      }
612    
# Line 550  namespace LinuxSampler { Line 626  namespace LinuxSampler {
626                  if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {                  if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {
627                      processResonanceEvent(itEvent);                      processResonanceEvent(itEvent);
628                  }                  }
629                  if (GetSignalUnitRack() == NULL) {                  if (pSignalUnitRack == NULL) {
630                      if (itEvent->Param.CC.Controller == pLFO1->ExtController) {                      if (itEvent->Param.CC.Controller == pLFO1->ExtController) {
631                          pLFO1->update(itEvent->Param.CC.Value);                          pLFO1->update(itEvent->Param.CC.Value);
632                      }                      }
# Line 564  namespace LinuxSampler { Line 640  namespace LinuxSampler {
640                  if (itEvent->Param.CC.Controller == 7) { // volume                  if (itEvent->Param.CC.Controller == 7) { // volume
641                      VolumeSmoother.update(AbstractEngine::VolumeCurve[itEvent->Param.CC.Value]);                      VolumeSmoother.update(AbstractEngine::VolumeCurve[itEvent->Param.CC.Value]);
642                  } else if (itEvent->Param.CC.Controller == 10) { // panpot                  } else if (itEvent->Param.CC.Controller == 10) { // panpot
643                      PanLeftSmoother.update(AbstractEngine::PanCurve[128 - itEvent->Param.CC.Value]);                      MIDIPan = CalculatePan(itEvent->Param.CC.Value);
                     PanRightSmoother.update(AbstractEngine::PanCurve[itEvent->Param.CC.Value]);  
644                  }                  }
645              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event
646                  processPitchEvent(itEvent);                  processPitchEvent(itEvent);
647              }              }
648    
649              ProcessCCEvent(itEvent);              ProcessCCEvent(itEvent);
650              if (GetSignalUnitRack() != NULL) {              if (pSignalUnitRack != NULL) {
651                  GetSignalUnitRack()->ProcessCCEvent(itEvent);                  pSignalUnitRack->ProcessCCEvent(itEvent);
652              }              }
653          }          }
654      }      }
# Line 606  namespace LinuxSampler { Line 681  namespace LinuxSampler {
681                  if (itEvent->Type == Event::type_release) {                  if (itEvent->Type == Event::type_release) {
682                      EnterReleaseStage();                      EnterReleaseStage();
683                  } else if (itEvent->Type == Event::type_cancel_release) {                  } else if (itEvent->Type == Event::type_cancel_release) {
684                      if (GetSignalUnitRack() == NULL) {                      if (pSignalUnitRack == NULL) {
685                          pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                          pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
686                          pEG2->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                          pEG2->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
687                      } else {                      } else {
688                          GetSignalUnitRack()->CancelRelease();                          pSignalUnitRack->CancelRelease();
689                      }                      }
690                  }                  }
691              }              }
# Line 638  namespace LinuxSampler { Line 713  namespace LinuxSampler {
713       * @param itNoteOffEvent - event which causes this voice to die soon       * @param itNoteOffEvent - event which causes this voice to die soon
714       */       */
715      void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {      void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {
716          if (GetSignalUnitRack() == NULL) {          if (pSignalUnitRack == NULL) {
717              const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());              const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());
718              pEngineChannel->PortamentoPos = (float) MIDIKey + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;              pEngineChannel->PortamentoPos = (float) MIDIKey + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;
719          } else {          } else {
# Line 705  namespace LinuxSampler { Line 780  namespace LinuxSampler {
780      }      }
781    
782      void AbstractVoice::EnterReleaseStage() {      void AbstractVoice::EnterReleaseStage() {
783          if (GetSignalUnitRack() == NULL) {          if (pSignalUnitRack == NULL) {
784              pEG1->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);              pEG1->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
785              pEG2->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);              pEG2->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
786          } else {          } else {
787              GetSignalUnitRack()->EnterReleaseStage();              pSignalUnitRack->EnterReleaseStage();
788          }          }
789      }      }
790    
791      bool AbstractVoice::EG1Finished() {      bool AbstractVoice::EG1Finished() {
792          if (GetSignalUnitRack() == NULL) {          if (pSignalUnitRack == NULL) {
793              return pEG1->getSegmentType() == EG::segment_end;              return pEG1->getSegmentType() == EG::segment_end;
794          } else {          } else {
795              return !GetSignalUnitRack()->GetEndpointUnit()->Active();              return !pSignalUnitRack->GetEndpointUnit()->Active();
796          }          }
797      }      }
798    

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

  ViewVC Help
Powered by ViewVC