/[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 2114 by persson, Tue Aug 10 12:05:19 2010 UTC revision 3564 by schoenebeck, Sat Aug 24 09:18:57 2019 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;
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)
# 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());
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);          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.Value : 1.f);
156            NoteVolume.setDefaultDuration(pNote ? pNote->Override.VolumeTime : DEFAULT_NOTE_VOLUME_TIME_S);
157            NoteVolume.setFinal(pNote ? pNote->Override.Volume.Final : false);
158    
159          // 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
160          long cachedsamples = GetSampleCacheSize() / SmplInfo.FrameSize;          long cachedsamples = GetSampleCacheSize() / SmplInfo.FrameSize;
161          DiskVoice          = cachedsamples < SmplInfo.TotalFrameCount;          DiskVoice          = cachedsamples < SmplInfo.TotalFrameCount;
162    
163            SetSampleStartOffset();
164    
165          if (DiskVoice) { // voice to be streamed from disk          if (DiskVoice) { // voice to be streamed from disk
166              if (cachedsamples > (GetEngine()->MaxSamplesPerCycle << CONFIG_MAX_PITCH)) {              if (cachedsamples > (GetEngine()->MaxSamplesPerCycle << CONFIG_MAX_PITCH)) {
167                  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 178  namespace LinuxSampler {
178              RAMLoop = (SmplInfo.HasLoops && (SmplInfo.LoopStart + SmplInfo.LoopLength) <= MaxRAMPos);              RAMLoop = (SmplInfo.HasLoops && (SmplInfo.LoopStart + SmplInfo.LoopLength) <= MaxRAMPos);
179    
180              if (OrderNewStream()) return -1;              if (OrderNewStream()) return -1;
181              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"));
182          }          }
183          else { // RAM only voice          else { // RAM only voice
184              MaxRAMPos = cachedsamples;              MaxRAMPos = cachedsamples;
# Line 171  namespace LinuxSampler { Line 194  namespace LinuxSampler {
194          }          }
195    
196          Pitch = CalculatePitchInfo(PitchBend);          Pitch = CalculatePitchInfo(PitchBend);
197            NotePitch.setCurveOnly(pNote ? pNote->Override.PitchCurve : DEFAULT_FADE_CURVE);
198            NotePitch.setCurrentValue(pNote ? pNote->Override.Pitch.Value : 1.0f);
199            NotePitch.setFinal(pNote ? pNote->Override.Pitch.Final : false);
200            NotePitch.setDefaultDuration(pNote ? pNote->Override.PitchTime : DEFAULT_NOTE_PITCH_TIME_S);
201            NoteCutoff.Value = (pNote) ? pNote->Override.Cutoff.Value : 1.0f;
202            NoteCutoff.Final = (pNote) ? pNote->Override.Cutoff.isFinal() : false;
203            NoteResonance.Value = (pNote) ? pNote->Override.Resonance.Value : 1.0f;
204            NoteResonance.Final = (pNote) ? pNote->Override.Resonance.Final : false;
205    
206          // 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
207          const double velrelease = 1 / GetVelocityRelease(itNoteOnEvent->Param.Note.Velocity);          const double velrelease = 1 / GetVelocityRelease(MIDIVelocity());
208    
209          // setup EG 1 (VCA EG)          if (pSignalUnitRack == NULL) { // setup EG 1 (VCA EG)
         {  
210              // get current value of EG1 controller              // get current value of EG1 controller
211              double eg1controllervalue = GetEG1ControllerValue(itNoteOnEvent->Param.Note.Velocity);              double eg1controllervalue = GetEG1ControllerValue(MIDIVelocity());
212    
213              // calculate influence of EG1 controller on EG1's parameters              // calculate influence of EG1 controller on EG1's parameters
214              EGInfo egInfo = CalculateEG1ControllerInfluence(eg1controllervalue);              EGInfo egInfo = CalculateEG1ControllerInfluence(eg1controllervalue);
215    
216              TriggerEG1(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity);              if (pNote) {
217                    pNote->Override.Attack.applyTo(egInfo.Attack);
218                    pNote->Override.Decay.applyTo(egInfo.Decay);
219                    pNote->Override.Release.applyTo(egInfo.Release);
220                }
221    
222                TriggerEG1(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, MIDIVelocity());
223            } else {
224                pSignalUnitRack->Trigger();
225          }          }
226    
227            const uint8_t pan = (pSignalUnitRack) ? pSignalUnitRack->GetEndpointUnit()->CalculatePan(MIDIPan) : MIDIPan;
228            for (int c = 0; c < 2; ++c) {
229                float value = (pNote) ? AbstractEngine::PanCurveValueNorm(pNote->Override.Pan.Value, c) : 1.f;
230                NotePan[c].setCurveOnly(pNote ? pNote->Override.PanCurve : DEFAULT_FADE_CURVE);
231                NotePan[c].setCurrentValue(value);
232                NotePan[c].setFinal(pNote ? pNote->Override.Pan.Final : false);
233                NotePan[c].setDefaultDuration(pNote ? pNote->Override.PanTime : DEFAULT_NOTE_PAN_TIME_S);
234            }
235    
236            PanLeftSmoother.trigger(
237                AbstractEngine::PanCurve[128 - pan],
238                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)
239            );
240            PanRightSmoother.trigger(
241                AbstractEngine::PanCurve[pan],
242                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)
243            );
244    
245  #ifdef CONFIG_INTERPOLATE_VOLUME  #ifdef CONFIG_INTERPOLATE_VOLUME
246          // setup initial volume in synthesis parameters          // setup initial volume in synthesis parameters
247      #ifdef CONFIG_PROCESS_MUTED_CHANNELS      #ifdef CONFIG_PROCESS_MUTED_CHANNELS
# Line 196  namespace LinuxSampler { Line 252  namespace LinuxSampler {
252          else          else
253      #else      #else
254          {          {
255              float finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pEG1->getLevel();              float finalVolume = pEngineChannel->MidiVolume * crossfadeVolume;
256                float fModVolume;
257                if (pSignalUnitRack == NULL) {
258                    fModVolume = pEG1->getLevel();
259                } else {
260                    fModVolume = pSignalUnitRack->GetEndpointUnit()->GetVolume();
261                }
262                NoteVolume.applyCurrentValueTo(fModVolume);
263                finalVolume *= fModVolume;
264    
265                float panL = PanLeftSmoother.render();
266                float panR = PanRightSmoother.render();
267                NotePan[0].applyCurrentValueTo(panL);
268                NotePan[1].applyCurrentValueTo(panR);
269    
270              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * pEngineChannel->GlobalPanLeft;              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * panL;
271              finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * pEngineChannel->GlobalPanRight;              finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * panR;
272          }          }
273      #endif      #endif
274  #endif  #endif
275    
276          // setup EG 2 (VCF Cutoff EG)          if (pSignalUnitRack == NULL) {
277          {              // setup EG 2 (VCF Cutoff EG)
278              // get current value of EG2 controller              {
279              double eg2controllervalue = GetEG2ControllerValue(itNoteOnEvent->Param.Note.Velocity);                  // get current value of EG2 controller
280                    double eg2controllervalue = GetEG2ControllerValue(MIDIVelocity());
281              // calculate influence of EG2 controller on EG2's parameters  
282              EGInfo egInfo = CalculateEG2ControllerInfluence(eg2controllervalue);                  // calculate influence of EG2 controller on EG2's parameters
283                    EGInfo egInfo = CalculateEG2ControllerInfluence(eg2controllervalue);
284    
285                    if (pNote) {
286                        pNote->Override.CutoffAttack.applyTo(egInfo.Attack);
287                        pNote->Override.CutoffDecay.applyTo(egInfo.Decay);
288                        pNote->Override.CutoffRelease.applyTo(egInfo.Release);
289                    }
290    
291              EG2.trigger (                  TriggerEG2(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, MIDIVelocity());
292                  uint(RgnInfo.EG2PreAttack),              }
                 RgnInfo.EG2Attack * egInfo.Attack,  
                 false,  
                 RgnInfo.EG2Decay1 * egInfo.Decay * velrelease,  
                 RgnInfo.EG2Decay2 * egInfo.Decay * velrelease,  
                 RgnInfo.EG2InfiniteSustain,  
                 uint(RgnInfo.EG2Sustain),  
                 RgnInfo.EG2Release * egInfo.Release * velrelease,  
                 velocityAttenuation,  
                 GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE  
             );  
         }  
