/[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 2931 by schoenebeck, Sat Jul 9 14:38:33 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    
122          SmplInfo   = GetSampleInfo();          SmplInfo   = GetSampleInfo();
123          RgnInfo    = GetRegionInfo();          RgnInfo    = GetRegionInfo();
124          InstrInfo  = GetInstrumentInfo();          InstrInfo  = GetInstrumentInfo();
125            
126            MIDIPan    = CalculatePan(pEngineChannel->iLastPanRequest);
127    
128            AboutToTrigger();
129    
130          // calculate volume          // calculate volume
131          const double velocityAttenuation = GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity);          const double velocityAttenuation = GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity);
# Line 124  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);
149          PanLeftSmoother.trigger(pEngineChannel->GlobalPanLeft, subfragmentRate);          NoteVolumeSmoother.trigger(pNote ? pNote->Override.Volume : 1.f, 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 156  namespace LinuxSampler { Line 170  namespace LinuxSampler {
170              RAMLoop = (SmplInfo.HasLoops && (SmplInfo.LoopStart + SmplInfo.LoopLength) <= MaxRAMPos);              RAMLoop = (SmplInfo.HasLoops && (SmplInfo.LoopStart + SmplInfo.LoopLength) <= MaxRAMPos);
171    
172              if (OrderNewStream()) return -1;              if (OrderNewStream()) return -1;
173              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"));
174          }          }
175          else { // RAM only voice          else { // RAM only voice
176              MaxRAMPos = cachedsamples;              MaxRAMPos = cachedsamples;
# Line 172  namespace LinuxSampler { Line 186  namespace LinuxSampler {
186          }          }
187    
188          Pitch = CalculatePitchInfo(PitchBend);          Pitch = CalculatePitchInfo(PitchBend);
189            NotePitch = (pNote) ? pNote->Override.Pitch : 1.0f;
190    
191          // 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
192          const double velrelease = 1 / GetVelocityRelease(itNoteOnEvent->Param.Note.Velocity);          const double velrelease = 1 / GetVelocityRelease(itNoteOnEvent->Param.Note.Velocity);
193    
194          // setup EG 1 (VCA EG)          if (pSignalUnitRack == NULL) { // setup EG 1 (VCA EG)
         {  
195              // get current value of EG1 controller              // get current value of EG1 controller
196              double eg1controllervalue = GetEG1ControllerValue(itNoteOnEvent->Param.Note.Velocity);              double eg1controllervalue = GetEG1ControllerValue(itNoteOnEvent->Param.Note.Velocity);
197    
# Line 185  namespace LinuxSampler { Line 199  namespace LinuxSampler {
199              EGInfo egInfo = CalculateEG1ControllerInfluence(eg1controllervalue);              EGInfo egInfo = CalculateEG1ControllerInfluence(eg1controllervalue);
200    
201              TriggerEG1(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity);              TriggerEG1(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity);
202            } else {
203                pSignalUnitRack->Trigger();
204          }          }
205    
206            const uint8_t pan = (pSignalUnitRack) ? pSignalUnitRack->GetEndpointUnit()->CalculatePan(MIDIPan) : MIDIPan;
207            NotePanLeft  = (pNote) ? AbstractEngine::PanCurveValueNorm(pNote->Override.Pan, 0 /*left*/ ) : 1.f;
208            NotePanRight = (pNote) ? AbstractEngine::PanCurveValueNorm(pNote->Override.Pan, 1 /*right*/) : 1.f;
209            PanLeftSmoother.trigger(
210                AbstractEngine::PanCurve[128 - pan] * NotePanLeft,
211                subfragmentRate
212            );
213            PanRightSmoother.trigger(
214                AbstractEngine::PanCurve[pan] * NotePanRight,
215                subfragmentRate
216            );
217    
218  #ifdef CONFIG_INTERPOLATE_VOLUME  #ifdef CONFIG_INTERPOLATE_VOLUME
219          // setup initial volume in synthesis parameters          // setup initial volume in synthesis parameters
220      #ifdef CONFIG_PROCESS_MUTED_CHANNELS      #ifdef CONFIG_PROCESS_MUTED_CHANNELS
# Line 197  namespace LinuxSampler { Line 225  namespace LinuxSampler {
225          else          else
226      #else      #else
227          {          {
228              float finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pEG1->getLevel();              float finalVolume;
229                if (pSignalUnitRack == NULL) {
230                    finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pEG1->getLevel();
231                } else {
232                    finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pSignalUnitRack->GetEndpointUnit()->GetVolume();
233                }
234    
235              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * pEngineChannel->GlobalPanLeft;              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * PanLeftSmoother.render();
236              finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * pEngineChannel->GlobalPanRight;              finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * PanRightSmoother.render();
237          }          }
238      #endif      #endif
239  #endif  #endif
240    
241          // setup EG 2 (VCF Cutoff EG)          if (pSignalUnitRack == NULL) {
242          {              // setup EG 2 (VCF Cutoff EG)
243              // get current value of EG2 controller              {
244              double eg2controllervalue = GetEG2ControllerValue(itNoteOnEvent->Param.Note.Velocity);                  // get current value of EG2 controller
245                    double eg2controllervalue = GetEG2ControllerValue(itNoteOnEvent->Param.Note.Velocity);
246    
247                    // calculate influence of EG2 controller on EG2's parameters
248                    EGInfo egInfo = CalculateEG2ControllerInfluence(eg2controllervalue);
249    
250                    TriggerEG2(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity);
251                }
252    
             // calculate influence of EG2 controller on EG2's parameters  
             EGInfo egInfo = CalculateEG2ControllerInfluence(eg2controllervalue);  
