/[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 2121 by schoenebeck, Tue Sep 14 17:09:08 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;          MidiKeyBase* pKeyInfo = GetMidiKeyInfo(MIDIKey);
107    
108            pGroupEvents = iKeyGroup ? pEngineChannel->ActiveKeyGroups[iKeyGroup] : 0;
109    
110          SmplInfo   = GetSampleInfo();          SmplInfo   = GetSampleInfo();
111          RgnInfo    = GetRegionInfo();          RgnInfo    = GetRegionInfo();
# Line 112  namespace LinuxSampler { Line 113  namespace LinuxSampler {
113    
114          // calculate volume          // calculate volume
115          const double velocityAttenuation = GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity);          const double velocityAttenuation = GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity);
116          float volume = CalculateVolume(velocityAttenuation);          float volume = CalculateVolume(velocityAttenuation) * pKeyInfo->Volume;
117          if (volume <= 0) return -1;          if (volume <= 0) return -1;
118    
119          // select channel mode (mono or stereo)          // select channel mode (mono or stereo)
# Line 123  namespace LinuxSampler { Line 124  namespace LinuxSampler {
124          // get starting crossfade volume level          // get starting crossfade volume level
125          float crossfadeVolume = CalculateCrossfadeVolume(itNoteOnEvent->Param.Note.Velocity);          float crossfadeVolume = CalculateCrossfadeVolume(itNoteOnEvent->Param.Note.Velocity);
126    
127          VolumeLeft  = volume * AbstractEngine::PanCurve[64 - RgnInfo.Pan];          VolumeLeft  = volume * pKeyInfo->PanLeft  * AbstractEngine::PanCurve[64 - RgnInfo.Pan];
128          VolumeRight = volume * AbstractEngine::PanCurve[64 + RgnInfo.Pan];          VolumeRight = volume * pKeyInfo->PanRight * AbstractEngine::PanCurve[64 + RgnInfo.Pan];
129    
130          float subfragmentRate = GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;          float subfragmentRate = GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;
131          CrossfadeSmoother.trigger(crossfadeVolume, subfragmentRate);          CrossfadeSmoother.trigger(crossfadeVolume, subfragmentRate);
# Line 183  namespace LinuxSampler { Line 184  namespace LinuxSampler {
184              // calculate influence of EG1 controller on EG1's parameters              // calculate influence of EG1 controller on EG1's parameters
185              EGInfo egInfo = CalculateEG1ControllerInfluence(eg1controllervalue);              EGInfo egInfo = CalculateEG1ControllerInfluence(eg1controllervalue);
186    
187              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  
             );  
