/[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 3302 by schoenebeck, Sun Jul 9 19:35:18 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;
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 : 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            NotePanLeft  = (pNote) ? AbstractEngine::PanCurveValueNorm(pNote->Override.Pan, 0 /*left*/ ) : 1.f;
225            NotePanRight = (pNote) ? AbstractEngine::PanCurveValueNorm(pNote->Override.Pan, 1 /*right*/) : 1.f;
226            PanLeftSmoother.trigger(
227                AbstractEngine::PanCurve[128 - pan] * NotePanLeft,
228                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)
229            );
230            PanRightSmoother.trigger(
231                AbstractEngine::PanCurve[pan] * NotePanRight,
232                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)
233            );
234    
235  #ifdef CONFIG_INTERPOLATE_VOLUME  #ifdef CONFIG_INTERPOLATE_VOLUME
236          // setup initial volume in synthesis parameters          // setup initial volume in synthesis parameters
237      #ifdef CONFIG_PROCESS_MUTED_CHANNELS      #ifdef CONFIG_PROCESS_MUTED_CHANNELS
# Line 196  namespace LinuxSampler { Line 242  namespace LinuxSampler {
242          else          else
243      #else      #else
244          {          {
245              float finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pEG1->getLevel();              float finalVolume;
246                if (pSignalUnitRack == NULL) {
247                    finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pEG1->getLevel();
248                } else {
249                    finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pSignalUnitRack->GetEndpointUnit()->GetVolume();
250                }
251    
252              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * pEngineChannel->GlobalPanLeft;              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * PanLeftSmoother.render();
253              finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * pEngineChannel->GlobalPanRight;              finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * PanRightSmoother.render();
254          }          }
255      #endif      #endif
256  #endif  #endif
257    
258          // setup EG 2 (VCF Cutoff EG)          if (pSignalUnitRack == NULL) {
259          {              // setup EG 2 (VCF Cutoff EG)
260              // get current value of EG2 controller              {
261              double eg2controllervalue = GetEG2ControllerValue(itNoteOnEvent->Param.Note.Velocity);                  // get current value of EG2 controller
262                    double eg2controllervalue = GetEG2ControllerValue(MIDIVelocity());
263    
264                    // calculate influence of EG2 controller on EG2's parameters
265                    EGInfo egInfo = CalculateEG2ControllerInfluence(eg2controllervalue);
266    
267                    TriggerEG2(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, MIDIVelocity());
268                }
269    
             // calculate influence of EG2 controller on EG2's parameters  
             EGInfo egInfo = CalculateEG2ControllerInfluence(eg2controllervalue);  
270    
271              EG2.trigger (              // setup EG 3 (VCO EG)
272                  uint(RgnInfo.EG2PreAttack),              {
273                  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
274                  false,                  bool  bPortamento = pEngineChannel->PortamentoMode && pEngineChannel->PortamentoPos >= 0.0f;
275                  RgnInfo.EG2Decay1 * egInfo.Decay * velrelease,                  float eg3depth = (bPortamento)
276                  RgnInfo.EG2Decay2 * egInfo.Decay * velrelease,                               ? RTMath::CentsToFreqRatio((pEngineChannel->PortamentoPos - (float) MIDIKey()) * 100)
277                  RgnInfo.EG2InfiniteSustain,                               : RTMath::CentsToFreqRatio(RgnInfo.EG3Depth);
278                  uint(RgnInfo.EG2Sustain),                  float eg3time = (bPortamento)
279                  RgnInfo.EG2Release * egInfo.Release * velrelease,                              ? pEngineChannel->PortamentoTime
280                  velocityAttenuation,                              : RgnInfo.EG3Attack;
281                  GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE                  EG3.trigger(eg3depth, eg3time, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
282              );                  dmsg(5,("PortamentoPos=%f, depth=%f, time=%f\n", pEngineChannel->PortamentoPos, eg3depth, eg3time));
283          }              }
284    
285    
286          // setup EG 3 (VCO EG)              // setup LFO 1 (VCA LFO)
287          {              InitLFO1();
288              // 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)
289              bool  bPortamento = pEngineChannel->PortamentoMode && pEngineChannel->PortamentoPos >= 0.0f;              InitLFO2();
290              float eg3depth = (bPortamento)              // setup LFO 3 (VCO LFO)
291                           ? 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));  
292          }          }
293    
294    
         // setup LFO 1 (VCA LFO)  
         InitLFO1();  
         // setup LFO 2 (VCF Cutoff LFO)  
         InitLFO2();  
         // setup LFO 3 (VCO LFO)  
         InitLFO3();  
   
   