293    
294    
295          // setup EG 3 (VCO EG)              // setup EG 3 (VCO EG)
296          {              {
297              // if portamento mode is on, we dedicate EG3 purely for portamento, otherwise if portamento is off we do as told by the patch                  // if portamento mode is on, we dedicate EG3 purely for portamento, otherwise if portamento is off we do as told by the patch
298              bool  bPortamento = pEngineChannel->PortamentoMode && pEngineChannel->PortamentoPos >= 0.0f;                  bool  bPortamento = pEngineChannel->PortamentoMode && pEngineChannel->PortamentoPos >= 0.0f;
299              float eg3depth = (bPortamento)                  float eg3depth = (bPortamento)
300                           ? RTMath::CentsToFreqRatio((pEngineChannel->PortamentoPos - (float) MIDIKey) * 100)                               ? RTMath::CentsToFreqRatio((pEngineChannel->PortamentoPos - (float) MIDIKey()) * 100)
301                           : RTMath::CentsToFreqRatio(RgnInfo.EG3Depth);                               : RTMath::CentsToFreqRatio(RgnInfo.EG3Depth);
302              float eg3time = (bPortamento)                  float eg3time = (bPortamento)
303                          ? pEngineChannel->PortamentoTime                              ? pEngineChannel->PortamentoTime
304                          : RgnInfo.EG3Attack;                              : RgnInfo.EG3Attack;
305              EG3.trigger(eg3depth, eg3time, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  EG3.trigger(eg3depth, eg3time, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
306              dmsg(5,("PortamentoPos=%f, depth=%f, time=%f\n", pEngineChannel->PortamentoPos, eg3depth, eg3time));                  dmsg(5,("PortamentoPos=%f, depth=%f, time=%f\n", pEngineChannel->PortamentoPos, eg3depth, eg3time));
307          }              }
308    
309    
310          // setup LFO 1 (VCA LFO)              // setup LFO 1 (VCA LFO)
311          InitLFO1();              InitLFO1();
312          // setup LFO 2 (VCF Cutoff LFO)              // setup LFO 2 (VCF Cutoff LFO)
313          InitLFO2();              InitLFO2();
314          // setup LFO 3 (VCO LFO)              // setup LFO 3 (VCO LFO)
315          InitLFO3();              InitLFO3();
316            }
317    
318    
319          #if CONFIG_FORCE_FILTER          #if CONFIG_FORCE_FILTER
# Line 281  namespace LinuxSampler { Line 347  namespace LinuxSampler {
347              VCFResonanceCtrl.value = pEngineChannel->ControllerTable[VCFResonanceCtrl.controller];              VCFResonanceCtrl.value = pEngineChannel->ControllerTable[VCFResonanceCtrl.controller];
348    
349              // calculate cutoff frequency              // calculate cutoff frequency
350              CutoffBase = CalculateCutoffBase(itNoteOnEvent->Param.Note.Velocity);              CutoffBase = CalculateCutoffBase(MIDIVelocity());
351    
352              VCFCutoffCtrl.fvalue = CalculateFinalCutoff(CutoffBase);              VCFCutoffCtrl.fvalue = CalculateFinalCutoff(CutoffBase);
353    
# Line 292  namespace LinuxSampler { Line 358  namespace LinuxSampler {
358              VCFCutoffCtrl.controller    = 0;              VCFCutoffCtrl.controller    = 0;
359              VCFResonanceCtrl.controller = 0;              VCFResonanceCtrl.controller = 0;
360          }          }
361            
362            const bool bEq =
363                pSignalUnitRack != NULL && pSignalUnitRack->HasEq() && pEq->HasSupport();
364    
365            if (bEq) {
366                pEq->GetInChannelLeft()->Clear();
367                pEq->GetInChannelRight()->Clear();
368                pEq->RenderAudio(GetEngine()->pAudioOutputDevice->MaxSamplesPerCycle());
369            }
370    
371          return 0; // success          return 0; // success
372      }      }
373        
374        void AbstractVoice::SetSampleStartOffset() {
375            double pos = RgnInfo.SampleStartOffset; // offset where we should start playback of sample
376    
377            // if another sample playback start position was requested by instrument
378            // script (built-in script function play_note())
379            if (pNote && pNote->Override.SampleOffset >= 0) {
380                double overridePos =
381                    double(SmplInfo.SampleRate) * double(pNote->Override.SampleOffset) / 1000000.0;
382                if (overridePos < SmplInfo.TotalFrameCount)
383                    pos = overridePos;
384            }
385    
386            finalSynthesisParameters.dPos = pos;
387            Pos = pos;
388        }
389    
390      /**      /**
391       *  Synthesizes the current audio fragment for this voice.       *  Synthesizes the current audio fragment for this voice.
# Line 305  namespace LinuxSampler { Line 396  namespace LinuxSampler {
396       *  @param Skip    - number of sample points to skip in output buffer       *  @param Skip    - number of sample points to skip in output buffer
397       */       */
398      void AbstractVoice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {      void AbstractVoice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {
399            bool delay = false; // Whether the voice playback should be delayed for this call
400            
401            if (pSignalUnitRack != NULL) {
402                uint delaySteps = pSignalUnitRack->GetEndpointUnit()->DelayTrigger();
403                if (delaySteps > 0) { // delay on the endpoint unit means delay of the voice playback
404                    if (delaySteps >= Samples) {
405                        pSignalUnitRack->GetEndpointUnit()->DecreaseDelay(Samples);
406                        delay = true;
407                    } else {
408                        pSignalUnitRack->GetEndpointUnit()->DecreaseDelay(delaySteps);
409                        Samples -= delaySteps;
410                        Skip += delaySteps;
411                    }
412                }
413            }
414            
415          AbstractEngineChannel* pChannel = pEngineChannel;          AbstractEngineChannel* pChannel = pEngineChannel;
416          finalSynthesisParameters.pOutLeft  = &pChannel->pChannelLeft->Buffer()[Skip];          MidiKeyBase* pMidiKeyInfo = GetMidiKeyInfo(MIDIKey());
417          finalSynthesisParameters.pOutRight = &pChannel->pChannelRight->Buffer()[Skip];  
418          finalSynthesisParameters.pSrc      = pSrc;          const bool bVoiceRequiresDedicatedRouting =
419                pEngineChannel->GetFxSendCount() > 0 &&
420                (pMidiKeyInfo->ReverbSend || pMidiKeyInfo->ChorusSend);
421            
422            const bool bEq =
423                pSignalUnitRack != NULL && pSignalUnitRack->HasEq() && pEq->HasSupport();
424    
425            if (bEq) {
426                pEq->GetInChannelLeft()->Clear();
427                pEq->GetInChannelRight()->Clear();
428                finalSynthesisParameters.pOutLeft  = &pEq->GetInChannelLeft()->Buffer()[Skip];
429                finalSynthesisParameters.pOutRight = &pEq->GetInChannelRight()->Buffer()[Skip];
430                pSignalUnitRack->UpdateEqSettings(pEq);
431            } else if (bVoiceRequiresDedicatedRouting) {
432                finalSynthesisParameters.pOutLeft  = &GetEngine()->pDedicatedVoiceChannelLeft->Buffer()[Skip];
433                finalSynthesisParameters.pOutRight = &GetEngine()->pDedicatedVoiceChannelRight->Buffer()[Skip];
434            } else {
435                finalSynthesisParameters.pOutLeft  = &pChannel->pChannelLeft->Buffer()[Skip];
436                finalSynthesisParameters.pOutRight = &pChannel->pChannelRight->Buffer()[Skip];
437            }
438            finalSynthesisParameters.pSrc = pSrc;
439    
440          RTList<Event>::Iterator itCCEvent = pChannel->pEvents->first();          RTList<Event>::Iterator itCCEvent = pChannel->pEvents->first();
441          RTList<Event>::Iterator itNoteEvent;          RTList<Event>::Iterator itNoteEvent;
442          GetFirstEventOnKey(MIDIKey, itNoteEvent);          GetFirstEventOnKey(HostKey(), itNoteEvent);
443    
444          RTList<Event>::Iterator itGroupEvent;          RTList<Event>::Iterator itGroupEvent;
445          if (pGroupEvents) itGroupEvent = pGroupEvents->first();          if (pGroupEvents && !Orphan) itGroupEvent = pGroupEvents->first();
446    
447          if (itTriggerEvent) { // skip events that happened before this voice was triggered          if (itTriggerEvent) { // skip events that happened before this voice was triggered
448              while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;              while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;
# Line 332  namespace LinuxSampler { Line 459  namespace LinuxSampler {
459              }              }
460          }          }
461    
462          uint killPos;          uint killPos = 0;
463          if (itKillEvent) {          if (itKillEvent) {
464              int maxFadeOutPos = Samples - GetEngine()->GetMinFadeOutSamples();              int maxFadeOutPos = Samples - GetEngine()->GetMinFadeOutSamples();
465              if (maxFadeOutPos < 0) {              if (maxFadeOutPos < 0) {
# Line 341  namespace LinuxSampler { Line 468  namespace LinuxSampler {
468                  // drivers that use Samples < MaxSamplesPerCycle).                  // drivers that use Samples < MaxSamplesPerCycle).
469                  // End the EG1 here, at pos 0, with a shorter max fade                  // End the EG1 here, at pos 0, with a shorter max fade
470                  // out time.                  // out time.
471                  pEG1->enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  if (pSignalUnitRack == NULL) {
472                        pEG1->enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
473                    } else {
474                        pSignalUnitRack->EnterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
475                    }
476                  itKillEvent = Pool<Event>::Iterator();                  itKillEvent = Pool<Event>::Iterator();
477              } else {              } else {
478                  killPos = RTMath::Min(itKillEvent->FragmentPos(), maxFadeOutPos);                  killPos = RTMath::Min(itKillEvent->FragmentPos(), maxFadeOutPos);
# Line 356  namespace LinuxSampler { Line 487  namespace LinuxSampler {
487              fFinalCutoff    = VCFCutoffCtrl.fvalue;              fFinalCutoff    = VCFCutoffCtrl.fvalue;
488              fFinalResonance = VCFResonanceCtrl.fvalue;              fFinalResonance = VCFResonanceCtrl.fvalue;
489    
490              // process MIDI control change and pitchbend events for this subfragment              // process MIDI control change, aftertouch and pitchbend events for this subfragment
491              processCCEvents(itCCEvent, iSubFragmentEnd);              processCCEvents(itCCEvent, iSubFragmentEnd);
492                uint8_t pan = MIDIPan;
493                if (pSignalUnitRack != NULL) pan = pSignalUnitRack->GetEndpointUnit()->CalculatePan(MIDIPan);
494    
495                PanLeftSmoother.update(AbstractEngine::PanCurve[128 - pan]);
496                PanRightSmoother.update(AbstractEngine::PanCurve[pan]);
497    
498              finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend;              finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend;
499    
500              float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render();              float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render();
501  #ifdef CONFIG_PROCESS_MUTED_CHANNELS  #ifdef CONFIG_PROCESS_MUTED_CHANNELS
502              if (pChannel->GetMute()) fFinalVolume = 0;              if (pChannel->GetMute()) fFinalVolume = 0;
# Line 369  namespace LinuxSampler { Line 506  namespace LinuxSampler {
506              processTransitionEvents(itNoteEvent, iSubFragmentEnd);              processTransitionEvents(itNoteEvent, iSubFragmentEnd);
507              processGroupEvents(itGroupEvent, iSubFragmentEnd);              processGroupEvents(itGroupEvent, iSubFragmentEnd);
508    
509              // if the voice was killed in this subfragment, or if the              float fModVolume = 1;
510              // filter EG is finished, switch EG1 to fade out stage              float fModPitch  = 1;
             if ((itKillEvent && killPos <= iSubFragmentEnd) ||  
                 (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&  
                  EG2.getSegmentType() == gig::EGADSR::segment_end)) {  
                 pEG1->enterFadeOutStage();  
                 itKillEvent = Pool<Event>::Iterator();  
             }  
511    
512              // process envelope generators              if (pSignalUnitRack == NULL) {
513              switch (pEG1->getSegmentType()) {                  // if the voice was killed in this subfragment, or if the
514                  case EG::segment_lin:                  // filter EG is finished, switch EG1 to fade out stage
515                      fFinalVolume *= pEG1->processLin();                  if ((itKillEvent && killPos <= iSubFragmentEnd) ||
516                      break;                      (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&
517                  case EG::segment_exp:                      pEG2->getSegmentType() == EG::segment_end)) {
518                      fFinalVolume *= pEG1->processExp();                      pEG1->enterFadeOutStage();
519                      break;                      itKillEvent = Pool<Event>::Iterator();
520                  case EG::segment_end:                  }
521                      fFinalVolume *= pEG1->getLevel();  
522                      break; // noop                  // process envelope generators
523                  case EG::segment_pow:                  switch (pEG1->getSegmentType()) {
524                      fFinalVolume *= pEG1->processPow();                      case EG::segment_lin:
525                      break;                          fModVolume *= pEG1->processLin();
526              }                          break;
527              switch (EG2.getSegmentType()) {                      case EG::segment_exp:
528                  case gig::EGADSR::segment_lin:                          fModVolume *= pEG1->processExp();
529                      fFinalCutoff *= EG2.processLin();                          break;
530                      break;                      case EG::segment_end:
531                  case gig::EGADSR::segment_exp:                          fModVolume *= pEG1->getLevel();
532                      fFinalCutoff *= EG2.processExp();                          break; // noop
533                      break;                      case EG::segment_pow:
534                  case gig::EGADSR::segment_end:                          fModVolume *= pEG1->processPow();
535                      fFinalCutoff *= EG2.getLevel();                          break;
536                      break; // noop                  }
537              }                  switch (pEG2->getSegmentType()) {
538              if (EG3.active()) finalSynthesisParameters.fFinalPitch *= EG3.render();                      case EG::segment_lin:
539                            fFinalCutoff *= pEG2->processLin();
540              // process low frequency oscillators                          break;
541              if (bLFO1Enabled) fFinalVolume *= (1.0f - pLFO1->render());                      case EG::segment_exp:
542              if (bLFO2Enabled) fFinalCutoff *= pLFO2->render();                          fFinalCutoff *= pEG2->processExp();
543              if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());                          break;
544                        case EG::segment_end:
545                            fFinalCutoff *= pEG2->getLevel();
546                            break; // noop
547                        case EG::segment_pow:
548                            fFinalCutoff *= pEG2->processPow();
549                            break;
550                    }
551                    if (EG3.active()) fModPitch *= EG3.render();
552    
553                    // process low frequency oscillators
554                    if (bLFO1Enabled) fModVolume   *= (1.0f - pLFO1->render());
555                    if (bLFO2Enabled) fFinalCutoff *= (1.0f - pLFO2->render());
556                    if (bLFO3Enabled) fModPitch *= RTMath::CentsToFreqRatio(pLFO3->render());
557                } else {
558                    // if the voice was killed in this subfragment, enter fade out stage
559                    if (itKillEvent && killPos <= iSubFragmentEnd) {
560                        pSignalUnitRack->EnterFadeOutStage();
561                        itKillEvent = Pool<Event>::Iterator();
562                    }
563                    
564                    // if the filter EG is finished, switch EG1 to fade out stage
565                    /*if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&
566                        pEG2->getSegmentType() == EG::segment_end) {
567                        pEG1->enterFadeOutStage();
568                        itKillEvent = Pool<Event>::Iterator();
569                    }*/
570                    // TODO: ^^^
571    
572                    fFinalVolume   *= pSignalUnitRack->GetEndpointUnit()->GetVolume();
573                    fFinalCutoff    = pSignalUnitRack->GetEndpointUnit()->CalculateFilterCutoff(fFinalCutoff);
574                    fFinalResonance = pSignalUnitRack->GetEndpointUnit()->CalculateResonance(fFinalResonance);
575                    
576                    fModPitch = pSignalUnitRack->GetEndpointUnit()->CalculatePitch(fModPitch);
577                }
578    
579                NoteVolume.renderApplyTo(fModVolume);
580                NotePitch.renderApplyTo(fModPitch);
581                NoteCutoff.applyTo(fFinalCutoff);
582                NoteResonance.applyTo(fFinalResonance);
583    
584                fFinalVolume *= fModVolume;
585    
586                finalSynthesisParameters.fFinalPitch *= fModPitch;
587    
588              // limit the pitch so we don't read outside the buffer              // limit the pitch so we don't read outside the buffer
589              finalSynthesisParameters.fFinalPitch = RTMath::Min(finalSynthesisParameters.fFinalPitch, float(1 << CONFIG_MAX_PITCH));              finalSynthesisParameters.fFinalPitch = RTMath::Min(finalSynthesisParameters.fFinalPitch, float(1 << CONFIG_MAX_PITCH));
# Line 429  namespace LinuxSampler { Line 603  namespace LinuxSampler {
603    
604              // prepare final synthesis parameters structure              // prepare final synthesis parameters structure
605              finalSynthesisParameters.uiToGo            = iSubFragmentEnd - i;              finalSynthesisParameters.uiToGo            = iSubFragmentEnd - i;
606    
607                float panL = PanLeftSmoother.render();
608                float panR = PanRightSmoother.render();
609                NotePan[0].renderApplyTo(panL);
610                NotePan[1].renderApplyTo(panR);
611    
612  #ifdef CONFIG_INTERPOLATE_VOLUME  #ifdef CONFIG_INTERPOLATE_VOLUME
613              finalSynthesisParameters.fFinalVolumeDeltaLeft  =              finalSynthesisParameters.fFinalVolumeDeltaLeft  =
614                  (fFinalVolume * VolumeLeft  * PanLeftSmoother.render() -                  (fFinalVolume * VolumeLeft  * panL -
615                   finalSynthesisParameters.fFinalVolumeLeft) / finalSynthesisParameters.uiToGo;                   finalSynthesisParameters.fFinalVolumeLeft) / finalSynthesisParameters.uiToGo;
616              finalSynthesisParameters.fFinalVolumeDeltaRight =              finalSynthesisParameters.fFinalVolumeDeltaRight =
617                  (fFinalVolume * VolumeRight * PanRightSmoother.render() -                  (fFinalVolume * VolumeRight * panR -
618                   finalSynthesisParameters.fFinalVolumeRight) / finalSynthesisParameters.uiToGo;                   finalSynthesisParameters.fFinalVolumeRight) / finalSynthesisParameters.uiToGo;
619  #else  #else
620              finalSynthesisParameters.fFinalVolumeLeft  =              finalSynthesisParameters.fFinalVolumeLeft  =
621                  fFinalVolume * VolumeLeft  * PanLeftSmoother.render();                  fFinalVolume * VolumeLeft  * panL;
622              finalSynthesisParameters.fFinalVolumeRight =              finalSynthesisParameters.fFinalVolumeRight =
623                  fFinalVolume * VolumeRight * PanRightSmoother.render();                  fFinalVolume * VolumeRight * panR;
624  #endif  #endif
625              // render audio for one subfragment              // render audio for one subfragment
626              RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);              if (!delay) RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);
627    
628              // stop the rendering if volume EG is finished              if (pSignalUnitRack == NULL) {
629              if (pEG1->getSegmentType() == EG::segment_end) break;                  // stop the rendering if volume EG is finished
630                    if (pEG1->getSegmentType() == EG::segment_end) break;
631                } else {
632                    // stop the rendering if the endpoint unit is not active
633                    if (!pSignalUnitRack->GetEndpointUnit()->Active()) break;
634                }
635    
636              const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;              const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;
637    
638              // increment envelopes' positions              if (pSignalUnitRack == NULL) {
639              if (pEG1->active()) {                  // increment envelopes' positions
640                    if (pEG1->active()) {
641    
642                        // 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
643                        if (SmplInfo.HasLoops && Pos <= SmplInfo.LoopStart && SmplInfo.LoopStart < newPos) {
644                            pEG1->update(EG::event_hold_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
645                        }
646    
647                  // 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);
648                  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);  
649                  }                  }
650                    if (pEG2->active()) {
651                  pEG1->increment(1);                      pEG2->increment(1);
652                  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);
653              }                  }
654              if (EG2.active()) {                  EG3.increment(1);
655                  EG2.increment(1);                  if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached
656                  if (!EG2.toStageEndLeft()) EG2.update(gig::EGADSR::event_stage_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);              } else {
657                        // 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
658                        /*if (SmplInfo.HasLoops && Pos <= SmplInfo.LoopStart && SmplInfo.LoopStart < newPos) {
659                            pEG1->update(EG::event_hold_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
660                        }*/
661                    // TODO: ^^^
662                    
663                    if (!delay) pSignalUnitRack->Increment();
664              }              }
             EG3.increment(1);  
             if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached  