188          }          }
189    
190  #ifdef CONFIG_INTERPOLATE_VOLUME  #ifdef CONFIG_INTERPOLATE_VOLUME
# Line 207  namespace LinuxSampler { Line 197  namespace LinuxSampler {
197          else          else
198      #else      #else
199          {          {
200              float finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * EG1.getLevel();              float finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pEG1->getLevel();
201    
202              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * pEngineChannel->GlobalPanLeft;              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * pEngineChannel->GlobalPanLeft;
203              finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * pEngineChannel->GlobalPanRight;              finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * pEngineChannel->GlobalPanRight;
# Line 224  namespace LinuxSampler { Line 214  namespace LinuxSampler {
214              EGInfo egInfo = CalculateEG2ControllerInfluence(eg2controllervalue);              EGInfo egInfo = CalculateEG2ControllerInfluence(eg2controllervalue);
215    
216              EG2.trigger (              EG2.trigger (
217                  RgnInfo.EG2PreAttack,                  uint(RgnInfo.EG2PreAttack),
218                  RgnInfo.EG2Attack * egInfo.Attack,                  RgnInfo.EG2Attack * egInfo.Attack,
219                  false,                  false,
220                  RgnInfo.EG2Decay1 * egInfo.Decay * velrelease,                  RgnInfo.EG2Decay1 * egInfo.Decay * velrelease,
221                  RgnInfo.EG2Decay2 * egInfo.Decay * velrelease,                  RgnInfo.EG2Decay2 * egInfo.Decay * velrelease,
222                  RgnInfo.EG2InfiniteSustain,                  RgnInfo.EG2InfiniteSustain,
223                  RgnInfo.EG2Sustain,                  uint(RgnInfo.EG2Sustain),
224                  RgnInfo.EG2Release * egInfo.Release * velrelease,                  RgnInfo.EG2Release * egInfo.Release * velrelease,
225                  velocityAttenuation,                  velocityAttenuation,
226                  GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE                  GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE
# Line 317  namespace LinuxSampler { Line 307  namespace LinuxSampler {
307       */       */
308      void AbstractVoice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {      void AbstractVoice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {
309          AbstractEngineChannel* pChannel = pEngineChannel;          AbstractEngineChannel* pChannel = pEngineChannel;
310          finalSynthesisParameters.pOutLeft  = &pChannel->pChannelLeft->Buffer()[Skip];          MidiKeyBase* pMidiKeyInfo = GetMidiKeyInfo(MIDIKey);
311          finalSynthesisParameters.pOutRight = &pChannel->pChannelRight->Buffer()[Skip];  
312          finalSynthesisParameters.pSrc      = pSrc;          const bool bVoiceRequiresDedicatedRouting =
313                pEngineChannel->GetFxSendCount() > 0 &&
314                (pMidiKeyInfo->ReverbSend || pMidiKeyInfo->ChorusSend);
315    
316            if (bVoiceRequiresDedicatedRouting) {
317                finalSynthesisParameters.pOutLeft  = &GetEngine()->pDedicatedVoiceChannelLeft->Buffer()[Skip];
318                finalSynthesisParameters.pOutRight = &GetEngine()->pDedicatedVoiceChannelRight->Buffer()[Skip];
319            } else {
320                finalSynthesisParameters.pOutLeft  = &pChannel->pChannelLeft->Buffer()[Skip];
321                finalSynthesisParameters.pOutRight = &pChannel->pChannelRight->Buffer()[Skip];
322            }
323            finalSynthesisParameters.pSrc = pSrc;
324    
325          RTList<Event>::Iterator itCCEvent = pChannel->pEvents->first();          RTList<Event>::Iterator itCCEvent = pChannel->pEvents->first();
326          RTList<Event>::Iterator itNoteEvent;          RTList<Event>::Iterator itNoteEvent;
327          GetFirstEventOnKey(MIDIKey, itNoteEvent);          GetFirstEventOnKey(MIDIKey, itNoteEvent);
328    
329            RTList<Event>::Iterator itGroupEvent;
330            if (pGroupEvents) itGroupEvent = pGroupEvents->first();
331    
332          if (itTriggerEvent) { // skip events that happened before this voice was triggered          if (itTriggerEvent) { // skip events that happened before this voice was triggered
333              while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;              while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;
334                while (itGroupEvent && itGroupEvent->FragmentPos() <= Skip) ++itGroupEvent;
335    
336              // we can't simply compare the timestamp here, because note events              // we can't simply compare the timestamp here, because note events
337              // 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
338              // 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 353  namespace LinuxSampler {
353                  // drivers that use Samples < MaxSamplesPerCycle).                  // drivers that use Samples < MaxSamplesPerCycle).
354                  // End the EG1 here, at pos 0, with a shorter max fade                  // End the EG1 here, at pos 0, with a shorter max fade
355                  // out time.                  // out time.
356                  EG1.enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  pEG1->enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
357                  itKillEvent = Pool<Event>::Iterator();                  itKillEvent = Pool<Event>::Iterator();
358              } else {              } else {
359                  killPos = RTMath::Min(itKillEvent->FragmentPos(), maxFadeOutPos);                  killPos = RTMath::Min(itKillEvent->FragmentPos(), maxFadeOutPos);
# Line 373  namespace LinuxSampler { Line 379  namespace LinuxSampler {
379    
380              // process transition events (note on, note off & sustain pedal)              // process transition events (note on, note off & sustain pedal)
381              processTransitionEvents(itNoteEvent, iSubFragmentEnd);              processTransitionEvents(itNoteEvent, iSubFragmentEnd);
382                processGroupEvents(itGroupEvent, iSubFragmentEnd);
383    
384              // if the voice was killed in this subfragment, or if the              // if the voice was killed in this subfragment, or if the
385              // filter EG is finished, switch EG1 to fade out stage              // filter EG is finished, switch EG1 to fade out stage
386              if ((itKillEvent && killPos <= iSubFragmentEnd) ||              if ((itKillEvent && killPos <= iSubFragmentEnd) ||
387                  (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&                  (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&
388                   EG2.getSegmentType() == gig::EGADSR::segment_end)) {                   EG2.getSegmentType() == gig::EGADSR::segment_end)) {
389                  EG1.enterFadeOutStage();                  pEG1->enterFadeOutStage();
390                  itKillEvent = Pool<Event>::Iterator();                  itKillEvent = Pool<Event>::Iterator();
391              }              }
392    
393              // process envelope generators              // process envelope generators
394              switch (EG1.getSegmentType()) {              switch (pEG1->getSegmentType()) {
395                  case gig::EGADSR::segment_lin:                  case EG::segment_lin:
396                      fFinalVolume *= EG1.processLin();                      fFinalVolume *= pEG1->processLin();
397                      break;                      break;
398                  case gig::EGADSR::segment_exp:                  case EG::segment_exp:
399                      fFinalVolume *= EG1.processExp();                      fFinalVolume *= pEG1->processExp();
400                      break;                      break;
401                  case gig::EGADSR::segment_end:                  case EG::segment_end:
402                      fFinalVolume *= EG1.getLevel();                      fFinalVolume *= pEG1->getLevel();
403                      break; // noop                      break; // noop
404                    case EG::segment_pow:
405                        fFinalVolume *= pEG1->processPow();
406                        break;
407              }              }
408              switch (EG2.getSegmentType()) {              switch (EG2.getSegmentType()) {
409                  case gig::EGADSR::segment_lin:                  case gig::EGADSR::segment_lin:
# Line 448  namespace LinuxSampler { Line 458  namespace LinuxSampler {
458              RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);              RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);
459    
460              // stop the rendering if volume EG is finished              // stop the rendering if volume EG is finished
461              if (EG1.getSegmentType() == gig::EGADSR::segment_end) break;              if (pEG1->getSegmentType() == EG::segment_end) break;
462    
463              const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;              const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;
464    
465              // increment envelopes' positions              // increment envelopes' positions
466              if (EG1.active()) {              if (pEG1->active()) {
467    
468                  // 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
469                  if (SmplInfo.HasLoops && Pos <= SmplInfo.LoopStart && SmplInfo.LoopStart < newPos) {                  if (SmplInfo.HasLoops && Pos <= SmplInfo.LoopStart && SmplInfo.LoopStart < newPos) {
470                      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);
471                  }                  }
472    
473                  EG1.increment(1);                  pEG1->increment(1);
474                  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);
475              }              }
476              if (EG2.active()) {              if (EG2.active()) {
477                  EG2.increment(1);                  EG2.increment(1);
# Line 473  namespace LinuxSampler { Line 483  namespace LinuxSampler {
483              Pos = newPos;              Pos = newPos;
484              i = iSubFragmentEnd;              i = iSubFragmentEnd;
485          }          }
486    
487            if (bVoiceRequiresDedicatedRouting) {
488                optional<float> effectSendLevels[2] = {
489                    pMidiKeyInfo->ReverbSend,
490                    pMidiKeyInfo->ChorusSend
491                };
492                GetEngine()->RouteDedicatedVoiceChannels(pEngineChannel, effectSendLevels, Samples);
493            }
494      }      }
495        
496      /**      /**
497       * Process given list of MIDI control change and pitch bend events for       * Process given list of MIDI control change and pitch bend events for
498       * the given time.       * the given time.
# Line 537  namespace LinuxSampler { Line 555  namespace LinuxSampler {
555       */       */
556      void AbstractVoice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) {      void AbstractVoice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) {
557          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
558              if (itEvent->Type == Event::type_release) {              // some voice types ignore note off
559                  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))) {
560                  EG2.update(gig::EGADSR::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  if (itEvent->Type == Event::type_release) {
561              } else if (itEvent->Type == Event::type_cancel_release) {                      EnterReleaseStage();
562                  EG1.update(gig::EGADSR::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  } else if (itEvent->Type == Event::type_cancel_release) {
563                  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);
564                        EG2.update(gig::EGADSR::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
565                    }
566              }              }
567          }          }
568      }      }
569    
570        /**
571         * Process given list of events aimed at all voices in a key group.
572         *
573         * @param itEvent - iterator pointing to the next event to be processed
574         * @param End     - youngest time stamp where processing should be stopped
575         */
576        void AbstractVoice::processGroupEvents(RTList<Event>::Iterator& itEvent, uint End) {
577            for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
578                ProcessGroupEvent(itEvent);
579            }
580        }
581    
582      /** @brief Update current portamento position.      /** @brief Update current portamento position.
583       *       *
584       * 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 636  namespace LinuxSampler {
636          volume *= GetSampleAttenuation() * pEngineChannel->GlobalVolume * GLOBAL_VOLUME;          volume *= GetSampleAttenuation() * pEngineChannel->GlobalVolume * GLOBAL_VOLUME;
637    
638          // the volume of release triggered samples depends on note length          // the volume of release triggered samples depends on note length
639          if (Type == Voice::type_release_trigger) {          if (Type & Voice::type_release_trigger) {
640              float noteLength = float(GetEngine()->FrameTime + Delay -              float noteLength = float(GetEngine()->FrameTime + Delay -
641                  GetNoteOnTime(MIDIKey) ) / GetEngine()->SampleRate;                  GetNoteOnTime(MIDIKey) ) / GetEngine()->SampleRate;
642    
643              float attenuation = 1 - 0.01053 * (256 >> RgnInfo.ReleaseTriggerDecay) * noteLength;              volume *= GetReleaseTriggerAttenuation(noteLength);
             volume *= attenuation;  
644          }          }
645    
646          return volume;          return volume;
647      }      }
648    
649        float AbstractVoice::GetReleaseTriggerAttenuation(float noteLength) {
650            return 1 - RgnInfo.ReleaseTriggerDecay * noteLength;
651        }
652    
653        void AbstractVoice::EnterReleaseStage() {
654            pEG1->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
655            EG2.update(gig::EGADSR::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
656        }
657    
658  } // namespace LinuxSampler  } // namespace LinuxSampler

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

  ViewVC Help
Powered by ViewVC