/[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 2205 by iliev, Mon Jul 11 17:52:01 2011 UTC revision 3118 by schoenebeck, Fri Apr 21 13:33:03 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-2016 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
# Line 126  namespace LinuxSampler { Line 141  namespace LinuxSampler {
141          // get starting crossfade volume level          // get starting crossfade volume level
142          float crossfadeVolume = CalculateCrossfadeVolume(itNoteOnEvent->Param.Note.Velocity);          float crossfadeVolume = CalculateCrossfadeVolume(itNoteOnEvent->Param.Note.Velocity);
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 /* 1ms */);
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;          NoteVolumeSmoother.trigger(pNote ? pNote->Override.Volume : 1.f, quickRampRate);
155    
156          // 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
157          long cachedsamples = GetSampleCacheSize() / SmplInfo.FrameSize;          long cachedsamples = GetSampleCacheSize() / SmplInfo.FrameSize;
158          DiskVoice          = cachedsamples < SmplInfo.TotalFrameCount;          DiskVoice          = cachedsamples < SmplInfo.TotalFrameCount;
159    
160            SetSampleStartOffset();
161    
162          if (DiskVoice) { // voice to be streamed from disk          if (DiskVoice) { // voice to be streamed from disk
163              if (cachedsamples > (GetEngine()->MaxSamplesPerCycle << CONFIG_MAX_PITCH)) {              if (cachedsamples > (GetEngine()->MaxSamplesPerCycle << CONFIG_MAX_PITCH)) {
164                  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 158  namespace LinuxSampler { Line 175  namespace LinuxSampler {
175              RAMLoop = (SmplInfo.HasLoops && (SmplInfo.LoopStart + SmplInfo.LoopLength) <= MaxRAMPos);              RAMLoop = (SmplInfo.HasLoops && (SmplInfo.LoopStart + SmplInfo.LoopLength) <= MaxRAMPos);
176    
177              if (OrderNewStream()) return -1;              if (OrderNewStream()) return -1;
178              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"));
179          }          }
180          else { // RAM only voice          else { // RAM only voice
181              MaxRAMPos = cachedsamples;              MaxRAMPos = cachedsamples;
# Line 174  namespace LinuxSampler { Line 191  namespace LinuxSampler {
191          }          }
192    
193          Pitch = CalculatePitchInfo(PitchBend);          Pitch = CalculatePitchInfo(PitchBend);
194            NotePitch = (pNote) ? pNote->Override.Pitch : 1.0f;
195            NoteCutoff = (pNote) ? pNote->Override.Cutoff : 1.0f;
196            NoteResonance = (pNote) ? pNote->Override.Resonance : 1.0f;
197    
198          // 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
199          const double velrelease = 1 / GetVelocityRelease(itNoteOnEvent->Param.Note.Velocity);          const double velrelease = 1 / GetVelocityRelease(itNoteOnEvent->Param.Note.Velocity);
200    
201          if (GetSignalUnitRack() == NULL) { // setup EG 1 (VCA EG)          if (pSignalUnitRack == NULL) { // setup EG 1 (VCA EG)
202              // get current value of EG1 controller              // get current value of EG1 controller
203              double eg1controllervalue = GetEG1ControllerValue(itNoteOnEvent->Param.Note.Velocity);              double eg1controllervalue = GetEG1ControllerValue(itNoteOnEvent->Param.Note.Velocity);
204    
205              // calculate influence of EG1 controller on EG1's parameters              // calculate influence of EG1 controller on EG1's parameters
206              EGInfo egInfo = CalculateEG1ControllerInfluence(eg1controllervalue);              EGInfo egInfo = CalculateEG1ControllerInfluence(eg1controllervalue);
207    
208                if (pNote) {
209                    egInfo.Attack  *= pNote->Override.Attack;
210                    egInfo.Decay   *= pNote->Override.Decay;
211                    egInfo.Release *= pNote->Override.Release;
212                }
213    
214              TriggerEG1(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity);              TriggerEG1(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity);
215          } else {          } else {
216              GetSignalUnitRack()->Trigger();              pSignalUnitRack->Trigger();
217          }          }
218    
219            const uint8_t pan = (pSignalUnitRack) ? pSignalUnitRack->GetEndpointUnit()->CalculatePan(MIDIPan) : MIDIPan;
220            NotePanLeft  = (pNote) ? AbstractEngine::PanCurveValueNorm(pNote->Override.Pan, 0 /*left*/ ) : 1.f;
221            NotePanRight = (pNote) ? AbstractEngine::PanCurveValueNorm(pNote->Override.Pan, 1 /*right*/) : 1.f;
222            PanLeftSmoother.trigger(
223                AbstractEngine::PanCurve[128 - pan] * NotePanLeft,
224                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)
225            );
226            PanRightSmoother.trigger(
227                AbstractEngine::PanCurve[pan] * NotePanRight,
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    
231  #ifdef CONFIG_INTERPOLATE_VOLUME  #ifdef CONFIG_INTERPOLATE_VOLUME
232          // setup initial volume in synthesis parameters          // setup initial volume in synthesis parameters
233      #ifdef CONFIG_PROCESS_MUTED_CHANNELS      #ifdef CONFIG_PROCESS_MUTED_CHANNELS
# Line 201  namespace LinuxSampler { Line 239  namespace LinuxSampler {
239      #else      #else
240          {          {
241              float finalVolume;              float finalVolume;
242              if (GetSignalUnitRack() == NULL) {              if (pSignalUnitRack == NULL) {
243                  finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pEG1->getLevel();                  finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pEG1->getLevel();
244              } else {              } else {
245                  finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * GetSignalUnitRack()->GetEndpointUnit()->GetVolume();                  finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pSignalUnitRack->GetEndpointUnit()->GetVolume();
246              }              }
247    
248              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * pEngineChannel->GlobalPanLeft;              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * PanLeftSmoother.render();
249              finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * pEngineChannel->GlobalPanRight;              finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * PanRightSmoother.render();
250          }          }
251      #endif      #endif
252  #endif  #endif
253    
254          if (GetSignalUnitRack() == NULL) {          if (pSignalUnitRack == NULL) {
255              // setup EG 2 (VCF Cutoff EG)              // setup EG 2 (VCF Cutoff EG)
256              {              {
257                  // get current value of EG2 controller                  // get current value of EG2 controller
# Line 231  namespace LinuxSampler { Line 269  namespace LinuxSampler {
269                  // 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
270                  bool  bPortamento = pEngineChannel->PortamentoMode && pEngineChannel->PortamentoPos >= 0.0f;                  bool  bPortamento = pEngineChannel->PortamentoMode && pEngineChannel->PortamentoPos >= 0.0f;
271                  float eg3depth = (bPortamento)                  float eg3depth = (bPortamento)
272                               ? RTMath::CentsToFreqRatio((pEngineChannel->PortamentoPos - (float) MIDIKey) * 100)                               ? RTMath::CentsToFreqRatio((pEngineChannel->PortamentoPos - (float) MIDIKey()) * 100)
273                               : RTMath::CentsToFreqRatio(RgnInfo.EG3Depth);                               : RTMath::CentsToFreqRatio(RgnInfo.EG3Depth);
274                  float eg3time = (bPortamento)                  float eg3time = (bPortamento)
275                              ? pEngineChannel->PortamentoTime                              ? pEngineChannel->PortamentoTime
# Line 292  namespace LinuxSampler { Line 330  namespace LinuxSampler {
330              VCFCutoffCtrl.controller    = 0;              VCFCutoffCtrl.controller    = 0;
331              VCFResonanceCtrl.controller = 0;              VCFResonanceCtrl.controller = 0;
332          }          }
333            
334            const bool bEq =
335                pSignalUnitRack != NULL && pSignalUnitRack->HasEq() && pEq->HasSupport();
336    
337            if (bEq) {
338                pEq->GetInChannelLeft()->Clear();
339                pEq->GetInChannelRight()->Clear();
340                pEq->RenderAudio(GetEngine()->pAudioOutputDevice->MaxSamplesPerCycle());
341            }
342    
343          return 0; // success          return 0; // success
344      }      }
345        
346        void AbstractVoice::SetSampleStartOffset() {
347            finalSynthesisParameters.dPos = RgnInfo.SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)
348            Pos = RgnInfo.SampleStartOffset;
349        }
350    
351      /**      /**
352       *  Synthesizes the current audio fragment for this voice.       *  Synthesizes the current audio fragment for this voice.
# Line 305  namespace LinuxSampler { Line 357  namespace LinuxSampler {
357       *  @param Skip    - number of sample points to skip in output buffer       *  @param Skip    - number of sample points to skip in output buffer
358       */       */
359      void AbstractVoice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {      void AbstractVoice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {
360            bool delay = false; // Whether the voice playback should be delayed for this call
361            
362            if (pSignalUnitRack != NULL) {
363                uint delaySteps = pSignalUnitRack->GetEndpointUnit()->DelayTrigger();
364                if (delaySteps > 0) { // delay on the endpoint unit means delay of the voice playback
365                    if (delaySteps >= Samples) {
366                        pSignalUnitRack->GetEndpointUnit()->DecreaseDelay(Samples);
367                        delay = true;
368                    } else {
369                        pSignalUnitRack->GetEndpointUnit()->DecreaseDelay(delaySteps);
370                        Samples -= delaySteps;
371                        Skip += delaySteps;
372                    }
373                }
374            }
375            
376          AbstractEngineChannel* pChannel = pEngineChannel;          AbstractEngineChannel* pChannel = pEngineChannel;
377          MidiKeyBase* pMidiKeyInfo = GetMidiKeyInfo(MIDIKey);          MidiKeyBase* pMidiKeyInfo = GetMidiKeyInfo(MIDIKey());
378    
379          const bool bVoiceRequiresDedicatedRouting =          const bool bVoiceRequiresDedicatedRouting =
380              pEngineChannel->GetFxSendCount() > 0 &&              pEngineChannel->GetFxSendCount() > 0 &&
381              (pMidiKeyInfo->ReverbSend || pMidiKeyInfo->ChorusSend);              (pMidiKeyInfo->ReverbSend || pMidiKeyInfo->ChorusSend);
382            
383            const bool bEq =
384                pSignalUnitRack != NULL && pSignalUnitRack->HasEq() && pEq->HasSupport();
385    
386          if (bVoiceRequiresDedicatedRouting) {          if (bEq) {
387                pEq->GetInChannelLeft()->Clear();
388                pEq->GetInChannelRight()->Clear();
389                finalSynthesisParameters.pOutLeft  = &pEq->GetInChannelLeft()->Buffer()[Skip];
390                finalSynthesisParameters.pOutRight = &pEq->GetInChannelRight()->Buffer()[Skip];
391                pSignalUnitRack->UpdateEqSettings(pEq);
392            } else if (bVoiceRequiresDedicatedRouting) {
393              finalSynthesisParameters.pOutLeft  = &GetEngine()->pDedicatedVoiceChannelLeft->Buffer()[Skip];              finalSynthesisParameters.pOutLeft  = &GetEngine()->pDedicatedVoiceChannelLeft->Buffer()[Skip];
394              finalSynthesisParameters.pOutRight = &GetEngine()->pDedicatedVoiceChannelRight->Buffer()[Skip];              finalSynthesisParameters.pOutRight = &GetEngine()->pDedicatedVoiceChannelRight->Buffer()[Skip];
395          } else {          } else {
# Line 323  namespace LinuxSampler { Line 400  namespace LinuxSampler {
400    
401          RTList<Event>::Iterator itCCEvent = pChannel->pEvents->first();          RTList<Event>::Iterator itCCEvent = pChannel->pEvents->first();
402          RTList<Event>::Iterator itNoteEvent;          RTList<Event>::Iterator itNoteEvent;
403          GetFirstEventOnKey(MIDIKey, itNoteEvent);          GetFirstEventOnKey(HostKey(), itNoteEvent);
404    
405          RTList<Event>::Iterator itGroupEvent;          RTList<Event>::Iterator itGroupEvent;
406          if (pGroupEvents) itGroupEvent = pGroupEvents->first();          if (pGroupEvents && !Orphan) itGroupEvent = pGroupEvents->first();
407    
408          if (itTriggerEvent) { // skip events that happened before this voice was triggered          if (itTriggerEvent) { // skip events that happened before this voice was triggered
409              while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;              while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;
# Line 343  namespace LinuxSampler { Line 420  namespace LinuxSampler {
420              }              }
421          }          }
422    
423          uint killPos;          uint killPos = 0;
424          if (itKillEvent) {          if (itKillEvent) {
425              int maxFadeOutPos = Samples - GetEngine()->GetMinFadeOutSamples();              int maxFadeOutPos = Samples - GetEngine()->GetMinFadeOutSamples();
426              if (maxFadeOutPos < 0) {              if (maxFadeOutPos < 0) {
# Line 352  namespace LinuxSampler { Line 429  namespace LinuxSampler {
429                  // drivers that use Samples < MaxSamplesPerCycle).                  // drivers that use Samples < MaxSamplesPerCycle).
430                  // End the EG1 here, at pos 0, with a shorter max fade                  // End the EG1 here, at pos 0, with a shorter max fade
431                  // out time.                  // out time.
432                  if (GetSignalUnitRack() == NULL) {                  if (pSignalUnitRack == NULL) {
433                      pEG1->enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                      pEG1->enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
434                  } else {                  } else {
435                      // TODO:                      pSignalUnitRack->EnterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
436                  }                  }
437                  itKillEvent = Pool<Event>::Iterator();                  itKillEvent = Pool<Event>::Iterator();
438              } else {              } else {
# Line 371  namespace LinuxSampler { Line 448  namespace LinuxSampler {
448              fFinalCutoff    = VCFCutoffCtrl.fvalue;              fFinalCutoff    = VCFCutoffCtrl.fvalue;
449              fFinalResonance = VCFResonanceCtrl.fvalue;              fFinalResonance = VCFResonanceCtrl.fvalue;
450    
451              // process MIDI control change and pitchbend events for this subfragment              // process MIDI control change, aftertouch and pitchbend events for this subfragment
452              processCCEvents(itCCEvent, iSubFragmentEnd);              processCCEvents(itCCEvent, iSubFragmentEnd);
453                uint8_t pan = MIDIPan;
454                if (pSignalUnitRack != NULL) pan = pSignalUnitRack->GetEndpointUnit()->CalculatePan(MIDIPan);
455    
456                PanLeftSmoother.update(AbstractEngine::PanCurve[128 - pan] * NotePanLeft);
457                PanRightSmoother.update(AbstractEngine::PanCurve[pan]      * NotePanRight);
458    
459              finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend;              finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend * NotePitch;
460              float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render();  
461                float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render() * NoteVolumeSmoother.render();
462  #ifdef CONFIG_PROCESS_MUTED_CHANNELS  #ifdef CONFIG_PROCESS_MUTED_CHANNELS
463              if (pChannel->GetMute()) fFinalVolume = 0;              if (pChannel->GetMute()) fFinalVolume = 0;
464  #endif  #endif
# Line 383  namespace LinuxSampler { Line 466  namespace LinuxSampler {
466              // process transition events (note on, note off & sustain pedal)              // process transition events (note on, note off & sustain pedal)
467              processTransitionEvents(itNoteEvent, iSubFragmentEnd);              processTransitionEvents(itNoteEvent, iSubFragmentEnd);
468              processGroupEvents(itGroupEvent, iSubFragmentEnd);              processGroupEvents(itGroupEvent, iSubFragmentEnd);
469                
470              if (GetSignalUnitRack() == NULL) {              if (pSignalUnitRack == NULL) {
471                  // if the voice was killed in this subfragment, or if the                  // if the voice was killed in this subfragment, or if the
472                  // filter EG is finished, switch EG1 to fade out stage                  // filter EG is finished, switch EG1 to fade out stage
473                  if ((itKillEvent && killPos <= iSubFragmentEnd) ||                  if ((itKillEvent && killPos <= iSubFragmentEnd) ||
# Line 427  namespace LinuxSampler { Line 510  namespace LinuxSampler {
510    
511                  // process low frequency oscillators                  // process low frequency oscillators
512                  if (bLFO1Enabled) fFinalVolume *= (1.0f - pLFO1->render());                  if (bLFO1Enabled) fFinalVolume *= (1.0f - pLFO1->render());
513                  if (bLFO2Enabled) fFinalCutoff *= pLFO2->render();                  if (bLFO2Enabled) fFinalCutoff *= (1.0f - pLFO2->render());
514                  if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());                  if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());
515              } else {              } else {
516                  // if the voice was killed in this subfragment, or if the                  // if the voice was killed in this subfragment, enter fade out stage
517                  // filter EG is finished, switch EG1 to fade out stage                  if (itKillEvent && killPos <= iSubFragmentEnd) {
518                  /*if ((itKillEvent && killPos <= iSubFragmentEnd) ||                      pSignalUnitRack->EnterFadeOutStage();
519                      (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&                      itKillEvent = Pool<Event>::Iterator();
520                      pEG2->getSegmentType() == EG::segment_end)) {                  }
521                    
522                    // if the filter EG is finished, switch EG1 to fade out stage
523                    /*if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&
524                        pEG2->getSegmentType() == EG::segment_end) {
525                      pEG1->enterFadeOutStage();                      pEG1->enterFadeOutStage();
526                      itKillEvent = Pool<Event>::Iterator();                      itKillEvent = Pool<Event>::Iterator();
527                  }*/                  }*/
528                  // TODO: ^^^                  // TODO: ^^^
529    
530                  fFinalVolume   *= GetSignalUnitRack()->GetEndpointUnit()->GetVolume();                  fFinalVolume   *= pSignalUnitRack->GetEndpointUnit()->GetVolume();
531                  fFinalCutoff    = GetSignalUnitRack()->GetEndpointUnit()->CalculateFilterCutoff(fFinalCutoff);                  fFinalCutoff    = pSignalUnitRack->GetEndpointUnit()->CalculateFilterCutoff(fFinalCutoff);
532                  fFinalResonance = GetSignalUnitRack()->GetEndpointUnit()->CalculateResonance(fFinalResonance);                  fFinalResonance = pSignalUnitRack->GetEndpointUnit()->CalculateResonance(fFinalResonance);
533                                    
534                  finalSynthesisParameters.fFinalPitch =                  finalSynthesisParameters.fFinalPitch =
535                      GetSignalUnitRack()->GetEndpointUnit()->CalculatePitch(finalSynthesisParameters.fFinalPitch);                      pSignalUnitRack->GetEndpointUnit()->CalculatePitch(finalSynthesisParameters.fFinalPitch);
536                                            
537              }              }
538                
539                fFinalCutoff    *= NoteCutoff;
540                fFinalResonance *= NoteResonance;
541    
542              // limit the pitch so we don't read outside the buffer              // limit the pitch so we don't read outside the buffer
543              finalSynthesisParameters.fFinalPitch = RTMath::Min(finalSynthesisParameters.fFinalPitch, float(1 << CONFIG_MAX_PITCH));              finalSynthesisParameters.fFinalPitch = RTMath::Min(finalSynthesisParameters.fFinalPitch, float(1 << CONFIG_MAX_PITCH));
544    
# Line 481  namespace LinuxSampler { Line 571  namespace LinuxSampler {
571                  fFinalVolume * VolumeRight * PanRightSmoother.render();                  fFinalVolume * VolumeRight * PanRightSmoother.render();
572  #endif  #endif
573              // render audio for one subfragment              // render audio for one subfragment
574              RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);              if (!delay) RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);
575    
576              if (GetSignalUnitRack() == NULL) {              if (pSignalUnitRack == NULL) {
577                  // stop the rendering if volume EG is finished                  // stop the rendering if volume EG is finished
578                  if (pEG1->getSegmentType() == EG::segment_end) break;                  if (pEG1->getSegmentType() == EG::segment_end) break;
579              } else {              } else {
580                  // stop the rendering if the endpoint unit is not active                  // stop the rendering if the endpoint unit is not active
581                  if (!GetSignalUnitRack()->GetEndpointUnit()->Active()) break;                  if (!pSignalUnitRack->GetEndpointUnit()->Active()) break;
582              }              }
583    
584              const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;              const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;
585    
586              if (GetSignalUnitRack() == NULL) {              if (pSignalUnitRack == NULL) {
587                  // increment envelopes' positions                  // increment envelopes' positions
588                  if (pEG1->active()) {                  if (pEG1->active()) {
589    
# Line 518  namespace LinuxSampler { Line 608  namespace LinuxSampler {
608                      }*/                      }*/
609                  // TODO: ^^^                  // TODO: ^^^
610                                    
611                  GetSignalUnitRack()->Increment();                  if (!delay) pSignalUnitRack->Increment();
612              }              }
613    
614              Pos = newPos;              Pos = newPos;
615              i = iSubFragmentEnd;              i = iSubFragmentEnd;
616          }          }
617            
618            if (delay) return;
619    
620          if (bVoiceRequiresDedicatedRouting) {          if (bVoiceRequiresDedicatedRouting) {
621                if (bEq) {
622                    pEq->RenderAudio(Samples);
623                    pEq->GetOutChannelLeft()->CopyTo(GetEngine()->pDedicatedVoiceChannelLeft, Samples);
624                    pEq->GetOutChannelRight()->CopyTo(GetEngine()->pDedicatedVoiceChannelRight, Samples);
625                }
626              optional<float> effectSendLevels[2] = {              optional<float> effectSendLevels[2] = {
627                  pMidiKeyInfo->ReverbSend,                  pMidiKeyInfo->ReverbSend,
628                  pMidiKeyInfo->ChorusSend                  pMidiKeyInfo->ChorusSend
629              };              };
630              GetEngine()->RouteDedicatedVoiceChannels(pEngineChannel, effectSendLevels, Samples);              GetEngine()->RouteDedicatedVoiceChannels(pEngineChannel, effectSendLevels, Samples);
631            } else if (bEq) {
632                pEq->RenderAudio(Samples);
633                pEq->GetOutChannelLeft()->MixTo(pChannel->pChannelLeft, Samples);
634                pEq->GetOutChannelRight()->MixTo(pChannel->pChannelRight, Samples);
635          }          }
636      }      }
637    
638      /**      /**
639       * Process given list of MIDI control change and pitch bend events for       * Process given list of MIDI control change, aftertouch and pitch bend
640       * the given time.       * events for the given time.
641       *       *
642       * @param itEvent - iterator pointing to the next event to be processed       * @param itEvent - iterator pointing to the next event to be processed
643       * @param End     - youngest time stamp where processing should be stopped       * @param End     - youngest time stamp where processing should be stopped
644       */       */
645      void AbstractVoice::processCCEvents(RTList<Event>::Iterator& itEvent, uint End) {      void AbstractVoice::processCCEvents(RTList<Event>::Iterator& itEvent, uint End) {
646          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
647              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)
648                    && itEvent->Param.CC.Controller) // if (valid) MIDI control change event
649                {
650                  if (itEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {                  if (itEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {
651                      ProcessCutoffEvent(itEvent);                      ProcessCutoffEvent(itEvent);
652                  }                  }
653                  if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {                  if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {
654                      processResonanceEvent(itEvent);                      processResonanceEvent(itEvent);
655                  }                  }
656                  if (GetSignalUnitRack() == NULL) {                  if (itEvent->Param.CC.Controller == CTRL_TABLE_IDX_AFTERTOUCH ||
657                        itEvent->Type == Event::type_channel_pressure)
658                    {
659                        ProcessChannelPressureEvent(itEvent);
660                    }
661                    if (pSignalUnitRack == NULL) {
662                      if (itEvent->Param.CC.Controller == pLFO1->ExtController) {                      if (itEvent->Param.CC.Controller == pLFO1->ExtController) {
663                          pLFO1->update(itEvent->Param.CC.Value);                          pLFO1->updateByMIDICtrlValue(itEvent->Param.CC.Value);
664                      }                      }
665                      if (itEvent->Param.CC.Controller == pLFO2->ExtController) {                      if (itEvent->Param.CC.Controller == pLFO2->ExtController) {
666                          pLFO2->update(itEvent->Param.CC.Value);                          pLFO2->updateByMIDICtrlValue(itEvent->Param.CC.Value);
667                      }                      }
668                      if (itEvent->Param.CC.Controller == pLFO3->ExtController) {                      if (itEvent->Param.CC.Controller == pLFO3->ExtController) {
669                          pLFO3->update(itEvent->Param.CC.Value);                          pLFO3->updateByMIDICtrlValue(itEvent->Param.CC.Value);
670                      }                      }
671                  }                  }
672                  if (itEvent->Param.CC.Controller == 7) { // volume                  if (itEvent->Param.CC.Controller == 7) { // volume
673                      VolumeSmoother.update(AbstractEngine::VolumeCurve[itEvent->Param.CC.Value]);                      VolumeSmoother.update(AbstractEngine::VolumeCurve[itEvent->Param.CC.Value]);
674                  } else if (itEvent->Param.CC.Controller == 10) { // panpot                  } else if (itEvent->Param.CC.Controller == 10) { // panpot
675                      PanLeftSmoother.update(AbstractEngine::PanCurve[128 - itEvent->Param.CC.Value]);                      MIDIPan = CalculatePan(itEvent->Param.CC.Value);
                     PanRightSmoother.update(AbstractEngine::PanCurve[itEvent->Param.CC.Value]);  
676                  }                  }
677              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event
678                  processPitchEvent(itEvent);                  processPitchEvent(itEvent);
679                } else if (itEvent->Type == Event::type_note_pressure) {
680                    ProcessPolyphonicKeyPressureEvent(itEvent);
681              }              }
682    
683              ProcessCCEvent(itEvent);              ProcessCCEvent(itEvent);
684              if (GetSignalUnitRack() != NULL) {              if (pSignalUnitRack != NULL) {
685                  GetSignalUnitRack()->ProcessCCEvent(itEvent);                  pSignalUnitRack->ProcessCCEvent(itEvent);
686              }              }
687          }          }
688      }      }
# Line 593  namespace LinuxSampler { Line 702  namespace LinuxSampler {
702      }      }
703    
704      /**      /**
705       * 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
706       * for the given time.       * note synthesis parameter events for the given time.
707       *       *
708       * @param itEvent - iterator pointing to the next event to be processed       * @param itEvent - iterator pointing to the next event to be processed
709       * @param End     - youngest time stamp where processing should be stopped       * @param End     - youngest time stamp where processing should be stopped
# Line 603  namespace LinuxSampler { Line 712  namespace LinuxSampler {
712          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
713              // some voice types ignore note off              // some voice types ignore note off
714              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))) {
715                  if (itEvent->Type == Event::type_release) {                  if (itEvent->Type == Event::type_release_key) {
716                      EnterReleaseStage();                      EnterReleaseStage();
717                  } else if (itEvent->Type == Event::type_cancel_release) {                  } else if (itEvent->Type == Event::type_cancel_release_key) {
718                      if (GetSignalUnitRack() == NULL) {                      if (pSignalUnitRack == NULL) {
719                          pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                          pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
720                          pEG2->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                          pEG2->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
721                      } else {                      } else {
722                          GetSignalUnitRack()->CancelRelease();                          pSignalUnitRack->CancelRelease();
723                      }                      }
724                  }                  }
725              }              }
726                // process stop-note events (caused by built-in instrument script function note_off())
727                if (itEvent->Type == Event::type_release_note && pNote &&
728                    pEngineChannel->pEngine->NoteByID( itEvent->Param.Note.ID ) == pNote)
729                {
730                    EnterReleaseStage();
731                }
732                // process synthesis parameter events (caused by built-in realt-time instrument script functions)
733                if (itEvent->Type == Event::type_note_synth_param && pNote &&
734                    pEngineChannel->pEngine->NoteByID( itEvent->Param.NoteSynthParam.NoteID ) == pNote)
735                {
736                    switch (itEvent->Param.NoteSynthParam.Type) {
737                        case Event::synth_param_volume:
738                            NoteVolumeSmoother.update(itEvent->Param.NoteSynthParam.AbsValue);
739                            break;
740                        case Event::synth_param_pitch:
741                            NotePitch = itEvent->Param.NoteSynthParam.AbsValue;
742                            break;
743                        case Event::synth_param_pan:
744                            NotePanLeft  = AbstractEngine::PanCurveValueNorm(itEvent->Param.NoteSynthParam.AbsValue, 0 /*left*/);
745                            NotePanRight = AbstractEngine::PanCurveValueNorm(itEvent->Param.NoteSynthParam.AbsValue, 1 /*right*/);
746                            break;
747                        case Event::synth_param_cutoff:
748                            NoteCutoff = itEvent->Param.NoteSynthParam.AbsValue;
749                            break;
750                        case Event::synth_param_resonance:
751                            NoteResonance = itEvent->Param.NoteSynthParam.AbsValue;
752                            break;
753                        case Event::synth_param_amp_lfo_depth:
754                            pLFO1->setScriptDepthFactor(itEvent->Param.NoteSynthParam.AbsValue);
755                            break;
756                        case Event::synth_param_amp_lfo_freq:
757                            pLFO1->setScriptFrequencyFactor(itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
758                            break;
759                        case Event::synth_param_pitch_lfo_depth:
760                            pLFO3->setScriptDepthFactor(itEvent->Param.NoteSynthParam.AbsValue);
761                            break;
762                        case Event::synth_param_pitch_lfo_freq:
763                            pLFO3->setScriptFrequencyFactor(itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
764                            break;
765    
766                        case Event::synth_param_attack:
767                        case Event::synth_param_decay:
768                        case Event::synth_param_release:
769                            break; // noop
770                    }
771                }
772          }          }
773      }      }
774    
# Line 638  namespace LinuxSampler { Line 793  namespace LinuxSampler {
793       * @param itNoteOffEvent - event which causes this voice to die soon       * @param itNoteOffEvent - event which causes this voice to die soon
794       */       */
795      void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {      void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {
796          if (GetSignalUnitRack() == NULL) {          if (pSignalUnitRack == NULL) {
797              const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());              const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());
798              pEngineChannel->PortamentoPos = (float) MIDIKey + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;              pEngineChannel->PortamentoPos = (float) MIDIKey() + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;
799          } else {          } else {
800              // TODO:              // TODO:
801          }          }
# Line 667  namespace LinuxSampler { Line 822  namespace LinuxSampler {
822    
823      Voice::PitchInfo AbstractVoice::CalculatePitchInfo(int PitchBend) {      Voice::PitchInfo AbstractVoice::CalculatePitchInfo(int PitchBend) {
824          PitchInfo pitch;          PitchInfo pitch;
825          double pitchbasecents = InstrInfo.FineTune + RgnInfo.FineTune + GetEngine()->ScaleTuning[MIDIKey % 12];          double pitchbasecents = InstrInfo.FineTune + RgnInfo.FineTune + GetEngine()->ScaleTuning[MIDIKey() % 12];
826    
827          // GSt behaviour: maximum transpose up is 40 semitones. If          // GSt behaviour: maximum transpose up is 40 semitones. If
828          // MIDI key is more than 40 semitones above unity note,          // MIDI key is more than 40 semitones above unity note,
829          // the transpose is not done.          // the transpose is not done.
830          if (!SmplInfo.Unpitched && (MIDIKey - (int) RgnInfo.UnityNote) < 40) pitchbasecents += (MIDIKey - (int) RgnInfo.UnityNote) * 100;          if (!SmplInfo.Unpitched && (MIDIKey() - (int) RgnInfo.UnityNote) < 40) pitchbasecents += (MIDIKey() - (int) RgnInfo.UnityNote) * 100;
831    
832          pitch.PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(SmplInfo.SampleRate) / double(GetEngine()->SampleRate));          pitch.PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(SmplInfo.SampleRate) / double(GetEngine()->SampleRate));
833          pitch.PitchBendRange = 1.0 / 8192.0 * 100.0 * InstrInfo.PitchbendRange;          pitch.PitchBendRange = 1.0 / 8192.0 * 100.0 * InstrInfo.PitchbendRange;
# Line 680  namespace LinuxSampler { Line 835  namespace LinuxSampler {
835    
836          return pitch;          return pitch;
837      }      }
838        
839        void AbstractVoice::onScaleTuningChanged() {
840            PitchInfo pitch = this->Pitch;
841            double pitchbasecents = InstrInfo.FineTune + RgnInfo.FineTune + GetEngine()->ScaleTuning[MIDIKey() % 12];
842            
843            // GSt behaviour: maximum transpose up is 40 semitones. If
844            // MIDI key is more than 40 semitones above unity note,
845            // the transpose is not done.
846            if (!SmplInfo.Unpitched && (MIDIKey() - (int) RgnInfo.UnityNote) < 40) pitchbasecents += (MIDIKey() - (int) RgnInfo.UnityNote) * 100;
847            
848            pitch.PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(SmplInfo.SampleRate) / double(GetEngine()->SampleRate));
849            this->Pitch = pitch;
850        }
851    
852      double AbstractVoice::CalculateVolume(double velocityAttenuation) {      double AbstractVoice::CalculateVolume(double velocityAttenuation) {
853          // For 16 bit samples, we downscale by 32768 to convert from          // For 16 bit samples, we downscale by 32768 to convert from
# Line 692  namespace LinuxSampler { Line 860  namespace LinuxSampler {
860          // the volume of release triggered samples depends on note length          // the volume of release triggered samples depends on note length
861          if (Type & Voice::type_release_trigger) {          if (Type & Voice::type_release_trigger) {
862              float noteLength = float(GetEngine()->FrameTime + Delay -              float noteLength = float(GetEngine()->FrameTime + Delay -
863                  GetNoteOnTime(MIDIKey) ) / GetEngine()->SampleRate;                  GetNoteOnTime(MIDIKey()) ) / GetEngine()->SampleRate;
864    
865              volume *= GetReleaseTriggerAttenuation(noteLength);              volume *= GetReleaseTriggerAttenuation(noteLength);
866          }          }
# Line 705  namespace LinuxSampler { Line 873  namespace LinuxSampler {
873      }      }
874    
875      void AbstractVoice::EnterReleaseStage() {      void AbstractVoice::EnterReleaseStage() {
876          if (GetSignalUnitRack() == NULL) {          if (pSignalUnitRack == NULL) {
877              pEG1->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);              pEG1->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
878              pEG2->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);              pEG2->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
879          } else {          } else {
880              GetSignalUnitRack()->EnterReleaseStage();              pSignalUnitRack->EnterReleaseStage();
881          }          }
882      }      }
883    
884      bool AbstractVoice::EG1Finished() {      bool AbstractVoice::EG1Finished() {
885          if (GetSignalUnitRack() == NULL) {          if (pSignalUnitRack == NULL) {
886              return pEG1->getSegmentType() == EG::segment_end;              return pEG1->getSegmentType() == EG::segment_end;
887          } else {          } else {
888              return !GetSignalUnitRack()->GetEndpointUnit()->Active();              return !pSignalUnitRack->GetEndpointUnit()->Active();
889          }          }
890      }      }
891    

Legend:
Removed from v.2205  
changed lines
  Added in v.3118

  ViewVC Help
Powered by ViewVC