/[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 2216 by iliev, Mon Jul 25 17:21:16 2011 UTC revision 3360 by schoenebeck, Fri Oct 27 21:19: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-2011 Christian Schoenebeck and Grigor Iliev        *   *   Copyright (C) 2009-2012 Christian Schoenebeck and Grigor Iliev        *
8     *   Copyright (C) 2013-2017 Christian Schoenebeck and Andreas Persson     *
9   *                                                                         *   *                                                                         *
10   *   This program is free software; you can redistribute it and/or modify  *   *   This program is free software; you can redistribute it and/or modify  *
11   *   it under the terms of the GNU General Public License as published by  *   *   it under the terms of the GNU General Public License as published by  *
# Line 26  Line 27 
27    
28  namespace LinuxSampler {  namespace LinuxSampler {
29    
30      AbstractVoice::AbstractVoice() {      AbstractVoice::AbstractVoice(SignalUnitRack* pRack): pSignalUnitRack(pRack) {
31          pEngineChannel = NULL;          pEngineChannel = NULL;
32          pLFO1 = new LFOUnsigned(1.0f);  // amplitude LFO (0..1 range)          pLFO1 = new LFOUnsigned(1.0f);  // amplitude LFO (0..1 range)
33          pLFO2 = new LFOUnsigned(1.0f);  // filter LFO (0..1 range)          pLFO2 = new LFOUnsigned(1.0f);  // filter LFO (0..1 range)
# Line 43  namespace LinuxSampler { Line 44  namespace LinuxSampler {
44    
45          finalSynthesisParameters.filterLeft.Reset();          finalSynthesisParameters.filterLeft.Reset();
46          finalSynthesisParameters.filterRight.Reset();          finalSynthesisParameters.filterRight.Reset();
47            
48            pEq          = NULL;
49            bEqSupport   = false;
50      }      }
51    
52      AbstractVoice::~AbstractVoice() {      AbstractVoice::~AbstractVoice() {
53          if (pLFO1) delete pLFO1;          if (pLFO1) delete pLFO1;
54          if (pLFO2) delete pLFO2;          if (pLFO2) delete pLFO2;
55          if (pLFO3) delete pLFO3;          if (pLFO3) delete pLFO3;
56            
57            if(pEq != NULL) delete pEq;
58        }
59                
60        void AbstractVoice::CreateEq() {
61            if(!bEqSupport) return;
62            if(pEq != NULL) delete pEq;
63            pEq = new EqSupport;
64            pEq->InitEffect(GetEngine()->pAudioOutputDevice);
65      }      }
66    
67      /**      /**
# Line 98  namespace LinuxSampler { Line 111  namespace LinuxSampler {
111          #endif // CONFIG_DEVMODE          #endif // CONFIG_DEVMODE
112    
113          Type            = VoiceType;          Type            = VoiceType;
114          MIDIKey         = itNoteOnEvent->Param.Note.Key;          pNote           = pEngineChannel->pEngine->NoteByID( itNoteOnEvent->Param.Note.ID );
115          PlaybackState   = playback_state_init; // mark voice as triggered, but no audio rendered yet          PlaybackState   = playback_state_init; // mark voice as triggered, but no audio rendered yet
116          Delay           = itNoteOnEvent->FragmentPos();          Delay           = itNoteOnEvent->FragmentPos();
117          itTriggerEvent  = itNoteOnEvent;          itTriggerEvent  = itNoteOnEvent;
118          itKillEvent     = Pool<Event>::Iterator();          itKillEvent     = Pool<Event>::Iterator();
119          MidiKeyBase* pKeyInfo = GetMidiKeyInfo(MIDIKey);          MidiKeyBase* pKeyInfo = GetMidiKeyInfo(MIDIKey());
120    
121          pGroupEvents = iKeyGroup ? pEngineChannel->ActiveKeyGroups[iKeyGroup] : 0;          pGroupEvents = iKeyGroup ? pEngineChannel->ActiveKeyGroups[iKeyGroup] : 0;
122    
# Line 111  namespace LinuxSampler { Line 124  namespace LinuxSampler {
124          RgnInfo    = GetRegionInfo();          RgnInfo    = GetRegionInfo();
125          InstrInfo  = GetInstrumentInfo();          InstrInfo  = GetInstrumentInfo();
126                    
127            MIDIPan    = CalculatePan(pEngineChannel->iLastPanRequest);
128    
129          AboutToTrigger();          AboutToTrigger();
130    
131          // calculate volume          // calculate volume
132          const double velocityAttenuation = GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity);          const double velocityAttenuation = GetVelocityAttenuation(MIDIVelocity());
133          float volume = CalculateVolume(velocityAttenuation) * pKeyInfo->Volume;          float volume = CalculateVolume(velocityAttenuation) * pKeyInfo->Volume;
134          if (volume <= 0) return -1;          if (volume <= 0) return -1;
135    
# Line 124  namespace LinuxSampler { Line 139  namespace LinuxSampler {
139          SYNTHESIS_MODE_SET_BITDEPTH24(SynthesisMode, SmplInfo.BitDepth == 24);          SYNTHESIS_MODE_SET_BITDEPTH24(SynthesisMode, SmplInfo.BitDepth == 24);
140    
141          // get starting crossfade volume level          // get starting crossfade volume level
142          float crossfadeVolume = CalculateCrossfadeVolume(itNoteOnEvent->Param.Note.Velocity);          float crossfadeVolume = CalculateCrossfadeVolume(MIDIVelocity());
143    
144          VolumeLeft  = volume * pKeyInfo->PanLeft  * AbstractEngine::PanCurve[64 - RgnInfo.Pan];          VolumeLeft  = volume * pKeyInfo->PanLeft;
145          VolumeRight = volume * pKeyInfo->PanRight * AbstractEngine::PanCurve[64 + RgnInfo.Pan];          VolumeRight = volume * pKeyInfo->PanRight;
146    
147          float subfragmentRate = GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;          // this rate is used for rather mellow volume fades
148            const float subfragmentRate = GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;
149            // this rate is used for very fast volume fades
150            const float quickRampRate = RTMath::Min(subfragmentRate, GetEngine()->SampleRate * 0.001f /* approx. 13ms */);
151          CrossfadeSmoother.trigger(crossfadeVolume, subfragmentRate);          CrossfadeSmoother.trigger(crossfadeVolume, subfragmentRate);
152    
153          VolumeSmoother.trigger(pEngineChannel->MidiVolume, subfragmentRate);          VolumeSmoother.trigger(pEngineChannel->MidiVolume, subfragmentRate);
154          PanLeftSmoother.trigger(pEngineChannel->GlobalPanLeft, subfragmentRate);          NoteVolume.setCurveOnly(pNote ? pNote->Override.VolumeCurve : DEFAULT_FADE_CURVE);
155          PanRightSmoother.trigger(pEngineChannel->GlobalPanRight, subfragmentRate);          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;
# Line 157  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 173  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          if (GetSignalUnitRack() == NULL) { // 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 {          } else {
220              GetSignalUnitRack()->Trigger();              pSignalUnitRack->Trigger();
221          }          }
222    
223            const uint8_t pan = (pSignalUnitRack) ? pSignalUnitRack->GetEndpointUnit()->CalculatePan(MIDIPan) : MIDIPan;
224            for (int c = 0; c < 2; ++c) {
225                float value = (pNote) ? AbstractEngine::PanCurveValueNorm(pNote->Override.Pan, c) : 1.f;
226                NotePan[c].setCurveOnly(pNote ? pNote->Override.PanCurve : DEFAULT_FADE_CURVE);
227                NotePan[c].setCurrentValue(value);
228                NotePan[c].setDefaultDuration(pNote ? pNote->Override.PanTime : DEFAULT_NOTE_PAN_TIME_S);
229            }
230    
231            PanLeftSmoother.trigger(
232                AbstractEngine::PanCurve[128 - pan],
233                quickRampRate //NOTE: maybe we should have 2 separate pan smoothers, one for MIDI CC10 (with slow rate) and one for instrument script change_pan() calls (with fast rate)
234            );
235            PanRightSmoother.trigger(
236                AbstractEngine::PanCurve[pan],
237                quickRampRate //NOTE: maybe we should have 2 separate pan smoothers, one for MIDI CC10 (with slow rate) and one for instrument script change_pan() calls (with fast rate)
238            );
239    
240  #ifdef CONFIG_INTERPOLATE_VOLUME  #ifdef CONFIG_INTERPOLATE_VOLUME
241          // setup initial volume in synthesis parameters          // setup initial volume in synthesis parameters
242      #ifdef CONFIG_PROCESS_MUTED_CHANNELS      #ifdef CONFIG_PROCESS_MUTED_CHANNELS
# Line 200  namespace LinuxSampler { Line 248  namespace LinuxSampler {
248      #else      #else
249          {          {
250              float finalVolume;              float finalVolume;
251              if (GetSignalUnitRack() == NULL) {              if (pSignalUnitRack == NULL) {
252                  finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pEG1->getLevel();                  finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pEG1->getLevel();
253              } else {              } else {
254                  finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * GetSignalUnitRack()->GetEndpointUnit()->GetVolume();                  finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pSignalUnitRack->GetEndpointUnit()->GetVolume();
255              }              }
256                finalVolume *= NoteVolume.currentValue();
257    
258              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * pEngineChannel->GlobalPanLeft;              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * PanLeftSmoother.render()  * NotePan[0].currentValue();
259              finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * pEngineChannel->GlobalPanRight;              finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * PanRightSmoother.render() * NotePan[1].currentValue();
260          }          }
261      #endif      #endif
262  #endif  #endif
263    
264          if (GetSignalUnitRack() == NULL) {          if (pSignalUnitRack == NULL) {
265              // setup EG 2 (VCF Cutoff EG)              // setup EG 2 (VCF Cutoff EG)
266              {              {
267                  // get current value of EG2 controller                  // get current value of EG2 controller
268                  double eg2controllervalue = GetEG2ControllerValue(itNoteOnEvent->Param.Note.Velocity);                  double eg2controllervalue = GetEG2ControllerValue(MIDIVelocity());
269    
270                  // calculate influence of EG2 controller on EG2's parameters                  // calculate influence of EG2 controller on EG2's parameters
271                  EGInfo egInfo = CalculateEG2ControllerInfluence(eg2controllervalue);                  EGInfo egInfo = CalculateEG2ControllerInfluence(eg2controllervalue);
272    
273                  TriggerEG2(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity);                  if (pNote) {
274                        egInfo.Attack  *= pNote->Override.CutoffAttack;
275                        egInfo.Decay   *= pNote->Override.CutoffDecay;
276                        egInfo.Release *= pNote->Override.CutoffRelease;
277                    }
278    
279                    TriggerEG2(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, MIDIVelocity());
280              }              }
281    
282    
# Line 230  namespace LinuxSampler { Line 285  namespace LinuxSampler {
285                  // 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
286                  bool  bPortamento = pEngineChannel->PortamentoMode && pEngineChannel->PortamentoPos >= 0.0f;                  bool  bPortamento = pEngineChannel->PortamentoMode && pEngineChannel->PortamentoPos >= 0.0f;
287                  float eg3depth = (bPortamento)                  float eg3depth = (bPortamento)
288                               ? RTMath::CentsToFreqRatio((pEngineChannel->PortamentoPos - (float) MIDIKey) * 100)                               ? RTMath::CentsToFreqRatio((pEngineChannel->PortamentoPos - (float) MIDIKey()) * 100)
289                               : RTMath::CentsToFreqRatio(RgnInfo.EG3Depth);                               : RTMath::CentsToFreqRatio(RgnInfo.EG3Depth);
290                  float eg3time = (bPortamento)                  float eg3time = (bPortamento)
291                              ? pEngineChannel->PortamentoTime                              ? pEngineChannel->PortamentoTime
# Line 280  namespace LinuxSampler { Line 335  namespace LinuxSampler {
335              VCFResonanceCtrl.value = pEngineChannel->ControllerTable[VCFResonanceCtrl.controller];              VCFResonanceCtrl.value = pEngineChannel->ControllerTable[VCFResonanceCtrl.controller];
336    
337              // calculate cutoff frequency              // calculate cutoff frequency
338              CutoffBase = CalculateCutoffBase(itNoteOnEvent->Param.Note.Velocity);              CutoffBase = CalculateCutoffBase(MIDIVelocity());
339    
340              VCFCutoffCtrl.fvalue = CalculateFinalCutoff(CutoffBase);              VCFCutoffCtrl.fvalue = CalculateFinalCutoff(CutoffBase);
341    
# Line 291  namespace LinuxSampler { Line 346  namespace LinuxSampler {
346              VCFCutoffCtrl.controller    = 0;              VCFCutoffCtrl.controller    = 0;
347              VCFResonanceCtrl.controller = 0;              VCFResonanceCtrl.controller = 0;
348          }          }
349            
350            const bool bEq =
351                pSignalUnitRack != NULL && pSignalUnitRack->HasEq() && pEq->HasSupport();
352    
353            if (bEq) {
354                pEq->GetInChannelLeft()->Clear();
355                pEq->GetInChannelRight()->Clear();
356                pEq->RenderAudio(GetEngine()->pAudioOutputDevice->MaxSamplesPerCycle());
357            }
358    
359          return 0; // success          return 0; // success
360      }      }
361            
362      void AbstractVoice::SetSampleStartOffset() {      void AbstractVoice::SetSampleStartOffset() {
363          finalSynthesisParameters.dPos = RgnInfo.SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)          double pos = RgnInfo.SampleStartOffset; // offset where we should start playback of sample
364          Pos = RgnInfo.SampleStartOffset;  
365            // if another sample playback start position was requested by instrument
366            // script (built-in script function play_note())
367            if (pNote && pNote->Override.SampleOffset >= 0) {
368                double overridePos =
369                    double(SmplInfo.SampleRate) * double(pNote->Override.SampleOffset) / 1000000.0;
370                if (overridePos < SmplInfo.TotalFrameCount)
371                    pos = overridePos;
372            }
373    
374            finalSynthesisParameters.dPos = pos;
375            Pos = pos;
376      }      }
377    
378      /**      /**
# Line 309  namespace LinuxSampler { Line 384  namespace LinuxSampler {
384       *  @param Skip    - number of sample points to skip in output buffer       *  @param Skip    - number of sample points to skip in output buffer
385       */       */
386      void AbstractVoice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {      void AbstractVoice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {
387            bool delay = false; // Whether the voice playback should be delayed for this call
388            
389            if (pSignalUnitRack != NULL) {
390                uint delaySteps = pSignalUnitRack->GetEndpointUnit()->DelayTrigger();
391                if (delaySteps > 0) { // delay on the endpoint unit means delay of the voice playback
392                    if (delaySteps >= Samples) {
393                        pSignalUnitRack->GetEndpointUnit()->DecreaseDelay(Samples);
394                        delay = true;
395                    } else {
396                        pSignalUnitRack->GetEndpointUnit()->DecreaseDelay(delaySteps);
397                        Samples -= delaySteps;
398                        Skip += delaySteps;
399                    }
400                }
401            }
402            
403          AbstractEngineChannel* pChannel = pEngineChannel;          AbstractEngineChannel* pChannel = pEngineChannel;
404          MidiKeyBase* pMidiKeyInfo = GetMidiKeyInfo(MIDIKey);          MidiKeyBase* pMidiKeyInfo = GetMidiKeyInfo(MIDIKey());
405    
406          const bool bVoiceRequiresDedicatedRouting =          const bool bVoiceRequiresDedicatedRouting =
407              pEngineChannel->GetFxSendCount() > 0 &&              pEngineChannel->GetFxSendCount() > 0 &&
408              (pMidiKeyInfo->ReverbSend || pMidiKeyInfo->ChorusSend);              (pMidiKeyInfo->ReverbSend || pMidiKeyInfo->ChorusSend);
409            
410            const bool bEq =
411                pSignalUnitRack != NULL && pSignalUnitRack->HasEq() && pEq->HasSupport();
412    
413          if (bVoiceRequiresDedicatedRouting) {          if (bEq) {
414                pEq->GetInChannelLeft()->Clear();
415                pEq->GetInChannelRight()->Clear();
416                finalSynthesisParameters.pOutLeft  = &pEq->GetInChannelLeft()->Buffer()[Skip];
417                finalSynthesisParameters.pOutRight = &pEq->GetInChannelRight()->Buffer()[Skip];
418                pSignalUnitRack->UpdateEqSettings(pEq);
419            } else if (bVoiceRequiresDedicatedRouting) {
420              finalSynthesisParameters.pOutLeft  = &GetEngine()->pDedicatedVoiceChannelLeft->Buffer()[Skip];              finalSynthesisParameters.pOutLeft  = &GetEngine()->pDedicatedVoiceChannelLeft->Buffer()[Skip];
421              finalSynthesisParameters.pOutRight = &GetEngine()->pDedicatedVoiceChannelRight->Buffer()[Skip];              finalSynthesisParameters.pOutRight = &GetEngine()->pDedicatedVoiceChannelRight->Buffer()[Skip];
422          } else {          } else {
# Line 327  namespace LinuxSampler { Line 427  namespace LinuxSampler {
427    
428          RTList<Event>::Iterator itCCEvent = pChannel->pEvents->first();          RTList<Event>::Iterator itCCEvent = pChannel->pEvents->first();
429          RTList<Event>::Iterator itNoteEvent;          RTList<Event>::Iterator itNoteEvent;
430          GetFirstEventOnKey(MIDIKey, itNoteEvent);          GetFirstEventOnKey(HostKey(), itNoteEvent);
431    
432          RTList<Event>::Iterator itGroupEvent;          RTList<Event>::Iterator itGroupEvent;
433          if (pGroupEvents) itGroupEvent = pGroupEvents->first();          if (pGroupEvents && !Orphan) itGroupEvent = pGroupEvents->first();
434    
435          if (itTriggerEvent) { // skip events that happened before this voice was triggered          if (itTriggerEvent) { // skip events that happened before this voice was triggered
436              while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;              while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;
# Line 347  namespace LinuxSampler { Line 447  namespace LinuxSampler {
447              }              }
448          }          }
449    
450          uint killPos;          uint killPos = 0;
451          if (itKillEvent) {          if (itKillEvent) {
452              int maxFadeOutPos = Samples - GetEngine()->GetMinFadeOutSamples();              int maxFadeOutPos = Samples - GetEngine()->GetMinFadeOutSamples();
453              if (maxFadeOutPos < 0) {              if (maxFadeOutPos < 0) {
# Line 356  namespace LinuxSampler { Line 456  namespace LinuxSampler {
456                  // drivers that use Samples < MaxSamplesPerCycle).                  // drivers that use Samples < MaxSamplesPerCycle).
457                  // End the EG1 here, at pos 0, with a shorter max fade                  // End the EG1 here, at pos 0, with a shorter max fade
458                  // out time.                  // out time.
459                  if (GetSignalUnitRack() == NULL) {                  if (pSignalUnitRack == NULL) {
460                      pEG1->enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                      pEG1->enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
461                  } else {                  } else {
462                      // TODO:                      pSignalUnitRack->EnterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
463                  }                  }
464                  itKillEvent = Pool<Event>::Iterator();                  itKillEvent = Pool<Event>::Iterator();
465              } else {              } else {
# Line 375  namespace LinuxSampler { Line 475  namespace LinuxSampler {
475              fFinalCutoff    = VCFCutoffCtrl.fvalue;              fFinalCutoff    = VCFCutoffCtrl.fvalue;
476              fFinalResonance = VCFResonanceCtrl.fvalue;              fFinalResonance = VCFResonanceCtrl.fvalue;
477    
478              // process MIDI control change and pitchbend events for this subfragment              // process MIDI control change, aftertouch and pitchbend events for this subfragment
479              processCCEvents(itCCEvent, iSubFragmentEnd);              processCCEvents(itCCEvent, iSubFragmentEnd);
480                uint8_t pan = MIDIPan;
481                if (pSignalUnitRack != NULL) pan = pSignalUnitRack->GetEndpointUnit()->CalculatePan(MIDIPan);
482    
483              finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend;              PanLeftSmoother.update(AbstractEngine::PanCurve[128 - pan]);
484              float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render();              PanRightSmoother.update(AbstractEngine::PanCurve[pan]);
485    
486                finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend * NotePitch.render();
487    
488                float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render() * NoteVolume.render();
489  #ifdef CONFIG_PROCESS_MUTED_CHANNELS  #ifdef CONFIG_PROCESS_MUTED_CHANNELS
490              if (pChannel->GetMute()) fFinalVolume = 0;              if (pChannel->GetMute()) fFinalVolume = 0;
491  #endif  #endif
# Line 387  namespace LinuxSampler { Line 493  namespace LinuxSampler {
493              // process transition events (note on, note off & sustain pedal)              // process transition events (note on, note off & sustain pedal)
494              processTransitionEvents(itNoteEvent, iSubFragmentEnd);              processTransitionEvents(itNoteEvent, iSubFragmentEnd);
495              processGroupEvents(itGroupEvent, iSubFragmentEnd);              processGroupEvents(itGroupEvent, iSubFragmentEnd);
496                
497              if (GetSignalUnitRack() == NULL) {              if (pSignalUnitRack == NULL) {
498                  // if the voice was killed in this subfragment, or if the                  // if the voice was killed in this subfragment, or if the
499                  // filter EG is finished, switch EG1 to fade out stage                  // filter EG is finished, switch EG1 to fade out stage
500                  if ((itKillEvent && killPos <= iSubFragmentEnd) ||                  if ((itKillEvent && killPos <= iSubFragmentEnd) ||
# Line 431  namespace LinuxSampler { Line 537  namespace LinuxSampler {
537    
538                  // process low frequency oscillators                  // process low frequency oscillators
539                  if (bLFO1Enabled) fFinalVolume *= (1.0f - pLFO1->render());                  if (bLFO1Enabled) fFinalVolume *= (1.0f - pLFO1->render());
540                  if (bLFO2Enabled) fFinalCutoff *= pLFO2->render();                  if (bLFO2Enabled) fFinalCutoff *= (1.0f - pLFO2->render());
541                  if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());                  if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());
542              } else {              } else {
543                  // if the voice was killed in this subfragment, or if the                  // if the voice was killed in this subfragment, enter fade out stage
544                  // filter EG is finished, switch EG1 to fade out stage                  if (itKillEvent && killPos <= iSubFragmentEnd) {
545                  /*if ((itKillEvent && killPos <= iSubFragmentEnd) ||                      pSignalUnitRack->EnterFadeOutStage();
546                      (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&                      itKillEvent = Pool<Event>::Iterator();
547                      pEG2->getSegmentType() == EG::segment_end)) {                  }
548                    
549                    // if the filter EG is finished, switch EG1 to fade out stage
550                    /*if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&
551                        pEG2->getSegmentType() == EG::segment_end) {
552                      pEG1->enterFadeOutStage();                      pEG1->enterFadeOutStage();
553                      itKillEvent = Pool<Event>::Iterator();                      itKillEvent = Pool<Event>::Iterator();
554                  }*/                  }*/
555                  // TODO: ^^^                  // TODO: ^^^
556    
557                  fFinalVolume   *= GetSignalUnitRack()->GetEndpointUnit()->GetVolume();                  fFinalVolume   *= pSignalUnitRack->GetEndpointUnit()->GetVolume();
558                  fFinalCutoff    = GetSignalUnitRack()->GetEndpointUnit()->CalculateFilterCutoff(fFinalCutoff);                  fFinalCutoff    = pSignalUnitRack->GetEndpointUnit()->CalculateFilterCutoff(fFinalCutoff);
559                  fFinalResonance = GetSignalUnitRack()->GetEndpointUnit()->CalculateResonance(fFinalResonance);                  fFinalResonance = pSignalUnitRack->GetEndpointUnit()->CalculateResonance(fFinalResonance);
560                                    
561                  finalSynthesisParameters.fFinalPitch =                  finalSynthesisParameters.fFinalPitch =
562                      GetSignalUnitRack()->GetEndpointUnit()->CalculatePitch(finalSynthesisParameters.fFinalPitch);                      pSignalUnitRack->GetEndpointUnit()->CalculatePitch(finalSynthesisParameters.fFinalPitch);
563                                            
564              }              }
565                
566                fFinalCutoff    *= NoteCutoff;
567                fFinalResonance *= NoteResonance;
568    
569              // limit the pitch so we don't read outside the buffer              // limit the pitch so we don't read outside the buffer
570              finalSynthesisParameters.fFinalPitch = RTMath::Min(finalSynthesisParameters.fFinalPitch, float(1 << CONFIG_MAX_PITCH));              finalSynthesisParameters.fFinalPitch = RTMath::Min(finalSynthesisParameters.fFinalPitch, float(1 << CONFIG_MAX_PITCH));
571    
# Line 473  namespace LinuxSampler { Line 586  namespace LinuxSampler {
586              finalSynthesisParameters.uiToGo            = iSubFragmentEnd - i;              finalSynthesisParameters.uiToGo            = iSubFragmentEnd - i;
587  #ifdef CONFIG_INTERPOLATE_VOLUME  #ifdef CONFIG_INTERPOLATE_VOLUME
588              finalSynthesisParameters.fFinalVolumeDeltaLeft  =              finalSynthesisParameters.fFinalVolumeDeltaLeft  =
589                  (fFinalVolume * VolumeLeft  * PanLeftSmoother.render() -                  (fFinalVolume * VolumeLeft  * PanLeftSmoother.render() * NotePan[0].render() -
590                   finalSynthesisParameters.fFinalVolumeLeft) / finalSynthesisParameters.uiToGo;                   finalSynthesisParameters.fFinalVolumeLeft) / finalSynthesisParameters.uiToGo;
591              finalSynthesisParameters.fFinalVolumeDeltaRight =              finalSynthesisParameters.fFinalVolumeDeltaRight =
592                  (fFinalVolume * VolumeRight * PanRightSmoother.render() -                  (fFinalVolume * VolumeRight * PanRightSmoother.render() * NotePan[1].render() -
593                   finalSynthesisParameters.fFinalVolumeRight) / finalSynthesisParameters.uiToGo;                   finalSynthesisParameters.fFinalVolumeRight) / finalSynthesisParameters.uiToGo;
594  #else  #else
595              finalSynthesisParameters.fFinalVolumeLeft  =              finalSynthesisParameters.fFinalVolumeLeft  =
596                  fFinalVolume * VolumeLeft  * PanLeftSmoother.render();                  fFinalVolume * VolumeLeft  * PanLeftSmoother.render()  * NotePan[0].render();
597              finalSynthesisParameters.fFinalVolumeRight =              finalSynthesisParameters.fFinalVolumeRight =
598                  fFinalVolume * VolumeRight * PanRightSmoother.render();                  fFinalVolume * VolumeRight * PanRightSmoother.render() * NotePan[1].render();
599  #endif  #endif
600              // render audio for one subfragment              // render audio for one subfragment
601              RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);              if (!delay) RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);
602    
603              if (GetSignalUnitRack() == NULL) {              if (pSignalUnitRack == NULL) {
604                  // stop the rendering if volume EG is finished                  // stop the rendering if volume EG is finished
605                  if (pEG1->getSegmentType() == EG::segment_end) break;                  if (pEG1->getSegmentType() == EG::segment_end) break;
606              } else {              } else {
607                  // stop the rendering if the endpoint unit is not active                  // stop the rendering if the endpoint unit is not active
608                  if (!GetSignalUnitRack()->GetEndpointUnit()->Active()) break;                  if (!pSignalUnitRack->GetEndpointUnit()->Active()) break;
609              }              }
610    
611              const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;              const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;
612    
613              if (GetSignalUnitRack() == NULL) {              if (pSignalUnitRack == NULL) {
614                  // increment envelopes' positions                  // increment envelopes' positions
615                  if (pEG1->active()) {                  if (pEG1->active()) {
616    
# Line 522  namespace LinuxSampler { Line 635  namespace LinuxSampler {
635                      }*/                      }*/
636                  // TODO: ^^^                  // TODO: ^^^
637                                    
638                  GetSignalUnitRack()->Increment();                  if (!delay) pSignalUnitRack->Increment();
639              }              }
640    
641              Pos = newPos;              Pos = newPos;
642              i = iSubFragmentEnd;              i = iSubFragmentEnd;
643          }          }
644            
645            if (delay) return;
646    
647          if (bVoiceRequiresDedicatedRouting) {          if (bVoiceRequiresDedicatedRouting) {
648                if (bEq) {
649                    pEq->RenderAudio(Samples);
650                    pEq->GetOutChannelLeft()->CopyTo(GetEngine()->pDedicatedVoiceChannelLeft, Samples);
651                    pEq->GetOutChannelRight()->CopyTo(GetEngine()->pDedicatedVoiceChannelRight, Samples);
652                }
653              optional<float> effectSendLevels[2] = {              optional<float> effectSendLevels[2] = {
654                  pMidiKeyInfo->ReverbSend,                  pMidiKeyInfo->ReverbSend,
655                  pMidiKeyInfo->ChorusSend                  pMidiKeyInfo->ChorusSend
656              };              };
657              GetEngine()->RouteDedicatedVoiceChannels(pEngineChannel, effectSendLevels, Samples);              GetEngine()->RouteDedicatedVoiceChannels(pEngineChannel, effectSendLevels, Samples);
658            } else if (bEq) {
659                pEq->RenderAudio(Samples);
660                pEq->GetOutChannelLeft()->MixTo(pChannel->pChannelLeft, Samples);
661                pEq->GetOutChannelRight()->MixTo(pChannel->pChannelRight, Samples);
662          }          }
663      }      }
664    
665      /**      /**
666       * Process given list of MIDI control change and pitch bend events for       * Process given list of MIDI control change, aftertouch and pitch bend
667       * the given time.       * events for the given time.
668       *       *
669       * @param itEvent - iterator pointing to the next event to be processed       * @param itEvent - iterator pointing to the next event to be processed
670       * @param End     - youngest time stamp where processing should be stopped       * @param End     - youngest time stamp where processing should be stopped
671       */       */
672      void AbstractVoice::processCCEvents(RTList<Event>::Iterator& itEvent, uint End) {      void AbstractVoice::processCCEvents(RTList<Event>::Iterator& itEvent, uint End) {
673          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
674              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)
675                    && itEvent->Param.CC.Controller) // if (valid) MIDI control change event
676                {
677                  if (itEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {                  if (itEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {
678                      ProcessCutoffEvent(itEvent);                      ProcessCutoffEvent(itEvent);
679                  }                  }
680                  if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {                  if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {
681                      processResonanceEvent(itEvent);                      processResonanceEvent(itEvent);
682                  }                  }
683                  if (GetSignalUnitRack() == NULL) {                  if (itEvent->Param.CC.Controller == CTRL_TABLE_IDX_AFTERTOUCH ||
684                        itEvent->Type == Event::type_channel_pressure)
685                    {
686                        ProcessChannelPressureEvent(itEvent);
687                    }
688                    if (pSignalUnitRack == NULL) {
689                      if (itEvent->Param.CC.Controller == pLFO1->ExtController) {                      if (itEvent->Param.CC.Controller == pLFO1->ExtController) {
690                          pLFO1->update(itEvent->Param.CC.Value);                          pLFO1->updateByMIDICtrlValue(itEvent->Param.CC.Value);
691                      }                      }
692                      if (itEvent->Param.CC.Controller == pLFO2->ExtController) {                      if (itEvent->Param.CC.Controller == pLFO2->ExtController) {
693                          pLFO2->update(itEvent->Param.CC.Value);                          pLFO2->updateByMIDICtrlValue(itEvent->Param.CC.Value);
694                      }                      }
695                      if (itEvent->Param.CC.Controller == pLFO3->ExtController) {                      if (itEvent->Param.CC.Controller == pLFO3->ExtController) {
696                          pLFO3->update(itEvent->Param.CC.Value);                          pLFO3->updateByMIDICtrlValue(itEvent->Param.CC.Value);
697                      }                      }
698                  }                  }
699                  if (itEvent->Param.CC.Controller == 7) { // volume                  if (itEvent->Param.CC.Controller == 7) { // volume
700                      VolumeSmoother.update(AbstractEngine::VolumeCurve[itEvent->Param.CC.Value]);                      VolumeSmoother.update(AbstractEngine::VolumeCurve[itEvent->Param.CC.Value]);
701                  } else if (itEvent->Param.CC.Controller == 10) { // panpot                  } else if (itEvent->Param.CC.Controller == 10) { // panpot
702                      PanLeftSmoother.update(AbstractEngine::PanCurve[128 - itEvent->Param.CC.Value]);                      MIDIPan = CalculatePan(itEvent->Param.CC.Value);
                     PanRightSmoother.update(AbstractEngine::PanCurve[itEvent->Param.CC.Value]);  
703                  }                  }
704              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event
705                  processPitchEvent(itEvent);                  processPitchEvent(itEvent);
706                } else if (itEvent->Type == Event::type_note_pressure) {
707                    ProcessPolyphonicKeyPressureEvent(itEvent);
708              }              }
709    
710              ProcessCCEvent(itEvent);              ProcessCCEvent(itEvent);
711              if (GetSignalUnitRack() != NULL) {              if (pSignalUnitRack != NULL) {
712                  GetSignalUnitRack()->ProcessCCEvent(itEvent);                  pSignalUnitRack->ProcessCCEvent(itEvent);
713              }              }
714          }          }
715      }      }
# Line 597  namespace LinuxSampler { Line 729  namespace LinuxSampler {
729      }      }
730    
731      /**      /**
732       * 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
733       * for the given time.       * note synthesis parameter events for the given time.
734       *       *
735       * @param itEvent - iterator pointing to the next event to be processed       * @param itEvent - iterator pointing to the next event to be processed
736       * @param End     - youngest time stamp where processing should be stopped       * @param End     - youngest time stamp where processing should be stopped
# Line 607  namespace LinuxSampler { Line 739  namespace LinuxSampler {
739          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
740              // some voice types ignore note off              // some voice types ignore note off
741              if (!(Type & (Voice::type_one_shot | Voice::type_release_trigger | Voice::type_controller_triggered))) {              if (!(Type & (Voice::type_one_shot | Voice::type_release_trigger | Voice::type_controller_triggered))) {
742                  if (itEvent->Type == Event::type_release) {                  if (itEvent->Type == Event::type_release_key) {
743                      EnterReleaseStage();                      EnterReleaseStage();
744                  } else if (itEvent->Type == Event::type_cancel_release) {                  } else if (itEvent->Type == Event::type_cancel_release_key) {
745                      if (GetSignalUnitRack() == NULL) {                      if (pSignalUnitRack == NULL) {
746                          pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                          pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
747                          pEG2->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                          pEG2->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
748                      } else {                      } else {
749                          GetSignalUnitRack()->CancelRelease();                          pSignalUnitRack->CancelRelease();
750                      }                      }
751                  }                  }
752              }              }
753                // process stop-note events (caused by built-in instrument script function note_off())
754                if (itEvent->Type == Event::type_release_note && pNote &&
755                    pEngineChannel->pEngine->NoteByID( itEvent->Param.Note.ID ) == pNote)
756                {
757                    EnterReleaseStage();
758                }
759                // process kill-note events (caused by built-in instrument script function fade_out())
760                if (itEvent->Type == Event::type_kill_note && pNote &&
761                    pEngineChannel->pEngine->NoteByID( itEvent->Param.Note.ID ) == pNote)
762                {
763                    Kill(itEvent);
764                }
765                // process synthesis parameter events (caused by built-in realt-time instrument script functions)
766                if (itEvent->Type == Event::type_note_synth_param && pNote &&
767                    pEngineChannel->pEngine->NoteByID( itEvent->Param.NoteSynthParam.NoteID ) == pNote)
768                {
769                    switch (itEvent->Param.NoteSynthParam.Type) {
770                        case Event::synth_param_volume:
771                            NoteVolume.fadeTo(itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
772                            break;
773                        case Event::synth_param_volume_time:
774                            NoteVolume.setDefaultDuration(itEvent->Param.NoteSynthParam.AbsValue);
775                            break;
776                        case Event::synth_param_volume_curve:
777                            NoteVolume.setCurve((fade_curve_t)itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
778                            break;
779                        case Event::synth_param_pitch:
780                            NotePitch.fadeTo(itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
781                            break;
782                        case Event::synth_param_pitch_time:
783                            NotePitch.setDefaultDuration(itEvent->Param.NoteSynthParam.AbsValue);
784                            break;
785                        case Event::synth_param_pitch_curve:
786                            NotePitch.setCurve((fade_curve_t)itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
787                            break;
788                        case Event::synth_param_pan:
789                            NotePan[0].fadeTo(
790                                AbstractEngine::PanCurveValueNorm(itEvent->Param.NoteSynthParam.AbsValue, 0 /*left*/),
791                                GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE
792                            );
793                            NotePan[1].fadeTo(
794                                AbstractEngine::PanCurveValueNorm(itEvent->Param.NoteSynthParam.AbsValue, 1 /*right*/),
795                                GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE
796                            );
797                            break;
798                        case Event::synth_param_pan_time:
799                            NotePan[0].setDefaultDuration(itEvent->Param.NoteSynthParam.AbsValue);
800                            NotePan[1].setDefaultDuration(itEvent->Param.NoteSynthParam.AbsValue);
801                            break;
802                        case Event::synth_param_pan_curve:
803                            NotePan[0].setCurve((fade_curve_t)itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
804                            NotePan[1].setCurve((fade_curve_t)itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
805                            break;
806                        case Event::synth_param_cutoff:
807                            NoteCutoff = itEvent->Param.NoteSynthParam.AbsValue;
808                            break;
809                        case Event::synth_param_resonance:
810                            NoteResonance = itEvent->Param.NoteSynthParam.AbsValue;
811                            break;
812                        case Event::synth_param_amp_lfo_depth:
813                            pLFO1->setScriptDepthFactor(itEvent->Param.NoteSynthParam.AbsValue);
814                            break;
815                        case Event::synth_param_amp_lfo_freq:
816                            pLFO1->setScriptFrequencyFactor(itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
817                            break;
818                        case Event::synth_param_cutoff_lfo_depth:
819                            pLFO2->setScriptDepthFactor(itEvent->Param.NoteSynthParam.AbsValue);
820                            break;
821                        case Event::synth_param_cutoff_lfo_freq:
822                            pLFO2->setScriptFrequencyFactor(itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
823                            break;
824                        case Event::synth_param_pitch_lfo_depth:
825                            pLFO3->setScriptDepthFactor(itEvent->Param.NoteSynthParam.AbsValue);
826                            break;
827                        case Event::synth_param_pitch_lfo_freq:
828                            pLFO3->setScriptFrequencyFactor(itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
829                            break;
830    
831                        case Event::synth_param_attack:
832                        case Event::synth_param_decay:
833                        case Event::synth_param_sustain:
834                        case Event::synth_param_release:
835                            break; // noop
836                    }
837                }
838          }          }
839      }      }
840    
# Line 642  namespace LinuxSampler { Line 859  namespace LinuxSampler {
859       * @param itNoteOffEvent - event which causes this voice to die soon       * @param itNoteOffEvent - event which causes this voice to die soon
860       */       */
861      void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {      void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {
862          if (GetSignalUnitRack() == NULL) {          if (pSignalUnitRack == NULL) {
863              const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());              const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());
864              pEngineChannel->PortamentoPos = (float) MIDIKey + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;              pEngineChannel->PortamentoPos = (float) MIDIKey() + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;
865          } else {          } else {
866              // TODO:              // TODO:
867          }          }
# Line 671  namespace LinuxSampler { Line 888  namespace LinuxSampler {
888    
889      Voice::PitchInfo AbstractVoice::CalculatePitchInfo(int PitchBend) {      Voice::PitchInfo AbstractVoice::CalculatePitchInfo(int PitchBend) {
890          PitchInfo pitch;          PitchInfo pitch;
891          double pitchbasecents = InstrInfo.FineTune + RgnInfo.FineTune + GetEngine()->ScaleTuning[MIDIKey % 12];          double pitchbasecents = InstrInfo.FineTune + RgnInfo.FineTune + GetEngine()->ScaleTuning[MIDIKey() % 12];
892    
893          // GSt behaviour: maximum transpose up is 40 semitones. If          // GSt behaviour: maximum transpose up is 40 semitones. If
894          // MIDI key is more than 40 semitones above unity note,          // MIDI key is more than 40 semitones above unity note,
895          // the transpose is not done.          // the transpose is not done.
896          if (!SmplInfo.Unpitched && (MIDIKey - (int) RgnInfo.UnityNote) < 40) pitchbasecents += (MIDIKey - (int) RgnInfo.UnityNote) * 100;          //
897            // Update: Removed this GSt misbehavior. I don't think that any stock
898            // gig sound requires it to resemble its original sound.
899            // -- Christian, 2017-07-09
900            if (!SmplInfo.Unpitched /* && (MIDIKey() - (int) RgnInfo.UnityNote) < 40*/)
901                pitchbasecents += (MIDIKey() - (int) RgnInfo.UnityNote) * 100;
902    
903          pitch.PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(SmplInfo.SampleRate) / double(GetEngine()->SampleRate));          pitch.PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(SmplInfo.SampleRate) / double(GetEngine()->SampleRate));
904          pitch.PitchBendRange = 1.0 / 8192.0 * 100.0 * InstrInfo.PitchbendRange;          pitch.PitchBendRange = 1.0 / 8192.0 * 100.0 * InstrInfo.PitchbendRange;
# Line 684  namespace LinuxSampler { Line 906  namespace LinuxSampler {
906    
907          return pitch;          return pitch;
908      }      }
909        
910        void AbstractVoice::onScaleTuningChanged() {
911            PitchInfo pitch = this->Pitch;
912            double pitchbasecents = InstrInfo.FineTune + RgnInfo.FineTune + GetEngine()->ScaleTuning[MIDIKey() % 12];
913            
914            // GSt behaviour: maximum transpose up is 40 semitones. If
915            // MIDI key is more than 40 semitones above unity note,
916            // the transpose is not done.
917            //
918            // Update: Removed this GSt misbehavior. I don't think that any stock
919            // gig sound requires it to resemble its original sound.
920            // -- Christian, 2017-07-09
921            if (!SmplInfo.Unpitched /* && (MIDIKey() - (int) RgnInfo.UnityNote) < 40*/)
922                pitchbasecents += (MIDIKey() - (int) RgnInfo.UnityNote) * 100;
923            
924            pitch.PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(SmplInfo.SampleRate) / double(GetEngine()->SampleRate));
925            this->Pitch = pitch;
926        }
927    
928      double AbstractVoice::CalculateVolume(double velocityAttenuation) {      double AbstractVoice::CalculateVolume(double velocityAttenuation) {
929          // For 16 bit samples, we downscale by 32768 to convert from          // For 16 bit samples, we downscale by 32768 to convert from
# Line 696  namespace LinuxSampler { Line 936  namespace LinuxSampler {
936          // the volume of release triggered samples depends on note length          // the volume of release triggered samples depends on note length
937          if (Type & Voice::type_release_trigger) {          if (Type & Voice::type_release_trigger) {
938              float noteLength = float(GetEngine()->FrameTime + Delay -              float noteLength = float(GetEngine()->FrameTime + Delay -
939                  GetNoteOnTime(MIDIKey) ) / GetEngine()->SampleRate;                  GetNoteOnTime(MIDIKey()) ) / GetEngine()->SampleRate;
940    
941              volume *= GetReleaseTriggerAttenuation(noteLength);              volume *= GetReleaseTriggerAttenuation(noteLength);
942          }          }
# Line 709  namespace LinuxSampler { Line 949  namespace LinuxSampler {
949      }      }
950    
951      void AbstractVoice::EnterReleaseStage() {      void AbstractVoice::EnterReleaseStage() {
952          if (GetSignalUnitRack() == NULL) {          if (pSignalUnitRack == NULL) {
953              pEG1->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);              pEG1->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
954              pEG2->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);              pEG2->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
955          } else {          } else {
956              GetSignalUnitRack()->EnterReleaseStage();              pSignalUnitRack->EnterReleaseStage();
957          }          }
958      }      }
959    
960      bool AbstractVoice::EG1Finished() {      bool AbstractVoice::EG1Finished() {
961          if (GetSignalUnitRack() == NULL) {          if (pSignalUnitRack == NULL) {
962              return pEG1->getSegmentType() == EG::segment_end;              return pEG1->getSegmentType() == EG::segment_end;
963          } else {          } else {
964              return !GetSignalUnitRack()->GetEndpointUnit()->Active();              return !pSignalUnitRack->GetEndpointUnit()->Active();
965          }          }
966      }      }
967    

Legend:
Removed from v.2216  
changed lines
  Added in v.3360

  ViewVC Help
Powered by ViewVC