/[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 2299 by iliev, Sun Dec 11 20:50:31 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 110  namespace LinuxSampler { Line 125  namespace LinuxSampler {
125          SmplInfo   = GetSampleInfo();          SmplInfo   = GetSampleInfo();
126          RgnInfo    = GetRegionInfo();          RgnInfo    = GetRegionInfo();
127          InstrInfo  = GetInstrumentInfo();          InstrInfo  = GetInstrumentInfo();
128            
129            AboutToTrigger();
130    
131          // calculate volume          // calculate volume
132          const double velocityAttenuation = GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity);          const double velocityAttenuation = GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity);
# Line 133  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 176  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          // 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 185  namespace LinuxSampler { Line 200  namespace LinuxSampler {
200              EGInfo egInfo = CalculateEG1ControllerInfluence(eg1controllervalue);              EGInfo egInfo = CalculateEG1ControllerInfluence(eg1controllervalue);
201    
202              TriggerEG1(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity);              TriggerEG1(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity);
203            } else {
204                pSignalUnitRack->Trigger();
205          }          }
206    
207  #ifdef CONFIG_INTERPOLATE_VOLUME  #ifdef CONFIG_INTERPOLATE_VOLUME
# Line 197  namespace LinuxSampler { Line 214  namespace LinuxSampler {
214          else          else
215      #else      #else
216          {          {
217              float finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pEG1->getLevel();              float finalVolume;
218                if (pSignalUnitRack == NULL) {
219                    finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pEG1->getLevel();
220                } else {
221                    finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pSignalUnitRack->GetEndpointUnit()->GetVolume();
222                }
223    
224              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * pEngineChannel->GlobalPanLeft;              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * pEngineChannel->GlobalPanLeft;
225              finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * pEngineChannel->GlobalPanRight;              finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * pEngineChannel->GlobalPanRight;
# Line 205  namespace LinuxSampler { Line 227  namespace LinuxSampler {
227      #endif      #endif
228  #endif  #endif
229    
230          // setup EG 2 (VCF Cutoff EG)          if (pSignalUnitRack == NULL) {
231          {              // setup EG 2 (VCF Cutoff EG)
232              // get current value of EG2 controller              {
233              double eg2controllervalue = GetEG2ControllerValue(itNoteOnEvent->Param.Note.Velocity);                  // get current value of EG2 controller
234                    double eg2controllervalue = GetEG2ControllerValue(itNoteOnEvent->Param.Note.Velocity);
235    
236                    // calculate influence of EG2 controller on EG2's parameters
237                    EGInfo egInfo = CalculateEG2ControllerInfluence(eg2controllervalue);
238    
239                    TriggerEG2(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity);
240                }
241    
             // calculate influence of EG2 controller on EG2's parameters  
             EGInfo egInfo = CalculateEG2ControllerInfluence(eg2controllervalue);  
242    
243              TriggerEG2(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity);              // setup EG 3 (VCO EG)
244          }              {
245                    // if portamento mode is on, we dedicate EG3 purely for portamento, otherwise if portamento is off we do as told by the patch
246                    bool  bPortamento = pEngineChannel->PortamentoMode && pEngineChannel->PortamentoPos >= 0.0f;
247                    float eg3depth = (bPortamento)
248                                 ? RTMath::CentsToFreqRatio((pEngineChannel->PortamentoPos - (float) MIDIKey) * 100)
249                                 : RTMath::CentsToFreqRatio(RgnInfo.EG3Depth);
250                    float eg3time = (bPortamento)
251                                ? pEngineChannel->PortamentoTime
252                                : RgnInfo.EG3Attack;
253                    EG3.trigger(eg3depth, eg3time, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
254                    dmsg(5,("PortamentoPos=%f, depth=%f, time=%f\n", pEngineChannel->PortamentoPos, eg3depth, eg3time));
255                }
256    
257    
258          // setup EG 3 (VCO EG)              // setup LFO 1 (VCA LFO)
259          {              InitLFO1();
260              // 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)
261              bool  bPortamento = pEngineChannel->PortamentoMode && pEngineChannel->PortamentoPos >= 0.0f;              InitLFO2();
262              float eg3depth = (bPortamento)              // setup LFO 3 (VCO LFO)
263                           ? 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));  
264          }          }
265    
266    
         // setup LFO 1 (VCA LFO)  
         InitLFO1();  
         // setup LFO 2 (VCF Cutoff LFO)  
         InitLFO2();  
         // setup LFO 3 (VCO LFO)  
         InitLFO3();  
   
   
