/[svn]/linuxsampler/trunk/src/engines/common/AbstractVoice.cpp
ViewVC logotype

Diff of /linuxsampler/trunk/src/engines/common/AbstractVoice.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 2114 by persson, Tue Aug 10 12:05:19 2010 UTC revision 2296 by iliev, Thu Dec 8 20:03:47 2011 UTC
# Line 4  Line 4 
4   *                                                                         *   *                                                                         *
5   *   Copyright (C) 2003,2004 by Benno Senoner and Christian Schoenebeck    *   *   Copyright (C) 2003,2004 by Benno Senoner and Christian Schoenebeck    *
6   *   Copyright (C) 2005-2008 Christian Schoenebeck                         *   *   Copyright (C) 2005-2008 Christian Schoenebeck                         *
7   *   Copyright (C) 2009-2010 Christian Schoenebeck and Grigor Iliev        *   *   Copyright (C) 2009-2011 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;
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)
# Line 99  namespace LinuxSampler { Line 99  namespace LinuxSampler {
99    
100          Type            = VoiceType;          Type            = VoiceType;
101          MIDIKey         = itNoteOnEvent->Param.Note.Key;          MIDIKey         = itNoteOnEvent->Param.Note.Key;
102            MIDIVelocity    = itNoteOnEvent->Param.Note.Velocity;
103            MIDIPan         = pEngineChannel->ControllerTable[10];
104            if (MIDIPan == 0 && pEngineChannel->GlobalPanRight == 1) MIDIPan = 64; // workaround used to determine whether the MIDI pan has not been set
105          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
106          Delay           = itNoteOnEvent->FragmentPos();          Delay           = itNoteOnEvent->FragmentPos();
107          itTriggerEvent  = itNoteOnEvent;          itTriggerEvent  = itNoteOnEvent;
108          itKillEvent     = Pool<Event>::Iterator();          itKillEvent     = Pool<Event>::Iterator();
109            MidiKeyBase* pKeyInfo = GetMidiKeyInfo(MIDIKey);
110    
111          pGroupEvents = iKeyGroup ? pEngineChannel->ActiveKeyGroups[iKeyGroup] : 0;          pGroupEvents = iKeyGroup ? pEngineChannel->ActiveKeyGroups[iKeyGroup] : 0;
112    
113          SmplInfo   = GetSampleInfo();          SmplInfo   = GetSampleInfo();
114          RgnInfo    = GetRegionInfo();          RgnInfo    = GetRegionInfo();
115          InstrInfo  = GetInstrumentInfo();          InstrInfo  = GetInstrumentInfo();
116            
117            AboutToTrigger();
118    
119          // calculate volume          // calculate volume
120          const double velocityAttenuation = GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity);          const double velocityAttenuation = GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity);
121          float volume = CalculateVolume(velocityAttenuation);          float volume = CalculateVolume(velocityAttenuation) * pKeyInfo->Volume;
122          if (volume <= 0) return -1;          if (volume <= 0) return -1;
123    
124          // select channel mode (mono or stereo)          // select channel mode (mono or stereo)
# Line 123  namespace LinuxSampler { Line 129  namespace LinuxSampler {
129          // get starting crossfade volume level          // get starting crossfade volume level
130          float crossfadeVolume = CalculateCrossfadeVolume(itNoteOnEvent->Param.Note.Velocity);          float crossfadeVolume = CalculateCrossfadeVolume(itNoteOnEvent->Param.Note.Velocity);
131    
132          VolumeLeft  = volume * AbstractEngine::PanCurve[64 - RgnInfo.Pan];          VolumeLeft  = volume * pKeyInfo->PanLeft  * AbstractEngine::PanCurve[64 - RgnInfo.Pan];
133          VolumeRight = volume * AbstractEngine::PanCurve[64 + RgnInfo.Pan];          VolumeRight = volume * pKeyInfo->PanRight * AbstractEngine::PanCurve[64 + RgnInfo.Pan];
134    
135          float subfragmentRate = GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;          float subfragmentRate = GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;
136          CrossfadeSmoother.trigger(crossfadeVolume, subfragmentRate);          CrossfadeSmoother.trigger(crossfadeVolume, subfragmentRate);
# Line 132  namespace LinuxSampler { Line 138  namespace LinuxSampler {
138          PanLeftSmoother.trigger(pEngineChannel->GlobalPanLeft, subfragmentRate);          PanLeftSmoother.trigger(pEngineChannel->GlobalPanLeft, subfragmentRate);
139          PanRightSmoother.trigger(pEngineChannel->GlobalPanRight, subfragmentRate);          PanRightSmoother.trigger(pEngineChannel->GlobalPanRight, subfragmentRate);
140    
         finalSynthesisParameters.dPos = RgnInfo.SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)  
         Pos = RgnInfo.SampleStartOffset;  
   
