/[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 2115 by persson, Thu Aug 12 15:36:15 2010 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-2010 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 32  namespace LinuxSampler { Line 32  namespace LinuxSampler {
32          pLFO2 = new LFOUnsigned(1.0f);  // filter EG (0..1 range)          pLFO2 = new LFOUnsigned(1.0f);  // filter EG (0..1 range)
33          pLFO3 = new LFOSigned(1200.0f); // pitch EG (-1200..+1200 range)          pLFO3 = new LFOSigned(1200.0f); // pitch EG (-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 51  namespace LinuxSampler { Line 50  namespace LinuxSampler {
50          if (pLFO2) delete pLFO2;          if (pLFO2) delete pLFO2;
51          if (pLFO3) delete pLFO3;          if (pLFO3) delete pLFO3;
52      }      }
53        
54      /**      /**
55       *  Resets voice variables. Should only be called if rendering process is       *  Resets voice variables. Should only be called if rendering process is
56       *  suspended / not running.       *  suspended / not running.
# Line 104  namespace LinuxSampler { Line 103  namespace LinuxSampler {
103          Delay           = itNoteOnEvent->FragmentPos();          Delay           = itNoteOnEvent->FragmentPos();
104          itTriggerEvent  = itNoteOnEvent;          itTriggerEvent  = itNoteOnEvent;
105          itKillEvent     = Pool<Event>::Iterator();          itKillEvent     = Pool<Event>::Iterator();
106          KeyGroup        = iKeyGroup;  
107            pGroupEvents = iKeyGroup ? pEngineChannel->ActiveKeyGroups[iKeyGroup] : 0;
108    
109          SmplInfo   = GetSampleInfo();          SmplInfo   = GetSampleInfo();
110          RgnInfo    = GetRegionInfo();          RgnInfo    = GetRegionInfo();
# Line 183  namespace LinuxSampler { Line 183  namespace LinuxSampler {
183              // calculate influence of EG1 controller on EG1's parameters              // calculate influence of EG1 controller on EG1's parameters
184              EGInfo egInfo = CalculateEG1ControllerInfluence(eg1controllervalue);              EGInfo egInfo = CalculateEG1ControllerInfluence(eg1controllervalue);
185    
186              EG1.trigger (              TriggerEG1(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity);
                 RgnInfo.EG1PreAttack,  
                 RgnInfo.EG1Attack * egInfo.Attack,  
                 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  
             );  
187          }          }
188    
189  #ifdef CONFIG_INTERPOLATE_VOLUME  #ifdef CONFIG_INTERPOLATE_VOLUME
# Line 207  namespace LinuxSampler { Line 196  namespace LinuxSampler {
196          else          else
197      #else      #else
198          {          {
199              float finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * EG1.getLevel();              float finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pEG1->getLevel();
200    
201              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * pEngineChannel->GlobalPanLeft;              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * pEngineChannel->GlobalPanLeft;
202              finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * pEngineChannel->GlobalPanRight;              finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * pEngineChannel->GlobalPanRight;
# Line 224  namespace LinuxSampler { Line 213  namespace LinuxSampler {
213              EGInfo egInfo = CalculateEG2ControllerInfluence(eg2controllervalue);              EGInfo egInfo = CalculateEG2ControllerInfluence(eg2controllervalue);
214    
215              EG2.trigger (              EG2.trigger (
216                  RgnInfo.EG2PreAttack,                  uint(RgnInfo.EG2PreAttack),
217                  RgnInfo.EG2Attack * egInfo.Attack,                  RgnInfo.EG2Attack * egInfo.Attack,
218                  false,                  false,
219                  RgnInfo.EG2Decay1 * egInfo.Decay * velrelease,                  RgnInfo.EG2Decay1 * egInfo.Decay * velrelease,
220                  RgnInfo.EG2Decay2 * egInfo.Decay * velrelease,                  RgnInfo.EG2Decay2 * egInfo.Decay * velrelease,
221                  RgnInfo.EG2InfiniteSustain,                  RgnInfo.EG2InfiniteSustain,
222                  RgnInfo.EG2Sustain,                  uint(RgnInfo.EG2Sustain),
223                  RgnInfo.EG2Release * egInfo.Release * velrelease,                  RgnInfo.EG2Release * egInfo.Release * velrelease,
224                  velocityAttenuation,                  velocityAttenuation,
225                  GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE                  GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE
# Line 325  namespace LinuxSampler { Line 314  namespace LinuxSampler {
314          RTList<Event>::Iterator itNoteEvent;          RTList<Event>::Iterator itNoteEvent;
315          GetFirstEventOnKey(MIDIKey, itNoteEvent);          GetFirstEventOnKey(MIDIKey, itNoteEvent);
316    
317            RTList<Event>::Iterator itGroupEvent;
318            if (pGroupEvents) itGroupEvent = pGroupEvents->first();
319    
320          if (itTriggerEvent) { // skip events that happened before this voice was triggered          if (itTriggerEvent) { // skip events that happened before this voice was triggered
321              while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;              while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;
322                while (itGroupEvent && itGroupEvent->FragmentPos() <= Skip) ++itGroupEvent;
323    
324              // we can't simply compare the timestamp here, because note events              // we can't simply compare the timestamp here, because note events
325              // 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
326              // 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 341  namespace LinuxSampler {
341                  // drivers that use Samples < MaxSamplesPerCycle).                  // drivers that use Samples < MaxSamplesPerCycle).
342                  // End the EG1 here, at pos 0, with a shorter max fade                  // End the EG1 here, at pos 0, with a shorter max fade
343                  // out time.                  // out time.
344                  EG1.enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  pEG1->enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
345                  itKillEvent = Pool<Event>::Iterator();                  itKillEvent = Pool<Event>::Iterator();
346              } else {              } else {
347                  killPos = RTMath::Min(itKillEvent->FragmentPos(), maxFadeOutPos);                  killPos = RTMath::Min(itKillEvent->FragmentPos(), maxFadeOutPos);
# Line 373  namespace LinuxSampler { Line 367  namespace LinuxSampler {
367    
368              // process transition events (note on, note off & sustain pedal)              // process transition events (note on, note off & sustain pedal)
369              processTransitionEvents(itNoteEvent, iSubFragmentEnd);              processTransitionEvents(itNoteEvent, iSubFragmentEnd);
370                processGroupEvents(itGroupEvent, iSubFragmentEnd);
371    
372              // if the voice was killed in this subfragment, or if the              // if the voice was killed in this subfragment, or if the
373              // filter EG is finished, switch EG1 to fade out stage              // filter EG is finished, switch EG1 to fade out stage
374              if ((itKillEvent && killPos <= iSubFragmentEnd) ||              if ((itKillEvent && killPos <= iSubFragmentEnd) ||
375                  (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&                  (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&
376                   EG2.getSegmentType() == gig::EGADSR::segment_end)) {                   EG2.getSegmentType() == gig::EGADSR::segment_end)) {
377                  EG1.enterFadeOutStage();                  pEG1->enterFadeOutStage();
378                  itKillEvent = Pool<Event>::Iterator();                  itKillEvent = Pool<Event>::Iterator();
379              }              }
380    
381              // process envelope generators              // process envelope generators
382              switch (EG1.getSegmentType()) {              switch (pEG1->getSegmentType()) {
383                  case gig::EGADSR::segment_lin:                  case EG::segment_lin:
384                      fFinalVolume *= EG1.processLin();                      fFinalVolume *= pEG1->processLin();
385                      break;                      break;
386                  case gig::EGADSR::segment_exp:                  case EG::segment_exp:
387                      fFinalVolume *= EG1.processExp();                      fFinalVolume *= pEG1->processExp();
388                      break;                      break;
389                  case gig::EGADSR::segment_end:                  case EG::segment_end:
390                      fFinalVolume *= EG1.getLevel();                      fFinalVolume *= pEG1->getLevel();
391                      break; // noop                      break; // noop
392                    case EG::segment_pow:
393                        fFinalVolume *= pEG1->processPow();
394                        break;
395              }              }
396              switch (EG2.getSegmentType()) {              switch (EG2.getSegmentType()) {
397                  case gig::EGADSR::segment_lin:                  case gig::EGADSR::segment_lin:
# Line 448  namespace LinuxSampler { Line 446  namespace LinuxSampler {
446              RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);              RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);
447    
448              // stop the rendering if volume EG is finished              // stop the rendering if volume EG is finished
449              if (EG1.getSegmentType() == gig::EGADSR::segment_end) break;              if (pEG1->getSegmentType() == EG::segment_end) break;
450    
451              const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;              const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;
452    
453              // increment envelopes' positions              // increment envelopes' positions
454              if (EG1.active()) {              if (pEG1->active()) {
455    
456                  // 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                  // 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
457                  if (SmplInfo.HasLoops && Pos <= SmplInfo.LoopStart && SmplInfo.LoopStart < newPos) {                  if (SmplInfo.HasLoops && Pos <= SmplInfo.LoopStart && SmplInfo.LoopStart < newPos) {
458                      EG1.update(gig::EGADSR::event_hold_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                      pEG1->update(EG::event_hold_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
459                  }                  }
460    
461                  EG1.increment(1);                  pEG1->increment(1);
462                  if (!EG1.toStageEndLeft()) EG1.update(gig::EGADSR::event_stage_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  if (!pEG1->toStageEndLeft()) pEG1->update(EG::event_stage_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
463              }              }
464              if (EG2.active()) {              if (EG2.active()) {
465                  EG2.increment(1);                  EG2.increment(1);
# Line 474  namespace LinuxSampler { Line 472  namespace LinuxSampler {
472              i = iSubFragmentEnd;              i = iSubFragmentEnd;
473          }          }
474      }      }
475        
476      /**      /**
477       * Process given list of MIDI control change and pitch bend events for       * Process given list of MIDI control change and pitch bend events for
478       * the given time.       * the given time.
# Line 537  namespace LinuxSampler { Line 535  namespace LinuxSampler {
535       */       */
536      void AbstractVoice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) {      void AbstractVoice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) {
537          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
538              if (itEvent->Type == Event::type_release) {              // some voice types ignore note off
539                  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))) {
540                  EG2.update(gig::EGADSR::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  if (itEvent->Type == Event::type_release) {
541              } else if (itEvent->Type == Event::type_cancel_release) {                      EnterReleaseStage();
542                  EG1.update(gig::EGADSR::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  } else if (itEvent->Type == Event::type_cancel_release) {
543                  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);
544                        EG2.update(gig::EGADSR::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
545                    }
546              }              }
547          }          }
548      }      }
549    
550        /**
551         * Process given list of events aimed at all voices in a key group.
552         *
553         * @param itEvent - iterator pointing to the next event to be processed
554         * @param End     - youngest time stamp where processing should be stopped
555         */
556        void AbstractVoice::processGroupEvents(RTList<Event>::Iterator& itEvent, uint End) {
557            for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
558                ProcessGroupEvent(itEvent);
559            }
560        }
561    
562      /** @brief Update current portamento position.      /** @brief Update current portamento position.
563       *       *
564       * 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 604  namespace LinuxSampler { Line 616  namespace LinuxSampler {
616          volume *= GetSampleAttenuation() * pEngineChannel->GlobalVolume * GLOBAL_VOLUME;          volume *= GetSampleAttenuation() * pEngineChannel->GlobalVolume * GLOBAL_VOLUME;
617    
618          // the volume of release triggered samples depends on note length          // the volume of release triggered samples depends on note length
619          if (Type == Voice::type_release_trigger) {          if (Type & Voice::type_release_trigger) {
620              float noteLength = float(GetEngine()->FrameTime + Delay -              float noteLength = float(GetEngine()->FrameTime + Delay -
621                  GetNoteOnTime(MIDIKey) ) / GetEngine()->SampleRate;                  GetNoteOnTime(MIDIKey) ) / GetEngine()->SampleRate;
622    
623              float attenuation = 1 - 0.01053 * (256 >> RgnInfo.ReleaseTriggerDecay) * noteLength;              volume *= GetReleaseTriggerAttenuation(noteLength);
             volume *= attenuation;  
624          }          }
625    
626          return volume;          return volume;
627      }      }
628    
629        float AbstractVoice::GetReleaseTriggerAttenuation(float noteLength) {
630            return 1 - RgnInfo.ReleaseTriggerDecay * noteLength;
631        }
632    
633        void AbstractVoice::EnterReleaseStage() {
634            pEG1->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
635            EG2.update(gig::EGADSR::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
636        }
637    
638  } // namespace LinuxSampler  } // namespace LinuxSampler

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

  ViewVC Help
Powered by ViewVC