253    
254              TriggerEG2(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity);              // setup EG 3 (VCO EG)
255          }              {
256                    // if portamento mode is on, we dedicate EG3 purely for portamento, otherwise if portamento is off we do as told by the patch
257                    bool  bPortamento = pEngineChannel->PortamentoMode && pEngineChannel->PortamentoPos >= 0.0f;
258                    float eg3depth = (bPortamento)
259                                 ? RTMath::CentsToFreqRatio((pEngineChannel->PortamentoPos - (float) MIDIKey()) * 100)
260                                 : RTMath::CentsToFreqRatio(RgnInfo.EG3Depth);
261                    float eg3time = (bPortamento)
262                                ? pEngineChannel->PortamentoTime
263                                : RgnInfo.EG3Attack;
264                    EG3.trigger(eg3depth, eg3time, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
265                    dmsg(5,("PortamentoPos=%f, depth=%f, time=%f\n", pEngineChannel->PortamentoPos, eg3depth, eg3time));
266                }
267    
268    
269          // setup EG 3 (VCO EG)              // setup LFO 1 (VCA LFO)
270          {              InitLFO1();
271              // 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)
272              bool  bPortamento = pEngineChannel->PortamentoMode && pEngineChannel->PortamentoPos >= 0.0f;              InitLFO2();
273              float eg3depth = (bPortamento)              // setup LFO 3 (VCO LFO)
274                           ? 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));  
275          }          }
276    
277    
         // setup LFO 1 (VCA LFO)  
         InitLFO1();  
         // setup LFO 2 (VCF Cutoff LFO)  
         InitLFO2();  
         // setup LFO 3 (VCO LFO)  
         InitLFO3();  
   
   
