/[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 3335 by schoenebeck, Sun Jul 30 14:33:15 2017 UTC
# Line 4  Line 4 
4   *                                                                         *   *                                                                         *
5   *   Copyright (C) 2003,2004 by Benno Senoner and Christian Schoenebeck    *   *   Copyright (C) 2003,2004 by Benno Senoner and Christian Schoenebeck    *
6   *   Copyright (C) 2005-2008 Christian Schoenebeck                         *   *   Copyright (C) 2005-2008 Christian Schoenebeck                         *
7   *   Copyright (C) 2009-2011 Christian Schoenebeck and Grigor Iliev        *   *   Copyright (C) 2009-2012 Christian Schoenebeck and Grigor Iliev        *
8     *   Copyright (C) 2013-2017 Christian Schoenebeck and Andreas Persson     *
9   *                                                                         *   *                                                                         *
10   *   This program is free software; you can redistribute it and/or modify  *   *   This program is free software; you can redistribute it and/or modify  *
11   *   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 27 
27    
28  namespace LinuxSampler {  namespace LinuxSampler {
29    
30      AbstractVoice::AbstractVoice() {      AbstractVoice::AbstractVoice(SignalUnitRack* pRack): pSignalUnitRack(pRack) {
31          pEngineChannel = NULL;          pEngineChannel = NULL;
32          pLFO1 = new LFOUnsigned(1.0f);  // amplitude LFO (0..1 range)          pLFO1 = new LFOUnsigned(1.0f);  // amplitude LFO (0..1 range)
33          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 44  namespace LinuxSampler {
44    
45          finalSynthesisParameters.filterLeft.Reset();          finalSynthesisParameters.filterLeft.Reset();
46          finalSynthesisParameters.filterRight.Reset();          finalSynthesisParameters.filterRight.Reset();
47            
48            pEq          = NULL;
49            bEqSupport   = false;
50      }      }
51    
52      AbstractVoice::~AbstractVoice() {      AbstractVoice::~AbstractVoice() {
53          if (pLFO1) delete pLFO1;          if (pLFO1) delete pLFO1;
54          if (pLFO2) delete pLFO2;          if (pLFO2) delete pLFO2;
55          if (pLFO3) delete pLFO3;          if (pLFO3) delete pLFO3;
56            
57            if(pEq != NULL) delete pEq;
58        }
59                
60        void AbstractVoice::CreateEq() {
61            if(!bEqSupport) return;
62            if(pEq != NULL) delete pEq;
63            pEq = new EqSupport;
64            pEq->InitEffect(GetEngine()->pAudioOutputDevice);
65      }      }
66    
67      /**      /**
# Line 98  namespace LinuxSampler { Line 111  namespace LinuxSampler {
111          #endif // CONFIG_DEVMODE          #endif // CONFIG_DEVMODE
112    
113          Type            = VoiceType;          Type            = VoiceType;
114          MIDIKey         = itNoteOnEvent->Param.Note.Key;          pNote           = pEngineChannel->pEngine->NoteByID( itNoteOnEvent->Param.Note.ID );
115          PlaybackState   = playback_state_init; // mark voice as triggered, but no audio rendered yet          PlaybackState   = playback_state_init; // mark voice as triggered, but no audio rendered yet
116          Delay           = itNoteOnEvent->FragmentPos();          Delay           = itNoteOnEvent->FragmentPos();
117          itTriggerEvent  = itNoteOnEvent;          itTriggerEvent  = itNoteOnEvent;
118          itKillEvent     = Pool<Event>::Iterator();          itKillEvent     = Pool<Event>::Iterator();
119          MidiKeyBase* pKeyInfo = GetMidiKeyInfo(MIDIKey);          MidiKeyBase* pKeyInfo = GetMidiKeyInfo(MIDIKey());
120    
121          pGroupEvents = iKeyGroup ? pEngineChannel->ActiveKeyGroups[iKeyGroup] : 0;          pGroupEvents = iKeyGroup ? pEngineChannel->ActiveKeyGroups[iKeyGroup] : 0;
122    
123          SmplInfo   = GetSampleInfo();          SmplInfo   = GetSampleInfo();
124          RgnInfo    = GetRegionInfo();          RgnInfo    = GetRegionInfo();
125          InstrInfo  = GetInstrumentInfo();          InstrInfo  = GetInstrumentInfo();
126            
127            MIDIPan    = CalculatePan(pEngineChannel->iLastPanRequest);
128    
129            AboutToTrigger();
130    
131          // calculate volume          // calculate volume
132          const double velocityAttenuation = GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity);          const double velocityAttenuation = GetVelocityAttenuation(MIDIVelocity());
133          float volume = CalculateVolume(velocityAttenuation) * pKeyInfo->Volume;          float volume = CalculateVolume(velocityAttenuation) * pKeyInfo->Volume;
134          if (volume <= 0) return -1;          if (volume <= 0) return -1;
135    
# Line 122  namespace LinuxSampler { Line 139  namespace LinuxSampler {
139          SYNTHESIS_MODE_SET_BITDEPTH24(SynthesisMode, SmplInfo.BitDepth == 24);          SYNTHESIS_MODE_SET_BITDEPTH24(SynthesisMode, SmplInfo.BitDepth == 24);
140    
141          // get starting crossfade volume level          // get starting crossfade volume level
142          float crossfadeVolume = CalculateCrossfadeVolume(itNoteOnEvent->Param.Note.Velocity);          float crossfadeVolume = CalculateCrossfadeVolume(MIDIVelocity());
143    
144          VolumeLeft  = volume * pKeyInfo->PanLeft  * AbstractEngine::PanCurve[64 - RgnInfo.Pan];          VolumeLeft  = volume * pKeyInfo->PanLeft;
145          VolumeRight = volume * pKeyInfo->PanRight * AbstractEngine::PanCurve[64 + RgnInfo.Pan];          VolumeRight = volume * pKeyInfo->PanRight;
146    
147          float subfragmentRate = GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;          // this rate is used for rather mellow volume fades
148            const float subfragmentRate = GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;
149            // this rate is used for very fast volume fades
150            const float quickRampRate = RTMath::Min(subfragmentRate, GetEngine()->SampleRate * 0.001f /* approx. 13ms */);
151          CrossfadeSmoother.trigger(crossfadeVolume, subfragmentRate);          CrossfadeSmoother.trigger(crossfadeVolume, subfragmentRate);
         VolumeSmoother.trigger(pEngineChannel->MidiVolume, subfragmentRate);  
         PanLeftSmoother.trigger(pEngineChannel->GlobalPanLeft, subfragmentRate);  
         PanRightSmoother.trigger(pEngineChannel->GlobalPanRight, subfragmentRate);  
152    
153          finalSynthesisParameters.dPos = RgnInfo.SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)          VolumeSmoother.trigger(pEngineChannel->MidiVolume, subfragmentRate);
154          Pos = RgnInfo.SampleStartOffset;          NoteVolume.setCurveOnly(pNote ? pNote->Override.VolumeCurve : DEFAULT_FADE_CURVE);
155            NoteVolume.setCurrentValue(pNote ? pNote->Override.Volume : 1.f);
156            NoteVolume.setDefaultDuration(pNote ? pNote->Override.VolumeTime : DEFAULT_NOTE_VOLUME_TIME_S);
157    
158          // 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
159          long cachedsamples = GetSampleCacheSize() / SmplInfo.FrameSize;          long cachedsamples = GetSampleCacheSize() / SmplInfo.FrameSize;
160          DiskVoice          = cachedsamples < SmplInfo.TotalFrameCount;          DiskVoice          = cachedsamples < SmplInfo.TotalFrameCount;
161    
162            SetSampleStartOffset();
163    
164          if (DiskVoice) { // voice to be streamed from disk          if (DiskVoice) { // voice to be streamed from disk
165              if (cachedsamples > (GetEngine()->MaxSamplesPerCycle << CONFIG_MAX_PITCH)) {              if (cachedsamples > (GetEngine()->MaxSamplesPerCycle << CONFIG_MAX_PITCH)) {
166                  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 177  namespace LinuxSampler {
177              RAMLoop = (SmplInfo.HasLoops && (SmplInfo.LoopStart + SmplInfo.LoopLength) <= MaxRAMPos);              RAMLoop = (SmplInfo.HasLoops && (SmplInfo.LoopStart + SmplInfo.LoopLength) <= MaxRAMPos);
178    
179              if (OrderNewStream()) return -1;              if (OrderNewStream()) return -1;
180              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"));
181          }          }
182          else { // RAM only voice          else { // RAM only voice
183              MaxRAMPos = cachedsamples;              MaxRAMPos = cachedsamples;
# Line 172  namespace LinuxSampler { Line 193  namespace LinuxSampler {
193          }          }
194    
195          Pitch = CalculatePitchInfo(PitchBend);          Pitch = CalculatePitchInfo(PitchBend);
196            NotePitch.setCurveOnly(pNote ? pNote->Override.PitchCurve : DEFAULT_FADE_CURVE);
197            NotePitch.setCurrentValue(pNote ? pNote->Override.Pitch : 1.0f);
198            NotePitch.setDefaultDuration(pNote ? pNote->Override.PitchTime : DEFAULT_NOTE_PITCH_TIME_S);
199            NoteCutoff = (pNote) ? pNote->Override.Cutoff : 1.0f;
200            NoteResonance = (pNote) ? pNote->Override.Resonance : 1.0f;
201    
202          // 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
203          const double velrelease = 1 / GetVelocityRelease(itNoteOnEvent->Param.Note.Velocity);          const double velrelease = 1 / GetVelocityRelease(MIDIVelocity());
204    
205          // setup EG 1 (VCA EG)          if (pSignalUnitRack == NULL) { // setup EG 1 (VCA EG)
         {  
206              // get current value of EG1 controller              // get current value of EG1 controller
207              double eg1controllervalue = GetEG1ControllerValue(itNoteOnEvent->Param.Note.Velocity);              double eg1controllervalue = GetEG1ControllerValue(MIDIVelocity());
208    
209              // calculate influence of EG1 controller on EG1's parameters              // calculate influence of EG1 controller on EG1's parameters
210              EGInfo egInfo = CalculateEG1ControllerInfluence(eg1controllervalue);              EGInfo egInfo = CalculateEG1ControllerInfluence(eg1controllervalue);
211    
212              TriggerEG1(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity);              if (pNote) {
213                    egInfo.Attack  *= pNote->Override.Attack;
214                    egInfo.Decay   *= pNote->Override.Decay;
215                    egInfo.Release *= pNote->Override.Release;
216                }
217    
218                TriggerEG1(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, MIDIVelocity());
219            } else {
220                pSignalUnitRack->Trigger();
221          }          }
222    
223            const uint8_t pan = (pSignalUnitRack) ? pSignalUnitRack->GetEndpointUnit()->CalculatePan(MIDIPan) : MIDIPan;
224            for (int c = 0; c < 2; ++c) {
225                float value = (pNote) ? AbstractEngine::PanCurveValueNorm(pNote->Override.Pan, c) : 1.f;
226                NotePan[c].setCurveOnly(pNote ? pNote->Override.PanCurve : DEFAULT_FADE_CURVE);
227                NotePan[c].setCurrentValue(value);
228                NotePan[c].setDefaultDuration(pNote ? pNote->Override.PanTime : DEFAULT_NOTE_PAN_TIME_S);
229            }
230    
231            PanLeftSmoother.trigger(
232                AbstractEngine::PanCurve[128 - pan],
233                quickRampRate //NOTE: maybe we should have 2 separate pan smoothers, one for MIDI CC10 (with slow rate) and one for instrument script change_pan() calls (with fast rate)
234            );
235            PanRightSmoother.trigger(
236                AbstractEngine::PanCurve[pan],
237                quickRampRate //NOTE: maybe we should have 2 separate pan smoothers, one for MIDI CC10 (with slow rate) and one for instrument script change_pan() calls (with fast rate)
238            );
239    
240  #ifdef CONFIG_INTERPOLATE_VOLUME  #ifdef CONFIG_INTERPOLATE_VOLUME
241          // setup initial volume in synthesis parameters          // setup initial volume in synthesis parameters
242      #ifdef CONFIG_PROCESS_MUTED_CHANNELS      #ifdef CONFIG_PROCESS_MUTED_CHANNELS
# Line 197  namespace LinuxSampler { Line 247  namespace LinuxSampler {
247          else          else
248      #else      #else
249          {          {
250              float finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pEG1->getLevel();              float finalVolume;
251                if (pSignalUnitRack == NULL) {
252                    finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pEG1->getLevel();
253                } else {
254                    finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pSignalUnitRack->GetEndpointUnit()->GetVolume();
255                }
256                finalVolume *= NoteVolume.currentValue();
257    
258              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * pEngineChannel->GlobalPanLeft;              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * PanLeftSmoother.render()  * NotePan[0].currentValue();
259              finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * pEngineChannel->GlobalPanRight;              finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * PanRightSmoother.render() * NotePan[1].currentValue();
260          }          }
261      #endif      #endif
262  #endif  #endif
263    
264          // setup EG 2 (VCF Cutoff EG)          if (pSignalUnitRack == NULL) {
265          {              // setup EG 2 (VCF Cutoff EG)
266              // get current value of EG2 controller              {
267              double eg2controllervalue = GetEG2ControllerValue(itNoteOnEvent->Param.Note.Velocity);                  // get current value of EG2 controller
268                    double eg2controllervalue = GetEG2ControllerValue(MIDIVelocity());
269    
270                    // calculate influence of EG2 controller on EG2's parameters
271                    EGInfo egInfo = CalculateEG2ControllerInfluence(eg2controllervalue);
272    
273                    TriggerEG2(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, MIDIVelocity());
274                }
275    
             // calculate influence of EG2 controller on EG2's parameters  
             EGInfo egInfo = CalculateEG2ControllerInfluence(eg2controllervalue);  
276    
277              TriggerEG2(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity);              // setup EG 3 (VCO EG)
278          }              {
279                    // if portamento mode is on, we dedicate EG3 purely for portamento, otherwise if portamento is off we do as told by the patch
280                    bool  bPortamento = pEngineChannel->PortamentoMode && pEngineChannel->PortamentoPos >= 0.0f;
281                    float eg3depth = (bPortamento)
282                                 ? RTMath::CentsToFreqRatio((pEngineChannel->PortamentoPos - (float) MIDIKey()) * 100)
283                                 : RTMath::CentsToFreqRatio(RgnInfo.EG3Depth);
284                    float eg3time = (bPortamento)
285                                ? pEngineChannel->PortamentoTime
286                                : RgnInfo.EG3Attack;
287                    EG3.trigger(eg3depth, eg3time, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
288                    dmsg(5,("PortamentoPos=%f, depth=%f, time=%f\n", pEngineChannel->PortamentoPos, eg3depth, eg3time));
289                }
290    
291    
292          // setup EG 3 (VCO EG)              // setup LFO 1 (VCA LFO)
293          {              InitLFO1();
294              // 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)
295              bool  bPortamento = pEngineChannel->PortamentoMode && pEngineChannel->PortamentoPos >= 0.0f;              InitLFO2();
296              float eg3depth = (bPortamento)              // setup LFO 3 (VCO LFO)
297                           ? 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));  
298          }          }
299    
300    
         // setup LFO 1 (VCA LFO)  
         InitLFO1();  
         // setup LFO 2 (VCF Cutoff LFO)  
         InitLFO2();  
         // setup LFO 3 (VCO LFO)  
         InitLFO3();  
   
   