665    
666              Pos = newPos;              Pos = newPos;
667              i = iSubFragmentEnd;              i = iSubFragmentEnd;
668          }          }
669            
670            if (delay) return;
671    
672            if (bVoiceRequiresDedicatedRouting) {
673                if (bEq) {
674                    pEq->RenderAudio(Samples);
675                    pEq->GetOutChannelLeft()->CopyTo(GetEngine()->pDedicatedVoiceChannelLeft, Samples);
676                    pEq->GetOutChannelRight()->CopyTo(GetEngine()->pDedicatedVoiceChannelRight, Samples);
677                }
678                optional<float> effectSendLevels[2] = {
679                    pMidiKeyInfo->ReverbSend,
680                    pMidiKeyInfo->ChorusSend
681                };
682                GetEngine()->RouteDedicatedVoiceChannels(pEngineChannel, effectSendLevels, Samples);
683            } else if (bEq) {
684                pEq->RenderAudio(Samples);
685                pEq->GetOutChannelLeft()->MixTo(pChannel->pChannelLeft, Samples);
686                pEq->GetOutChannelRight()->MixTo(pChannel->pChannelRight, Samples);
687            }
688      }      }
689    
690      /**      /**
691       * Process given list of MIDI control change and pitch bend events for       * Process given list of MIDI control change, aftertouch and pitch bend
692       * the given time.       * events for the given time.
693       *       *
694       * @param itEvent - iterator pointing to the next event to be processed       * @param itEvent - iterator pointing to the next event to be processed
695       * @param End     - youngest time stamp where processing should be stopped       * @param End     - youngest time stamp where processing should be stopped
696       */       */
697      void AbstractVoice::processCCEvents(RTList<Event>::Iterator& itEvent, uint End) {      void AbstractVoice::processCCEvents(RTList<Event>::Iterator& itEvent, uint End) {
698          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
699              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)
700                    && itEvent->Param.CC.Controller) // if (valid) MIDI control change event
701                {
702                  if (itEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {                  if (itEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {
703                      ProcessCutoffEvent(itEvent);                      ProcessCutoffEvent(itEvent);
704                  }                  }
705                  if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {                  if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {
706                      processResonanceEvent(itEvent);                      processResonanceEvent(itEvent);
707                  }                  }
708                  if (itEvent->Param.CC.Controller == pLFO1->ExtController) {                  if (itEvent->Param.CC.Controller == CTRL_TABLE_IDX_AFTERTOUCH ||
709                      pLFO1->update(itEvent->Param.CC.Value);                      itEvent->Type == Event::type_channel_pressure)
710                  }                  {
711                  if (itEvent->Param.CC.Controller == pLFO2->ExtController) {                      ProcessChannelPressureEvent(itEvent);
                     pLFO2->update(itEvent->Param.CC.Value);  
712                  }                  }
713                  if (itEvent->Param.CC.Controller == pLFO3->ExtController) {                  if (pSignalUnitRack == NULL) {
714                      pLFO3->update(itEvent->Param.CC.Value);                      if (itEvent->Param.CC.Controller == pLFO1->ExtController) {
715                            pLFO1->updateByMIDICtrlValue(itEvent->Param.CC.Value);
716                        }
717                        if (itEvent->Param.CC.Controller == pLFO2->ExtController) {
718                            pLFO2->updateByMIDICtrlValue(itEvent->Param.CC.Value);
719                        }
720                        if (itEvent->Param.CC.Controller == pLFO3->ExtController) {
721                            pLFO3->updateByMIDICtrlValue(itEvent->Param.CC.Value);
722                        }
723                  }                  }
724                  if (itEvent->Param.CC.Controller == 7) { // volume                  if (itEvent->Param.CC.Controller == 7) { // volume
725                      VolumeSmoother.update(AbstractEngine::VolumeCurve[itEvent->Param.CC.Value]);                      VolumeSmoother.update(AbstractEngine::VolumeCurve[itEvent->Param.CC.Value]);
726                  } else if (itEvent->Param.CC.Controller == 10) { // panpot                  } else if (itEvent->Param.CC.Controller == 10) { // panpot
727                      PanLeftSmoother.update(AbstractEngine::PanCurve[128 - itEvent->Param.CC.Value]);                      MIDIPan = CalculatePan(itEvent->Param.CC.Value);
                     PanRightSmoother.update(AbstractEngine::PanCurve[itEvent->Param.CC.Value]);  
728                  }                  }
729              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event
730                  processPitchEvent(itEvent);                  processPitchEvent(itEvent);
731                } else if (itEvent->Type == Event::type_note_pressure) {
732                    ProcessPolyphonicKeyPressureEvent(itEvent);
733              }              }
734    
735              ProcessCCEvent(itEvent);              ProcessCCEvent(itEvent);
736                if (pSignalUnitRack != NULL) {
737                    pSignalUnitRack->ProcessCCEvent(itEvent);
738                }
739          }          }
740      }      }
741    
# Line 527  namespace LinuxSampler { Line 754  namespace LinuxSampler {
754      }      }
755    
756      /**      /**
757       * 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
758       * for the given time.       * note synthesis parameter events for the given time.
759       *       *
760       * @param itEvent - iterator pointing to the next event to be processed       * @param itEvent - iterator pointing to the next event to be processed
761       * @param End     - youngest time stamp where processing should be stopped       * @param End     - youngest time stamp where processing should be stopped
762       */       */
763      void AbstractVoice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) {      void AbstractVoice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) {
764          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
765              if (Type != Voice::type_release_trigger) {              // some voice types ignore note off
766                if (!(Type & (Voice::type_one_shot | Voice::type_release_trigger | Voice::type_controller_triggered))) {
767                  if (itEvent->Type == Event::type_release) {                  if (itEvent->Type == Event::type_release_key) {
768                      EnterReleaseStage();                      EnterReleaseStage();
769                  } else if (itEvent->Type == Event::type_cancel_release) {                  } else if (itEvent->Type == Event::type_cancel_release_key) {
770                      pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                      if (pSignalUnitRack == NULL) {
771                      EG2.update(gig::EGADSR::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                          pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
772                            pEG2->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
773                        } else {
774                            pSignalUnitRack->CancelRelease();
775                        }
776                    }
777                }
778                // process stop-note events (caused by built-in instrument script function note_off())
779                if (itEvent->Type == Event::type_release_note && pNote &&
780                    pEngineChannel->pEngine->NoteByID( itEvent->Param.Note.ID ) == pNote)
781                {
782                    EnterReleaseStage();
783                }
784                // process kill-note events (caused by built-in instrument script function fade_out())
785                if (itEvent->Type == Event::type_kill_note && pNote &&
786                    pEngineChannel->pEngine->NoteByID( itEvent->Param.Note.ID ) == pNote)
787                {
788                    Kill(itEvent);
789                }
790                // process synthesis parameter events (caused by built-in realt-time instrument script functions)
791                if (itEvent->Type == Event::type_note_synth_param && pNote &&
792                    pEngineChannel->pEngine->NoteByID( itEvent->Param.NoteSynthParam.NoteID ) == pNote)
793                {
794                    switch (itEvent->Param.NoteSynthParam.Type) {
795                        case Event::synth_param_volume:
796                            NoteVolume.fadeTo(itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
797                            NoteVolume.setFinal(itEvent->Param.NoteSynthParam.isFinal());
798                            break;
799                        case Event::synth_param_volume_time:
800                            NoteVolume.setDefaultDuration(itEvent->Param.NoteSynthParam.AbsValue);
801                            break;
802                        case Event::synth_param_volume_curve:
803                            NoteVolume.setCurve((fade_curve_t)itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
804                            break;
805                        case Event::synth_param_pitch:
806                            NotePitch.fadeTo(itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
807                            NotePitch.setFinal(itEvent->Param.NoteSynthParam.isFinal());
808                            break;
809                        case Event::synth_param_pitch_time:
810                            NotePitch.setDefaultDuration(itEvent->Param.NoteSynthParam.AbsValue);
811                            break;
812                        case Event::synth_param_pitch_curve:
813                            NotePitch.setCurve((fade_curve_t)itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
814                            break;
815                        case Event::synth_param_pan:
816                            NotePan[0].fadeTo(
817                                AbstractEngine::PanCurveValueNorm(itEvent->Param.NoteSynthParam.AbsValue, 0 /*left*/),
818                                GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE
819                            );
820                            NotePan[1].fadeTo(
821                                AbstractEngine::PanCurveValueNorm(itEvent->Param.NoteSynthParam.AbsValue, 1 /*right*/),
822                                GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE
823                            );
824                            NotePan[0].setFinal(itEvent->Param.NoteSynthParam.isFinal());
825                            NotePan[1].setFinal(itEvent->Param.NoteSynthParam.isFinal());
826                            break;
827                        case Event::synth_param_pan_time:
828                            NotePan[0].setDefaultDuration(itEvent->Param.NoteSynthParam.AbsValue);
829                            NotePan[1].setDefaultDuration(itEvent->Param.NoteSynthParam.AbsValue);
830                            break;
831                        case Event::synth_param_pan_curve:
832                            NotePan[0].setCurve((fade_curve_t)itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
833                            NotePan[1].setCurve((fade_curve_t)itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
834                            break;
835                        case Event::synth_param_cutoff:
836                            NoteCutoff.Value = itEvent->Param.NoteSynthParam.AbsValue;
837                            NoteCutoff.Final = itEvent->Param.NoteSynthParam.isFinal();
838                            break;
839                        case Event::synth_param_resonance:
840                            NoteResonance.Value = itEvent->Param.NoteSynthParam.AbsValue;
841                            NoteResonance.Final = itEvent->Param.NoteSynthParam.isFinal();
842                            break;
843                        case Event::synth_param_amp_lfo_depth:
844                            pLFO1->setScriptDepthFactor(
845                                itEvent->Param.NoteSynthParam.AbsValue,
846                                itEvent->Param.NoteSynthParam.isFinal()
847                            );
848                            break;
849                        case Event::synth_param_amp_lfo_freq:
850                            if (itEvent->Param.NoteSynthParam.isFinal())
851                                pLFO1->setScriptFrequencyFinal(itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
852                            else
853                                pLFO1->setScriptFrequencyFactor(itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
854                            break;
855                        case Event::synth_param_cutoff_lfo_depth:
856                            pLFO2->setScriptDepthFactor(
857                                itEvent->Param.NoteSynthParam.AbsValue,
858                                itEvent->Param.NoteSynthParam.isFinal()
859                            );
860                            break;
861                        case Event::synth_param_cutoff_lfo_freq:
862                            if (itEvent->Param.NoteSynthParam.isFinal())
863                                pLFO2->setScriptFrequencyFinal(itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
864                            else
865                                pLFO2->setScriptFrequencyFactor(itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
866                            break;
867                        case Event::synth_param_pitch_lfo_depth:
868                            pLFO3->setScriptDepthFactor(
869                                itEvent->Param.NoteSynthParam.AbsValue,
870                                itEvent->Param.NoteSynthParam.isFinal()
871                            );
872                            break;
873                        case Event::synth_param_pitch_lfo_freq:
874                            pLFO3->setScriptFrequencyFactor(itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
875                            break;
876    
877                        case Event::synth_param_attack:
878                        case Event::synth_param_decay:
879                        case Event::synth_param_sustain:
880                        case Event::synth_param_release:
881                            break; // noop
882                  }                  }
883              }              }
884          }          }
# Line 568  namespace LinuxSampler { Line 905  namespace LinuxSampler {
905       * @param itNoteOffEvent - event which causes this voice to die soon       * @param itNoteOffEvent - event which causes this voice to die soon
906       */       */
907      void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {      void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {
908          const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());          if (pSignalUnitRack == NULL) {
909          pEngineChannel->PortamentoPos = (float) MIDIKey + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;              const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());
910                pEngineChannel->PortamentoPos = (float) MIDIKey() + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;
911            } else {
912                // TODO:
913            }
914      }      }
915    
916      /**      /**
# Line 593  namespace LinuxSampler { Line 934  namespace LinuxSampler {
934    
935      Voice::PitchInfo AbstractVoice::CalculatePitchInfo(int PitchBend) {      Voice::PitchInfo AbstractVoice::CalculatePitchInfo(int PitchBend) {
936          PitchInfo pitch;          PitchInfo pitch;
937          double pitchbasecents = InstrInfo.FineTune + RgnInfo.FineTune + GetEngine()->ScaleTuning[MIDIKey % 12];          double pitchbasecents = InstrInfo.FineTune + RgnInfo.FineTune + GetEngine()->ScaleTuning[MIDIKey() % 12];
938    
939          // GSt behaviour: maximum transpose up is 40 semitones. If          // GSt behaviour: maximum transpose up is 40 semitones. If
940          // MIDI key is more than 40 semitones above unity note,          // MIDI key is more than 40 semitones above unity note,
941          // the transpose is not done.          // the transpose is not done.
942          if (!SmplInfo.Unpitched && (MIDIKey - (int) RgnInfo.UnityNote) < 40) pitchbasecents += (MIDIKey - (int) RgnInfo.UnityNote) * 100;          //
943            // Update: Removed this GSt misbehavior. I don't think that any stock
944            // gig sound requires it to resemble its original sound.
945            // -- Christian, 2017-07-09
946            if (!SmplInfo.Unpitched /* && (MIDIKey() - (int) RgnInfo.UnityNote) < 40*/)
947                pitchbasecents += (MIDIKey() - (int) RgnInfo.UnityNote) * 100;
948    
949          pitch.PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(SmplInfo.SampleRate) / double(GetEngine()->SampleRate));          pitch.PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(SmplInfo.SampleRate) / double(GetEngine()->SampleRate));
950          pitch.PitchBendRange = 1.0 / 8192.0 * 100.0 * InstrInfo.PitchbendRange;          pitch.PitchBendRange = 1.0 / 8192.0 * 100.0 * InstrInfo.PitchbendRange;
# Line 606  namespace LinuxSampler { Line 952  namespace LinuxSampler {
952    
953          return pitch;          return pitch;
954      }      }
955        
956        void AbstractVoice::onScaleTuningChanged() {
957            PitchInfo pitch = this->Pitch;
958            double pitchbasecents = InstrInfo.FineTune + RgnInfo.FineTune + GetEngine()->ScaleTuning[MIDIKey() % 12];
959            
960            // GSt behaviour: maximum transpose up is 40 semitones. If
961            // MIDI key is more than 40 semitones above unity note,
962            // the transpose is not done.
963            //
964            // Update: Removed this GSt misbehavior. I don't think that any stock
965            // gig sound requires it to resemble its original sound.
966            // -- Christian, 2017-07-09
967            if (!SmplInfo.Unpitched /* && (MIDIKey() - (int) RgnInfo.UnityNote) < 40*/)
968                pitchbasecents += (MIDIKey() - (int) RgnInfo.UnityNote) * 100;
969            
970            pitch.PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(SmplInfo.SampleRate) / double(GetEngine()->SampleRate));
971            this->Pitch = pitch;
972        }
973    
974      double AbstractVoice::CalculateVolume(double velocityAttenuation) {      double AbstractVoice::CalculateVolume(double velocityAttenuation) {
975          // For 16 bit samples, we downscale by 32768 to convert from          // For 16 bit samples, we downscale by 32768 to convert from
# Line 616  namespace LinuxSampler { Line 980  namespace LinuxSampler {
980          volume *= GetSampleAttenuation() * pEngineChannel->GlobalVolume * GLOBAL_VOLUME;          volume *= GetSampleAttenuation() * pEngineChannel->GlobalVolume * GLOBAL_VOLUME;
981    
982          // the volume of release triggered samples depends on note length          // the volume of release triggered samples depends on note length
983          if (Type == Voice::type_release_trigger) {          if (Type & Voice::type_release_trigger) {
984              float noteLength = float(GetEngine()->FrameTime + Delay -              float noteLength = float(GetEngine()->FrameTime + Delay -
985                  GetNoteOnTime(MIDIKey) ) / GetEngine()->SampleRate;                  GetNoteOnTime(MIDIKey()) ) / GetEngine()->SampleRate;
986    
987              volume *= GetReleaseTriggerAttenuation(noteLength);              volume *= GetReleaseTriggerAttenuation(noteLength);
988          }          }
# Line 631  namespace LinuxSampler { Line 995  namespace LinuxSampler {
995      }      }
996    
997      void AbstractVoice::EnterReleaseStage() {      void AbstractVoice::EnterReleaseStage() {
998          pEG1->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);          if (pSignalUnitRack == NULL) {
999          EG2.update(gig::EGADSR::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);              pEG1->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
1000                pEG2->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
1001            } else {
1002                pSignalUnitRack->EnterReleaseStage();
1003            }
1004        }
1005    
1006        bool AbstractVoice::EG1Finished() {
1007            if (pSignalUnitRack == NULL) {
1008                return pEG1->getSegmentType() == EG::segment_end;
1009            } else {
1010                return !pSignalUnitRack->GetEndpointUnit()->Active();
1011            }
1012      }      }
1013    
1014  } // namespace LinuxSampler  } // namespace LinuxSampler

Legend:
Removed from v.2114  
changed lines
  Added in v.3564

  ViewVC Help
Powered by ViewVC