278          #if CONFIG_FORCE_FILTER          #if CONFIG_FORCE_FILTER
279          const bool bUseFilter = true;          const bool bUseFilter = true;
280          #else // use filter only if instrument file told so          #else // use filter only if instrument file told so
# Line 282  namespace LinuxSampler { Line 317  namespace LinuxSampler {
317              VCFCutoffCtrl.controller    = 0;              VCFCutoffCtrl.controller    = 0;
318              VCFResonanceCtrl.controller = 0;              VCFResonanceCtrl.controller = 0;
319          }          }
320            
321            const bool bEq =
322                pSignalUnitRack != NULL && pSignalUnitRack->HasEq() && pEq->HasSupport();
323    
324            if (bEq) {
325                pEq->GetInChannelLeft()->Clear();
326                pEq->GetInChannelRight()->Clear();
327                pEq->RenderAudio(GetEngine()->pAudioOutputDevice->MaxSamplesPerCycle());
328            }
329    
330          return 0; // success          return 0; // success
331      }      }
332        
333        void AbstractVoice::SetSampleStartOffset() {
334            finalSynthesisParameters.dPos = RgnInfo.SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)
335            Pos = RgnInfo.SampleStartOffset;
336        }
337    
338      /**      /**
339       *  Synthesizes the current audio fragment for this voice.       *  Synthesizes the current audio fragment for this voice.
# Line 295  namespace LinuxSampler { Line 344  namespace LinuxSampler {
344       *  @param Skip    - number of sample points to skip in output buffer       *  @param Skip    - number of sample points to skip in output buffer
345       */       */
346      void AbstractVoice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {      void AbstractVoice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {
347            bool delay = false; // Whether the voice playback should be delayed for this call
348            
349            if (pSignalUnitRack != NULL) {
350                uint delaySteps = pSignalUnitRack->GetEndpointUnit()->DelayTrigger();
351                if (delaySteps > 0) { // delay on the endpoint unit means delay of the voice playback
352                    if (delaySteps >= Samples) {
353                        pSignalUnitRack->GetEndpointUnit()->DecreaseDelay(Samples);
354                        delay = true;
355                    } else {
356                        pSignalUnitRack->GetEndpointUnit()->DecreaseDelay(delaySteps);
357                        Samples -= delaySteps;
358                        Skip += delaySteps;
359                    }
360                }
361            }
362            
363          AbstractEngineChannel* pChannel = pEngineChannel;          AbstractEngineChannel* pChannel = pEngineChannel;
364          MidiKeyBase* pMidiKeyInfo = GetMidiKeyInfo(MIDIKey);          MidiKeyBase* pMidiKeyInfo = GetMidiKeyInfo(MIDIKey());
365    
366          const bool bVoiceRequiresDedicatedRouting =          const bool bVoiceRequiresDedicatedRouting =
367              pEngineChannel->GetFxSendCount() > 0 &&              pEngineChannel->GetFxSendCount() > 0 &&
368              (pMidiKeyInfo->ReverbSend || pMidiKeyInfo->ChorusSend);              (pMidiKeyInfo->ReverbSend || pMidiKeyInfo->ChorusSend);
369            
370          if (bVoiceRequiresDedicatedRouting) {          const bool bEq =
371                pSignalUnitRack != NULL && pSignalUnitRack->HasEq() && pEq->HasSupport();
372    
373            if (bEq) {
374                pEq->GetInChannelLeft()->Clear();
375                pEq->GetInChannelRight()->Clear();
376                finalSynthesisParameters.pOutLeft  = &pEq->GetInChannelLeft()->Buffer()[Skip];
377                finalSynthesisParameters.pOutRight = &pEq->GetInChannelRight()->Buffer()[Skip];
378                pSignalUnitRack->UpdateEqSettings(pEq);
379            } else if (bVoiceRequiresDedicatedRouting) {
380              finalSynthesisParameters.pOutLeft  = &GetEngine()->pDedicatedVoiceChannelLeft->Buffer()[Skip];              finalSynthesisParameters.pOutLeft  = &GetEngine()->pDedicatedVoiceChannelLeft->Buffer()[Skip];
381              finalSynthesisParameters.pOutRight = &GetEngine()->pDedicatedVoiceChannelRight->Buffer()[Skip];              finalSynthesisParameters.pOutRight = &GetEngine()->pDedicatedVoiceChannelRight->Buffer()[Skip];
382          } else {          } else {
# Line 313  namespace LinuxSampler { Line 387  namespace LinuxSampler {
387    
388          RTList<Event>::Iterator itCCEvent = pChannel->pEvents->first();          RTList<Event>::Iterator itCCEvent = pChannel->pEvents->first();
389          RTList<Event>::Iterator itNoteEvent;          RTList<Event>::Iterator itNoteEvent;
390          GetFirstEventOnKey(MIDIKey, itNoteEvent);          GetFirstEventOnKey(HostKey(), itNoteEvent);
391    
392          RTList<Event>::Iterator itGroupEvent;          RTList<Event>::Iterator itGroupEvent;
393          if (pGroupEvents) itGroupEvent = pGroupEvents->first();          if (pGroupEvents && !Orphan) itGroupEvent = pGroupEvents->first();
394    
395          if (itTriggerEvent) { // skip events that happened before this voice was triggered          if (itTriggerEvent) { // skip events that happened before this voice was triggered
396              while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;              while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;
# Line 342  namespace LinuxSampler { Line 416  namespace LinuxSampler {
416                  // drivers that use Samples < MaxSamplesPerCycle).                  // drivers that use Samples < MaxSamplesPerCycle).
417                  // End the EG1 here, at pos 0, with a shorter max fade                  // End the EG1 here, at pos 0, with a shorter max fade
418                  // out time.                  // out time.
419                  pEG1->enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  if (pSignalUnitRack == NULL) {
420                        pEG1->enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
421                    } else {
422                        pSignalUnitRack->EnterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
423                    }
424                  itKillEvent = Pool<Event>::Iterator();                  itKillEvent = Pool<Event>::Iterator();
425              } else {              } else {
426                  killPos = RTMath::Min(itKillEvent->FragmentPos(), maxFadeOutPos);                  killPos = RTMath::Min(itKillEvent->FragmentPos(), maxFadeOutPos);
# Line 357  namespace LinuxSampler { Line 435  namespace LinuxSampler {
435              fFinalCutoff    = VCFCutoffCtrl.fvalue;              fFinalCutoff    = VCFCutoffCtrl.fvalue;
436              fFinalResonance = VCFResonanceCtrl.fvalue;              fFinalResonance = VCFResonanceCtrl.fvalue;
437    
438              // process MIDI control change and pitchbend events for this subfragment              // process MIDI control change, aftertouch and pitchbend events for this subfragment
439              processCCEvents(itCCEvent, iSubFragmentEnd);              processCCEvents(itCCEvent, iSubFragmentEnd);
440                uint8_t pan = MIDIPan;
441                if (pSignalUnitRack != NULL) pan = pSignalUnitRack->GetEndpointUnit()->CalculatePan(MIDIPan);
442    
443                PanLeftSmoother.update(AbstractEngine::PanCurve[128 - pan] * NotePanLeft);
444                PanRightSmoother.update(AbstractEngine::PanCurve[pan]      * NotePanRight);
445    
446                finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend * NotePitch;
447    
448              finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend;              float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render() * NoteVolumeSmoother.render();
             float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render();  
449  #ifdef CONFIG_PROCESS_MUTED_CHANNELS  #ifdef CONFIG_PROCESS_MUTED_CHANNELS
450              if (pChannel->GetMute()) fFinalVolume = 0;              if (pChannel->GetMute()) fFinalVolume = 0;
451  #endif  #endif
# Line 369  namespace LinuxSampler { Line 453  namespace LinuxSampler {
453              // process transition events (note on, note off & sustain pedal)              // process transition events (note on, note off & sustain pedal)
454              processTransitionEvents(itNoteEvent, iSubFragmentEnd);              processTransitionEvents(itNoteEvent, iSubFragmentEnd);
455              processGroupEvents(itGroupEvent, iSubFragmentEnd);              processGroupEvents(itGroupEvent, iSubFragmentEnd);
456                
457                if (pSignalUnitRack == NULL) {
458                    // if the voice was killed in this subfragment, or if the
459                    // filter EG is finished, switch EG1 to fade out stage
460                    if ((itKillEvent && killPos <= iSubFragmentEnd) ||
461                        (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&
462                        pEG2->getSegmentType() == EG::segment_end)) {
463                        pEG1->enterFadeOutStage();
464                        itKillEvent = Pool<Event>::Iterator();
465                    }
466    
467              // if the voice was killed in this subfragment, or if the                  // process envelope generators
468              // filter EG is finished, switch EG1 to fade out stage                  switch (pEG1->getSegmentType()) {
469              if ((itKillEvent && killPos <= iSubFragmentEnd) ||                      case EG::segment_lin:
470                  (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&                          fFinalVolume *= pEG1->processLin();
471                   pEG2->getSegmentType() == EG::segment_end)) {                          break;
472                  pEG1->enterFadeOutStage();                      case EG::segment_exp:
473                  itKillEvent = Pool<Event>::Iterator();                          fFinalVolume *= pEG1->processExp();
474              }                          break;
475                        case EG::segment_end:
476                            fFinalVolume *= pEG1->getLevel();
477                            break; // noop
478                        case EG::segment_pow:
479                            fFinalVolume *= pEG1->processPow();
480                            break;
481                    }
482                    switch (pEG2->getSegmentType()) {
483                        case EG::segment_lin:
484                            fFinalCutoff *= pEG2->processLin();
485                            break;
486                        case EG::segment_exp:
487                            fFinalCutoff *= pEG2->processExp();
488                            break;
489                        case EG::segment_end:
490                            fFinalCutoff *= pEG2->getLevel();
491                            break; // noop
492                        case EG::segment_pow:
493                            fFinalCutoff *= pEG2->processPow();
494                            break;
495                    }
496                    if (EG3.active()) finalSynthesisParameters.fFinalPitch *= EG3.render();
497    
498              // process envelope generators                  // process low frequency oscillators
499              switch (pEG1->getSegmentType()) {                  if (bLFO1Enabled) fFinalVolume *= (1.0f - pLFO1->render());
500                  case EG::segment_lin:                  if (bLFO2Enabled) fFinalCutoff *= (1.0f - pLFO2->render());
501                      fFinalVolume *= pEG1->processLin();                  if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());
502                      break;              } else {
503                  case EG::segment_exp:                  // if the voice was killed in this subfragment, enter fade out stage
504                      fFinalVolume *= pEG1->processExp();                  if (itKillEvent && killPos <= iSubFragmentEnd) {
505                      break;                      pSignalUnitRack->EnterFadeOutStage();
506                  case EG::segment_end:                      itKillEvent = Pool<Event>::Iterator();
507                      fFinalVolume *= pEG1->getLevel();                  }
508                      break; // noop                  
509                  case EG::segment_pow:                  // if the filter EG is finished, switch EG1 to fade out stage
510                      fFinalVolume *= pEG1->processPow();                  /*if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&
511                      break;                      pEG2->getSegmentType() == EG::segment_end) {
512              }                      pEG1->enterFadeOutStage();
513              switch (pEG2->getSegmentType()) {                      itKillEvent = Pool<Event>::Iterator();
514                  case EG::segment_lin:                  }*/
515                      fFinalCutoff *= pEG2->processLin();                  // TODO: ^^^
516                      break;  
517                  case EG::segment_exp:                  fFinalVolume   *= pSignalUnitRack->GetEndpointUnit()->GetVolume();
518                      fFinalCutoff *= pEG2->processExp();                  fFinalCutoff    = pSignalUnitRack->GetEndpointUnit()->CalculateFilterCutoff(fFinalCutoff);
519                      break;                  fFinalResonance = pSignalUnitRack->GetEndpointUnit()->CalculateResonance(fFinalResonance);
520                  case EG::segment_end:                  
521                      fFinalCutoff *= pEG2->getLevel();                  finalSynthesisParameters.fFinalPitch =
522                      break; // noop                      pSignalUnitRack->GetEndpointUnit()->CalculatePitch(finalSynthesisParameters.fFinalPitch);
523                  case EG::segment_pow:                      
                     fFinalCutoff *= pEG2->processPow();  
                     break;  
524              }              }
525              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());  
   
526              // limit the pitch so we don't read outside the buffer              // limit the pitch so we don't read outside the buffer
527              finalSynthesisParameters.fFinalPitch = RTMath::Min(finalSynthesisParameters.fFinalPitch, float(1 << CONFIG_MAX_PITCH));              finalSynthesisParameters.fFinalPitch = RTMath::Min(finalSynthesisParameters.fFinalPitch, float(1 << CONFIG_MAX_PITCH));
528    
# Line 447  namespace LinuxSampler { Line 555  namespace LinuxSampler {
555                  fFinalVolume * VolumeRight * PanRightSmoother.render();                  fFinalVolume * VolumeRight * PanRightSmoother.render();
556  #endif  #endif
557              // render audio for one subfragment              // render audio for one subfragment
558              RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);              if (!delay) RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);
559    
560              // stop the rendering if volume EG is finished              if (pSignalUnitRack == NULL) {
561              if (pEG1->getSegmentType() == EG::segment_end) break;                  // stop the rendering if volume EG is finished
562                    if (pEG1->getSegmentType() == EG::segment_end) break;
563                } else {
564                    // stop the rendering if the endpoint unit is not active
565                    if (!pSignalUnitRack->GetEndpointUnit()->Active()) break;
566                }
567    
568              const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;              const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;
569    
570              // increment envelopes' positions              if (pSignalUnitRack == NULL) {
571              if (pEG1->active()) {                  // increment envelopes' positions
572                    if (pEG1->active()) {
573    
574                        // 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
575                        if (SmplInfo.HasLoops && Pos <= SmplInfo.LoopStart && SmplInfo.LoopStart < newPos) {
576                            pEG1->update(EG::event_hold_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
577                        }
578    
579                  // 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);
580                  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);  
581                  }                  }
582                    if (pEG2->active()) {
583                  pEG1->increment(1);                      pEG2->increment(1);
584                  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);
585              }                  }
586              if (pEG2->active()) {                  EG3.increment(1);
587                  pEG2->increment(1);                  if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached
588                  if (!pEG2->toStageEndLeft()) pEG2->update(EG::event_stage_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);              } else {
589                        // 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
590                        /*if (SmplInfo.HasLoops && Pos <= SmplInfo.LoopStart && SmplInfo.LoopStart < newPos) {
591                            pEG1->update(EG::event_hold_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
592                        }*/
593                    // TODO: ^^^
594                    
595                    if (!delay) pSignalUnitRack->Increment();
596              }              }
             EG3.increment(1);  
             if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached  