301          #if CONFIG_FORCE_FILTER          #if CONFIG_FORCE_FILTER
302          const bool bUseFilter = true;          const bool bUseFilter = true;
303          #else // use filter only if instrument file told so          #else // use filter only if instrument file told so
# Line 271  namespace LinuxSampler { Line 329  namespace LinuxSampler {
329              VCFResonanceCtrl.value = pEngineChannel->ControllerTable[VCFResonanceCtrl.controller];              VCFResonanceCtrl.value = pEngineChannel->ControllerTable[VCFResonanceCtrl.controller];
330    
331              // calculate cutoff frequency              // calculate cutoff frequency
332              CutoffBase = CalculateCutoffBase(itNoteOnEvent->Param.Note.Velocity);              CutoffBase = CalculateCutoffBase(MIDIVelocity());
333    
334              VCFCutoffCtrl.fvalue = CalculateFinalCutoff(CutoffBase);              VCFCutoffCtrl.fvalue = CalculateFinalCutoff(CutoffBase);
335    
# Line 282  namespace LinuxSampler { Line 340  namespace LinuxSampler {
340              VCFCutoffCtrl.controller    = 0;              VCFCutoffCtrl.controller    = 0;
341              VCFResonanceCtrl.controller = 0;              VCFResonanceCtrl.controller = 0;
342          }          }
343            
344            const bool bEq =
345                pSignalUnitRack != NULL && pSignalUnitRack->HasEq() && pEq->HasSupport();
346    
347            if (bEq) {
348                pEq->GetInChannelLeft()->Clear();
349                pEq->GetInChannelRight()->Clear();
350                pEq->RenderAudio(GetEngine()->pAudioOutputDevice->MaxSamplesPerCycle());
351            }
352    
353          return 0; // success          return 0; // success
354      }      }
355        
356        void AbstractVoice::SetSampleStartOffset() {
357            double pos = RgnInfo.SampleStartOffset; // offset where we should start playback of sample
358    
359            // if another sample playback start position was requested by instrument
360            // script (built-in script function play_note())
361            if (pNote && pNote->Override.SampleOffset >= 0) {
362                double overridePos =
363                    double(SmplInfo.SampleRate) * double(pNote->Override.SampleOffset) / 1000000.0;
364                if (overridePos < SmplInfo.TotalFrameCount)
365                    pos = overridePos;
366            }
367    
368            finalSynthesisParameters.dPos = pos;
369            Pos = pos;
370        }
371    
372      /**      /**
373       *  Synthesizes the current audio fragment for this voice.       *  Synthesizes the current audio fragment for this voice.
# Line 295  namespace LinuxSampler { Line 378  namespace LinuxSampler {
378       *  @param Skip    - number of sample points to skip in output buffer       *  @param Skip    - number of sample points to skip in output buffer
379       */       */
380      void AbstractVoice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {      void AbstractVoice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {
381            bool delay = false; // Whether the voice playback should be delayed for this call
382            
383            if (pSignalUnitRack != NULL) {
384                uint delaySteps = pSignalUnitRack->GetEndpointUnit()->DelayTrigger();
385                if (delaySteps > 0) { // delay on the endpoint unit means delay of the voice playback
386                    if (delaySteps >= Samples) {
387                        pSignalUnitRack->GetEndpointUnit()->DecreaseDelay(Samples);
388                        delay = true;
389                    } else {
390                        pSignalUnitRack->GetEndpointUnit()->DecreaseDelay(delaySteps);
391                        Samples -= delaySteps;
392                        Skip += delaySteps;
393                    }
394                }
395            }
396            
397          AbstractEngineChannel* pChannel = pEngineChannel;          AbstractEngineChannel* pChannel = pEngineChannel;
398          MidiKeyBase* pMidiKeyInfo = GetMidiKeyInfo(MIDIKey);          MidiKeyBase* pMidiKeyInfo = GetMidiKeyInfo(MIDIKey());
399    
400          const bool bVoiceRequiresDedicatedRouting =          const bool bVoiceRequiresDedicatedRouting =
401              pEngineChannel->GetFxSendCount() > 0 &&              pEngineChannel->GetFxSendCount() > 0 &&
402              (pMidiKeyInfo->ReverbSend || pMidiKeyInfo->ChorusSend);              (pMidiKeyInfo->ReverbSend || pMidiKeyInfo->ChorusSend);
403            
404          if (bVoiceRequiresDedicatedRouting) {          const bool bEq =
405                pSignalUnitRack != NULL && pSignalUnitRack->HasEq() && pEq->HasSupport();
406    
407            if (bEq) {
408                pEq->GetInChannelLeft()->Clear();
409                pEq->GetInChannelRight()->Clear();
410                finalSynthesisParameters.pOutLeft  = &pEq->GetInChannelLeft()->Buffer()[Skip];
411                finalSynthesisParameters.pOutRight = &pEq->GetInChannelRight()->Buffer()[Skip];
412                pSignalUnitRack->UpdateEqSettings(pEq);
413            } else if (bVoiceRequiresDedicatedRouting) {
414              finalSynthesisParameters.pOutLeft  = &GetEngine()->pDedicatedVoiceChannelLeft->Buffer()[Skip];              finalSynthesisParameters.pOutLeft  = &GetEngine()->pDedicatedVoiceChannelLeft->Buffer()[Skip];
415              finalSynthesisParameters.pOutRight = &GetEngine()->pDedicatedVoiceChannelRight->Buffer()[Skip];              finalSynthesisParameters.pOutRight = &GetEngine()->pDedicatedVoiceChannelRight->Buffer()[Skip];
416          } else {          } else {
# Line 313  namespace LinuxSampler { Line 421  namespace LinuxSampler {
421    
422          RTList<Event>::Iterator itCCEvent = pChannel->pEvents->first();          RTList<Event>::Iterator itCCEvent = pChannel->pEvents->first();
423          RTList<Event>::Iterator itNoteEvent;          RTList<Event>::Iterator itNoteEvent;
424          GetFirstEventOnKey(MIDIKey, itNoteEvent);          GetFirstEventOnKey(HostKey(), itNoteEvent);
425    
426          RTList<Event>::Iterator itGroupEvent;          RTList<Event>::Iterator itGroupEvent;
427          if (pGroupEvents) itGroupEvent = pGroupEvents->first();          if (pGroupEvents && !Orphan) itGroupEvent = pGroupEvents->first();
428    
429          if (itTriggerEvent) { // skip events that happened before this voice was triggered          if (itTriggerEvent) { // skip events that happened before this voice was triggered
430              while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;              while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;
# Line 333  namespace LinuxSampler { Line 441  namespace LinuxSampler {
441              }              }
442          }          }
443    
444          uint killPos;          uint killPos = 0;
445          if (itKillEvent) {          if (itKillEvent) {
446              int maxFadeOutPos = Samples - GetEngine()->GetMinFadeOutSamples();              int maxFadeOutPos = Samples - GetEngine()->GetMinFadeOutSamples();
447              if (maxFadeOutPos < 0) {              if (maxFadeOutPos < 0) {
# Line 342  namespace LinuxSampler { Line 450  namespace LinuxSampler {
450                  // drivers that use Samples < MaxSamplesPerCycle).                  // drivers that use Samples < MaxSamplesPerCycle).
451                  // End the EG1 here, at pos 0, with a shorter max fade                  // End the EG1 here, at pos 0, with a shorter max fade
452                  // out time.                  // out time.
453                  pEG1->enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  if (pSignalUnitRack == NULL) {
454                        pEG1->enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
455                    } else {
456                        pSignalUnitRack->EnterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
457                    }
458                  itKillEvent = Pool<Event>::Iterator();                  itKillEvent = Pool<Event>::Iterator();
459              } else {              } else {
460                  killPos = RTMath::Min(itKillEvent->FragmentPos(), maxFadeOutPos);                  killPos = RTMath::Min(itKillEvent->FragmentPos(), maxFadeOutPos);
# Line 357  namespace LinuxSampler { Line 469  namespace LinuxSampler {
469              fFinalCutoff    = VCFCutoffCtrl.fvalue;              fFinalCutoff    = VCFCutoffCtrl.fvalue;
470              fFinalResonance = VCFResonanceCtrl.fvalue;              fFinalResonance = VCFResonanceCtrl.fvalue;
471    
472              // process MIDI control change and pitchbend events for this subfragment              // process MIDI control change, aftertouch and pitchbend events for this subfragment
473              processCCEvents(itCCEvent, iSubFragmentEnd);              processCCEvents(itCCEvent, iSubFragmentEnd);
474                uint8_t pan = MIDIPan;
475                if (pSignalUnitRack != NULL) pan = pSignalUnitRack->GetEndpointUnit()->CalculatePan(MIDIPan);
476    
477                PanLeftSmoother.update(AbstractEngine::PanCurve[128 - pan]);
478                PanRightSmoother.update(AbstractEngine::PanCurve[pan]);
479    
480                finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend * NotePitch.render();
481    
482              finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend;              float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render() * NoteVolume.render();
             float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render();  
483  #ifdef CONFIG_PROCESS_MUTED_CHANNELS  #ifdef CONFIG_PROCESS_MUTED_CHANNELS
484              if (pChannel->GetMute()) fFinalVolume = 0;              if (pChannel->GetMute()) fFinalVolume = 0;
485  #endif  #endif
# Line 369  namespace LinuxSampler { Line 487  namespace LinuxSampler {
487              // process transition events (note on, note off & sustain pedal)              // process transition events (note on, note off & sustain pedal)
488              processTransitionEvents(itNoteEvent, iSubFragmentEnd);              processTransitionEvents(itNoteEvent, iSubFragmentEnd);
489              processGroupEvents(itGroupEvent, iSubFragmentEnd);              processGroupEvents(itGroupEvent, iSubFragmentEnd);
490                
491                if (pSignalUnitRack == NULL) {
492                    // if the voice was killed in this subfragment, or if the
493                    // filter EG is finished, switch EG1 to fade out stage
494                    if ((itKillEvent && killPos <= iSubFragmentEnd) ||
495                        (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&
496                        pEG2->getSegmentType() == EG::segment_end)) {
497                        pEG1->enterFadeOutStage();
498                        itKillEvent = Pool<Event>::Iterator();
499                    }
500    
501              // if the voice was killed in this subfragment, or if the                  // process envelope generators
502              // filter EG is finished, switch EG1 to fade out stage                  switch (pEG1->getSegmentType()) {
503              if ((itKillEvent && killPos <= iSubFragmentEnd) ||                      case EG::segment_lin:
504                  (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&                          fFinalVolume *= pEG1->processLin();
505                   pEG2->getSegmentType() == EG::segment_end)) {                          break;
506                  pEG1->enterFadeOutStage();                      case EG::segment_exp:
507                  itKillEvent = Pool<Event>::Iterator();                          fFinalVolume *= pEG1->processExp();
508              }                          break;
509                        case EG::segment_end:
510                            fFinalVolume *= pEG1->getLevel();
511                            break; // noop
512                        case EG::segment_pow:
513                            fFinalVolume *= pEG1->processPow();
514                            break;
515                    }
516                    switch (pEG2->getSegmentType()) {
517                        case EG::segment_lin:
518                            fFinalCutoff *= pEG2->processLin();
519                            break;
520                        case EG::segment_exp:
521                            fFinalCutoff *= pEG2->processExp();
522                            break;
523                        case EG::segment_end:
524                            fFinalCutoff *= pEG2->getLevel();
525                            break; // noop
526                        case EG::segment_pow:
527                            fFinalCutoff *= pEG2->processPow();
528                            break;
529                    }
530                    if (EG3.active()) finalSynthesisParameters.fFinalPitch *= EG3.render();
531    
532              // process envelope generators                  // process low frequency oscillators
533              switch (pEG1->getSegmentType()) {                  if (bLFO1Enabled) fFinalVolume *= (1.0f - pLFO1->render());
534                  case EG::segment_lin:                  if (bLFO2Enabled) fFinalCutoff *= (1.0f - pLFO2->render());
535                      fFinalVolume *= pEG1->processLin();                  if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());
536                      break;              } else {
537                  case EG::segment_exp:                  // if the voice was killed in this subfragment, enter fade out stage
538                      fFinalVolume *= pEG1->processExp();                  if (itKillEvent && killPos <= iSubFragmentEnd) {
539                      break;                      pSignalUnitRack->EnterFadeOutStage();
540                  case EG::segment_end:                      itKillEvent = Pool<Event>::Iterator();
541                      fFinalVolume *= pEG1->getLevel();                  }
542                      break; // noop                  
543                  case EG::segment_pow:                  // if the filter EG is finished, switch EG1 to fade out stage
544                      fFinalVolume *= pEG1->processPow();                  /*if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&
545                      break;                      pEG2->getSegmentType() == EG::segment_end) {
546              }                      pEG1->enterFadeOutStage();
547              switch (pEG2->getSegmentType()) {                      itKillEvent = Pool<Event>::Iterator();
548                  case EG::segment_lin:                  }*/
549                      fFinalCutoff *= pEG2->processLin();                  // TODO: ^^^
550                      break;  
551                  case EG::segment_exp:                  fFinalVolume   *= pSignalUnitRack->GetEndpointUnit()->GetVolume();
552                      fFinalCutoff *= pEG2->processExp();                  fFinalCutoff    = pSignalUnitRack->GetEndpointUnit()->CalculateFilterCutoff(fFinalCutoff);
553                      break;                  fFinalResonance = pSignalUnitRack->GetEndpointUnit()->CalculateResonance(fFinalResonance);
554                  case EG::segment_end:                  
555                      fFinalCutoff *= pEG2->getLevel();                  finalSynthesisParameters.fFinalPitch =
556                      break; // noop                      pSignalUnitRack->GetEndpointUnit()->CalculatePitch(finalSynthesisParameters.fFinalPitch);
557                  case EG::segment_pow:                      
                     fFinalCutoff *= pEG2->processPow();  
                     break;  
558              }              }
             if (EG3.active()) finalSynthesisParameters.fFinalPitch *= EG3.render();  
559    
560              // process low frequency oscillators              fFinalCutoff    *= NoteCutoff;
561              if (bLFO1Enabled) fFinalVolume *= (1.0f - pLFO1->render());              fFinalResonance *= NoteResonance;
             if (bLFO2Enabled) fFinalCutoff *= pLFO2->render();  
             if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());  
562    
563              // limit the pitch so we don't read outside the buffer              // limit the pitch so we don't read outside the buffer
564              finalSynthesisParameters.fFinalPitch = RTMath::Min(finalSynthesisParameters.fFinalPitch, float(1 << CONFIG_MAX_PITCH));              finalSynthesisParameters.fFinalPitch = RTMath::Min(finalSynthesisParameters.fFinalPitch, float(1 << CONFIG_MAX_PITCH));
# Line 435  namespace LinuxSampler { Line 580  namespace LinuxSampler {
580              finalSynthesisParameters.uiToGo            = iSubFragmentEnd - i;              finalSynthesisParameters.uiToGo            = iSubFragmentEnd - i;
581  #ifdef CONFIG_INTERPOLATE_VOLUME  #ifdef CONFIG_INTERPOLATE_VOLUME
582              finalSynthesisParameters.fFinalVolumeDeltaLeft  =              finalSynthesisParameters.fFinalVolumeDeltaLeft  =
583                  (fFinalVolume * VolumeLeft  * PanLeftSmoother.render() -                  (fFinalVolume * VolumeLeft  * PanLeftSmoother.render() * NotePan[0].render() -
584                   finalSynthesisParameters.fFinalVolumeLeft) / finalSynthesisParameters.uiToGo;                   finalSynthesisParameters.fFinalVolumeLeft) / finalSynthesisParameters.uiToGo;
585              finalSynthesisParameters.fFinalVolumeDeltaRight =              finalSynthesisParameters.fFinalVolumeDeltaRight =
586                  (fFinalVolume * VolumeRight * PanRightSmoother.render() -                  (fFinalVolume * VolumeRight * PanRightSmoother.render() * NotePan[1].render() -
587                   finalSynthesisParameters.fFinalVolumeRight) / finalSynthesisParameters.uiToGo;                   finalSynthesisParameters.fFinalVolumeRight) / finalSynthesisParameters.uiToGo;
588  #else  #else
589              finalSynthesisParameters.fFinalVolumeLeft  =              finalSynthesisParameters.fFinalVolumeLeft  =
590                  fFinalVolume * VolumeLeft  * PanLeftSmoother.render();                  fFinalVolume * VolumeLeft  * PanLeftSmoother.render()  * NotePan[0].render();
591              finalSynthesisParameters.fFinalVolumeRight =              finalSynthesisParameters.fFinalVolumeRight =
592                  fFinalVolume * VolumeRight * PanRightSmoother.render();                  fFinalVolume * VolumeRight * PanRightSmoother.render() * NotePan[1].render();
593  #endif  #endif
594              // render audio for one subfragment              // render audio for one subfragment
595              RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);              if (!delay) RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);
596    
597              // stop the rendering if volume EG is finished              if (pSignalUnitRack == NULL) {
598              if (pEG1->getSegmentType() == EG::segment_end) break;                  // stop the rendering if volume EG is finished
599                    if (pEG1->getSegmentType() == EG::segment_end) break;
600                } else {
601                    // stop the rendering if the endpoint unit is not active
602                    if (!pSignalUnitRack->GetEndpointUnit()->Active()) break;
603                }
604    
605              const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;              const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;
606    
607              // increment envelopes' positions              if (pSignalUnitRack == NULL) {
608              if (pEG1->active()) {                  // increment envelopes' positions
609                    if (pEG1->active()) {
610    
611                        // 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
612                        if (SmplInfo.HasLoops && Pos <= SmplInfo.LoopStart && SmplInfo.LoopStart < newPos) {
613                            pEG1->update(EG::event_hold_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
614                        }
615    
616                  // 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);
617                  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);  
618                  }                  }
619                    if (pEG2->active()) {
620                  pEG1->increment(1);                      pEG2->increment(1);
621                  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);
622              }                  }
623              if (pEG2->active()) {                  EG3.increment(1);
624                  pEG2->increment(1);                  if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached
625                  if (!pEG2->toStageEndLeft()) pEG2->update(EG::event_stage_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);              } else {
626                        // 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
627                        /*if (SmplInfo.HasLoops && Pos <= SmplInfo.LoopStart && SmplInfo.LoopStart < newPos) {
628                            pEG1->update(EG::event_hold_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
629                        }*/
630                    // TODO: ^^^
631                    
632                    if (!delay) pSignalUnitRack->Increment();
633              }              }
             EG3.increment(1);  
             if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached  