267          #if CONFIG_FORCE_FILTER          #if CONFIG_FORCE_FILTER
268          const bool bUseFilter = true;          const bool bUseFilter = true;
269          #else // use filter only if instrument file told so          #else // use filter only if instrument file told so
# Line 282  namespace LinuxSampler { Line 306  namespace LinuxSampler {
306              VCFCutoffCtrl.controller    = 0;              VCFCutoffCtrl.controller    = 0;
307              VCFResonanceCtrl.controller = 0;              VCFResonanceCtrl.controller = 0;
308          }          }
309            
310            const bool bEq =
311                pSignalUnitRack != NULL && pSignalUnitRack->HasEq() && pEq->HasSupport();
312    
313            if (bEq) {
314                pEq->GetInChannelLeft()->Clear();
315                pEq->GetInChannelRight()->Clear();
316                pEq->RenderAudio(GetEngine()->pAudioOutputDevice->MaxSamplesPerCycle());
317            }
318    
319          return 0; // success          return 0; // success
320      }      }
321        
322        void AbstractVoice::SetSampleStartOffset() {
323            finalSynthesisParameters.dPos = RgnInfo.SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)
324            Pos = RgnInfo.SampleStartOffset;
325        }
326    
327      /**      /**
328       *  Synthesizes the current audio fragment for this voice.       *  Synthesizes the current audio fragment for this voice.
# Line 295  namespace LinuxSampler { Line 333  namespace LinuxSampler {
333       *  @param Skip    - number of sample points to skip in output buffer       *  @param Skip    - number of sample points to skip in output buffer
334       */       */
335      void AbstractVoice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {      void AbstractVoice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {
336            bool delay = false; // Whether the voice playback should be delayed for this call
337            
338            if (pSignalUnitRack != NULL) {
339                uint delaySteps = pSignalUnitRack->GetEndpointUnit()->DelayTrigger();
340                if (delaySteps > 0) { // delay on the endpoint unit means delay of the voice playback
341                    if (delaySteps >= Samples) {
342                        pSignalUnitRack->GetEndpointUnit()->DecreaseDelay(Samples);
343                        delay = true;
344                    } else {
345                        pSignalUnitRack->GetEndpointUnit()->DecreaseDelay(delaySteps);
346                        Samples -= delaySteps;
347                        Skip += delaySteps;
348                    }
349                }
350            }
351            
352          AbstractEngineChannel* pChannel = pEngineChannel;          AbstractEngineChannel* pChannel = pEngineChannel;
353          MidiKeyBase* pMidiKeyInfo = GetMidiKeyInfo(MIDIKey);          MidiKeyBase* pMidiKeyInfo = GetMidiKeyInfo(MIDIKey);
354    
355          const bool bVoiceRequiresDedicatedRouting =          const bool bVoiceRequiresDedicatedRouting =
356              pEngineChannel->GetFxSendCount() > 0 &&              pEngineChannel->GetFxSendCount() > 0 &&
357              (pMidiKeyInfo->ReverbSend || pMidiKeyInfo->ChorusSend);              (pMidiKeyInfo->ReverbSend || pMidiKeyInfo->ChorusSend);
358            
359          if (bVoiceRequiresDedicatedRouting) {          const bool bEq =
360                pSignalUnitRack != NULL && pSignalUnitRack->HasEq() && pEq->HasSupport();
361    
362            if (bEq) {
363                pEq->GetInChannelLeft()->Clear();
364                pEq->GetInChannelRight()->Clear();
365                finalSynthesisParameters.pOutLeft  = &pEq->GetInChannelLeft()->Buffer()[Skip];
366                finalSynthesisParameters.pOutRight = &pEq->GetInChannelRight()->Buffer()[Skip];
367                pSignalUnitRack->UpdateEqSettings(pEq);
368            } else if (bVoiceRequiresDedicatedRouting) {
369              finalSynthesisParameters.pOutLeft  = &GetEngine()->pDedicatedVoiceChannelLeft->Buffer()[Skip];              finalSynthesisParameters.pOutLeft  = &GetEngine()->pDedicatedVoiceChannelLeft->Buffer()[Skip];
370              finalSynthesisParameters.pOutRight = &GetEngine()->pDedicatedVoiceChannelRight->Buffer()[Skip];              finalSynthesisParameters.pOutRight = &GetEngine()->pDedicatedVoiceChannelRight->Buffer()[Skip];
371          } else {          } else {
# Line 342  namespace LinuxSampler { Line 405  namespace LinuxSampler {
405                  // drivers that use Samples < MaxSamplesPerCycle).                  // drivers that use Samples < MaxSamplesPerCycle).
406                  // End the EG1 here, at pos 0, with a shorter max fade                  // End the EG1 here, at pos 0, with a shorter max fade
407                  // out time.                  // out time.
408                  pEG1->enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  if (pSignalUnitRack == NULL) {
409                        pEG1->enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
410                    } else {
411                        // TODO:
412                    }
413                  itKillEvent = Pool<Event>::Iterator();                  itKillEvent = Pool<Event>::Iterator();
414              } else {              } else {
415                  killPos = RTMath::Min(itKillEvent->FragmentPos(), maxFadeOutPos);                  killPos = RTMath::Min(itKillEvent->FragmentPos(), maxFadeOutPos);
# Line 359  namespace LinuxSampler { Line 426  namespace LinuxSampler {
426    
427              // process MIDI control change and pitchbend events for this subfragment              // process MIDI control change and pitchbend events for this subfragment
428              processCCEvents(itCCEvent, iSubFragmentEnd);              processCCEvents(itCCEvent, iSubFragmentEnd);
429                uint8_t pan = MIDIPan;
430                if (pSignalUnitRack != NULL) pan = pSignalUnitRack->GetEndpointUnit()->CaluclatePan(pan);
431                
432                PanLeftSmoother.update(AbstractEngine::PanCurve[128 - pan]);
433                PanRightSmoother.update(AbstractEngine::PanCurve[pan]);
434    
435              finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend;              finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend;
436              float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render();              float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render();
# Line 369  namespace LinuxSampler { Line 441  namespace LinuxSampler {
441              // process transition events (note on, note off & sustain pedal)              // process transition events (note on, note off & sustain pedal)
442              processTransitionEvents(itNoteEvent, iSubFragmentEnd);              processTransitionEvents(itNoteEvent, iSubFragmentEnd);
443              processGroupEvents(itGroupEvent, iSubFragmentEnd);              processGroupEvents(itGroupEvent, iSubFragmentEnd);
444                
445                if (pSignalUnitRack == NULL) {
446                    // if the voice was killed in this subfragment, or if the
447                    // filter EG is finished, switch EG1 to fade out stage
448                    if ((itKillEvent && killPos <= iSubFragmentEnd) ||
449                        (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&
450                        pEG2->getSegmentType() == EG::segment_end)) {
451                        pEG1->enterFadeOutStage();
452                        itKillEvent = Pool<Event>::Iterator();
453                    }
454    
455              // if the voice was killed in this subfragment, or if the                  // process envelope generators
456              // filter EG is finished, switch EG1 to fade out stage                  switch (pEG1->getSegmentType()) {
457              if ((itKillEvent && killPos <= iSubFragmentEnd) ||                      case EG::segment_lin:
458                  (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&                          fFinalVolume *= pEG1->processLin();
459                   pEG2->getSegmentType() == EG::segment_end)) {                          break;
460                  pEG1->enterFadeOutStage();                      case EG::segment_exp:
461                  itKillEvent = Pool<Event>::Iterator();                          fFinalVolume *= pEG1->processExp();
462              }                          break;
463                        case EG::segment_end:
464                            fFinalVolume *= pEG1->getLevel();
465                            break; // noop
466                        case EG::segment_pow:
467                            fFinalVolume *= pEG1->processPow();
468                            break;
469                    }
470                    switch (pEG2->getSegmentType()) {
471                        case EG::segment_lin:
472                            fFinalCutoff *= pEG2->processLin();
473                            break;
474                        case EG::segment_exp:
475                            fFinalCutoff *= pEG2->processExp();
476                            break;
477                        case EG::segment_end:
478                            fFinalCutoff *= pEG2->getLevel();
479                            break; // noop
480                        case EG::segment_pow:
481                            fFinalCutoff *= pEG2->processPow();
482                            break;
483                    }
484                    if (EG3.active()) finalSynthesisParameters.fFinalPitch *= EG3.render();
485    
486              // process envelope generators                  // process low frequency oscillators
487              switch (pEG1->getSegmentType()) {                  if (bLFO1Enabled) fFinalVolume *= (1.0f - pLFO1->render());
488                  case EG::segment_lin:                  if (bLFO2Enabled) fFinalCutoff *= pLFO2->render();
489                      fFinalVolume *= pEG1->processLin();                  if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());
490                      break;              } else {
491                  case EG::segment_exp:                  // if the voice was killed in this subfragment, or if the
492                      fFinalVolume *= pEG1->processExp();                  // filter EG is finished, switch EG1 to fade out stage
493                      break;                  /*if ((itKillEvent && killPos <= iSubFragmentEnd) ||
494                  case EG::segment_end:                      (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&
495                      fFinalVolume *= pEG1->getLevel();                      pEG2->getSegmentType() == EG::segment_end)) {
496                      break; // noop                      pEG1->enterFadeOutStage();
497                  case EG::segment_pow:                      itKillEvent = Pool<Event>::Iterator();
498                      fFinalVolume *= pEG1->processPow();                  }*/
499                      break;                  // TODO: ^^^
500              }  
501              switch (pEG2->getSegmentType()) {                  fFinalVolume   *= pSignalUnitRack->GetEndpointUnit()->GetVolume();
502                  case EG::segment_lin:                  fFinalCutoff    = pSignalUnitRack->GetEndpointUnit()->CalculateFilterCutoff(fFinalCutoff);
503                      fFinalCutoff *= pEG2->processLin();                  fFinalResonance = pSignalUnitRack->GetEndpointUnit()->CalculateResonance(fFinalResonance);
504                      break;                  
505                  case EG::segment_exp:                  finalSynthesisParameters.fFinalPitch =
506                      fFinalCutoff *= pEG2->processExp();                      pSignalUnitRack->GetEndpointUnit()->CalculatePitch(finalSynthesisParameters.fFinalPitch);
507                      break;                      
                 case EG::segment_end:  
                     fFinalCutoff *= pEG2->getLevel();  
                     break; // noop  
                 case EG::segment_pow:  
                     fFinalCutoff *= pEG2->processPow();  
                     break;  
508              }              }
509              if (EG3.active()) finalSynthesisParameters.fFinalPitch *= EG3.render();              
   
             // process low frequency oscillators  
             if (bLFO1Enabled) fFinalVolume *= (1.0f - pLFO1->render());  
             if (bLFO2Enabled) fFinalCutoff *= pLFO2->render();  
             if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());  
   
510              // limit the pitch so we don't read outside the buffer              // limit the pitch so we don't read outside the buffer
511              finalSynthesisParameters.fFinalPitch = RTMath::Min(finalSynthesisParameters.fFinalPitch, float(1 << CONFIG_MAX_PITCH));              finalSynthesisParameters.fFinalPitch = RTMath::Min(finalSynthesisParameters.fFinalPitch, float(1 << CONFIG_MAX_PITCH));
512    
# Line 447  namespace LinuxSampler { Line 539  namespace LinuxSampler {
539                  fFinalVolume * VolumeRight * PanRightSmoother.render();                  fFinalVolume * VolumeRight * PanRightSmoother.render();
540  #endif  #endif
541              // render audio for one subfragment              // render audio for one subfragment
542              RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);              if (!delay) RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);
543    
544              // stop the rendering if volume EG is finished              if (pSignalUnitRack == NULL) {
545              if (pEG1->getSegmentType() == EG::segment_end) break;                  // stop the rendering if volume EG is finished
546                    if (pEG1->getSegmentType() == EG::segment_end) break;
547                } else {
548                    // stop the rendering if the endpoint unit is not active
549                    if (!pSignalUnitRack->GetEndpointUnit()->Active()) break;
550                }
551    
552              const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;              const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;
553    
554              // increment envelopes' positions              if (pSignalUnitRack == NULL) {
555              if (pEG1->active()) {                  // increment envelopes' positions
556                    if (pEG1->active()) {
557    
558                        // 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
559                        if (SmplInfo.HasLoops && Pos <= SmplInfo.LoopStart && SmplInfo.LoopStart < newPos) {
560                            pEG1->update(EG::event_hold_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
561                        }
562    
563                  // 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);
564                  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);  
565                  }                  }
566                    if (pEG2->active()) {
567                  pEG1->increment(1);                      pEG2->increment(1);
568                  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);
569              }                  }
570              if (pEG2->active()) {                  EG3.increment(1);
571                  pEG2->increment(1);                  if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached
572                  if (!pEG2->toStageEndLeft()) pEG2->update(EG::event_stage_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);              } else {
573                        // 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
574                        /*if (SmplInfo.HasLoops && Pos <= SmplInfo.LoopStart && SmplInfo.LoopStart < newPos) {
575                            pEG1->update(EG::event_hold_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
576                        }*/
577                    // TODO: ^^^
578                    
579                    if (!delay) pSignalUnitRack->Increment();
580              }              }
             EG3.increment(1);  
             if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached  