597    
598              Pos = newPos;              Pos = newPos;
599              i = iSubFragmentEnd;              i = iSubFragmentEnd;
600          }          }
601            
602            if (delay) return;
603    
604          if (bVoiceRequiresDedicatedRouting) {          if (bVoiceRequiresDedicatedRouting) {
605                if (bEq) {
606                    pEq->RenderAudio(Samples);
607                    pEq->GetOutChannelLeft()->CopyTo(GetEngine()->pDedicatedVoiceChannelLeft, Samples);
608                    pEq->GetOutChannelRight()->CopyTo(GetEngine()->pDedicatedVoiceChannelRight, Samples);
609                }
610              optional<float> effectSendLevels[2] = {              optional<float> effectSendLevels[2] = {
611                  pMidiKeyInfo->ReverbSend,                  pMidiKeyInfo->ReverbSend,
612                  pMidiKeyInfo->ChorusSend                  pMidiKeyInfo->ChorusSend
613              };              };
614              GetEngine()->RouteDedicatedVoiceChannels(pEngineChannel, effectSendLevels, Samples);              GetEngine()->RouteDedicatedVoiceChannels(pEngineChannel, effectSendLevels, Samples);
615            } else if (bEq) {
616                pEq->RenderAudio(Samples);
617                pEq->GetOutChannelLeft()->MixTo(pChannel->pChannelLeft, Samples);
618                pEq->GetOutChannelRight()->MixTo(pChannel->pChannelRight, Samples);
619          }          }
620      }      }
621    
622      /**      /**
623       * Process given list of MIDI control change and pitch bend events for       * Process given list of MIDI control change, aftertouch and pitch bend
624       * the given time.       * events for the given time.
625       *       *
626       * @param itEvent - iterator pointing to the next event to be processed       * @param itEvent - iterator pointing to the next event to be processed
627       * @param End     - youngest time stamp where processing should be stopped       * @param End     - youngest time stamp where processing should be stopped
# Line 501  namespace LinuxSampler { Line 635  namespace LinuxSampler {
635                  if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {                  if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {
636                      processResonanceEvent(itEvent);                      processResonanceEvent(itEvent);
637                  }                  }
638                  if (itEvent->Param.CC.Controller == pLFO1->ExtController) {                  if (pSignalUnitRack == NULL) {
639                      pLFO1->update(itEvent->Param.CC.Value);                      if (itEvent->Param.CC.Controller == pLFO1->ExtController) {
640                  }                          pLFO1->update(itEvent->Param.CC.Value);
641                  if (itEvent->Param.CC.Controller == pLFO2->ExtController) {                      }
642                      pLFO2->update(itEvent->Param.CC.Value);                      if (itEvent->Param.CC.Controller == pLFO2->ExtController) {
643                  }                          pLFO2->update(itEvent->Param.CC.Value);
644                  if (itEvent->Param.CC.Controller == pLFO3->ExtController) {                      }
645                      pLFO3->update(itEvent->Param.CC.Value);                      if (itEvent->Param.CC.Controller == pLFO3->ExtController) {
646                            pLFO3->update(itEvent->Param.CC.Value);
647                        }
648                  }                  }
649                  if (itEvent->Param.CC.Controller == 7) { // volume                  if (itEvent->Param.CC.Controller == 7) { // volume
650                      VolumeSmoother.update(AbstractEngine::VolumeCurve[itEvent->Param.CC.Value]);                      VolumeSmoother.update(AbstractEngine::VolumeCurve[itEvent->Param.CC.Value]);
651                  } else if (itEvent->Param.CC.Controller == 10) { // panpot                  } else if (itEvent->Param.CC.Controller == 10) { // panpot
652                      PanLeftSmoother.update(AbstractEngine::PanCurve[128 - itEvent->Param.CC.Value]);                      MIDIPan = CalculatePan(itEvent->Param.CC.Value);
                     PanRightSmoother.update(AbstractEngine::PanCurve[itEvent->Param.CC.Value]);  
653                  }                  }
654              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event
655                  processPitchEvent(itEvent);                  processPitchEvent(itEvent);
656                } else if (itEvent->Type == Event::type_channel_pressure) {
657                    ProcessChannelPressureEvent(itEvent);
658                } else if (itEvent->Type == Event::type_note_pressure) {
659                    ProcessPolyphonicKeyPressureEvent(itEvent);
660              }              }
661    
662              ProcessCCEvent(itEvent);              ProcessCCEvent(itEvent);
663                if (pSignalUnitRack != NULL) {
664                    pSignalUnitRack->ProcessCCEvent(itEvent);
665                }
666          }          }
667      }      }
668    
# Line 539  namespace LinuxSampler { Line 681  namespace LinuxSampler {
681      }      }
682    
683      /**      /**
684       * Process given list of MIDI note on, note off and sustain pedal events       * Process given list of MIDI note on, note off, sustain pedal events and
685       * for the given time.       * note synthesis parameter events for the given time.
686       *       *
687       * @param itEvent - iterator pointing to the next event to be processed       * @param itEvent - iterator pointing to the next event to be processed
688       * @param End     - youngest time stamp where processing should be stopped       * @param End     - youngest time stamp where processing should be stopped
# Line 552  namespace LinuxSampler { Line 694  namespace LinuxSampler {
694                  if (itEvent->Type == Event::type_release) {                  if (itEvent->Type == Event::type_release) {
695                      EnterReleaseStage();                      EnterReleaseStage();
696                  } else if (itEvent->Type == Event::type_cancel_release) {                  } else if (itEvent->Type == Event::type_cancel_release) {
697                      pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                      if (pSignalUnitRack == NULL) {
698                      pEG2->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                          pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
699                            pEG2->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
700                        } else {
701                            pSignalUnitRack->CancelRelease();
702                        }
703                    }
704                }
705                // process synthesis parameter events (caused by built-in realt-time instrument script functions)
706                if (itEvent->Type == Event::type_note_synth_param && pNote &&
707                    pEngineChannel->pEngine->NoteByID( itEvent->Param.NoteSynthParam.NoteID ) == pNote)
708                {
709                    switch (itEvent->Param.NoteSynthParam.Type) {
710                        case Event::synth_param_volume:
711                            NoteVolumeSmoother.update(itEvent->Param.NoteSynthParam.AbsValue);
712                            break;
713                        case Event::synth_param_pitch:
714                            NotePitch = itEvent->Param.NoteSynthParam.AbsValue;
715                            break;
716                        case Event::synth_param_pan:
717                            NotePanLeft  = AbstractEngine::PanCurveValueNorm(itEvent->Param.NoteSynthParam.AbsValue, 0 /*left*/);
718                            NotePanRight = AbstractEngine::PanCurveValueNorm(itEvent->Param.NoteSynthParam.AbsValue, 1 /*right*/);
719                            break;
720                  }                  }
721              }              }
722          }          }
# Line 580  namespace LinuxSampler { Line 743  namespace LinuxSampler {
743       * @param itNoteOffEvent - event which causes this voice to die soon       * @param itNoteOffEvent - event which causes this voice to die soon
744       */       */
745      void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {      void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {
746          const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());          if (pSignalUnitRack == NULL) {
747          pEngineChannel->PortamentoPos = (float) MIDIKey + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;              const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());
748                pEngineChannel->PortamentoPos = (float) MIDIKey() + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;
749            } else {
750                // TODO:
751            }
752      }      }
753    
754      /**      /**
# Line 605  namespace LinuxSampler { Line 772  namespace LinuxSampler {
772    
773      Voice::PitchInfo AbstractVoice::CalculatePitchInfo(int PitchBend) {      Voice::PitchInfo AbstractVoice::CalculatePitchInfo(int PitchBend) {
774          PitchInfo pitch;          PitchInfo pitch;
775          double pitchbasecents = InstrInfo.FineTune + RgnInfo.FineTune + GetEngine()->ScaleTuning[MIDIKey % 12];          double pitchbasecents = InstrInfo.FineTune + RgnInfo.FineTune + GetEngine()->ScaleTuning[MIDIKey() % 12];
776    
777          // GSt behaviour: maximum transpose up is 40 semitones. If          // GSt behaviour: maximum transpose up is 40 semitones. If
778          // MIDI key is more than 40 semitones above unity note,          // MIDI key is more than 40 semitones above unity note,
779          // the transpose is not done.          // the transpose is not done.
780          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;
781    
782          pitch.PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(SmplInfo.SampleRate) / double(GetEngine()->SampleRate));          pitch.PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(SmplInfo.SampleRate) / double(GetEngine()->SampleRate));
783          pitch.PitchBendRange = 1.0 / 8192.0 * 100.0 * InstrInfo.PitchbendRange;          pitch.PitchBendRange = 1.0 / 8192.0 * 100.0 * InstrInfo.PitchbendRange;
# Line 618  namespace LinuxSampler { Line 785  namespace LinuxSampler {
785    
786          return pitch;          return pitch;
787      }      }
788        
789        void AbstractVoice::onScaleTuningChanged() {
790            PitchInfo pitch = this->Pitch;
791            double pitchbasecents = InstrInfo.FineTune + RgnInfo.FineTune + GetEngine()->ScaleTuning[MIDIKey() % 12];
792            
793            // GSt behaviour: maximum transpose up is 40 semitones. If
794            // MIDI key is more than 40 semitones above unity note,
795            // the transpose is not done.
796            if (!SmplInfo.Unpitched && (MIDIKey() - (int) RgnInfo.UnityNote) < 40) pitchbasecents += (MIDIKey() - (int) RgnInfo.UnityNote) * 100;
797            
798            pitch.PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(SmplInfo.SampleRate) / double(GetEngine()->SampleRate));
799            this->Pitch = pitch;
800        }
801    
802      double AbstractVoice::CalculateVolume(double velocityAttenuation) {      double AbstractVoice::CalculateVolume(double velocityAttenuation) {
803          // For 16 bit samples, we downscale by 32768 to convert from          // For 16 bit samples, we downscale by 32768 to convert from
# Line 630  namespace LinuxSampler { Line 810  namespace LinuxSampler {
810          // the volume of release triggered samples depends on note length          // the volume of release triggered samples depends on note length
811          if (Type & Voice::type_release_trigger) {          if (Type & Voice::type_release_trigger) {
812              float noteLength = float(GetEngine()->FrameTime + Delay -              float noteLength = float(GetEngine()->FrameTime + Delay -
813                  GetNoteOnTime(MIDIKey) ) / GetEngine()->SampleRate;                  GetNoteOnTime(MIDIKey()) ) / GetEngine()->SampleRate;
814    
815              volume *= GetReleaseTriggerAttenuation(noteLength);              volume *= GetReleaseTriggerAttenuation(noteLength);
816          }          }
# Line 643  namespace LinuxSampler { Line 823  namespace LinuxSampler {
823      }      }
824    
825      void AbstractVoice::EnterReleaseStage() {      void AbstractVoice::EnterReleaseStage() {
826          pEG1->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);          if (pSignalUnitRack == NULL) {
827          pEG2->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);              pEG1->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
828                pEG2->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
829            } else {
830                pSignalUnitRack->EnterReleaseStage();
831            }
832        }
833    
834        bool AbstractVoice::EG1Finished() {
835            if (pSignalUnitRack == NULL) {
836                return pEG1->getSegmentType() == EG::segment_end;
837            } else {
838                return !pSignalUnitRack->GetEndpointUnit()->Active();
839            }
840      }      }
841    
842  } // namespace LinuxSampler  } // namespace LinuxSampler

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

  ViewVC Help
Powered by ViewVC