634    
635              Pos = newPos;              Pos = newPos;
636              i = iSubFragmentEnd;              i = iSubFragmentEnd;
637          }          }
638            
639            if (delay) return;
640    
641          if (bVoiceRequiresDedicatedRouting) {          if (bVoiceRequiresDedicatedRouting) {
642                if (bEq) {
643                    pEq->RenderAudio(Samples);
644                    pEq->GetOutChannelLeft()->CopyTo(GetEngine()->pDedicatedVoiceChannelLeft, Samples);
645                    pEq->GetOutChannelRight()->CopyTo(GetEngine()->pDedicatedVoiceChannelRight, Samples);
646                }
647              optional<float> effectSendLevels[2] = {              optional<float> effectSendLevels[2] = {
648                  pMidiKeyInfo->ReverbSend,                  pMidiKeyInfo->ReverbSend,
649                  pMidiKeyInfo->ChorusSend                  pMidiKeyInfo->ChorusSend
650              };              };
651              GetEngine()->RouteDedicatedVoiceChannels(pEngineChannel, effectSendLevels, Samples);              GetEngine()->RouteDedicatedVoiceChannels(pEngineChannel, effectSendLevels, Samples);
652            } else if (bEq) {
653                pEq->RenderAudio(Samples);
654                pEq->GetOutChannelLeft()->MixTo(pChannel->pChannelLeft, Samples);
655                pEq->GetOutChannelRight()->MixTo(pChannel->pChannelRight, Samples);
656          }          }
657      }      }
658    
659      /**      /**
660       * Process given list of MIDI control change and pitch bend events for       * Process given list of MIDI control change, aftertouch and pitch bend
661       * the given time.       * events for the given time.
662       *       *
663       * @param itEvent - iterator pointing to the next event to be processed       * @param itEvent - iterator pointing to the next event to be processed
664       * @param End     - youngest time stamp where processing should be stopped       * @param End     - youngest time stamp where processing should be stopped
665       */       */
666      void AbstractVoice::processCCEvents(RTList<Event>::Iterator& itEvent, uint End) {      void AbstractVoice::processCCEvents(RTList<Event>::Iterator& itEvent, uint End) {
667          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
668              if (itEvent->Type == Event::type_control_change && itEvent->Param.CC.Controller) { // if (valid) MIDI control change event              if ((itEvent->Type == Event::type_control_change || itEvent->Type == Event::type_channel_pressure)
669                    && itEvent->Param.CC.Controller) // if (valid) MIDI control change event
670                {
671                  if (itEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {                  if (itEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {
672                      ProcessCutoffEvent(itEvent);                      ProcessCutoffEvent(itEvent);
673                  }                  }
674                  if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {                  if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {
675                      processResonanceEvent(itEvent);                      processResonanceEvent(itEvent);
676                  }                  }
677                  if (itEvent->Param.CC.Controller == pLFO1->ExtController) {                  if (itEvent->Param.CC.Controller == CTRL_TABLE_IDX_AFTERTOUCH ||
678                      pLFO1->update(itEvent->Param.CC.Value);                      itEvent->Type == Event::type_channel_pressure)
679                    {
680                        ProcessChannelPressureEvent(itEvent);
681                  }                  }
682                  if (itEvent->Param.CC.Controller == pLFO2->ExtController) {                  if (pSignalUnitRack == NULL) {
683                      pLFO2->update(itEvent->Param.CC.Value);                      if (itEvent->Param.CC.Controller == pLFO1->ExtController) {
684                  }                          pLFO1->updateByMIDICtrlValue(itEvent->Param.CC.Value);
685                  if (itEvent->Param.CC.Controller == pLFO3->ExtController) {                      }
686                      pLFO3->update(itEvent->Param.CC.Value);                      if (itEvent->Param.CC.Controller == pLFO2->ExtController) {
687                            pLFO2->updateByMIDICtrlValue(itEvent->Param.CC.Value);
688                        }
689                        if (itEvent->Param.CC.Controller == pLFO3->ExtController) {
690                            pLFO3->updateByMIDICtrlValue(itEvent->Param.CC.Value);
691                        }
692                  }                  }
693                  if (itEvent->Param.CC.Controller == 7) { // volume                  if (itEvent->Param.CC.Controller == 7) { // volume
694                      VolumeSmoother.update(AbstractEngine::VolumeCurve[itEvent->Param.CC.Value]);                      VolumeSmoother.update(AbstractEngine::VolumeCurve[itEvent->Param.CC.Value]);
695                  } else if (itEvent->Param.CC.Controller == 10) { // panpot                  } else if (itEvent->Param.CC.Controller == 10) { // panpot
696                      PanLeftSmoother.update(AbstractEngine::PanCurve[128 - itEvent->Param.CC.Value]);                      MIDIPan = CalculatePan(itEvent->Param.CC.Value);
                     PanRightSmoother.update(AbstractEngine::PanCurve[itEvent->Param.CC.Value]);  
697                  }                  }
698              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event
699                  processPitchEvent(itEvent);                  processPitchEvent(itEvent);
700                } else if (itEvent->Type == Event::type_note_pressure) {
701                    ProcessPolyphonicKeyPressureEvent(itEvent);
702              }              }
703    
704              ProcessCCEvent(itEvent);              ProcessCCEvent(itEvent);
705                if (pSignalUnitRack != NULL) {
706                    pSignalUnitRack->ProcessCCEvent(itEvent);
707                }
708          }          }
709      }      }
710    
# Line 539  namespace LinuxSampler { Line 723  namespace LinuxSampler {
723      }      }
724    
725      /**      /**
726       * 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
727       * for the given time.       * note synthesis parameter events for the given time.
728       *       *
729       * @param itEvent - iterator pointing to the next event to be processed       * @param itEvent - iterator pointing to the next event to be processed
730       * @param End     - youngest time stamp where processing should be stopped       * @param End     - youngest time stamp where processing should be stopped
# Line 549  namespace LinuxSampler { Line 733  namespace LinuxSampler {
733          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
734              // some voice types ignore note off              // some voice types ignore note off
735              if (!(Type & (Voice::type_one_shot | Voice::type_release_trigger | Voice::type_controller_triggered))) {              if (!(Type & (Voice::type_one_shot | Voice::type_release_trigger | Voice::type_controller_triggered))) {
736                  if (itEvent->Type == Event::type_release) {                  if (itEvent->Type == Event::type_release_key) {
737                      EnterReleaseStage();                      EnterReleaseStage();
738                  } else if (itEvent->Type == Event::type_cancel_release) {                  } else if (itEvent->Type == Event::type_cancel_release_key) {
739                      pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                      if (pSignalUnitRack == NULL) {
740                      pEG2->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                          pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
741                            pEG2->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
742                        } else {
743                            pSignalUnitRack->CancelRelease();
744                        }
745                    }
746                }
747                // process stop-note events (caused by built-in instrument script function note_off())
748                if (itEvent->Type == Event::type_release_note && pNote &&
749                    pEngineChannel->pEngine->NoteByID( itEvent->Param.Note.ID ) == pNote)
750                {
751                    EnterReleaseStage();
752                }
753                // process kill-note events (caused by built-in instrument script function fade_out())
754                if (itEvent->Type == Event::type_kill_note && pNote &&
755                    pEngineChannel->pEngine->NoteByID( itEvent->Param.Note.ID ) == pNote)
756                {
757                    Kill(itEvent);
758                }
759                // process synthesis parameter events (caused by built-in realt-time instrument script functions)
760                if (itEvent->Type == Event::type_note_synth_param && pNote &&
761                    pEngineChannel->pEngine->NoteByID( itEvent->Param.NoteSynthParam.NoteID ) == pNote)
762                {
763                    switch (itEvent->Param.NoteSynthParam.Type) {
764                        case Event::synth_param_volume:
765                            NoteVolume.fadeTo(itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
766                            break;
767                        case Event::synth_param_volume_time:
768                            NoteVolume.setDefaultDuration(itEvent->Param.NoteSynthParam.AbsValue);
769                            break;
770                        case Event::synth_param_volume_curve:
771                            NoteVolume.setCurve((fade_curve_t)itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
772                            break;
773                        case Event::synth_param_pitch:
774                            NotePitch.fadeTo(itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
775                            break;
776                        case Event::synth_param_pitch_time:
777                            NotePitch.setDefaultDuration(itEvent->Param.NoteSynthParam.AbsValue);
778                            break;
779                        case Event::synth_param_pitch_curve:
780                            NotePitch.setCurve((fade_curve_t)itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
781                            break;
782                        case Event::synth_param_pan:
783                            NotePan[0].fadeTo(
784                                AbstractEngine::PanCurveValueNorm(itEvent->Param.NoteSynthParam.AbsValue, 0 /*left*/),
785                                GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE
786                            );
787                            NotePan[1].fadeTo(
788                                AbstractEngine::PanCurveValueNorm(itEvent->Param.NoteSynthParam.AbsValue, 1 /*right*/),
789                                GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE
790                            );
791                            break;
792                        case Event::synth_param_pan_time:
793                            NotePan[0].setDefaultDuration(itEvent->Param.NoteSynthParam.AbsValue);
794                            NotePan[1].setDefaultDuration(itEvent->Param.NoteSynthParam.AbsValue);
795                            break;
796                        case Event::synth_param_pan_curve:
797                            NotePan[0].setCurve((fade_curve_t)itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
798                            NotePan[1].setCurve((fade_curve_t)itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
799                            break;
800                        case Event::synth_param_cutoff:
801                            NoteCutoff = itEvent->Param.NoteSynthParam.AbsValue;
802                            break;
803                        case Event::synth_param_resonance:
804                            NoteResonance = itEvent->Param.NoteSynthParam.AbsValue;
805                            break;
806                        case Event::synth_param_amp_lfo_depth:
807                            pLFO1->setScriptDepthFactor(itEvent->Param.NoteSynthParam.AbsValue);
808                            break;
809                        case Event::synth_param_amp_lfo_freq:
810                            pLFO1->setScriptFrequencyFactor(itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
811                            break;
812                        case Event::synth_param_pitch_lfo_depth:
813                            pLFO3->setScriptDepthFactor(itEvent->Param.NoteSynthParam.AbsValue);
814                            break;
815                        case Event::synth_param_pitch_lfo_freq:
816                            pLFO3->setScriptFrequencyFactor(itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
817                            break;
818    
819                        case Event::synth_param_attack:
820                        case Event::synth_param_decay:
821                        case Event::synth_param_sustain:
822                        case Event::synth_param_release:
823                            break; // noop
824                  }                  }
825              }              }
826          }          }
# Line 580  namespace LinuxSampler { Line 847  namespace LinuxSampler {
847       * @param itNoteOffEvent - event which causes this voice to die soon       * @param itNoteOffEvent - event which causes this voice to die soon
848       */       */
849      void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {      void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {
850          const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());          if (pSignalUnitRack == NULL) {
851          pEngineChannel->PortamentoPos = (float) MIDIKey + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;              const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());
852                pEngineChannel->PortamentoPos = (float) MIDIKey() + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;
853            } else {
854                // TODO:
855            }
856      }      }
857    
858      /**      /**
# Line 605  namespace LinuxSampler { Line 876  namespace LinuxSampler {
876    
877      Voice::PitchInfo AbstractVoice::CalculatePitchInfo(int PitchBend) {      Voice::PitchInfo AbstractVoice::CalculatePitchInfo(int PitchBend) {
878          PitchInfo pitch;          PitchInfo pitch;
879          double pitchbasecents = InstrInfo.FineTune + RgnInfo.FineTune + GetEngine()->ScaleTuning[MIDIKey % 12];          double pitchbasecents = InstrInfo.FineTune + RgnInfo.FineTune + GetEngine()->ScaleTuning[MIDIKey() % 12];
880    
881          // GSt behaviour: maximum transpose up is 40 semitones. If          // GSt behaviour: maximum transpose up is 40 semitones. If
882          // MIDI key is more than 40 semitones above unity note,          // MIDI key is more than 40 semitones above unity note,
883          // the transpose is not done.          // the transpose is not done.
884          if (!SmplInfo.Unpitched && (MIDIKey - (int) RgnInfo.UnityNote) < 40) pitchbasecents += (MIDIKey - (int) RgnInfo.UnityNote) * 100;          //
885            // Update: Removed this GSt misbehavior. I don't think that any stock
886            // gig sound requires it to resemble its original sound.
887            // -- Christian, 2017-07-09
888            if (!SmplInfo.Unpitched /* && (MIDIKey() - (int) RgnInfo.UnityNote) < 40*/)
889                pitchbasecents += (MIDIKey() - (int) RgnInfo.UnityNote) * 100;
890    
891          pitch.PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(SmplInfo.SampleRate) / double(GetEngine()->SampleRate));          pitch.PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(SmplInfo.SampleRate) / double(GetEngine()->SampleRate));
892          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 894  namespace LinuxSampler {
894    
895          return pitch;          return pitch;
896      }      }
897        
898        void AbstractVoice::onScaleTuningChanged() {
899            PitchInfo pitch = this->Pitch;
900            double pitchbasecents = InstrInfo.FineTune + RgnInfo.FineTune + GetEngine()->ScaleTuning[MIDIKey() % 12];
901            
902            // GSt behaviour: maximum transpose up is 40 semitones. If
903            // MIDI key is more than 40 semitones above unity note,
904            // the transpose is not done.
905            //
906            // Update: Removed this GSt misbehavior. I don't think that any stock
907            // gig sound requires it to resemble its original sound.
908            // -- Christian, 2017-07-09
909            if (!SmplInfo.Unpitched /* && (MIDIKey() - (int) RgnInfo.UnityNote) < 40*/)
910                pitchbasecents += (MIDIKey() - (int) RgnInfo.UnityNote) * 100;
911            
912            pitch.PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(SmplInfo.SampleRate) / double(GetEngine()->SampleRate));
913            this->Pitch = pitch;
914        }
915    
916      double AbstractVoice::CalculateVolume(double velocityAttenuation) {      double AbstractVoice::CalculateVolume(double velocityAttenuation) {
917          // 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 924  namespace LinuxSampler {
924          // the volume of release triggered samples depends on note length          // the volume of release triggered samples depends on note length
925          if (Type & Voice::type_release_trigger) {          if (Type & Voice::type_release_trigger) {
926              float noteLength = float(GetEngine()->FrameTime + Delay -              float noteLength = float(GetEngine()->FrameTime + Delay -
927                  GetNoteOnTime(MIDIKey) ) / GetEngine()->SampleRate;                  GetNoteOnTime(MIDIKey()) ) / GetEngine()->SampleRate;
928    
929              volume *= GetReleaseTriggerAttenuation(noteLength);              volume *= GetReleaseTriggerAttenuation(noteLength);
930          }          }
# Line 643  namespace LinuxSampler { Line 937  namespace LinuxSampler {
937      }      }
938    
939      void AbstractVoice::EnterReleaseStage() {      void AbstractVoice::EnterReleaseStage() {
940          pEG1->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);          if (pSignalUnitRack == NULL) {
941          pEG2->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);              pEG1->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
942                pEG2->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
943            } else {
944                pSignalUnitRack->EnterReleaseStage();
945            }
946        }
947    
948        bool AbstractVoice::EG1Finished() {
949            if (pSignalUnitRack == NULL) {
950                return pEG1->getSegmentType() == EG::segment_end;
951            } else {
952                return !pSignalUnitRack->GetEndpointUnit()->Active();
953            }
954      }      }
955    
956  } // namespace LinuxSampler  } // namespace LinuxSampler

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

  ViewVC Help
Powered by ViewVC