/[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 2032 by persson, Fri Nov 20 20:13:08 2009 UTC revision 2559 by schoenebeck, Sun May 18 17:38:25 2014 UTC
# Line 3  Line 3 
3   *   LinuxSampler - modular, streaming capable sampler                     *   *   LinuxSampler - modular, streaming capable sampler                     *
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-2009 Christian Schoenebeck                         *   *   Copyright (C) 2005-2008 Christian Schoenebeck                         *
7   *   Copyright (C) 2009 Grigor Iliev                                       *   *   Copyright (C) 2009-2012 Christian Schoenebeck and Grigor Iliev        *
8   *                                                                         *   *                                                                         *
9   *   This program is free software; you can redistribute it and/or modify  *   *   This program is free software; you can redistribute it and/or modify  *
10   *   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 26 
26    
27  namespace LinuxSampler {  namespace LinuxSampler {
28    
29      AbstractVoice::AbstractVoice() {      AbstractVoice::AbstractVoice(SignalUnitRack* pRack): pSignalUnitRack(pRack) {
30          pEngineChannel = NULL;          pEngineChannel = NULL;
31          pLFO1 = new LFOUnsigned(1.0f);  // amplitude EG (0..1 range)          pLFO1 = new LFOUnsigned(1.0f);  // amplitude LFO (0..1 range)
32          pLFO2 = new LFOUnsigned(1.0f);  // filter EG (0..1 range)          pLFO2 = new LFOUnsigned(1.0f);  // filter LFO (0..1 range)
33          pLFO3 = new LFOSigned(1200.0f); // pitch EG (-1200..+1200 range)          pLFO3 = new LFOSigned(1200.0f); // pitch LFO (-1200..+1200 range)
34          PlaybackState = playback_state_end;          PlaybackState = playback_state_end;
         KeyGroup = 0;  
35          SynthesisMode = 0; // set all mode bits to 0 first          SynthesisMode = 0; // set all mode bits to 0 first
36          // select synthesis implementation (asm core is not supported ATM)          // select synthesis implementation (asm core is not supported ATM)
37          #if 0 // CONFIG_ASM && ARCH_X86          #if 0 // CONFIG_ASM && ARCH_X86
# Line 44  namespace LinuxSampler { Line 43  namespace LinuxSampler {
43    
44          finalSynthesisParameters.filterLeft.Reset();          finalSynthesisParameters.filterLeft.Reset();
45          finalSynthesisParameters.filterRight.Reset();          finalSynthesisParameters.filterRight.Reset();
46            
47            pEq          = NULL;
48            bEqSupport   = false;
49      }      }
50    
51      AbstractVoice::~AbstractVoice() {      AbstractVoice::~AbstractVoice() {
52          if (pLFO1) delete pLFO1;          if (pLFO1) delete pLFO1;
53          if (pLFO2) delete pLFO2;          if (pLFO2) delete pLFO2;
54          if (pLFO3) delete pLFO3;          if (pLFO3) delete pLFO3;
55            
56            if(pEq != NULL) delete pEq;
57      }      }
58                    
59        void AbstractVoice::CreateEq() {
60            if(!bEqSupport) return;
61            if(pEq != NULL) delete pEq;
62            pEq = new EqSupport;
63            pEq->InitEffect(GetEngine()->pAudioOutputDevice);
64        }
65    
66      /**      /**
67       *  Resets voice variables. Should only be called if rendering process is       *  Resets voice variables. Should only be called if rendering process is
68       *  suspended / not running.       *  suspended / not running.
# Line 100  namespace LinuxSampler { Line 111  namespace LinuxSampler {
111    
112          Type            = VoiceType;          Type            = VoiceType;
113          MIDIKey         = itNoteOnEvent->Param.Note.Key;          MIDIKey         = itNoteOnEvent->Param.Note.Key;
114            MIDIVelocity    = itNoteOnEvent->Param.Note.Velocity;
115          PlaybackState   = playback_state_init; // mark voice as triggered, but no audio rendered yet          PlaybackState   = playback_state_init; // mark voice as triggered, but no audio rendered yet
116          Delay           = itNoteOnEvent->FragmentPos();          Delay           = itNoteOnEvent->FragmentPos();
117          itTriggerEvent  = itNoteOnEvent;          itTriggerEvent  = itNoteOnEvent;
118          itKillEvent     = Pool<Event>::Iterator();          itKillEvent     = Pool<Event>::Iterator();
119          KeyGroup        = iKeyGroup;          MidiKeyBase* pKeyInfo = GetMidiKeyInfo(MIDIKey);
120    
121            pGroupEvents = iKeyGroup ? pEngineChannel->ActiveKeyGroups[iKeyGroup] : 0;
122    
123          SmplInfo   = GetSampleInfo();          SmplInfo   = GetSampleInfo();
124          RgnInfo    = GetRegionInfo();          RgnInfo    = GetRegionInfo();
125          InstrInfo  = GetInstrumentInfo();          InstrInfo  = GetInstrumentInfo();
126            
127            MIDIPan    = CalculatePan(pEngineChannel->iLastPanRequest);
128    
129            AboutToTrigger();
130    
131          // calculate volume          // calculate volume
132          const double velocityAttenuation = GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity);          const double velocityAttenuation = GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity);
133          float volume = CalculateVolume(velocityAttenuation);          float volume = CalculateVolume(velocityAttenuation) * pKeyInfo->Volume;
134          if (volume <= 0) return -1;          if (volume <= 0) return -1;
135    
136          // select channel mode (mono or stereo)          // select channel mode (mono or stereo)
# Line 123  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 * AbstractEngine::PanCurve[64 - RgnInfo.Pan];          VolumeLeft  = volume * pKeyInfo->PanLeft;
145          VolumeRight = volume * AbstractEngine::PanCurve[64 + RgnInfo.Pan];          VolumeRight = volume * pKeyInfo->PanRight;
146    
147          float subfragmentRate = GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;          float subfragmentRate = GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;
148          CrossfadeSmoother.trigger(crossfadeVolume, subfragmentRate);          CrossfadeSmoother.trigger(crossfadeVolume, subfragmentRate);
149          VolumeSmoother.trigger(pEngineChannel->MidiVolume, subfragmentRate);          VolumeSmoother.trigger(pEngineChannel->MidiVolume, subfragmentRate);
         PanLeftSmoother.trigger(pEngineChannel->GlobalPanLeft, subfragmentRate);  
         PanRightSmoother.trigger(pEngineChannel->GlobalPanRight, subfragmentRate);  
   
         finalSynthesisParameters.dPos = RgnInfo.SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)  
         Pos = RgnInfo.SampleStartOffset;  
150    
151          // 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
152          long cachedsamples = GetSampleCacheSize() / SmplInfo.FrameSize;          long cachedsamples = GetSampleCacheSize() / SmplInfo.FrameSize;
153          DiskVoice          = cachedsamples < SmplInfo.TotalFrameCount;          DiskVoice          = cachedsamples < SmplInfo.TotalFrameCount;
154    
155            SetSampleStartOffset();
156    
157          if (DiskVoice) { // voice to be streamed from disk          if (DiskVoice) { // voice to be streamed from disk
158              if (cachedsamples > (GetEngine()->MaxSamplesPerCycle << CONFIG_MAX_PITCH)) {              if (cachedsamples > (GetEngine()->MaxSamplesPerCycle << CONFIG_MAX_PITCH)) {
159                  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 175  namespace LinuxSampler { Line 190  namespace LinuxSampler {
190          // 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
191          const double velrelease = 1 / GetVelocityRelease(itNoteOnEvent->Param.Note.Velocity);          const double velrelease = 1 / GetVelocityRelease(itNoteOnEvent->Param.Note.Velocity);
192    
193          // setup EG 1 (VCA EG)          if (pSignalUnitRack == NULL) { // setup EG 1 (VCA EG)
         {  
194              // get current value of EG1 controller              // get current value of EG1 controller
195              double eg1controllervalue = GetEG1ControllerValue(itNoteOnEvent->Param.Note.Velocity);              double eg1controllervalue = GetEG1ControllerValue(itNoteOnEvent->Param.Note.Velocity);
196    
197              // calculate influence of EG1 controller on EG1's parameters              // calculate influence of EG1 controller on EG1's parameters
198              EGInfo egInfo = CalculateEG1ControllerInfluence(eg1controllervalue);              EGInfo egInfo = CalculateEG1ControllerInfluence(eg1controllervalue);
199    
200              EG1.trigger (              TriggerEG1(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity);
201                  RgnInfo.EG1PreAttack,          } else {
202                  RgnInfo.EG1Attack * egInfo.Attack,              pSignalUnitRack->Trigger();
                 RgnInfo.EG1Hold,  
                 RgnInfo.EG1Decay1 * egInfo.Decay * velrelease,  
                 RgnInfo.EG1Decay2 * egInfo.Decay * velrelease,  
                 RgnInfo.EG1InfiniteSustain,  
                 RgnInfo.EG1Sustain,  
                 RgnInfo.EG1Release * egInfo.Release * velrelease,  
                 velocityAttenuation,  
                 GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE  
             );  
203          }          }
204    
205            uint8_t pan = MIDIPan;
206            if (pSignalUnitRack) pan = pSignalUnitRack->GetEndpointUnit()->CalculatePan(MIDIPan);
207            PanLeftSmoother.trigger(AbstractEngine::PanCurve[128 - pan], subfragmentRate);
208            PanRightSmoother.trigger(AbstractEngine::PanCurve[pan], subfragmentRate);
209    
210  #ifdef CONFIG_INTERPOLATE_VOLUME  #ifdef CONFIG_INTERPOLATE_VOLUME
211          // setup initial volume in synthesis parameters          // setup initial volume in synthesis parameters
212      #ifdef CONFIG_PROCESS_MUTED_CHANNELS      #ifdef CONFIG_PROCESS_MUTED_CHANNELS
# Line 207  namespace LinuxSampler { Line 217  namespace LinuxSampler {
217          else          else
218      #else      #else
219          {          {
220              float finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * EG1.getLevel();              float finalVolume;
221                if (pSignalUnitRack == NULL) {
222                    finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pEG1->getLevel();
223                } else {
224                    finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pSignalUnitRack->GetEndpointUnit()->GetVolume();
225                }
226    
227              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * pEngineChannel->GlobalPanLeft;              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * PanLeftSmoother.render();
228              finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * pEngineChannel->GlobalPanRight;              finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * PanRightSmoother.render();
229          }          }
230      #endif      #endif
231  #endif  #endif
232    
233          // setup EG 2 (VCF Cutoff EG)          if (pSignalUnitRack == NULL) {
234          {              // setup EG 2 (VCF Cutoff EG)
235              // get current value of EG2 controller              {
236              double eg2controllervalue = GetEG2ControllerValue(itNoteOnEvent->Param.Note.Velocity);                  // get current value of EG2 controller
237                    double eg2controllervalue = GetEG2ControllerValue(itNoteOnEvent->Param.Note.Velocity);
238    
239                    // calculate influence of EG2 controller on EG2's parameters
240                    EGInfo egInfo = CalculateEG2ControllerInfluence(eg2controllervalue);
241    
242                    TriggerEG2(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity);
243                }
244    
             // calculate influence of EG2 controller on EG2's parameters  
             EGInfo egInfo = CalculateEG2ControllerInfluence(eg2controllervalue);  
245    
246              EG2.trigger (              // setup EG 3 (VCO EG)
247                  RgnInfo.EG2PreAttack,              {
248                  RgnInfo.EG2Attack * egInfo.Attack,                  // if portamento mode is on, we dedicate EG3 purely for portamento, otherwise if portamento is off we do as told by the patch
249                  false,                  bool  bPortamento = pEngineChannel->PortamentoMode && pEngineChannel->PortamentoPos >= 0.0f;
250                  RgnInfo.EG2Decay1 * egInfo.Decay * velrelease,                  float eg3depth = (bPortamento)
251                  RgnInfo.EG2Decay2 * egInfo.Decay * velrelease,                               ? RTMath::CentsToFreqRatio((pEngineChannel->PortamentoPos - (float) MIDIKey) * 100)
252                  RgnInfo.EG2InfiniteSustain,                               : RTMath::CentsToFreqRatio(RgnInfo.EG3Depth);
253                  RgnInfo.EG2Sustain,                  float eg3time = (bPortamento)
254                  RgnInfo.EG2Release * egInfo.Release * velrelease,                              ? pEngineChannel->PortamentoTime
255                  velocityAttenuation,                              : RgnInfo.EG3Attack;
256                  GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE                  EG3.trigger(eg3depth, eg3time, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
257              );                  dmsg(5,("PortamentoPos=%f, depth=%f, time=%f\n", pEngineChannel->PortamentoPos, eg3depth, eg3time));
258          }              }
259    
260    
261          // setup EG 3 (VCO EG)              // setup LFO 1 (VCA LFO)
262          {              InitLFO1();
263              // if portamento mode is on, we dedicate EG3 purely for portamento, otherwise if portamento is off we do as told by the patch              // setup LFO 2 (VCF Cutoff LFO)
264              bool  bPortamento = pEngineChannel->PortamentoMode && pEngineChannel->PortamentoPos >= 0.0f;              InitLFO2();
265              float eg3depth = (bPortamento)              // setup LFO 3 (VCO LFO)
266                           ? RTMath::CentsToFreqRatio((pEngineChannel->PortamentoPos - (float) MIDIKey) * 100)              InitLFO3();
                          : RTMath::CentsToFreqRatio(RgnInfo.EG3Depth);  
             float eg3time = (bPortamento)  
                         ? pEngineChannel->PortamentoTime  
                         : RgnInfo.EG3Attack;  
             EG3.trigger(eg3depth, eg3time, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);  
             dmsg(5,("PortamentoPos=%f, depth=%f, time=%f\n", pEngineChannel->PortamentoPos, eg3depth, eg3time));  
267          }          }
268    
269    
         // setup LFO 1 (VCA LFO)  
         InitLFO1();  
         // setup LFO 2 (VCF Cutoff LFO)  
         InitLFO2();  
         // setup LFO 3 (VCO LFO)  
         InitLFO3();  
   
   
270          #if CONFIG_FORCE_FILTER          #if CONFIG_FORCE_FILTER
271          const bool bUseFilter = true;          const bool bUseFilter = true;
272          #else // use filter only if instrument file told so          #else // use filter only if instrument file told so
# Line 303  namespace LinuxSampler { Line 309  namespace LinuxSampler {
309              VCFCutoffCtrl.controller    = 0;              VCFCutoffCtrl.controller    = 0;
310              VCFResonanceCtrl.controller = 0;              VCFResonanceCtrl.controller = 0;
311          }          }
312            
313            const bool bEq =
314                pSignalUnitRack != NULL && pSignalUnitRack->HasEq() && pEq->HasSupport();
315    
316            if (bEq) {
317                pEq->GetInChannelLeft()->Clear();
318                pEq->GetInChannelRight()->Clear();
319                pEq->RenderAudio(GetEngine()->pAudioOutputDevice->MaxSamplesPerCycle());
320            }
321    
322          return 0; // success          return 0; // success
323      }      }
324        
325        void AbstractVoice::SetSampleStartOffset() {
326            finalSynthesisParameters.dPos = RgnInfo.SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)
327            Pos = RgnInfo.SampleStartOffset;
328        }
329    
330      /**      /**
331       *  Synthesizes the current audio fragment for this voice.       *  Synthesizes the current audio fragment for this voice.
# Line 316  namespace LinuxSampler { Line 336  namespace LinuxSampler {
336       *  @param Skip    - number of sample points to skip in output buffer       *  @param Skip    - number of sample points to skip in output buffer
337       */       */
338      void AbstractVoice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {      void AbstractVoice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {
339            bool delay = false; // Whether the voice playback should be delayed for this call
340            
341            if (pSignalUnitRack != NULL) {
342                uint delaySteps = pSignalUnitRack->GetEndpointUnit()->DelayTrigger();
343                if (delaySteps > 0) { // delay on the endpoint unit means delay of the voice playback
344                    if (delaySteps >= Samples) {
345                        pSignalUnitRack->GetEndpointUnit()->DecreaseDelay(Samples);
346                        delay = true;
347                    } else {
348                        pSignalUnitRack->GetEndpointUnit()->DecreaseDelay(delaySteps);
349                        Samples -= delaySteps;
350                        Skip += delaySteps;
351                    }
352                }
353            }
354            
355          AbstractEngineChannel* pChannel = pEngineChannel;          AbstractEngineChannel* pChannel = pEngineChannel;
356          finalSynthesisParameters.pOutLeft  = &pChannel->pChannelLeft->Buffer()[Skip];          MidiKeyBase* pMidiKeyInfo = GetMidiKeyInfo(MIDIKey);
357          finalSynthesisParameters.pOutRight = &pChannel->pChannelRight->Buffer()[Skip];  
358          finalSynthesisParameters.pSrc      = pSrc;          const bool bVoiceRequiresDedicatedRouting =
359                pEngineChannel->GetFxSendCount() > 0 &&
360                (pMidiKeyInfo->ReverbSend || pMidiKeyInfo->ChorusSend);
361            
362            const bool bEq =
363                pSignalUnitRack != NULL && pSignalUnitRack->HasEq() && pEq->HasSupport();
364    
365            if (bEq) {
366                pEq->GetInChannelLeft()->Clear();
367                pEq->GetInChannelRight()->Clear();
368                finalSynthesisParameters.pOutLeft  = &pEq->GetInChannelLeft()->Buffer()[Skip];
369                finalSynthesisParameters.pOutRight = &pEq->GetInChannelRight()->Buffer()[Skip];
370                pSignalUnitRack->UpdateEqSettings(pEq);
371            } else if (bVoiceRequiresDedicatedRouting) {
372                finalSynthesisParameters.pOutLeft  = &GetEngine()->pDedicatedVoiceChannelLeft->Buffer()[Skip];
373                finalSynthesisParameters.pOutRight = &GetEngine()->pDedicatedVoiceChannelRight->Buffer()[Skip];
374            } else {
375                finalSynthesisParameters.pOutLeft  = &pChannel->pChannelLeft->Buffer()[Skip];
376                finalSynthesisParameters.pOutRight = &pChannel->pChannelRight->Buffer()[Skip];
377            }
378            finalSynthesisParameters.pSrc = pSrc;
379    
380          RTList<Event>::Iterator itCCEvent = pChannel->pEvents->first();          RTList<Event>::Iterator itCCEvent = pChannel->pEvents->first();
381          RTList<Event>::Iterator itNoteEvent;          RTList<Event>::Iterator itNoteEvent;
382          GetFirstEventOnKey(MIDIKey, itNoteEvent);          GetFirstEventOnKey(MIDIKey, itNoteEvent);
383    
384            RTList<Event>::Iterator itGroupEvent;
385            if (pGroupEvents && !Orphan) itGroupEvent = pGroupEvents->first();
386    
387          if (itTriggerEvent) { // skip events that happened before this voice was triggered          if (itTriggerEvent) { // skip events that happened before this voice was triggered
388              while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;              while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;
389                while (itGroupEvent && itGroupEvent->FragmentPos() <= Skip) ++itGroupEvent;
390    
391              // we can't simply compare the timestamp here, because note events              // we can't simply compare the timestamp here, because note events
392              // might happen on the same time stamp, so we have to deal on the              // might happen on the same time stamp, so we have to deal on the
393              // actual sequence the note events arrived instead (see bug #112)              // actual sequence the note events arrived instead (see bug #112)
# Line 347  namespace LinuxSampler { Line 408  namespace LinuxSampler {
408                  // drivers that use Samples < MaxSamplesPerCycle).                  // drivers that use Samples < MaxSamplesPerCycle).
409                  // End the EG1 here, at pos 0, with a shorter max fade                  // End the EG1 here, at pos 0, with a shorter max fade
410                  // out time.                  // out time.
411                  EG1.enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  if (pSignalUnitRack == NULL) {
412                        pEG1->enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
413                    } else {
414                        pSignalUnitRack->EnterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
415                    }
416                  itKillEvent = Pool<Event>::Iterator();                  itKillEvent = Pool<Event>::Iterator();
417              } else {              } else {
418                  killPos = RTMath::Min(itKillEvent->FragmentPos(), maxFadeOutPos);                  killPos = RTMath::Min(itKillEvent->FragmentPos(), maxFadeOutPos);
# Line 362  namespace LinuxSampler { Line 427  namespace LinuxSampler {
427              fFinalCutoff    = VCFCutoffCtrl.fvalue;              fFinalCutoff    = VCFCutoffCtrl.fvalue;
428              fFinalResonance = VCFResonanceCtrl.fvalue;              fFinalResonance = VCFResonanceCtrl.fvalue;
429    
430              // process MIDI control change and pitchbend events for this subfragment              // process MIDI control change, aftertouch and pitchbend events for this subfragment
431              processCCEvents(itCCEvent, iSubFragmentEnd);              processCCEvents(itCCEvent, iSubFragmentEnd);
432                uint8_t pan = MIDIPan;
433                if (pSignalUnitRack != NULL) pan = pSignalUnitRack->GetEndpointUnit()->CalculatePan(MIDIPan);
434                
435                PanLeftSmoother.update(AbstractEngine::PanCurve[128 - pan]);
436                PanRightSmoother.update(AbstractEngine::PanCurve[pan]);
437    
438              finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend;              finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend;
439              float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render();              float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render();
# Line 373  namespace LinuxSampler { Line 443  namespace LinuxSampler {
443    
444              // process transition events (note on, note off & sustain pedal)              // process transition events (note on, note off & sustain pedal)
445              processTransitionEvents(itNoteEvent, iSubFragmentEnd);              processTransitionEvents(itNoteEvent, iSubFragmentEnd);
446                processGroupEvents(itGroupEvent, iSubFragmentEnd);
447                
448                if (pSignalUnitRack == NULL) {
449                    // if the voice was killed in this subfragment, or if the
450                    // filter EG is finished, switch EG1 to fade out stage
451                    if ((itKillEvent && killPos <= iSubFragmentEnd) ||
452                        (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&
453                        pEG2->getSegmentType() == EG::segment_end)) {
454                        pEG1->enterFadeOutStage();
455                        itKillEvent = Pool<Event>::Iterator();
456                    }
457    
458              // if the voice was killed in this subfragment, or if the                  // process envelope generators
459              // filter EG is finished, switch EG1 to fade out stage                  switch (pEG1->getSegmentType()) {
460              if ((itKillEvent && killPos <= iSubFragmentEnd) ||                      case EG::segment_lin:
461                  (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&                          fFinalVolume *= pEG1->processLin();
462                   EG2.getSegmentType() == gig::EGADSR::segment_end)) {                          break;
463                  EG1.enterFadeOutStage();                      case EG::segment_exp:
464                  itKillEvent = Pool<Event>::Iterator();                          fFinalVolume *= pEG1->processExp();
465              }                          break;
466                        case EG::segment_end:
467              // process envelope generators                          fFinalVolume *= pEG1->getLevel();
468              switch (EG1.getSegmentType()) {                          break; // noop
469                  case gig::EGADSR::segment_lin:                      case EG::segment_pow:
470                      fFinalVolume *= EG1.processLin();                          fFinalVolume *= pEG1->processPow();
471                      break;                          break;
472                  case gig::EGADSR::segment_exp:                  }
473                      fFinalVolume *= EG1.processExp();                  switch (pEG2->getSegmentType()) {
474                      break;                      case EG::segment_lin:
475                  case gig::EGADSR::segment_end:                          fFinalCutoff *= pEG2->processLin();
476                      fFinalVolume *= EG1.getLevel();                          break;
477                      break; // noop                      case EG::segment_exp:
478              }                          fFinalCutoff *= pEG2->processExp();
479              switch (EG2.getSegmentType()) {                          break;
480                  case gig::EGADSR::segment_lin:                      case EG::segment_end:
481                      fFinalCutoff *= EG2.processLin();                          fFinalCutoff *= pEG2->getLevel();
482                      break;                          break; // noop
483                  case gig::EGADSR::segment_exp:                      case EG::segment_pow:
484                      fFinalCutoff *= EG2.processExp();                          fFinalCutoff *= pEG2->processPow();
485                      break;                          break;
486                  case gig::EGADSR::segment_end:                  }
487                      fFinalCutoff *= EG2.getLevel();                  if (EG3.active()) finalSynthesisParameters.fFinalPitch *= EG3.render();
                     break; // noop  
             }  
             if (EG3.active()) finalSynthesisParameters.fFinalPitch *= EG3.render();  
   
             // process low frequency oscillators  
             if (bLFO1Enabled) fFinalVolume *= (1.0f - pLFO1->render());  
             if (bLFO2Enabled) fFinalCutoff *= pLFO2->render();  
             if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());  
488    
489                    // process low frequency oscillators
490                    if (bLFO1Enabled) fFinalVolume *= (1.0f - pLFO1->render());
491                    if (bLFO2Enabled) fFinalCutoff *= pLFO2->render();
492                    if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());
493                } else {
494                    // if the voice was killed in this subfragment, enter fade out stage
495                    if (itKillEvent && killPos <= iSubFragmentEnd) {
496                        pSignalUnitRack->EnterFadeOutStage();
497                        itKillEvent = Pool<Event>::Iterator();
498                    }
499                    
500                    // if the filter EG is finished, switch EG1 to fade out stage
501                    /*if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&
502                        pEG2->getSegmentType() == EG::segment_end) {
503                        pEG1->enterFadeOutStage();
504                        itKillEvent = Pool<Event>::Iterator();
505                    }*/
506                    // TODO: ^^^
507    
508                    fFinalVolume   *= pSignalUnitRack->GetEndpointUnit()->GetVolume();
509                    fFinalCutoff    = pSignalUnitRack->GetEndpointUnit()->CalculateFilterCutoff(fFinalCutoff);
510                    fFinalResonance = pSignalUnitRack->GetEndpointUnit()->CalculateResonance(fFinalResonance);
511                    
512                    finalSynthesisParameters.fFinalPitch =
513                        pSignalUnitRack->GetEndpointUnit()->CalculatePitch(finalSynthesisParameters.fFinalPitch);
514                        
515                }
516                
517              // limit the pitch so we don't read outside the buffer              // limit the pitch so we don't read outside the buffer
518              finalSynthesisParameters.fFinalPitch = RTMath::Min(finalSynthesisParameters.fFinalPitch, float(1 << CONFIG_MAX_PITCH));              finalSynthesisParameters.fFinalPitch = RTMath::Min(finalSynthesisParameters.fFinalPitch, float(1 << CONFIG_MAX_PITCH));
519    
# Line 445  namespace LinuxSampler { Line 546  namespace LinuxSampler {
546                  fFinalVolume * VolumeRight * PanRightSmoother.render();                  fFinalVolume * VolumeRight * PanRightSmoother.render();
547  #endif  #endif
548              // render audio for one subfragment              // render audio for one subfragment
549              RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);              if (!delay) RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);
550    
551              // stop the rendering if volume EG is finished              if (pSignalUnitRack == NULL) {
552              if (EG1.getSegmentType() == gig::EGADSR::segment_end) break;                  // stop the rendering if volume EG is finished
553                    if (pEG1->getSegmentType() == EG::segment_end) break;
554                } else {
555                    // stop the rendering if the endpoint unit is not active
556                    if (!pSignalUnitRack->GetEndpointUnit()->Active()) break;
557                }
558    
559              const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;              const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;
560    
561              // increment envelopes' positions              if (pSignalUnitRack == NULL) {
562              if (EG1.active()) {                  // increment envelopes' positions
563                    if (pEG1->active()) {
564    
565                        // if sample has a loop and loop start has been reached in this subfragment, send a special event to EG1 to let it finish the attack hold stage
566                        if (SmplInfo.HasLoops && Pos <= SmplInfo.LoopStart && SmplInfo.LoopStart < newPos) {
567                            pEG1->update(EG::event_hold_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
568                        }
569    
570                  // if sample has a loop and loop start has been reached in this subfragment, send a special event to EG1 to let it finish the attack hold stage                      pEG1->increment(1);
571                  if (SmplInfo.HasLoops && Pos <= SmplInfo.LoopStart && SmplInfo.LoopStart < newPos) {                      if (!pEG1->toStageEndLeft()) pEG1->update(EG::event_stage_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
                     EG1.update(gig::EGADSR::event_hold_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);  
572                  }                  }
573                    if (pEG2->active()) {
574                  EG1.increment(1);                      pEG2->increment(1);
575                  if (!EG1.toStageEndLeft()) EG1.update(gig::EGADSR::event_stage_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                      if (!pEG2->toStageEndLeft()) pEG2->update(EG::event_stage_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
576              }                  }
577              if (EG2.active()) {                  EG3.increment(1);
578                  EG2.increment(1);                  if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached
579                  if (!EG2.toStageEndLeft()) EG2.update(gig::EGADSR::event_stage_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);              } else {
580                        // if sample has a loop and loop start has been reached in this subfragment, send a special event to EG1 to let it finish the attack hold stage
581                        /*if (SmplInfo.HasLoops && Pos <= SmplInfo.LoopStart && SmplInfo.LoopStart < newPos) {
582                            pEG1->update(EG::event_hold_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
583                        }*/
584                    // TODO: ^^^
585                    
586                    if (!delay) pSignalUnitRack->Increment();
587              }              }
             EG3.increment(1);  
             if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached  
588    
589              Pos = newPos;              Pos = newPos;
590              i = iSubFragmentEnd;              i = iSubFragmentEnd;
591          }          }
592            
593            if (delay) return;
594    
595            if (bVoiceRequiresDedicatedRouting) {
596                if (bEq) {
597                    pEq->RenderAudio(Samples);
598                    pEq->GetOutChannelLeft()->CopyTo(GetEngine()->pDedicatedVoiceChannelLeft, Samples);
599                    pEq->GetOutChannelRight()->CopyTo(GetEngine()->pDedicatedVoiceChannelRight, Samples);
600                }
601                optional<float> effectSendLevels[2] = {
602                    pMidiKeyInfo->ReverbSend,
603                    pMidiKeyInfo->ChorusSend
604                };
605                GetEngine()->RouteDedicatedVoiceChannels(pEngineChannel, effectSendLevels, Samples);
606            } else if (bEq) {
607                pEq->RenderAudio(Samples);
608                pEq->GetOutChannelLeft()->MixTo(pChannel->pChannelLeft, Samples);
609                pEq->GetOutChannelRight()->MixTo(pChannel->pChannelRight, Samples);
610            }
611      }      }
612        
613      /**      /**
614       * Process given list of MIDI control change and pitch bend events for       * Process given list of MIDI control change, aftertouch and pitch bend
615       * the given time.       * events for the given time.
616       *       *
617       * @param itEvent - iterator pointing to the next event to be processed       * @param itEvent - iterator pointing to the next event to be processed
618       * @param End     - youngest time stamp where processing should be stopped       * @param End     - youngest time stamp where processing should be stopped
# Line 491  namespace LinuxSampler { Line 626  namespace LinuxSampler {
626                  if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {                  if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {
627                      processResonanceEvent(itEvent);                      processResonanceEvent(itEvent);
628                  }                  }
629                  if (itEvent->Param.CC.Controller == pLFO1->ExtController) {                  if (pSignalUnitRack == NULL) {
630                      pLFO1->update(itEvent->Param.CC.Value);                      if (itEvent->Param.CC.Controller == pLFO1->ExtController) {
631                  }                          pLFO1->update(itEvent->Param.CC.Value);
632                  if (itEvent->Param.CC.Controller == pLFO2->ExtController) {                      }
633                      pLFO2->update(itEvent->Param.CC.Value);                      if (itEvent->Param.CC.Controller == pLFO2->ExtController) {
634                  }                          pLFO2->update(itEvent->Param.CC.Value);
635                  if (itEvent->Param.CC.Controller == pLFO3->ExtController) {                      }
636                      pLFO3->update(itEvent->Param.CC.Value);                      if (itEvent->Param.CC.Controller == pLFO3->ExtController) {
637                            pLFO3->update(itEvent->Param.CC.Value);
638                        }
639                  }                  }
640                  if (itEvent->Param.CC.Controller == 7) { // volume                  if (itEvent->Param.CC.Controller == 7) { // volume
641                      VolumeSmoother.update(AbstractEngine::VolumeCurve[itEvent->Param.CC.Value]);                      VolumeSmoother.update(AbstractEngine::VolumeCurve[itEvent->Param.CC.Value]);
642                  } else if (itEvent->Param.CC.Controller == 10) { // panpot                  } else if (itEvent->Param.CC.Controller == 10) { // panpot
643                      PanLeftSmoother.update(AbstractEngine::PanCurve[128 - itEvent->Param.CC.Value]);                      MIDIPan = CalculatePan(itEvent->Param.CC.Value);
                     PanRightSmoother.update(AbstractEngine::PanCurve[itEvent->Param.CC.Value]);  
644                  }                  }
645              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event
646                  processPitchEvent(itEvent);                  processPitchEvent(itEvent);
647                } else if (itEvent->Type == Event::type_channel_pressure) {
648                    ProcessChannelPressureEvent(itEvent);
649                } else if (itEvent->Type == Event::type_note_pressure) {
650                    ProcessPolyphonicKeyPressureEvent(itEvent);
651              }              }
652    
653              ProcessCCEvent(itEvent);              ProcessCCEvent(itEvent);
654                if (pSignalUnitRack != NULL) {
655                    pSignalUnitRack->ProcessCCEvent(itEvent);
656                }
657          }          }
658      }      }
659    
# Line 537  namespace LinuxSampler { Line 680  namespace LinuxSampler {
680       */       */
681      void AbstractVoice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) {      void AbstractVoice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) {
682          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
683              if (itEvent->Type == Event::type_release) {              // some voice types ignore note off
684                  EG1.update(gig::EGADSR::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);              if (!(Type & (Voice::type_one_shot | Voice::type_release_trigger | Voice::type_controller_triggered))) {
685                  EG2.update(gig::EGADSR::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  if (itEvent->Type == Event::type_release) {
686              } else if (itEvent->Type == Event::type_cancel_release) {                      EnterReleaseStage();
687                  EG1.update(gig::EGADSR::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  } else if (itEvent->Type == Event::type_cancel_release) {
688                  EG2.update(gig::EGADSR::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                      if (pSignalUnitRack == NULL) {
689                            pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
690                            pEG2->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
691                        } else {
692                            pSignalUnitRack->CancelRelease();
693                        }
694                    }
695              }              }
696          }          }
697      }      }
698    
699        /**
700         * Process given list of events aimed at all voices in a key group.
701         *
702         * @param itEvent - iterator pointing to the next event to be processed
703         * @param End     - youngest time stamp where processing should be stopped
704         */
705        void AbstractVoice::processGroupEvents(RTList<Event>::Iterator& itEvent, uint End) {
706            for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
707                ProcessGroupEvent(itEvent);
708            }
709        }
710    
711      /** @brief Update current portamento position.      /** @brief Update current portamento position.
712       *       *
713       * Will be called when portamento mode is enabled to get the final       * Will be called when portamento mode is enabled to get the final
# Line 556  namespace LinuxSampler { Line 717  namespace LinuxSampler {
717       * @param itNoteOffEvent - event which causes this voice to die soon       * @param itNoteOffEvent - event which causes this voice to die soon
718       */       */
719      void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {      void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {
720          const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());          if (pSignalUnitRack == NULL) {
721          pEngineChannel->PortamentoPos = (float) MIDIKey + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;              const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());
722                pEngineChannel->PortamentoPos = (float) MIDIKey + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;
723            } else {
724                // TODO:
725            }
726      }      }
727    
728      /**      /**
# Line 594  namespace LinuxSampler { Line 759  namespace LinuxSampler {
759    
760          return pitch;          return pitch;
761      }      }
762        
763        void AbstractVoice::onScaleTuningChanged() {
764            PitchInfo pitch = this->Pitch;
765            double pitchbasecents = InstrInfo.FineTune + RgnInfo.FineTune + GetEngine()->ScaleTuning[MIDIKey % 12];
766            
767            // GSt behaviour: maximum transpose up is 40 semitones. If
768            // MIDI key is more than 40 semitones above unity note,
769            // the transpose is not done.
770            if (!SmplInfo.Unpitched && (MIDIKey - (int) RgnInfo.UnityNote) < 40) pitchbasecents += (MIDIKey - (int) RgnInfo.UnityNote) * 100;
771            
772            pitch.PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(SmplInfo.SampleRate) / double(GetEngine()->SampleRate));
773            this->Pitch = pitch;
774        }
775    
776      double AbstractVoice::CalculateVolume(double velocityAttenuation) {      double AbstractVoice::CalculateVolume(double velocityAttenuation) {
777          // For 16 bit samples, we downscale by 32768 to convert from          // For 16 bit samples, we downscale by 32768 to convert from
# Line 604  namespace LinuxSampler { Line 782  namespace LinuxSampler {
782          volume *= GetSampleAttenuation() * pEngineChannel->GlobalVolume * GLOBAL_VOLUME;          volume *= GetSampleAttenuation() * pEngineChannel->GlobalVolume * GLOBAL_VOLUME;
783    
784          // the volume of release triggered samples depends on note length          // the volume of release triggered samples depends on note length
785          if (Type == Voice::type_release_trigger) {          if (Type & Voice::type_release_trigger) {
786              float noteLength = float(GetEngine()->FrameTime + Delay -              float noteLength = float(GetEngine()->FrameTime + Delay -
787                  GetNoteOnTime(MIDIKey) ) / GetEngine()->SampleRate;                  GetNoteOnTime(MIDIKey) ) / GetEngine()->SampleRate;
788    
789              float attenuation = 1 - 0.01053 * (256 >> RgnInfo.ReleaseTriggerDecay) * noteLength;              volume *= GetReleaseTriggerAttenuation(noteLength);
             volume *= attenuation;  
790          }          }
791    
792          return volume;          return volume;
793      }      }
794    
795        float AbstractVoice::GetReleaseTriggerAttenuation(float noteLength) {
796            return 1 - RgnInfo.ReleaseTriggerDecay * noteLength;
797        }
798    
799        void AbstractVoice::EnterReleaseStage() {
800            if (pSignalUnitRack == NULL) {
801                pEG1->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
802                pEG2->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
803            } else {
804                pSignalUnitRack->EnterReleaseStage();
805            }
806        }
807    
808        bool AbstractVoice::EG1Finished() {
809            if (pSignalUnitRack == NULL) {
810                return pEG1->getSegmentType() == EG::segment_end;
811            } else {
812                return !pSignalUnitRack->GetEndpointUnit()->Active();
813            }
814        }
815    
816  } // namespace LinuxSampler  } // namespace LinuxSampler

Legend:
Removed from v.2032  
changed lines
  Added in v.2559

  ViewVC Help
Powered by ViewVC