/[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 2216 by iliev, Mon Jul 25 17:21:16 2011 UTC revision 2879 by schoenebeck, Tue Apr 19 14:07:53 2016 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-2015 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 98  namespace LinuxSampler { Line 110  namespace LinuxSampler {
110          #endif // CONFIG_DEVMODE          #endif // CONFIG_DEVMODE
111    
112          Type            = VoiceType;          Type            = VoiceType;
113          MIDIKey         = itNoteOnEvent->Param.Note.Key;          pNote           = pEngineChannel->pEngine->NoteByID( itNoteOnEvent->Param.Note.ID );
114          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
115          Delay           = itNoteOnEvent->FragmentPos();          Delay           = itNoteOnEvent->FragmentPos();
116          itTriggerEvent  = itNoteOnEvent;          itTriggerEvent  = itNoteOnEvent;
117          itKillEvent     = Pool<Event>::Iterator();          itKillEvent     = Pool<Event>::Iterator();
118          MidiKeyBase* pKeyInfo = GetMidiKeyInfo(MIDIKey);          MidiKeyBase* pKeyInfo = GetMidiKeyInfo(MIDIKey());
119    
120          pGroupEvents = iKeyGroup ? pEngineChannel->ActiveKeyGroups[iKeyGroup] : 0;          pGroupEvents = iKeyGroup ? pEngineChannel->ActiveKeyGroups[iKeyGroup] : 0;
121    
# Line 111  namespace LinuxSampler { Line 123  namespace LinuxSampler {
123          RgnInfo    = GetRegionInfo();          RgnInfo    = GetRegionInfo();
124          InstrInfo  = GetInstrumentInfo();          InstrInfo  = GetInstrumentInfo();
125                    
126            MIDIPan    = CalculatePan(pEngineChannel->iLastPanRequest);
127    
128          AboutToTrigger();          AboutToTrigger();
129    
130          // calculate volume          // calculate volume
# Line 126  namespace LinuxSampler { Line 140  namespace LinuxSampler {
140          // get starting crossfade volume level          // get starting crossfade volume level
141          float crossfadeVolume = CalculateCrossfadeVolume(itNoteOnEvent->Param.Note.Velocity);          float crossfadeVolume = CalculateCrossfadeVolume(itNoteOnEvent->Param.Note.Velocity);
142    
143          VolumeLeft  = volume * pKeyInfo->PanLeft  * AbstractEngine::PanCurve[64 - RgnInfo.Pan];          VolumeLeft  = volume * pKeyInfo->PanLeft;
144          VolumeRight = volume * pKeyInfo->PanRight * AbstractEngine::PanCurve[64 + RgnInfo.Pan];          VolumeRight = volume * pKeyInfo->PanRight;
145    
146          float subfragmentRate = GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;          float subfragmentRate = GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;
147          CrossfadeSmoother.trigger(crossfadeVolume, subfragmentRate);          CrossfadeSmoother.trigger(crossfadeVolume, subfragmentRate);
148          VolumeSmoother.trigger(pEngineChannel->MidiVolume, subfragmentRate);          VolumeSmoother.trigger(pEngineChannel->MidiVolume, subfragmentRate);
         PanLeftSmoother.trigger(pEngineChannel->GlobalPanLeft, subfragmentRate);  
         PanRightSmoother.trigger(pEngineChannel->GlobalPanRight, subfragmentRate);  
149    
150          // 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
151          long cachedsamples = GetSampleCacheSize() / SmplInfo.FrameSize;          long cachedsamples = GetSampleCacheSize() / SmplInfo.FrameSize;
# Line 157  namespace LinuxSampler { Line 169  namespace LinuxSampler {
169              RAMLoop = (SmplInfo.HasLoops && (SmplInfo.LoopStart + SmplInfo.LoopLength) <= MaxRAMPos);              RAMLoop = (SmplInfo.HasLoops && (SmplInfo.LoopStart + SmplInfo.LoopLength) <= MaxRAMPos);
170    
171              if (OrderNewStream()) return -1;              if (OrderNewStream()) return -1;
172              dmsg(4,("Disk voice launched (cached samples: %d, total Samples: %d, MaxRAMPos: %d, RAMLooping: %s)\n", cachedsamples, SmplInfo.TotalFrameCount, MaxRAMPos, (RAMLoop) ? "yes" : "no"));              dmsg(4,("Disk voice launched (cached samples: %ld, total Samples: %d, MaxRAMPos: %lu, RAMLooping: %s)\n", cachedsamples, SmplInfo.TotalFrameCount, MaxRAMPos, (RAMLoop) ? "yes" : "no"));
173          }          }
174          else { // RAM only voice          else { // RAM only voice
175              MaxRAMPos = cachedsamples;              MaxRAMPos = cachedsamples;
# Line 177  namespace LinuxSampler { Line 189  namespace LinuxSampler {
189          // 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
190          const double velrelease = 1 / GetVelocityRelease(itNoteOnEvent->Param.Note.Velocity);          const double velrelease = 1 / GetVelocityRelease(itNoteOnEvent->Param.Note.Velocity);
191    
192          if (GetSignalUnitRack() == NULL) { // setup EG 1 (VCA EG)          if (pSignalUnitRack == NULL) { // setup EG 1 (VCA EG)
193              // get current value of EG1 controller              // get current value of EG1 controller
194              double eg1controllervalue = GetEG1ControllerValue(itNoteOnEvent->Param.Note.Velocity);              double eg1controllervalue = GetEG1ControllerValue(itNoteOnEvent->Param.Note.Velocity);
195    
# Line 186  namespace LinuxSampler { Line 198  namespace LinuxSampler {
198    
199              TriggerEG1(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity);              TriggerEG1(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity);
200          } else {          } else {
201              GetSignalUnitRack()->Trigger();              pSignalUnitRack->Trigger();
202          }          }
203    
204            uint8_t pan = MIDIPan;
205            if (pSignalUnitRack) pan = pSignalUnitRack->GetEndpointUnit()->CalculatePan(MIDIPan);
206            PanLeftSmoother.trigger(AbstractEngine::PanCurve[128 - pan], subfragmentRate);
207            PanRightSmoother.trigger(AbstractEngine::PanCurve[pan], subfragmentRate);
208    
209  #ifdef CONFIG_INTERPOLATE_VOLUME  #ifdef CONFIG_INTERPOLATE_VOLUME
210          // setup initial volume in synthesis parameters          // setup initial volume in synthesis parameters
211      #ifdef CONFIG_PROCESS_MUTED_CHANNELS      #ifdef CONFIG_PROCESS_MUTED_CHANNELS
# Line 200  namespace LinuxSampler { Line 217  namespace LinuxSampler {
217      #else      #else
218          {          {
219              float finalVolume;              float finalVolume;
220              if (GetSignalUnitRack() == NULL) {              if (pSignalUnitRack == NULL) {
221                  finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pEG1->getLevel();                  finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pEG1->getLevel();
222              } else {              } else {
223                  finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * GetSignalUnitRack()->GetEndpointUnit()->GetVolume();                  finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pSignalUnitRack->GetEndpointUnit()->GetVolume();
224              }              }
225    
226              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * pEngineChannel->GlobalPanLeft;              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * PanLeftSmoother.render();
227              finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * pEngineChannel->GlobalPanRight;              finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * PanRightSmoother.render();
228          }          }
229      #endif      #endif
230  #endif  #endif
231    
232          if (GetSignalUnitRack() == NULL) {          if (pSignalUnitRack == NULL) {
233              // setup EG 2 (VCF Cutoff EG)              // setup EG 2 (VCF Cutoff EG)
234              {              {
235                  // get current value of EG2 controller                  // get current value of EG2 controller
# Line 230  namespace LinuxSampler { Line 247  namespace LinuxSampler {
247                  // if portamento mode is on, we dedicate EG3 purely for portamento, otherwise if portamento is off we do as told by the patch                  // if portamento mode is on, we dedicate EG3 purely for portamento, otherwise if portamento is off we do as told by the patch
248                  bool  bPortamento = pEngineChannel->PortamentoMode && pEngineChannel->PortamentoPos >= 0.0f;                  bool  bPortamento = pEngineChannel->PortamentoMode && pEngineChannel->PortamentoPos >= 0.0f;
249                  float eg3depth = (bPortamento)                  float eg3depth = (bPortamento)
250                               ? RTMath::CentsToFreqRatio((pEngineChannel->PortamentoPos - (float) MIDIKey) * 100)                               ? RTMath::CentsToFreqRatio((pEngineChannel->PortamentoPos - (float) MIDIKey()) * 100)
251                               : RTMath::CentsToFreqRatio(RgnInfo.EG3Depth);                               : RTMath::CentsToFreqRatio(RgnInfo.EG3Depth);
252                  float eg3time = (bPortamento)                  float eg3time = (bPortamento)
253                              ? pEngineChannel->PortamentoTime                              ? pEngineChannel->PortamentoTime
# Line 291  namespace LinuxSampler { Line 308  namespace LinuxSampler {
308              VCFCutoffCtrl.controller    = 0;              VCFCutoffCtrl.controller    = 0;
309              VCFResonanceCtrl.controller = 0;              VCFResonanceCtrl.controller = 0;
310          }          }
311            
312            const bool bEq =
313                pSignalUnitRack != NULL && pSignalUnitRack->HasEq() && pEq->HasSupport();
314    
315            if (bEq) {
316                pEq->GetInChannelLeft()->Clear();
317                pEq->GetInChannelRight()->Clear();
318                pEq->RenderAudio(GetEngine()->pAudioOutputDevice->MaxSamplesPerCycle());
319            }
320    
321          return 0; // success          return 0; // success
322      }      }
# Line 309  namespace LinuxSampler { Line 335  namespace LinuxSampler {
335       *  @param Skip    - number of sample points to skip in output buffer       *  @param Skip    - number of sample points to skip in output buffer
336       */       */
337      void AbstractVoice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {      void AbstractVoice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {
338            bool delay = false; // Whether the voice playback should be delayed for this call
339            
340            if (pSignalUnitRack != NULL) {
341                uint delaySteps = pSignalUnitRack->GetEndpointUnit()->DelayTrigger();
342                if (delaySteps > 0) { // delay on the endpoint unit means delay of the voice playback
343                    if (delaySteps >= Samples) {
344                        pSignalUnitRack->GetEndpointUnit()->DecreaseDelay(Samples);
345                        delay = true;
346                    } else {
347                        pSignalUnitRack->GetEndpointUnit()->DecreaseDelay(delaySteps);
348                        Samples -= delaySteps;
349                        Skip += delaySteps;
350                    }
351                }
352            }
353            
354          AbstractEngineChannel* pChannel = pEngineChannel;          AbstractEngineChannel* pChannel = pEngineChannel;
355          MidiKeyBase* pMidiKeyInfo = GetMidiKeyInfo(MIDIKey);          MidiKeyBase* pMidiKeyInfo = GetMidiKeyInfo(MIDIKey());
356    
357          const bool bVoiceRequiresDedicatedRouting =          const bool bVoiceRequiresDedicatedRouting =
358              pEngineChannel->GetFxSendCount() > 0 &&              pEngineChannel->GetFxSendCount() > 0 &&
359              (pMidiKeyInfo->ReverbSend || pMidiKeyInfo->ChorusSend);              (pMidiKeyInfo->ReverbSend || pMidiKeyInfo->ChorusSend);
360            
361            const bool bEq =
362                pSignalUnitRack != NULL && pSignalUnitRack->HasEq() && pEq->HasSupport();
363    
364          if (bVoiceRequiresDedicatedRouting) {          if (bEq) {
365                pEq->GetInChannelLeft()->Clear();
366                pEq->GetInChannelRight()->Clear();
367                finalSynthesisParameters.pOutLeft  = &pEq->GetInChannelLeft()->Buffer()[Skip];
368                finalSynthesisParameters.pOutRight = &pEq->GetInChannelRight()->Buffer()[Skip];
369                pSignalUnitRack->UpdateEqSettings(pEq);
370            } else if (bVoiceRequiresDedicatedRouting) {
371              finalSynthesisParameters.pOutLeft  = &GetEngine()->pDedicatedVoiceChannelLeft->Buffer()[Skip];              finalSynthesisParameters.pOutLeft  = &GetEngine()->pDedicatedVoiceChannelLeft->Buffer()[Skip];
372              finalSynthesisParameters.pOutRight = &GetEngine()->pDedicatedVoiceChannelRight->Buffer()[Skip];              finalSynthesisParameters.pOutRight = &GetEngine()->pDedicatedVoiceChannelRight->Buffer()[Skip];
373          } else {          } else {
# Line 327  namespace LinuxSampler { Line 378  namespace LinuxSampler {
378    
379          RTList<Event>::Iterator itCCEvent = pChannel->pEvents->first();          RTList<Event>::Iterator itCCEvent = pChannel->pEvents->first();
380          RTList<Event>::Iterator itNoteEvent;          RTList<Event>::Iterator itNoteEvent;
381          GetFirstEventOnKey(MIDIKey, itNoteEvent);          GetFirstEventOnKey(HostKey(), itNoteEvent);
382    
383          RTList<Event>::Iterator itGroupEvent;          RTList<Event>::Iterator itGroupEvent;
384          if (pGroupEvents) itGroupEvent = pGroupEvents->first();          if (pGroupEvents && !Orphan) itGroupEvent = pGroupEvents->first();
385    
386          if (itTriggerEvent) { // skip events that happened before this voice was triggered          if (itTriggerEvent) { // skip events that happened before this voice was triggered
387              while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;              while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;
# Line 356  namespace LinuxSampler { Line 407  namespace LinuxSampler {
407                  // drivers that use Samples < MaxSamplesPerCycle).                  // drivers that use Samples < MaxSamplesPerCycle).
408                  // End the EG1 here, at pos 0, with a shorter max fade                  // End the EG1 here, at pos 0, with a shorter max fade
409                  // out time.                  // out time.
410                  if (GetSignalUnitRack() == NULL) {                  if (pSignalUnitRack == NULL) {
411                      pEG1->enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                      pEG1->enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
412                  } else {                  } else {
413                      // TODO:                      pSignalUnitRack->EnterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
414                  }                  }
415                  itKillEvent = Pool<Event>::Iterator();                  itKillEvent = Pool<Event>::Iterator();
416              } else {              } else {
# Line 375  namespace LinuxSampler { Line 426  namespace LinuxSampler {
426              fFinalCutoff    = VCFCutoffCtrl.fvalue;              fFinalCutoff    = VCFCutoffCtrl.fvalue;
427              fFinalResonance = VCFResonanceCtrl.fvalue;              fFinalResonance = VCFResonanceCtrl.fvalue;
428    
429              // process MIDI control change and pitchbend events for this subfragment              // process MIDI control change, aftertouch and pitchbend events for this subfragment
430              processCCEvents(itCCEvent, iSubFragmentEnd);              processCCEvents(itCCEvent, iSubFragmentEnd);
431                uint8_t pan = MIDIPan;
432                if (pSignalUnitRack != NULL) pan = pSignalUnitRack->GetEndpointUnit()->CalculatePan(MIDIPan);
433                
434                PanLeftSmoother.update(AbstractEngine::PanCurve[128 - pan]);
435                PanRightSmoother.update(AbstractEngine::PanCurve[pan]);
436    
437              finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend;              finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend;
438              float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render();              float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render();
# Line 387  namespace LinuxSampler { Line 443  namespace LinuxSampler {
443              // process transition events (note on, note off & sustain pedal)              // process transition events (note on, note off & sustain pedal)
444              processTransitionEvents(itNoteEvent, iSubFragmentEnd);              processTransitionEvents(itNoteEvent, iSubFragmentEnd);
445              processGroupEvents(itGroupEvent, iSubFragmentEnd);              processGroupEvents(itGroupEvent, iSubFragmentEnd);
446                
447              if (GetSignalUnitRack() == NULL) {              if (pSignalUnitRack == NULL) {
448                  // if the voice was killed in this subfragment, or if the                  // if the voice was killed in this subfragment, or if the
449                  // filter EG is finished, switch EG1 to fade out stage                  // filter EG is finished, switch EG1 to fade out stage
450                  if ((itKillEvent && killPos <= iSubFragmentEnd) ||                  if ((itKillEvent && killPos <= iSubFragmentEnd) ||
# Line 431  namespace LinuxSampler { Line 487  namespace LinuxSampler {
487    
488                  // process low frequency oscillators                  // process low frequency oscillators
489                  if (bLFO1Enabled) fFinalVolume *= (1.0f - pLFO1->render());                  if (bLFO1Enabled) fFinalVolume *= (1.0f - pLFO1->render());
490                  if (bLFO2Enabled) fFinalCutoff *= pLFO2->render();                  if (bLFO2Enabled) fFinalCutoff *= (1.0f - pLFO2->render());
491                  if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());                  if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());
492              } else {              } else {
493                  // if the voice was killed in this subfragment, or if the                  // if the voice was killed in this subfragment, enter fade out stage
494                  // filter EG is finished, switch EG1 to fade out stage                  if (itKillEvent && killPos <= iSubFragmentEnd) {
495                  /*if ((itKillEvent && killPos <= iSubFragmentEnd) ||                      pSignalUnitRack->EnterFadeOutStage();
496                      (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&                      itKillEvent = Pool<Event>::Iterator();
497                      pEG2->getSegmentType() == EG::segment_end)) {                  }
498                    
499                    // if the filter EG is finished, switch EG1 to fade out stage
500                    /*if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&
501                        pEG2->getSegmentType() == EG::segment_end) {
502                      pEG1->enterFadeOutStage();                      pEG1->enterFadeOutStage();
503                      itKillEvent = Pool<Event>::Iterator();                      itKillEvent = Pool<Event>::Iterator();
504                  }*/                  }*/
505                  // TODO: ^^^                  // TODO: ^^^
506    
507                  fFinalVolume   *= GetSignalUnitRack()->GetEndpointUnit()->GetVolume();                  fFinalVolume   *= pSignalUnitRack->GetEndpointUnit()->GetVolume();
508                  fFinalCutoff    = GetSignalUnitRack()->GetEndpointUnit()->CalculateFilterCutoff(fFinalCutoff);                  fFinalCutoff    = pSignalUnitRack->GetEndpointUnit()->CalculateFilterCutoff(fFinalCutoff);
509                  fFinalResonance = GetSignalUnitRack()->GetEndpointUnit()->CalculateResonance(fFinalResonance);                  fFinalResonance = pSignalUnitRack->GetEndpointUnit()->CalculateResonance(fFinalResonance);
510                                    
511                  finalSynthesisParameters.fFinalPitch =                  finalSynthesisParameters.fFinalPitch =
512                      GetSignalUnitRack()->GetEndpointUnit()->CalculatePitch(finalSynthesisParameters.fFinalPitch);                      pSignalUnitRack->GetEndpointUnit()->CalculatePitch(finalSynthesisParameters.fFinalPitch);
513                                            
514              }              }
515                            
# Line 485  namespace LinuxSampler { Line 545  namespace LinuxSampler {
545                  fFinalVolume * VolumeRight * PanRightSmoother.render();                  fFinalVolume * VolumeRight * PanRightSmoother.render();
546  #endif  #endif
547              // render audio for one subfragment              // render audio for one subfragment
548              RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);              if (!delay) RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);
549    
550              if (GetSignalUnitRack() == NULL) {              if (pSignalUnitRack == NULL) {
551                  // stop the rendering if volume EG is finished                  // stop the rendering if volume EG is finished
552                  if (pEG1->getSegmentType() == EG::segment_end) break;                  if (pEG1->getSegmentType() == EG::segment_end) break;
553              } else {              } else {
554                  // stop the rendering if the endpoint unit is not active                  // stop the rendering if the endpoint unit is not active
555                  if (!GetSignalUnitRack()->GetEndpointUnit()->Active()) break;                  if (!pSignalUnitRack->GetEndpointUnit()->Active()) break;
556              }              }
557    
558              const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;              const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;
559    
560              if (GetSignalUnitRack() == NULL) {              if (pSignalUnitRack == NULL) {
561                  // increment envelopes' positions                  // increment envelopes' positions
562                  if (pEG1->active()) {                  if (pEG1->active()) {
563    
# Line 522  namespace LinuxSampler { Line 582  namespace LinuxSampler {
582                      }*/                      }*/
583                  // TODO: ^^^                  // TODO: ^^^
584                                    
585                  GetSignalUnitRack()->Increment();                  if (!delay) pSignalUnitRack->Increment();
586              }              }
587    
588              Pos = newPos;              Pos = newPos;
589              i = iSubFragmentEnd;              i = iSubFragmentEnd;
590          }          }
591            
592            if (delay) return;
593    
594          if (bVoiceRequiresDedicatedRouting) {          if (bVoiceRequiresDedicatedRouting) {
595                if (bEq) {
596                    pEq->RenderAudio(Samples);
597                    pEq->GetOutChannelLeft()->CopyTo(GetEngine()->pDedicatedVoiceChannelLeft, Samples);
598                    pEq->GetOutChannelRight()->CopyTo(GetEngine()->pDedicatedVoiceChannelRight, Samples);
599                }
600              optional<float> effectSendLevels[2] = {              optional<float> effectSendLevels[2] = {
601                  pMidiKeyInfo->ReverbSend,                  pMidiKeyInfo->ReverbSend,
602                  pMidiKeyInfo->ChorusSend                  pMidiKeyInfo->ChorusSend
603              };              };
604              GetEngine()->RouteDedicatedVoiceChannels(pEngineChannel, effectSendLevels, Samples);              GetEngine()->RouteDedicatedVoiceChannels(pEngineChannel, effectSendLevels, Samples);
605            } else if (bEq) {
606                pEq->RenderAudio(Samples);
607                pEq->GetOutChannelLeft()->MixTo(pChannel->pChannelLeft, Samples);
608                pEq->GetOutChannelRight()->MixTo(pChannel->pChannelRight, Samples);
609          }          }
610      }      }
611    
612      /**      /**
613       * Process given list of MIDI control change and pitch bend events for       * Process given list of MIDI control change, aftertouch and pitch bend
614       * the given time.       * events for the given time.
615       *       *
616       * @param itEvent - iterator pointing to the next event to be processed       * @param itEvent - iterator pointing to the next event to be processed
617       * @param End     - youngest time stamp where processing should be stopped       * @param End     - youngest time stamp where processing should be stopped
# Line 554  namespace LinuxSampler { Line 625  namespace LinuxSampler {
625                  if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {                  if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {
626                      processResonanceEvent(itEvent);                      processResonanceEvent(itEvent);
627                  }                  }
628                  if (GetSignalUnitRack() == NULL) {                  if (pSignalUnitRack == NULL) {
629                      if (itEvent->Param.CC.Controller == pLFO1->ExtController) {                      if (itEvent->Param.CC.Controller == pLFO1->ExtController) {
630                          pLFO1->update(itEvent->Param.CC.Value);                          pLFO1->update(itEvent->Param.CC.Value);
631                      }                      }
# Line 568  namespace LinuxSampler { Line 639  namespace LinuxSampler {
639                  if (itEvent->Param.CC.Controller == 7) { // volume                  if (itEvent->Param.CC.Controller == 7) { // volume
640                      VolumeSmoother.update(AbstractEngine::VolumeCurve[itEvent->Param.CC.Value]);                      VolumeSmoother.update(AbstractEngine::VolumeCurve[itEvent->Param.CC.Value]);
641                  } else if (itEvent->Param.CC.Controller == 10) { // panpot                  } else if (itEvent->Param.CC.Controller == 10) { // panpot
642                      PanLeftSmoother.update(AbstractEngine::PanCurve[128 - itEvent->Param.CC.Value]);                      MIDIPan = CalculatePan(itEvent->Param.CC.Value);
                     PanRightSmoother.update(AbstractEngine::PanCurve[itEvent->Param.CC.Value]);  
643                  }                  }
644              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event
645                  processPitchEvent(itEvent);                  processPitchEvent(itEvent);
646                } else if (itEvent->Type == Event::type_channel_pressure) {
647                    ProcessChannelPressureEvent(itEvent);
648                } else if (itEvent->Type == Event::type_note_pressure) {
649                    ProcessPolyphonicKeyPressureEvent(itEvent);
650              }              }
651    
652              ProcessCCEvent(itEvent);              ProcessCCEvent(itEvent);
653              if (GetSignalUnitRack() != NULL) {              if (pSignalUnitRack != NULL) {
654                  GetSignalUnitRack()->ProcessCCEvent(itEvent);                  pSignalUnitRack->ProcessCCEvent(itEvent);
655              }              }
656          }          }
657      }      }
# Line 610  namespace LinuxSampler { Line 684  namespace LinuxSampler {
684                  if (itEvent->Type == Event::type_release) {                  if (itEvent->Type == Event::type_release) {
685                      EnterReleaseStage();                      EnterReleaseStage();
686                  } else if (itEvent->Type == Event::type_cancel_release) {                  } else if (itEvent->Type == Event::type_cancel_release) {
687                      if (GetSignalUnitRack() == NULL) {                      if (pSignalUnitRack == NULL) {
688                          pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                          pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
689                          pEG2->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                          pEG2->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
690                      } else {                      } else {
691                          GetSignalUnitRack()->CancelRelease();                          pSignalUnitRack->CancelRelease();
692                      }                      }
693                  }                  }
694              }              }
# Line 642  namespace LinuxSampler { Line 716  namespace LinuxSampler {
716       * @param itNoteOffEvent - event which causes this voice to die soon       * @param itNoteOffEvent - event which causes this voice to die soon
717       */       */
718      void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {      void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {
719          if (GetSignalUnitRack() == NULL) {          if (pSignalUnitRack == NULL) {
720              const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());              const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());
721              pEngineChannel->PortamentoPos = (float) MIDIKey + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;              pEngineChannel->PortamentoPos = (float) MIDIKey() + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;
722          } else {          } else {
723              // TODO:              // TODO:
724          }          }
# Line 671  namespace LinuxSampler { Line 745  namespace LinuxSampler {
745    
746      Voice::PitchInfo AbstractVoice::CalculatePitchInfo(int PitchBend) {      Voice::PitchInfo AbstractVoice::CalculatePitchInfo(int PitchBend) {
747          PitchInfo pitch;          PitchInfo pitch;
748          double pitchbasecents = InstrInfo.FineTune + RgnInfo.FineTune + GetEngine()->ScaleTuning[MIDIKey % 12];          double pitchbasecents = InstrInfo.FineTune + RgnInfo.FineTune + GetEngine()->ScaleTuning[MIDIKey() % 12];
749    
750          // GSt behaviour: maximum transpose up is 40 semitones. If          // GSt behaviour: maximum transpose up is 40 semitones. If
751          // MIDI key is more than 40 semitones above unity note,          // MIDI key is more than 40 semitones above unity note,
752          // the transpose is not done.          // the transpose is not done.
753          if (!SmplInfo.Unpitched && (MIDIKey - (int) RgnInfo.UnityNote) < 40) pitchbasecents += (MIDIKey - (int) RgnInfo.UnityNote) * 100;          if (!SmplInfo.Unpitched && (MIDIKey() - (int) RgnInfo.UnityNote) < 40) pitchbasecents += (MIDIKey() - (int) RgnInfo.UnityNote) * 100;
754    
755          pitch.PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(SmplInfo.SampleRate) / double(GetEngine()->SampleRate));          pitch.PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(SmplInfo.SampleRate) / double(GetEngine()->SampleRate));
756          pitch.PitchBendRange = 1.0 / 8192.0 * 100.0 * InstrInfo.PitchbendRange;          pitch.PitchBendRange = 1.0 / 8192.0 * 100.0 * InstrInfo.PitchbendRange;
# Line 684  namespace LinuxSampler { Line 758  namespace LinuxSampler {
758    
759          return pitch;          return pitch;
760      }      }
761        
762        void AbstractVoice::onScaleTuningChanged() {
763            PitchInfo pitch = this->Pitch;
764            double pitchbasecents = InstrInfo.FineTune + RgnInfo.FineTune + GetEngine()->ScaleTuning[MIDIKey() % 12];
765            
766            // GSt behaviour: maximum transpose up is 40 semitones. If
767            // MIDI key is more than 40 semitones above unity note,
768            // the transpose is not done.
769            if (!SmplInfo.Unpitched && (MIDIKey() - (int) RgnInfo.UnityNote) < 40) pitchbasecents += (MIDIKey() - (int) RgnInfo.UnityNote) * 100;
770            
771            pitch.PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(SmplInfo.SampleRate) / double(GetEngine()->SampleRate));
772            this->Pitch = pitch;
773        }
774    
775      double AbstractVoice::CalculateVolume(double velocityAttenuation) {      double AbstractVoice::CalculateVolume(double velocityAttenuation) {
776          // For 16 bit samples, we downscale by 32768 to convert from          // For 16 bit samples, we downscale by 32768 to convert from
# Line 696  namespace LinuxSampler { Line 783  namespace LinuxSampler {
783          // the volume of release triggered samples depends on note length          // the volume of release triggered samples depends on note length
784          if (Type & Voice::type_release_trigger) {          if (Type & Voice::type_release_trigger) {
785              float noteLength = float(GetEngine()->FrameTime + Delay -              float noteLength = float(GetEngine()->FrameTime + Delay -
786                  GetNoteOnTime(MIDIKey) ) / GetEngine()->SampleRate;                  GetNoteOnTime(MIDIKey()) ) / GetEngine()->SampleRate;
787    
788              volume *= GetReleaseTriggerAttenuation(noteLength);              volume *= GetReleaseTriggerAttenuation(noteLength);
789          }          }
# Line 709  namespace LinuxSampler { Line 796  namespace LinuxSampler {
796      }      }
797    
798      void AbstractVoice::EnterReleaseStage() {      void AbstractVoice::EnterReleaseStage() {
799          if (GetSignalUnitRack() == NULL) {          if (pSignalUnitRack == NULL) {
800              pEG1->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);              pEG1->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
801              pEG2->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);              pEG2->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
802          } else {          } else {
803              GetSignalUnitRack()->EnterReleaseStage();              pSignalUnitRack->EnterReleaseStage();
804          }          }
805      }      }
806    
807      bool AbstractVoice::EG1Finished() {      bool AbstractVoice::EG1Finished() {
808          if (GetSignalUnitRack() == NULL) {          if (pSignalUnitRack == NULL) {
809              return pEG1->getSegmentType() == EG::segment_end;              return pEG1->getSegmentType() == EG::segment_end;
810          } else {          } else {
811              return !GetSignalUnitRack()->GetEndpointUnit()->Active();              return !pSignalUnitRack->GetEndpointUnit()->Active();
812          }          }
813      }      }
814    

Legend:
Removed from v.2216  
changed lines
  Added in v.2879

  ViewVC Help
Powered by ViewVC