295          #if CONFIG_FORCE_FILTER          #if CONFIG_FORCE_FILTER
296          const bool bUseFilter = true;          const bool bUseFilter = true;
297          #else // use filter only if instrument file told so          #else // use filter only if instrument file told so
# Line 281  namespace LinuxSampler { Line 323  namespace LinuxSampler {
323              VCFResonanceCtrl.value = pEngineChannel->ControllerTable[VCFResonanceCtrl.controller];              VCFResonanceCtrl.value = pEngineChannel->ControllerTable[VCFResonanceCtrl.controller];
324    
325              // calculate cutoff frequency              // calculate cutoff frequency
326              CutoffBase = CalculateCutoffBase(itNoteOnEvent->Param.Note.Velocity);              CutoffBase = CalculateCutoffBase(MIDIVelocity());
327    
328              VCFCutoffCtrl.fvalue = CalculateFinalCutoff(CutoffBase);              VCFCutoffCtrl.fvalue = CalculateFinalCutoff(CutoffBase);
329    
# Line 292  namespace LinuxSampler { Line 334  namespace LinuxSampler {
334              VCFCutoffCtrl.controller    = 0;              VCFCutoffCtrl.controller    = 0;
335              VCFResonanceCtrl.controller = 0;              VCFResonanceCtrl.controller = 0;
336          }          }
337            
338            const bool bEq =
339                pSignalUnitRack != NULL && pSignalUnitRack->HasEq() && pEq->HasSupport();
340    
341            if (bEq) {
342                pEq->GetInChannelLeft()->Clear();
343                pEq->GetInChannelRight()->Clear();
344                pEq->RenderAudio(GetEngine()->pAudioOutputDevice->MaxSamplesPerCycle());
345            }
346    
347          return 0; // success          return 0; // success
348      }      }
349        
350        void AbstractVoice::SetSampleStartOffset() {
351            double pos = RgnInfo.SampleStartOffset; // offset where we should start playback of sample
352    
353            // if another sample playback start position was requested by instrument
354            // script (built-in script function play_note())
355            if (pNote && pNote->Override.SampleOffset >= 0) {
356                double overridePos =
357                    double(SmplInfo.SampleRate) * double(pNote->Override.SampleOffset) / 1000000.0;
358                if (overridePos < SmplInfo.TotalFrameCount)
359                    pos = overridePos;
360            }
361    
362            finalSynthesisParameters.dPos = pos;
363            Pos = pos;
364        }
365    
366      /**      /**
367       *  Synthesizes the current audio fragment for this voice.       *  Synthesizes the current audio fragment for this voice.
# Line 305  namespace LinuxSampler { Line 372  namespace LinuxSampler {
372       *  @param Skip    - number of sample points to skip in output buffer       *  @param Skip    - number of sample points to skip in output buffer
373       */       */
374      void AbstractVoice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {      void AbstractVoice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {
375            bool delay = false; // Whether the voice playback should be delayed for this call
376            
377            if (pSignalUnitRack != NULL) {
378                uint delaySteps = pSignalUnitRack->GetEndpointUnit()->DelayTrigger();
379                if (delaySteps > 0) { // delay on the endpoint unit means delay of the voice playback
380                    if (delaySteps >= Samples) {
381                        pSignalUnitRack->GetEndpointUnit()->DecreaseDelay(Samples);
382                        delay = true;
383                    } else {
384                        pSignalUnitRack->GetEndpointUnit()->DecreaseDelay(delaySteps);
385                        Samples -= delaySteps;
386                        Skip += delaySteps;
387                    }
388                }
389            }
390            
391          AbstractEngineChannel* pChannel = pEngineChannel;          AbstractEngineChannel* pChannel = pEngineChannel;
392          finalSynthesisParameters.pOutLeft  = &pChannel->pChannelLeft->Buffer()[Skip];          MidiKeyBase* pMidiKeyInfo = GetMidiKeyInfo(MIDIKey());
393          finalSynthesisParameters.pOutRight = &pChannel->pChannelRight->Buffer()[Skip];  
394          finalSynthesisParameters.pSrc      = pSrc;          const bool bVoiceRequiresDedicatedRouting =
395                pEngineChannel->GetFxSendCount() > 0 &&
396                (pMidiKeyInfo->ReverbSend || pMidiKeyInfo->ChorusSend);
397            
398            const bool bEq =
399                pSignalUnitRack != NULL && pSignalUnitRack->HasEq() && pEq->HasSupport();
400    
401            if (bEq) {
402                pEq->GetInChannelLeft()->Clear();
403                pEq->GetInChannelRight()->Clear();
404                finalSynthesisParameters.pOutLeft  = &pEq->GetInChannelLeft()->Buffer()[Skip];
405                finalSynthesisParameters.pOutRight = &pEq->GetInChannelRight()->Buffer()[Skip];
406                pSignalUnitRack->UpdateEqSettings(pEq);
407            } else if (bVoiceRequiresDedicatedRouting) {
408                finalSynthesisParameters.pOutLeft  = &GetEngine()->pDedicatedVoiceChannelLeft->Buffer()[Skip];
409                finalSynthesisParameters.pOutRight = &GetEngine()->pDedicatedVoiceChannelRight->Buffer()[Skip];
410            } else {
411                finalSynthesisParameters.pOutLeft  = &pChannel->pChannelLeft->Buffer()[Skip];
412                finalSynthesisParameters.pOutRight = &pChannel->pChannelRight->Buffer()[Skip];
413            }
414            finalSynthesisParameters.pSrc = pSrc;
415    
416          RTList<Event>::Iterator itCCEvent = pChannel->pEvents->first();          RTList<Event>::Iterator itCCEvent = pChannel->pEvents->first();
417          RTList<Event>::Iterator itNoteEvent;          RTList<Event>::Iterator itNoteEvent;
418          GetFirstEventOnKey(MIDIKey, itNoteEvent);          GetFirstEventOnKey(HostKey(), itNoteEvent);
419    
420          RTList<Event>::Iterator itGroupEvent;          RTList<Event>::Iterator itGroupEvent;
421          if (pGroupEvents) itGroupEvent = pGroupEvents->first();          if (pGroupEvents && !Orphan) itGroupEvent = pGroupEvents->first();
422    
423          if (itTriggerEvent) { // skip events that happened before this voice was triggered          if (itTriggerEvent) { // skip events that happened before this voice was triggered
424              while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;              while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;
# Line 332  namespace LinuxSampler { Line 435  namespace LinuxSampler {
435              }              }
436          }          }
437    
438          uint killPos;          uint killPos = 0;
439          if (itKillEvent) {          if (itKillEvent) {
440              int maxFadeOutPos = Samples - GetEngine()->GetMinFadeOutSamples();              int maxFadeOutPos = Samples - GetEngine()->GetMinFadeOutSamples();
441              if (maxFadeOutPos < 0) {              if (maxFadeOutPos < 0) {
# Line 341  namespace LinuxSampler { Line 444  namespace LinuxSampler {
444                  // drivers that use Samples < MaxSamplesPerCycle).                  // drivers that use Samples < MaxSamplesPerCycle).
445                  // End the EG1 here, at pos 0, with a shorter max fade                  // End the EG1 here, at pos 0, with a shorter max fade
446                  // out time.                  // out time.
447                  pEG1->enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  if (pSignalUnitRack == NULL) {
448                        pEG1->enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
449                    } else {
450                        pSignalUnitRack->EnterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
451                    }
452                  itKillEvent = Pool<Event>::Iterator();                  itKillEvent = Pool<Event>::Iterator();
453              } else {              } else {
454                  killPos = RTMath::Min(itKillEvent->FragmentPos(), maxFadeOutPos);                  killPos = RTMath::Min(itKillEvent->FragmentPos(), maxFadeOutPos);
# Line 356  namespace LinuxSampler { Line 463  namespace LinuxSampler {
463              fFinalCutoff    = VCFCutoffCtrl.fvalue;              fFinalCutoff    = VCFCutoffCtrl.fvalue;
464              fFinalResonance = VCFResonanceCtrl.fvalue;              fFinalResonance = VCFResonanceCtrl.fvalue;
465    
466              // process MIDI control change and pitchbend events for this subfragment              // process MIDI control change, aftertouch and pitchbend events for this subfragment
467              processCCEvents(itCCEvent, iSubFragmentEnd);              processCCEvents(itCCEvent, iSubFragmentEnd);
468                uint8_t pan = MIDIPan;
469                if (pSignalUnitRack != NULL) pan = pSignalUnitRack->GetEndpointUnit()->CalculatePan(MIDIPan);
470    
471                PanLeftSmoother.update(AbstractEngine::PanCurve[128 - pan] * NotePanLeft);
472                PanRightSmoother.update(AbstractEngine::PanCurve[pan]      * NotePanRight);
473    
474                finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend * NotePitch.render();
475    
476              finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend;              float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render() * NoteVolume.render();
             float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render();  
477  #ifdef CONFIG_PROCESS_MUTED_CHANNELS  #ifdef CONFIG_PROCESS_MUTED_CHANNELS
478              if (pChannel->GetMute()) fFinalVolume = 0;              if (pChannel->GetMute()) fFinalVolume = 0;
479  #endif  #endif
# Line 368  namespace LinuxSampler { Line 481  namespace LinuxSampler {
481              // process transition events (note on, note off & sustain pedal)              // process transition events (note on, note off & sustain pedal)
482              processTransitionEvents(itNoteEvent, iSubFragmentEnd);              processTransitionEvents(itNoteEvent, iSubFragmentEnd);
483              processGroupEvents(itGroupEvent, iSubFragmentEnd);              processGroupEvents(itGroupEvent, iSubFragmentEnd);
484                
485                if (pSignalUnitRack == NULL) {
486                    // if the voice was killed in this subfragment, or if the
487                    // filter EG is finished, switch EG1 to fade out stage
488                    if ((itKillEvent && killPos <= iSubFragmentEnd) ||
489                        (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&
490                        pEG2->getSegmentType() == EG::segment_end)) {
491                        pEG1->enterFadeOutStage();
492                        itKillEvent = Pool<Event>::Iterator();
493                    }
494    
495              // if the voice was killed in this subfragment, or if the                  // process envelope generators
496              // filter EG is finished, switch EG1 to fade out stage                  switch (pEG1->getSegmentType()) {
497              if ((itKillEvent && killPos <= iSubFragmentEnd) ||                      case EG::segment_lin:
498                  (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&                          fFinalVolume *= pEG1->processLin();
499                   EG2.getSegmentType() == gig::EGADSR::segment_end)) {                          break;
500                  pEG1->enterFadeOutStage();                      case EG::segment_exp:
501                  itKillEvent = Pool<Event>::Iterator();                          fFinalVolume *= pEG1->processExp();
502              }                          break;
503                        case EG::segment_end:
504                            fFinalVolume *= pEG1->getLevel();
505                            break; // noop
506                        case EG::segment_pow:
507                            fFinalVolume *= pEG1->processPow();
508                            break;
509                    }
510                    switch (pEG2->getSegmentType()) {
511                        case EG::segment_lin:
512                            fFinalCutoff *= pEG2->processLin();
513                            break;
514                        case EG::segment_exp:
515                            fFinalCutoff *= pEG2->processExp();
516                            break;
517                        case EG::segment_end:
518                            fFinalCutoff *= pEG2->getLevel();
519                            break; // noop
520                        case EG::segment_pow:
521                            fFinalCutoff *= pEG2->processPow();
522                            break;
523                    }
524                    if (EG3.active()) finalSynthesisParameters.fFinalPitch *= EG3.render();
525    
526              // process envelope generators                  // process low frequency oscillators
527              switch (pEG1->getSegmentType()) {                  if (bLFO1Enabled) fFinalVolume *= (1.0f - pLFO1->render());
528                  case EG::segment_lin:                  if (bLFO2Enabled) fFinalCutoff *= (1.0f - pLFO2->render());
529                      fFinalVolume *= pEG1->processLin();                  if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());
530                      break;              } else {
531                  case EG::segment_exp:                  // if the voice was killed in this subfragment, enter fade out stage
532                      fFinalVolume *= pEG1->processExp();                  if (itKillEvent && killPos <= iSubFragmentEnd) {
533                      break;                      pSignalUnitRack->EnterFadeOutStage();
534                  case EG::segment_end:                      itKillEvent = Pool<Event>::Iterator();
535                      fFinalVolume *= pEG1->getLevel();                  }
536                      break; // noop                  
537                  case EG::segment_pow:                  // if the filter EG is finished, switch EG1 to fade out stage
538                      fFinalVolume *= pEG1->processPow();                  /*if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&
539                      break;                      pEG2->getSegmentType() == EG::segment_end) {
540                        pEG1->enterFadeOutStage();
541                        itKillEvent = Pool<Event>::Iterator();
542                    }*/
543                    // TODO: ^^^
544    
545                    fFinalVolume   *= pSignalUnitRack->GetEndpointUnit()->GetVolume();
546                    fFinalCutoff    = pSignalUnitRack->GetEndpointUnit()->CalculateFilterCutoff(fFinalCutoff);
547                    fFinalResonance = pSignalUnitRack->GetEndpointUnit()->CalculateResonance(fFinalResonance);
548                    
549                    finalSynthesisParameters.fFinalPitch =
550                        pSignalUnitRack->GetEndpointUnit()->CalculatePitch(finalSynthesisParameters.fFinalPitch);
551                        
552              }              }
553              switch (EG2.getSegmentType()) {  
554                  case gig::EGADSR::segment_lin:              fFinalCutoff    *= NoteCutoff;
555                      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());  
556    
557              // limit the pitch so we don't read outside the buffer              // limit the pitch so we don't read outside the buffer
558              finalSynthesisParameters.fFinalPitch = RTMath::Min(finalSynthesisParameters.fFinalPitch, float(1 << CONFIG_MAX_PITCH));              finalSynthesisParameters.fFinalPitch = RTMath::Min(finalSynthesisParameters.fFinalPitch, float(1 << CONFIG_MAX_PITCH));
# Line 443  namespace LinuxSampler { Line 586  namespace LinuxSampler {
586                  fFinalVolume * VolumeRight * PanRightSmoother.render();                  fFinalVolume * VolumeRight * PanRightSmoother.render();
587  #endif  #endif
588              // render audio for one subfragment              // render audio for one subfragment
589              RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);              if (!delay) RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);
590    
591              // stop the rendering if volume EG is finished              if (pSignalUnitRack == NULL) {
592              if (pEG1->getSegmentType() == EG::segment_end) break;                  // stop the rendering if volume EG is finished
593                    if (pEG1->getSegmentType() == EG::segment_end) break;
594                } else {
595                    // stop the rendering if the endpoint unit is not active
596                    if (!pSignalUnitRack->GetEndpointUnit()->Active()) break;
597                }
598    
599              const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;              const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;
600    
601              // increment envelopes' positions              if (pSignalUnitRack == NULL) {
602              if (pEG1->active()) {                  // increment envelopes' positions
603                    if (pEG1->active()) {
604    
605                        // 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
606                        if (SmplInfo.HasLoops && Pos <= SmplInfo.LoopStart && SmplInfo.LoopStart < newPos) {
607                            pEG1->update(EG::event_hold_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
608                        }
609    
610                  // 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);
611                  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);  
612                  }                  }
613                    if (pEG2->active()) {
614                  pEG1->increment(1);                      pEG2->increment(1);
615                  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);
616              }                  }
617              if (EG2.active()) {                  EG3.increment(1);
618                  EG2.increment(1);                  if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached
619                  if (!EG2.toStageEndLeft()) EG2.update(gig::EGADSR::event_stage_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);              } else {
620                        // 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
621                        /*if (SmplInfo.HasLoops && Pos <= SmplInfo.LoopStart && SmplInfo.LoopStart < newPos) {
622                            pEG1->update(EG::event_hold_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
623                        }*/
624                    // TODO: ^^^
625                    
626                    if (!delay) pSignalUnitRack->Increment();
627              }              }
             EG3.increment(1);  
             if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached  