141          // 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
142          long cachedsamples = GetSampleCacheSize() / SmplInfo.FrameSize;          long cachedsamples = GetSampleCacheSize() / SmplInfo.FrameSize;
143          DiskVoice          = cachedsamples < SmplInfo.TotalFrameCount;          DiskVoice          = cachedsamples < SmplInfo.TotalFrameCount;
144    
145            SetSampleStartOffset();
146    
147          if (DiskVoice) { // voice to be streamed from disk          if (DiskVoice) { // voice to be streamed from disk
148              if (cachedsamples > (GetEngine()->MaxSamplesPerCycle << CONFIG_MAX_PITCH)) {              if (cachedsamples > (GetEngine()->MaxSamplesPerCycle << CONFIG_MAX_PITCH)) {
149                  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 180  namespace LinuxSampler {
180          // 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
181          const double velrelease = 1 / GetVelocityRelease(itNoteOnEvent->Param.Note.Velocity);          const double velrelease = 1 / GetVelocityRelease(itNoteOnEvent->Param.Note.Velocity);
182    
183          // setup EG 1 (VCA EG)          if (pSignalUnitRack == NULL) { // setup EG 1 (VCA EG)
         {  
184              // get current value of EG1 controller              // get current value of EG1 controller
185              double eg1controllervalue = GetEG1ControllerValue(itNoteOnEvent->Param.Note.Velocity);              double eg1controllervalue = GetEG1ControllerValue(itNoteOnEvent->Param.Note.Velocity);
186    
# Line 184  namespace LinuxSampler { Line 188  namespace LinuxSampler {
188              EGInfo egInfo = CalculateEG1ControllerInfluence(eg1controllervalue);              EGInfo egInfo = CalculateEG1ControllerInfluence(eg1controllervalue);
189    
190              TriggerEG1(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity);              TriggerEG1(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity);
191            } else {
192                pSignalUnitRack->Trigger();
193          }          }
194    
195  #ifdef CONFIG_INTERPOLATE_VOLUME  #ifdef CONFIG_INTERPOLATE_VOLUME
# Line 196  namespace LinuxSampler { Line 202  namespace LinuxSampler {
202          else          else
203      #else      #else
204          {          {
205              float finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pEG1->getLevel();              float finalVolume;
206                if (pSignalUnitRack == NULL) {
207                    finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pEG1->getLevel();
208                } else {
209                    finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pSignalUnitRack->GetEndpointUnit()->GetVolume();
210                }
211    
212              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * pEngineChannel->GlobalPanLeft;              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * pEngineChannel->GlobalPanLeft;
213              finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * pEngineChannel->GlobalPanRight;              finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * pEngineChannel->GlobalPanRight;
# Line 204  namespace LinuxSampler { Line 215  namespace LinuxSampler {
215      #endif      #endif
216  #endif  #endif
217    
218          // setup EG 2 (VCF Cutoff EG)          if (pSignalUnitRack == NULL) {
219          {              // setup EG 2 (VCF Cutoff EG)
220              // get current value of EG2 controller              {
221              double eg2controllervalue = GetEG2ControllerValue(itNoteOnEvent->Param.Note.Velocity);                  // get current value of EG2 controller
222                    double eg2controllervalue = GetEG2ControllerValue(itNoteOnEvent->Param.Note.Velocity);
223    
224                    // calculate influence of EG2 controller on EG2's parameters
225                    EGInfo egInfo = CalculateEG2ControllerInfluence(eg2controllervalue);
226    
227                    TriggerEG2(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity);
228                }
229    
             // calculate influence of EG2 controller on EG2's parameters  
             EGInfo egInfo = CalculateEG2ControllerInfluence(eg2controllervalue);  
230    
231              EG2.trigger (              // setup EG 3 (VCO EG)
232                  uint(RgnInfo.EG2PreAttack),              {
233                  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
234                  false,                  bool  bPortamento = pEngineChannel->PortamentoMode && pEngineChannel->PortamentoPos >= 0.0f;
235                  RgnInfo.EG2Decay1 * egInfo.Decay * velrelease,                  float eg3depth = (bPortamento)
236                  RgnInfo.EG2Decay2 * egInfo.Decay * velrelease,                               ? RTMath::CentsToFreqRatio((pEngineChannel->PortamentoPos - (float) MIDIKey) * 100)
237                  RgnInfo.EG2InfiniteSustain,                               : RTMath::CentsToFreqRatio(RgnInfo.EG3Depth);
238                  uint(RgnInfo.EG2Sustain),                  float eg3time = (bPortamento)
239                  RgnInfo.EG2Release * egInfo.Release * velrelease,                              ? pEngineChannel->PortamentoTime
240                  velocityAttenuation,                              : RgnInfo.EG3Attack;
241                  GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE                  EG3.trigger(eg3depth, eg3time, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
242              );                  dmsg(5,("PortamentoPos=%f, depth=%f, time=%f\n", pEngineChannel->PortamentoPos, eg3depth, eg3time));
243          }              }
244    
245    
246          // setup EG 3 (VCO EG)              // setup LFO 1 (VCA LFO)
247          {              InitLFO1();
248              // 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)
249              bool  bPortamento = pEngineChannel->PortamentoMode && pEngineChannel->PortamentoPos >= 0.0f;              InitLFO2();
250              float eg3depth = (bPortamento)              // setup LFO 3 (VCO LFO)
251                           ? 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));  
252          }          }
253    
254    
         // setup LFO 1 (VCA LFO)  
         InitLFO1();  
         // setup LFO 2 (VCF Cutoff LFO)  
         InitLFO2();  
         // setup LFO 3 (VCO LFO)  
         InitLFO3();  
   
   
255          #if CONFIG_FORCE_FILTER          #if CONFIG_FORCE_FILTER
256          const bool bUseFilter = true;          const bool bUseFilter = true;
257          #else // use filter only if instrument file told so          #else // use filter only if instrument file told so
# Line 295  namespace LinuxSampler { Line 297  namespace LinuxSampler {
297    
298          return 0; // success          return 0; // success
299      }      }
300        
301        void AbstractVoice::SetSampleStartOffset() {
302            finalSynthesisParameters.dPos = RgnInfo.SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)
303            Pos = RgnInfo.SampleStartOffset;
304        }
305    
306      /**      /**
307       *  Synthesizes the current audio fragment for this voice.       *  Synthesizes the current audio fragment for this voice.
# Line 306  namespace LinuxSampler { Line 313  namespace LinuxSampler {
313       */       */
314      void AbstractVoice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {      void AbstractVoice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {
315          AbstractEngineChannel* pChannel = pEngineChannel;          AbstractEngineChannel* pChannel = pEngineChannel;
316          finalSynthesisParameters.pOutLeft  = &pChannel->pChannelLeft->Buffer()[Skip];          MidiKeyBase* pMidiKeyInfo = GetMidiKeyInfo(MIDIKey);
317          finalSynthesisParameters.pOutRight = &pChannel->pChannelRight->Buffer()[Skip];  
318          finalSynthesisParameters.pSrc      = pSrc;          const bool bVoiceRequiresDedicatedRouting =
319                pEngineChannel->GetFxSendCount() > 0 &&
320                (pMidiKeyInfo->ReverbSend || pMidiKeyInfo->ChorusSend);
321            
322            const bool bEq =
323                pSignalUnitRack != NULL && pSignalUnitRack->HasEq() && GetEngine()->pEq->HasSupport();
324    
325            if (bEq) {
326                GetEngine()->pEq->GetInChannelLeft()->Clear();
327                GetEngine()->pEq->GetInChannelRight()->Clear();
328                finalSynthesisParameters.pOutLeft  = &GetEngine()->pEq->GetInChannelLeft()->Buffer()[Skip];
329                finalSynthesisParameters.pOutRight = &GetEngine()->pEq->GetInChannelRight()->Buffer()[Skip];
330                pSignalUnitRack->UpdateEqSettings(GetEngine()->pEq);
331            } else if (bVoiceRequiresDedicatedRouting) {
332                finalSynthesisParameters.pOutLeft  = &GetEngine()->pDedicatedVoiceChannelLeft->Buffer()[Skip];
333                finalSynthesisParameters.pOutRight = &GetEngine()->pDedicatedVoiceChannelRight->Buffer()[Skip];
334            } else {
335                finalSynthesisParameters.pOutLeft  = &pChannel->pChannelLeft->Buffer()[Skip];
336                finalSynthesisParameters.pOutRight = &pChannel->pChannelRight->Buffer()[Skip];
337            }
338            finalSynthesisParameters.pSrc = pSrc;
339    
340          RTList<Event>::Iterator itCCEvent = pChannel->pEvents->first();          RTList<Event>::Iterator itCCEvent = pChannel->pEvents->first();
341          RTList<Event>::Iterator itNoteEvent;          RTList<Event>::Iterator itNoteEvent;
# Line 341  namespace LinuxSampler { Line 368  namespace LinuxSampler {
368                  // drivers that use Samples < MaxSamplesPerCycle).                  // drivers that use Samples < MaxSamplesPerCycle).
369                  // End the EG1 here, at pos 0, with a shorter max fade                  // End the EG1 here, at pos 0, with a shorter max fade
370                  // out time.                  // out time.
371                  pEG1->enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  if (pSignalUnitRack == NULL) {
372                        pEG1->enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
373                    } else {
374                        // TODO:
375                    }
376                  itKillEvent = Pool<Event>::Iterator();                  itKillEvent = Pool<Event>::Iterator();
377              } else {              } else {
378                  killPos = RTMath::Min(itKillEvent->FragmentPos(), maxFadeOutPos);                  killPos = RTMath::Min(itKillEvent->FragmentPos(), maxFadeOutPos);
# Line 358  namespace LinuxSampler { Line 389  namespace LinuxSampler {
389    
390              // process MIDI control change and pitchbend events for this subfragment              // process MIDI control change and pitchbend events for this subfragment
391              processCCEvents(itCCEvent, iSubFragmentEnd);              processCCEvents(itCCEvent, iSubFragmentEnd);
392                uint8_t pan = MIDIPan;
393                if (pSignalUnitRack != NULL) pan = pSignalUnitRack->GetEndpointUnit()->CaluclatePan(pan);
394                
395                PanLeftSmoother.update(AbstractEngine::PanCurve[128 - pan]);
396                PanRightSmoother.update(AbstractEngine::PanCurve[pan]);
397    
398              finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend;              finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend;
399              float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render();              float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render();
# Line 369  namespace LinuxSampler { Line 405  namespace LinuxSampler {
405              processTransitionEvents(itNoteEvent, iSubFragmentEnd);              processTransitionEvents(itNoteEvent, iSubFragmentEnd);
406              processGroupEvents(itGroupEvent, iSubFragmentEnd);              processGroupEvents(itGroupEvent, iSubFragmentEnd);
407    
408              // if the voice was killed in this subfragment, or if the              if (pSignalUnitRack == NULL) {
409              // filter EG is finished, switch EG1 to fade out stage                  // if the voice was killed in this subfragment, or if the
410              if ((itKillEvent && killPos <= iSubFragmentEnd) ||                  // filter EG is finished, switch EG1 to fade out stage
411                  (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&                  if ((itKillEvent && killPos <= iSubFragmentEnd) ||
412                   EG2.getSegmentType() == gig::EGADSR::segment_end)) {                      (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&
413                  pEG1->enterFadeOutStage();                      pEG2->getSegmentType() == EG::segment_end)) {
414                  itKillEvent = Pool<Event>::Iterator();                      pEG1->enterFadeOutStage();
415              }                      itKillEvent = Pool<Event>::Iterator();
416                    }
417    
418              // process envelope generators                  // process envelope generators
419              switch (pEG1->getSegmentType()) {                  switch (pEG1->getSegmentType()) {
420                  case EG::segment_lin:                      case EG::segment_lin:
421                      fFinalVolume *= pEG1->processLin();                          fFinalVolume *= pEG1->processLin();
422                      break;                          break;
423                  case EG::segment_exp:                      case EG::segment_exp:
424                      fFinalVolume *= pEG1->processExp();                          fFinalVolume *= pEG1->processExp();
425                      break;                          break;
426                  case EG::segment_end:                      case EG::segment_end:
427                      fFinalVolume *= pEG1->getLevel();                          fFinalVolume *= pEG1->getLevel();
428                      break; // noop                          break; // noop
429                  case EG::segment_pow:                      case EG::segment_pow:
430                      fFinalVolume *= pEG1->processPow();                          fFinalVolume *= pEG1->processPow();
431                      break;                          break;
432              }                  }
433              switch (EG2.getSegmentType()) {                  switch (pEG2->getSegmentType()) {
434                  case gig::EGADSR::segment_lin:                      case EG::segment_lin:
435                      fFinalCutoff *= EG2.processLin();                          fFinalCutoff *= pEG2->processLin();
436                      break;                          break;
437                  case gig::EGADSR::segment_exp:                      case EG::segment_exp:
438                      fFinalCutoff *= EG2.processExp();                          fFinalCutoff *= pEG2->processExp();
439                      break;                          break;
440                  case gig::EGADSR::segment_end:                      case EG::segment_end:
441                      fFinalCutoff *= EG2.getLevel();                          fFinalCutoff *= pEG2->getLevel();
442                      break; // noop                          break; // noop
443              }                      case EG::segment_pow:
444              if (EG3.active()) finalSynthesisParameters.fFinalPitch *= EG3.render();                          fFinalCutoff *= pEG2->processPow();
445                            break;
446              // process low frequency oscillators                  }
447              if (bLFO1Enabled) fFinalVolume *= (1.0f - pLFO1->render());                  if (EG3.active()) finalSynthesisParameters.fFinalPitch *= EG3.render();
             if (bLFO2Enabled) fFinalCutoff *= pLFO2->render();  
             if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());  
448    
449                    // process low frequency oscillators
450                    if (bLFO1Enabled) fFinalVolume *= (1.0f - pLFO1->render());
451                    if (bLFO2Enabled) fFinalCutoff *= pLFO2->render();
452                    if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());
453                } else {
454                    // if the voice was killed in this subfragment, or if the
455                    // filter EG is finished, switch EG1 to fade out stage
456                    /*if ((itKillEvent && killPos <= iSubFragmentEnd) ||
457                        (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&
458                        pEG2->getSegmentType() == EG::segment_end)) {
459                        pEG1->enterFadeOutStage();
460                        itKillEvent = Pool<Event>::Iterator();
461                    }*/
462                    // TODO: ^^^
463    
464                    fFinalVolume   *= pSignalUnitRack->GetEndpointUnit()->GetVolume();
465                    fFinalCutoff    = pSignalUnitRack->GetEndpointUnit()->CalculateFilterCutoff(fFinalCutoff);
466                    fFinalResonance = pSignalUnitRack->GetEndpointUnit()->CalculateResonance(fFinalResonance);
467                    
468                    finalSynthesisParameters.fFinalPitch =
469                        pSignalUnitRack->GetEndpointUnit()->CalculatePitch(finalSynthesisParameters.fFinalPitch);
470                        
471                }
472                
473              // limit the pitch so we don't read outside the buffer              // limit the pitch so we don't read outside the buffer
474              finalSynthesisParameters.fFinalPitch = RTMath::Min(finalSynthesisParameters.fFinalPitch, float(1 << CONFIG_MAX_PITCH));              finalSynthesisParameters.fFinalPitch = RTMath::Min(finalSynthesisParameters.fFinalPitch, float(1 << CONFIG_MAX_PITCH));
475    
# Line 445  namespace LinuxSampler { Line 504  namespace LinuxSampler {
504              // render audio for one subfragment              // render audio for one subfragment
505              RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);              RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);
506    
507              // stop the rendering if volume EG is finished              if (pSignalUnitRack == NULL) {
508              if (pEG1->getSegmentType() == EG::segment_end) break;                  // stop the rendering if volume EG is finished
509                    if (pEG1->getSegmentType() == EG::segment_end) break;
510                } else {
511                    // stop the rendering if the endpoint unit is not active
512                    if (!pSignalUnitRack->GetEndpointUnit()->Active()) break;
513                }
514    
515              const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;              const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;
516    
517              // increment envelopes' positions              if (pSignalUnitRack == NULL) {
518              if (pEG1->active()) {                  // increment envelopes' positions
519                    if (pEG1->active()) {
520    
521                        // 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
522                        if (SmplInfo.HasLoops && Pos <= SmplInfo.LoopStart && SmplInfo.LoopStart < newPos) {
523                            pEG1->update(EG::event_hold_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
524                        }
525    
526                  // 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);
527                  if (SmplInfo.HasLoops && Pos <= SmplInfo.LoopStart && SmplInfo.LoopStart < newPos) {                      if (!pEG1->toStageEndLeft()) pEG1->update(EG::event_stage_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
                     pEG1->update(EG::event_hold_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);  
528                  }                  }
529                    if (pEG2->active()) {
530                  pEG1->increment(1);                      pEG2->increment(1);
531                  if (!pEG1->toStageEndLeft()) pEG1->update(EG::event_stage_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                      if (!pEG2->toStageEndLeft()) pEG2->update(EG::event_stage_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
532              }                  }
533              if (EG2.active()) {                  EG3.increment(1);
534                  EG2.increment(1);                  if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached
535                  if (!EG2.toStageEndLeft()) EG2.update(gig::EGADSR::event_stage_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);              } else {
536                        // 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
537                        /*if (SmplInfo.HasLoops && Pos <= SmplInfo.LoopStart && SmplInfo.LoopStart < newPos) {
538                            pEG1->update(EG::event_hold_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
539                        }*/
540                    // TODO: ^^^
541                    
542                    pSignalUnitRack->Increment();
543              }              }
             EG3.increment(1);  
             if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached  
544    
545              Pos = newPos;              Pos = newPos;
546              i = iSubFragmentEnd;              i = iSubFragmentEnd;
547          }          }
548    
549            if (bVoiceRequiresDedicatedRouting) {
550                if (bEq) {
551                    GetEngine()->pEq->RenderAudio(Samples);
552                    GetEngine()->pEq->GetOutChannelLeft()->CopyTo(GetEngine()->pDedicatedVoiceChannelLeft, Samples);
553                    GetEngine()->pEq->GetOutChannelRight()->CopyTo(GetEngine()->pDedicatedVoiceChannelRight, Samples);
554                }
555                optional<float> effectSendLevels[2] = {
556                    pMidiKeyInfo->ReverbSend,
557                    pMidiKeyInfo->ChorusSend
558                };
559                GetEngine()->RouteDedicatedVoiceChannels(pEngineChannel, effectSendLevels, Samples);
560            } else if (bEq) {
561                GetEngine()->pEq->RenderAudio(Samples);
562                GetEngine()->pEq->GetOutChannelLeft()->CopyTo(pChannel->pChannelLeft, Samples);
563                GetEngine()->pEq->GetOutChannelRight()->CopyTo(pChannel->pChannelRight, Samples);
564            }
565      }      }
566    
567      /**      /**
# Line 489  namespace LinuxSampler { Line 580  namespace LinuxSampler {
580                  if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {                  if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {
581                      processResonanceEvent(itEvent);                      processResonanceEvent(itEvent);
582                  }                  }
583                  if (itEvent->Param.CC.Controller == pLFO1->ExtController) {                  if (pSignalUnitRack == NULL) {
584                      pLFO1->update(itEvent->Param.CC.Value);                      if (itEvent->Param.CC.Controller == pLFO1->ExtController) {
585                  }                          pLFO1->update(itEvent->Param.CC.Value);
586                  if (itEvent->Param.CC.Controller == pLFO2->ExtController) {                      }
587                      pLFO2->update(itEvent->Param.CC.Value);                      if (itEvent->Param.CC.Controller == pLFO2->ExtController) {
588                  }                          pLFO2->update(itEvent->Param.CC.Value);
589                  if (itEvent->Param.CC.Controller == pLFO3->ExtController) {                      }
590                      pLFO3->update(itEvent->Param.CC.Value);                      if (itEvent->Param.CC.Controller == pLFO3->ExtController) {
591                            pLFO3->update(itEvent->Param.CC.Value);
592                        }
593                  }                  }
594                  if (itEvent->Param.CC.Controller == 7) { // volume                  if (itEvent->Param.CC.Controller == 7) { // volume
595                      VolumeSmoother.update(AbstractEngine::VolumeCurve[itEvent->Param.CC.Value]);                      VolumeSmoother.update(AbstractEngine::VolumeCurve[itEvent->Param.CC.Value]);
596                  } else if (itEvent->Param.CC.Controller == 10) { // panpot                  } else if (itEvent->Param.CC.Controller == 10) { // panpot
597                      PanLeftSmoother.update(AbstractEngine::PanCurve[128 - itEvent->Param.CC.Value]);                      MIDIPan = itEvent->Param.CC.Value;
                     PanRightSmoother.update(AbstractEngine::PanCurve[itEvent->Param.CC.Value]);  
598                  }                  }
599              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event
600                  processPitchEvent(itEvent);                  processPitchEvent(itEvent);
601              }              }
602    
603              ProcessCCEvent(itEvent);              ProcessCCEvent(itEvent);
604                if (pSignalUnitRack != NULL) {
605                    pSignalUnitRack->ProcessCCEvent(itEvent);
606                }
607          }          }
608      }      }
609    
# Line 535  namespace LinuxSampler { Line 630  namespace LinuxSampler {
630       */       */
631      void AbstractVoice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) {      void AbstractVoice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) {
632          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
633              if (Type != Voice::type_release_trigger) {              // some voice types ignore note off
634                if (!(Type & (Voice::type_one_shot | Voice::type_release_trigger | Voice::type_controller_triggered))) {
635                  if (itEvent->Type == Event::type_release) {                  if (itEvent->Type == Event::type_release) {
636                      EnterReleaseStage();                      EnterReleaseStage();
637                  } else if (itEvent->Type == Event::type_cancel_release) {                  } else if (itEvent->Type == Event::type_cancel_release) {
638                      pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                      if (pSignalUnitRack == NULL) {
639                      EG2.update(gig::EGADSR::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                          pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
640                            pEG2->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
641                        } else {
642                            pSignalUnitRack->CancelRelease();
643                        }
644                  }                  }
645              }              }
646          }          }
# Line 568  namespace LinuxSampler { Line 667  namespace LinuxSampler {
667       * @param itNoteOffEvent - event which causes this voice to die soon       * @param itNoteOffEvent - event which causes this voice to die soon
668       */       */
669      void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {      void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {
670          const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());          if (pSignalUnitRack == NULL) {
671          pEngineChannel->PortamentoPos = (float) MIDIKey + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;              const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());
672                pEngineChannel->PortamentoPos = (float) MIDIKey + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;
673            } else {
674                // TODO:
675            }
676      }      }
677    
678      /**      /**
# Line 616  namespace LinuxSampler { Line 719  namespace LinuxSampler {
719          volume *= GetSampleAttenuation() * pEngineChannel->GlobalVolume * GLOBAL_VOLUME;          volume *= GetSampleAttenuation() * pEngineChannel->GlobalVolume * GLOBAL_VOLUME;
720    
721          // the volume of release triggered samples depends on note length          // the volume of release triggered samples depends on note length
722          if (Type == Voice::type_release_trigger) {          if (Type & Voice::type_release_trigger) {
723              float noteLength = float(GetEngine()->FrameTime + Delay -              float noteLength = float(GetEngine()->FrameTime + Delay -
724                  GetNoteOnTime(MIDIKey) ) / GetEngine()->SampleRate;                  GetNoteOnTime(MIDIKey) ) / GetEngine()->SampleRate;
725    
# Line 631  namespace LinuxSampler { Line 734  namespace LinuxSampler {
734      }      }
735    
736      void AbstractVoice::EnterReleaseStage() {      void AbstractVoice::EnterReleaseStage() {
737          pEG1->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);          if (pSignalUnitRack == NULL) {
738          EG2.update(gig::EGADSR::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);              pEG1->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
739                pEG2->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
740            } else {
741                pSignalUnitRack->EnterReleaseStage();
742            }
743        }
744    
745        bool AbstractVoice::EG1Finished() {
746            if (pSignalUnitRack == NULL) {
747                return pEG1->getSegmentType() == EG::segment_end;
748            } else {
749                return !pSignalUnitRack->GetEndpointUnit()->Active();
750            }
751      }      }
752    
753  } // namespace LinuxSampler  } // namespace LinuxSampler

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

  ViewVC Help
Powered by ViewVC