581    
582              Pos = newPos;              Pos = newPos;
583              i = iSubFragmentEnd;              i = iSubFragmentEnd;
584          }          }
585            
586            if (delay) return;
587    
588          if (bVoiceRequiresDedicatedRouting) {          if (bVoiceRequiresDedicatedRouting) {
589                if (bEq) {
590                    pEq->RenderAudio(Samples);
591                    pEq->GetOutChannelLeft()->CopyTo(GetEngine()->pDedicatedVoiceChannelLeft, Samples);
592                    pEq->GetOutChannelRight()->CopyTo(GetEngine()->pDedicatedVoiceChannelRight, Samples);
593                }
594              optional<float> effectSendLevels[2] = {              optional<float> effectSendLevels[2] = {
595                  pMidiKeyInfo->ReverbSend,                  pMidiKeyInfo->ReverbSend,
596                  pMidiKeyInfo->ChorusSend                  pMidiKeyInfo->ChorusSend
597              };              };
598              GetEngine()->RouteDedicatedVoiceChannels(pEngineChannel, effectSendLevels, Samples);              GetEngine()->RouteDedicatedVoiceChannels(pEngineChannel, effectSendLevels, Samples);
599            } else if (bEq) {
600                pEq->RenderAudio(Samples);
601                pEq->GetOutChannelLeft()->MixTo(pChannel->pChannelLeft, Samples);
602                pEq->GetOutChannelRight()->MixTo(pChannel->pChannelRight, Samples);
603          }          }
604      }      }
605    
# Line 501  namespace LinuxSampler { Line 619  namespace LinuxSampler {
619                  if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {                  if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {
620                      processResonanceEvent(itEvent);                      processResonanceEvent(itEvent);
621                  }                  }
622                  if (itEvent->Param.CC.Controller == pLFO1->ExtController) {                  if (pSignalUnitRack == NULL) {
623                      pLFO1->update(itEvent->Param.CC.Value);                      if (itEvent->Param.CC.Controller == pLFO1->ExtController) {
624                  }                          pLFO1->update(itEvent->Param.CC.Value);
625                  if (itEvent->Param.CC.Controller == pLFO2->ExtController) {                      }
626                      pLFO2->update(itEvent->Param.CC.Value);                      if (itEvent->Param.CC.Controller == pLFO2->ExtController) {
627                  }                          pLFO2->update(itEvent->Param.CC.Value);
628                  if (itEvent->Param.CC.Controller == pLFO3->ExtController) {                      }
629                      pLFO3->update(itEvent->Param.CC.Value);                      if (itEvent->Param.CC.Controller == pLFO3->ExtController) {
630                            pLFO3->update(itEvent->Param.CC.Value);
631                        }
632                  }                  }
633                  if (itEvent->Param.CC.Controller == 7) { // volume                  if (itEvent->Param.CC.Controller == 7) { // volume
634                      VolumeSmoother.update(AbstractEngine::VolumeCurve[itEvent->Param.CC.Value]);                      VolumeSmoother.update(AbstractEngine::VolumeCurve[itEvent->Param.CC.Value]);
635                  } else if (itEvent->Param.CC.Controller == 10) { // panpot                  } else if (itEvent->Param.CC.Controller == 10) { // panpot
636                      PanLeftSmoother.update(AbstractEngine::PanCurve[128 - itEvent->Param.CC.Value]);                      MIDIPan = itEvent->Param.CC.Value;
                     PanRightSmoother.update(AbstractEngine::PanCurve[itEvent->Param.CC.Value]);  
637                  }                  }
638              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event
639                  processPitchEvent(itEvent);                  processPitchEvent(itEvent);
640              }              }
641    
642              ProcessCCEvent(itEvent);              ProcessCCEvent(itEvent);
643                if (pSignalUnitRack != NULL) {
644                    pSignalUnitRack->ProcessCCEvent(itEvent);
645                }
646          }          }
647      }      }
648    
# Line 552  namespace LinuxSampler { Line 674  namespace LinuxSampler {
674                  if (itEvent->Type == Event::type_release) {                  if (itEvent->Type == Event::type_release) {
675                      EnterReleaseStage();                      EnterReleaseStage();
676                  } else if (itEvent->Type == Event::type_cancel_release) {                  } else if (itEvent->Type == Event::type_cancel_release) {
677                      pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                      if (pSignalUnitRack == NULL) {
678                      pEG2->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                          pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
679                            pEG2->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
680                        } else {
681                            pSignalUnitRack->CancelRelease();
682                        }
683                  }                  }
684              }              }
685          }          }
# Line 580  namespace LinuxSampler { Line 706  namespace LinuxSampler {
706       * @param itNoteOffEvent - event which causes this voice to die soon       * @param itNoteOffEvent - event which causes this voice to die soon
707       */       */
708      void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {      void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {
709          const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());          if (pSignalUnitRack == NULL) {
710          pEngineChannel->PortamentoPos = (float) MIDIKey + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;              const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());
711                pEngineChannel->PortamentoPos = (float) MIDIKey + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;
712            } else {
713                // TODO:
714            }
715      }      }
716    
717      /**      /**
# Line 643  namespace LinuxSampler { Line 773  namespace LinuxSampler {
773      }      }
774    
775      void AbstractVoice::EnterReleaseStage() {      void AbstractVoice::EnterReleaseStage() {
776          pEG1->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);          if (pSignalUnitRack == NULL) {
777          pEG2->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);              pEG1->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
778                pEG2->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
779            } else {
780                pSignalUnitRack->EnterReleaseStage();
781            }
782        }
783    
784        bool AbstractVoice::EG1Finished() {
785            if (pSignalUnitRack == NULL) {
786                return pEG1->getSegmentType() == EG::segment_end;
787            } else {
788                return !pSignalUnitRack->GetEndpointUnit()->Active();
789            }
790      }      }
791    
792  } // namespace LinuxSampler  } // namespace LinuxSampler

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

  ViewVC Help
Powered by ViewVC