628    
629              Pos = newPos;              Pos = newPos;
630              i = iSubFragmentEnd;              i = iSubFragmentEnd;
631          }          }
632            
633            if (delay) return;
634    
635            if (bVoiceRequiresDedicatedRouting) {
636                if (bEq) {
637                    pEq->RenderAudio(Samples);
638                    pEq->GetOutChannelLeft()->CopyTo(GetEngine()->pDedicatedVoiceChannelLeft, Samples);
639                    pEq->GetOutChannelRight()->CopyTo(GetEngine()->pDedicatedVoiceChannelRight, Samples);
640                }
641                optional<float> effectSendLevels[2] = {
642                    pMidiKeyInfo->ReverbSend,
643                    pMidiKeyInfo->ChorusSend
644                };
645                GetEngine()->RouteDedicatedVoiceChannels(pEngineChannel, effectSendLevels, Samples);
646            } else if (bEq) {
647                pEq->RenderAudio(Samples);
648                pEq->GetOutChannelLeft()->MixTo(pChannel->pChannelLeft, Samples);
649                pEq->GetOutChannelRight()->MixTo(pChannel->pChannelRight, Samples);
650            }
651      }      }
652    
653      /**      /**
654       * Process given list of MIDI control change and pitch bend events for       * Process given list of MIDI control change, aftertouch and pitch bend
655       * the given time.       * events for the given time.
656       *       *
657       * @param itEvent - iterator pointing to the next event to be processed       * @param itEvent - iterator pointing to the next event to be processed
658       * @param End     - youngest time stamp where processing should be stopped       * @param End     - youngest time stamp where processing should be stopped
659       */       */
660      void AbstractVoice::processCCEvents(RTList<Event>::Iterator& itEvent, uint End) {      void AbstractVoice::processCCEvents(RTList<Event>::Iterator& itEvent, uint End) {
661          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
662              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)
663                    && itEvent->Param.CC.Controller) // if (valid) MIDI control change event
664                {
665                  if (itEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {                  if (itEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {
666                      ProcessCutoffEvent(itEvent);                      ProcessCutoffEvent(itEvent);
667                  }                  }
668                  if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {                  if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {
669                      processResonanceEvent(itEvent);                      processResonanceEvent(itEvent);
670                  }                  }
671                  if (itEvent->Param.CC.Controller == pLFO1->ExtController) {                  if (itEvent->Param.CC.Controller == CTRL_TABLE_IDX_AFTERTOUCH ||
672                      pLFO1->update(itEvent->Param.CC.Value);                      itEvent->Type == Event::type_channel_pressure)
673                  }                  {
674                  if (itEvent->Param.CC.Controller == pLFO2->ExtController) {                      ProcessChannelPressureEvent(itEvent);
                     pLFO2->update(itEvent->Param.CC.Value);  
675                  }                  }
676                  if (itEvent->Param.CC.Controller == pLFO3->ExtController) {                  if (pSignalUnitRack == NULL) {
677                      pLFO3->update(itEvent->Param.CC.Value);                      if (itEvent->Param.CC.Controller == pLFO1->ExtController) {
678                            pLFO1->updateByMIDICtrlValue(itEvent->Param.CC.Value);
679                        }
680                        if (itEvent->Param.CC.Controller == pLFO2->ExtController) {
681                            pLFO2->updateByMIDICtrlValue(itEvent->Param.CC.Value);
682                        }
683                        if (itEvent->Param.CC.Controller == pLFO3->ExtController) {
684                            pLFO3->updateByMIDICtrlValue(itEvent->Param.CC.Value);
685                        }
686                  }                  }
687                  if (itEvent->Param.CC.Controller == 7) { // volume                  if (itEvent->Param.CC.Controller == 7) { // volume
688                      VolumeSmoother.update(AbstractEngine::VolumeCurve[itEvent->Param.CC.Value]);                      VolumeSmoother.update(AbstractEngine::VolumeCurve[itEvent->Param.CC.Value]);
689                  } else if (itEvent->Param.CC.Controller == 10) { // panpot                  } else if (itEvent->Param.CC.Controller == 10) { // panpot
690                      PanLeftSmoother.update(AbstractEngine::PanCurve[128 - itEvent->Param.CC.Value]);                      MIDIPan = CalculatePan(itEvent->Param.CC.Value);
                     PanRightSmoother.update(AbstractEngine::PanCurve[itEvent->Param.CC.Value]);  
691                  }                  }
692              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event
693                  processPitchEvent(itEvent);                  processPitchEvent(itEvent);
694                } else if (itEvent->Type == Event::type_note_pressure) {
695                    ProcessPolyphonicKeyPressureEvent(itEvent);
696              }              }
697    
698              ProcessCCEvent(itEvent);              ProcessCCEvent(itEvent);
699                if (pSignalUnitRack != NULL) {
700                    pSignalUnitRack->ProcessCCEvent(itEvent);
701                }
702          }          }
703      }      }
704    
# Line 527  namespace LinuxSampler { Line 717  namespace LinuxSampler {
717      }      }
718    
719      /**      /**
720       * 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
721       * for the given time.       * note synthesis parameter events for the given time.
722       *       *
723       * @param itEvent - iterator pointing to the next event to be processed       * @param itEvent - iterator pointing to the next event to be processed
724       * @param End     - youngest time stamp where processing should be stopped       * @param End     - youngest time stamp where processing should be stopped
725       */       */
726      void AbstractVoice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) {      void AbstractVoice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) {
727          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
728              if (Type != Voice::type_release_trigger) {              // some voice types ignore note off
729                if (!(Type & (Voice::type_one_shot | Voice::type_release_trigger | Voice::type_controller_triggered))) {
730                  if (itEvent->Type == Event::type_release) {                  if (itEvent->Type == Event::type_release_key) {
731                      EnterReleaseStage();                      EnterReleaseStage();
732                  } else if (itEvent->Type == Event::type_cancel_release) {                  } else if (itEvent->Type == Event::type_cancel_release_key) {
733                      pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                      if (pSignalUnitRack == NULL) {
734                      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);
735                            pEG2->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
736                        } else {
737                            pSignalUnitRack->CancelRelease();
738                        }
739                    }
740                }
741                // process stop-note events (caused by built-in instrument script function note_off())
742                if (itEvent->Type == Event::type_release_note && pNote &&
743                    pEngineChannel->pEngine->NoteByID( itEvent->Param.Note.ID ) == pNote)
744                {
745                    EnterReleaseStage();
746                }
747                // process kill-note events (caused by built-in instrument script function fade_out())
748                if (itEvent->Type == Event::type_kill_note && pNote &&
749                    pEngineChannel->pEngine->NoteByID( itEvent->Param.Note.ID ) == pNote)
750                {
751                    Kill(itEvent);
752                }
753                // process synthesis parameter events (caused by built-in realt-time instrument script functions)
754                if (itEvent->Type == Event::type_note_synth_param && pNote &&
755                    pEngineChannel->pEngine->NoteByID( itEvent->Param.NoteSynthParam.NoteID ) == pNote)
756                {
757                    switch (itEvent->Param.NoteSynthParam.Type) {
758                        case Event::synth_param_volume:
759                            NoteVolume.fadeTo(itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
760                            break;
761                        case Event::synth_param_volume_time:
762                            NoteVolume.setDefaultDuration(itEvent->Param.NoteSynthParam.AbsValue);
763                            break;
764                        case Event::synth_param_volume_curve:
765                            NoteVolume.setCurve((fade_curve_t)itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
766                            break;
767                        case Event::synth_param_pitch:
768                            NotePitch.fadeTo(itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
769                            break;
770                        case Event::synth_param_pitch_time:
771                            NotePitch.setDefaultDuration(itEvent->Param.NoteSynthParam.AbsValue);
772                            break;
773                        case Event::synth_param_pitch_curve:
774                            NotePitch.setCurve((fade_curve_t)itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
775                            break;
776                        case Event::synth_param_pan:
777                            NotePanLeft  = AbstractEngine::PanCurveValueNorm(itEvent->Param.NoteSynthParam.AbsValue, 0 /*left*/);
778                            NotePanRight = AbstractEngine::PanCurveValueNorm(itEvent->Param.NoteSynthParam.AbsValue, 1 /*right*/);
779                            break;
780                        case Event::synth_param_cutoff:
781                            NoteCutoff = itEvent->Param.NoteSynthParam.AbsValue;
782                            break;
783                        case Event::synth_param_resonance:
784                            NoteResonance = itEvent->Param.NoteSynthParam.AbsValue;
785                            break;
786                        case Event::synth_param_amp_lfo_depth:
787                            pLFO1->setScriptDepthFactor(itEvent->Param.NoteSynthParam.AbsValue);
788                            break;
789                        case Event::synth_param_amp_lfo_freq:
790                            pLFO1->setScriptFrequencyFactor(itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
791                            break;
792                        case Event::synth_param_pitch_lfo_depth:
793                            pLFO3->setScriptDepthFactor(itEvent->Param.NoteSynthParam.AbsValue);
794                            break;
795                        case Event::synth_param_pitch_lfo_freq:
796                            pLFO3->setScriptFrequencyFactor(itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
797                            break;
798    
799                        case Event::synth_param_attack:
800                        case Event::synth_param_decay:
801                        case Event::synth_param_release:
802                            break; // noop
803                  }                  }
804              }              }
805          }          }
# Line 568  namespace LinuxSampler { Line 826  namespace LinuxSampler {
826       * @param itNoteOffEvent - event which causes this voice to die soon       * @param itNoteOffEvent - event which causes this voice to die soon
827       */       */
828      void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {      void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {
829          const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());          if (pSignalUnitRack == NULL) {
830          pEngineChannel->PortamentoPos = (float) MIDIKey + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;              const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());
831                pEngineChannel->PortamentoPos = (float) MIDIKey() + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;
832            } else {
833                // TODO:
834            }
835      }      }
836    
837      /**      /**
# Line 593  namespace LinuxSampler { Line 855  namespace LinuxSampler {
855    
856      Voice::PitchInfo AbstractVoice::CalculatePitchInfo(int PitchBend) {      Voice::PitchInfo AbstractVoice::CalculatePitchInfo(int PitchBend) {
857          PitchInfo pitch;          PitchInfo pitch;
858          double pitchbasecents = InstrInfo.FineTune + RgnInfo.FineTune + GetEngine()->ScaleTuning[MIDIKey % 12];          double pitchbasecents = InstrInfo.FineTune + RgnInfo.FineTune + GetEngine()->ScaleTuning[MIDIKey() % 12];
859    
860          // GSt behaviour: maximum transpose up is 40 semitones. If          // GSt behaviour: maximum transpose up is 40 semitones. If
861          // MIDI key is more than 40 semitones above unity note,          // MIDI key is more than 40 semitones above unity note,
862          // the transpose is not done.          // the transpose is not done.
863          if (!SmplInfo.Unpitched && (MIDIKey - (int) RgnInfo.UnityNote) < 40) pitchbasecents += (MIDIKey - (int) RgnInfo.UnityNote) * 100;          //
864            // Update: Removed this GSt misbehavior. I don't think that any stock
865            // gig sound requires it to resemble its original sound.
866            // -- Christian, 2017-07-09
867            if (!SmplInfo.Unpitched /* && (MIDIKey() - (int) RgnInfo.UnityNote) < 40*/)
868                pitchbasecents += (MIDIKey() - (int) RgnInfo.UnityNote) * 100;
869    
870          pitch.PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(SmplInfo.SampleRate) / double(GetEngine()->SampleRate));          pitch.PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(SmplInfo.SampleRate) / double(GetEngine()->SampleRate));
871          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 873  namespace LinuxSampler {
873    
874          return pitch;          return pitch;
875      }      }
876        
877        void AbstractVoice::onScaleTuningChanged() {
878            PitchInfo pitch = this->Pitch;
879            double pitchbasecents = InstrInfo.FineTune + RgnInfo.FineTune + GetEngine()->ScaleTuning[MIDIKey() % 12];
880            
881            // GSt behaviour: maximum transpose up is 40 semitones. If
882            // MIDI key is more than 40 semitones above unity note,
883            // the transpose is not done.
884            //
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));
892            this->Pitch = pitch;
893        }
894    
895      double AbstractVoice::CalculateVolume(double velocityAttenuation) {      double AbstractVoice::CalculateVolume(double velocityAttenuation) {
896          // 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 901  namespace LinuxSampler {
901          volume *= GetSampleAttenuation() * pEngineChannel->GlobalVolume * GLOBAL_VOLUME;          volume *= GetSampleAttenuation() * pEngineChannel->GlobalVolume * GLOBAL_VOLUME;
902    
903          // the volume of release triggered samples depends on note length          // the volume of release triggered samples depends on note length
904          if (Type == Voice::type_release_trigger) {          if (Type & Voice::type_release_trigger) {
905              float noteLength = float(GetEngine()->FrameTime + Delay -              float noteLength = float(GetEngine()->FrameTime + Delay -
906                  GetNoteOnTime(MIDIKey) ) / GetEngine()->SampleRate;                  GetNoteOnTime(MIDIKey()) ) / GetEngine()->SampleRate;
907    
908              volume *= GetReleaseTriggerAttenuation(noteLength);              volume *= GetReleaseTriggerAttenuation(noteLength);
909          }          }
# Line 631  namespace LinuxSampler { Line 916  namespace LinuxSampler {
916      }      }
917    
918      void AbstractVoice::EnterReleaseStage() {      void AbstractVoice::EnterReleaseStage() {
919          pEG1->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);          if (pSignalUnitRack == NULL) {
920          EG2.update(gig::EGADSR::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);              pEG1->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
921                pEG2->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
922            } else {
923                pSignalUnitRack->EnterReleaseStage();
924            }
925        }
926    
927        bool AbstractVoice::EG1Finished() {
928            if (pSignalUnitRack == NULL) {
929                return pEG1->getSegmentType() == EG::segment_end;
930            } else {
931                return !pSignalUnitRack->GetEndpointUnit()->Active();
932            }
933      }      }
934    
935  } // namespace LinuxSampler  } // namespace LinuxSampler

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

  ViewVC Help
Powered by ViewVC