/[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 2061 by persson, Tue Feb 23 18:32:31 2010 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-2010 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 EG (0..1 range)          pLFO1 = new LFOUnsigned(1.0f);  // amplitude LFO (0..1 range)
33          pLFO2 = new LFOUnsigned(1.0f);  // filter EG (0..1 range)          pLFO2 = new LFOUnsigned(1.0f);  // filter LFO (0..1 range)
34          pLFO3 = new LFOSigned(1200.0f); // pitch EG (-1200..+1200 range)          pLFO3 = new LFOSigned(1200.0f); // pitch LFO (-1200..+1200 range)
35          PlaybackState = playback_state_end;          PlaybackState = playback_state_end;
         KeyGroup = 0;  
36          SynthesisMode = 0; // set all mode bits to 0 first          SynthesisMode = 0; // set all mode bits to 0 first
37          // select synthesis implementation (asm core is not supported ATM)          // select synthesis implementation (asm core is not supported ATM)
38          #if 0 // CONFIG_ASM && ARCH_X86          #if 0 // CONFIG_ASM && ARCH_X86
# Line 44  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 99  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          KeyGroup        = iKeyGroup;          MidiKeyBase* pKeyInfo = GetMidiKeyInfo(MIDIKey());
120    
121            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);          float volume = CalculateVolume(velocityAttenuation) * pKeyInfo->Volume;
134          if (volume <= 0) return -1;          if (volume <= 0) return -1;
135    
136          // select channel mode (mono or stereo)          // select channel mode (mono or stereo)
# Line 121  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 * AbstractEngine::PanCurve[64 - RgnInfo.Pan];          VolumeLeft  = volume * pKeyInfo->PanLeft;
145          VolumeRight = volume * 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 155  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 171  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 196  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              EG2.trigger (              // setup EG 3 (VCO EG)
278                  uint(RgnInfo.EG2PreAttack),              {
279                  RgnInfo.EG2Attack * egInfo.Attack,                  // if portamento mode is on, we dedicate EG3 purely for portamento, otherwise if portamento is off we do as told by the patch
280                  false,                  bool  bPortamento = pEngineChannel->PortamentoMode && pEngineChannel->PortamentoPos >= 0.0f;
281                  RgnInfo.EG2Decay1 * egInfo.Decay * velrelease,                  float eg3depth = (bPortamento)
282                  RgnInfo.EG2Decay2 * egInfo.Decay * velrelease,                               ? RTMath::CentsToFreqRatio((pEngineChannel->PortamentoPos - (float) MIDIKey()) * 100)
283                  RgnInfo.EG2InfiniteSustain,                               : RTMath::CentsToFreqRatio(RgnInfo.EG3Depth);
284                  uint(RgnInfo.EG2Sustain),                  float eg3time = (bPortamento)
285                  RgnInfo.EG2Release * egInfo.Release * velrelease,                              ? pEngineChannel->PortamentoTime
286                  velocityAttenuation,                              : RgnInfo.EG3Attack;
287                  GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE                  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 281  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 292  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 305  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          finalSynthesisParameters.pOutLeft  = &pChannel->pChannelLeft->Buffer()[Skip];          MidiKeyBase* pMidiKeyInfo = GetMidiKeyInfo(MIDIKey());
399          finalSynthesisParameters.pOutRight = &pChannel->pChannelRight->Buffer()[Skip];  
400          finalSynthesisParameters.pSrc      = pSrc;          const bool bVoiceRequiresDedicatedRouting =
401                pEngineChannel->GetFxSendCount() > 0 &&
402                (pMidiKeyInfo->ReverbSend || pMidiKeyInfo->ChorusSend);
403            
404            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];
415                finalSynthesisParameters.pOutRight = &GetEngine()->pDedicatedVoiceChannelRight->Buffer()[Skip];
416            } else {
417                finalSynthesisParameters.pOutLeft  = &pChannel->pChannelLeft->Buffer()[Skip];
418                finalSynthesisParameters.pOutRight = &pChannel->pChannelRight->Buffer()[Skip];
419            }
420            finalSynthesisParameters.pSrc = pSrc;
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;
427            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;
431                while (itGroupEvent && itGroupEvent->FragmentPos() <= Skip) ++itGroupEvent;
432    
433              // we can't simply compare the timestamp here, because note events              // we can't simply compare the timestamp here, because note events
434              // might happen on the same time stamp, so we have to deal on the              // might happen on the same time stamp, so we have to deal on the
435              // actual sequence the note events arrived instead (see bug #112)              // actual sequence the note events arrived instead (see bug #112)
# Line 327  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 336  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 351  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              finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend;              PanLeftSmoother.update(AbstractEngine::PanCurve[128 - pan]);
478              float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render();              PanRightSmoother.update(AbstractEngine::PanCurve[pan]);
479    
480                finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend * NotePitch.render();
481    
482                float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render() * NoteVolume.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
486    
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);
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                   EG2.getSegmentType() == gig::EGADSR::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                        itKillEvent = Pool<Event>::Iterator();
548                    }*/
549                    // TODO: ^^^
550    
551                    fFinalVolume   *= pSignalUnitRack->GetEndpointUnit()->GetVolume();
552                    fFinalCutoff    = pSignalUnitRack->GetEndpointUnit()->CalculateFilterCutoff(fFinalCutoff);
553                    fFinalResonance = pSignalUnitRack->GetEndpointUnit()->CalculateResonance(fFinalResonance);
554                    
555                    finalSynthesisParameters.fFinalPitch =
556                        pSignalUnitRack->GetEndpointUnit()->CalculatePitch(finalSynthesisParameters.fFinalPitch);
557                        
558              }              }
559              switch (EG2.getSegmentType()) {  
560                  case gig::EGADSR::segment_lin:              fFinalCutoff    *= NoteCutoff;
561                      fFinalCutoff *= EG2.processLin();              fFinalResonance *= NoteResonance;
                     break;  
                 case gig::EGADSR::segment_exp:  
                     fFinalCutoff *= EG2.processExp();  
                     break;  
                 case gig::EGADSR::segment_end:  
                     fFinalCutoff *= EG2.getLevel();  
                     break; // noop  
             }  
             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());  
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 425  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 (EG2.active()) {                  EG3.increment(1);
624                  EG2.increment(1);                  if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached
625                  if (!EG2.toStageEndLeft()) EG2.update(gig::EGADSR::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) {
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] = {
648                    pMidiKeyInfo->ReverbSend,
649                    pMidiKeyInfo->ChorusSend
650                };
651                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                  if (itEvent->Param.CC.Controller == pLFO2->ExtController) {                      ProcessChannelPressureEvent(itEvent);
                     pLFO2->update(itEvent->Param.CC.Value);  
681                  }                  }
682                  if (itEvent->Param.CC.Controller == pLFO3->ExtController) {                  if (pSignalUnitRack == NULL) {
683                      pLFO3->update(itEvent->Param.CC.Value);                      if (itEvent->Param.CC.Controller == pLFO1->ExtController) {
684                            pLFO1->updateByMIDICtrlValue(itEvent->Param.CC.Value);
685                        }
686                        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 521  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
731       */       */
732      void AbstractVoice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) {      void AbstractVoice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) {
733          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
734              if (itEvent->Type == Event::type_release) {              // some voice types ignore note off
735                  pEG1->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);              if (!(Type & (Voice::type_one_shot | Voice::type_release_trigger | Voice::type_controller_triggered))) {
736                  EG2.update(gig::EGADSR::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  if (itEvent->Type == Event::type_release_key) {
737              } else if (itEvent->Type == Event::type_cancel_release) {                      EnterReleaseStage();
738                  pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  } else if (itEvent->Type == Event::type_cancel_release_key) {
739                  EG2.update(gig::EGADSR::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                      if (pSignalUnitRack == NULL) {
740                            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          }          }
827      }      }
828    
829        /**
830         * Process given list of events aimed at all voices in a key group.
831         *
832         * @param itEvent - iterator pointing to the next event to be processed
833         * @param End     - youngest time stamp where processing should be stopped
834         */
835        void AbstractVoice::processGroupEvents(RTList<Event>::Iterator& itEvent, uint End) {
836            for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
837                ProcessGroupEvent(itEvent);
838            }
839        }
840    
841      /** @brief Update current portamento position.      /** @brief Update current portamento position.
842       *       *
843       * Will be called when portamento mode is enabled to get the final       * Will be called when portamento mode is enabled to get the final
# Line 548  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 573  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 586  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 596  namespace LinuxSampler { Line 922  namespace LinuxSampler {
922          volume *= GetSampleAttenuation() * pEngineChannel->GlobalVolume * GLOBAL_VOLUME;          volume *= GetSampleAttenuation() * pEngineChannel->GlobalVolume * GLOBAL_VOLUME;
923    
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 609  namespace LinuxSampler { Line 935  namespace LinuxSampler {
935      float AbstractVoice::GetReleaseTriggerAttenuation(float noteLength) {      float AbstractVoice::GetReleaseTriggerAttenuation(float noteLength) {
936          return 1 - RgnInfo.ReleaseTriggerDecay * noteLength;          return 1 - RgnInfo.ReleaseTriggerDecay * noteLength;
937      }      }
938    
939        void AbstractVoice::EnterReleaseStage() {
940            if (pSignalUnitRack == NULL) {
941                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.2061  
changed lines
  Added in v.3335

  ViewVC Help
Powered by ViewVC