/[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 2055 by persson, Sat Jan 30 10:30:02 2010 UTC revision 2175 by persson, Mon Apr 25 08:12:36 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 28  namespace LinuxSampler { Line 28  namespace LinuxSampler {
28    
29      AbstractVoice::AbstractVoice() {      AbstractVoice::AbstractVoice() {
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 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 212  namespace LinuxSampler { Line 213  namespace LinuxSampler {
213              // calculate influence of EG2 controller on EG2's parameters              // calculate influence of EG2 controller on EG2's parameters
214              EGInfo egInfo = CalculateEG2ControllerInfluence(eg2controllervalue);              EGInfo egInfo = CalculateEG2ControllerInfluence(eg2controllervalue);
215    
216              EG2.trigger (              TriggerEG2(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity);
                 uint(RgnInfo.EG2PreAttack),  
                 RgnInfo.EG2Attack * egInfo.Attack,  
                 false,  
                 RgnInfo.EG2Decay1 * egInfo.Decay * velrelease,  
                 RgnInfo.EG2Decay2 * egInfo.Decay * velrelease,  
                 RgnInfo.EG2InfiniteSustain,  
                 uint(RgnInfo.EG2Sustain),  
                 RgnInfo.EG2Release * egInfo.Release * velrelease,  
                 velocityAttenuation,  
                 GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE  
             );  
217          }          }
218    
219    
# Line 306  namespace LinuxSampler { Line 296  namespace LinuxSampler {
296       */       */
297      void AbstractVoice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {      void AbstractVoice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {
298          AbstractEngineChannel* pChannel = pEngineChannel;          AbstractEngineChannel* pChannel = pEngineChannel;
299          finalSynthesisParameters.pOutLeft  = &pChannel->pChannelLeft->Buffer()[Skip];          MidiKeyBase* pMidiKeyInfo = GetMidiKeyInfo(MIDIKey);
300          finalSynthesisParameters.pOutRight = &pChannel->pChannelRight->Buffer()[Skip];  
301          finalSynthesisParameters.pSrc      = pSrc;          const bool bVoiceRequiresDedicatedRouting =
302                pEngineChannel->GetFxSendCount() > 0 &&
303                (pMidiKeyInfo->ReverbSend || pMidiKeyInfo->ChorusSend);
304    
305            if (bVoiceRequiresDedicatedRouting) {
306                finalSynthesisParameters.pOutLeft  = &GetEngine()->pDedicatedVoiceChannelLeft->Buffer()[Skip];
307                finalSynthesisParameters.pOutRight = &GetEngine()->pDedicatedVoiceChannelRight->Buffer()[Skip];
308            } else {
309                finalSynthesisParameters.pOutLeft  = &pChannel->pChannelLeft->Buffer()[Skip];
310                finalSynthesisParameters.pOutRight = &pChannel->pChannelRight->Buffer()[Skip];
311            }
312            finalSynthesisParameters.pSrc = pSrc;
313    
314          RTList<Event>::Iterator itCCEvent = pChannel->pEvents->first();          RTList<Event>::Iterator itCCEvent = pChannel->pEvents->first();
315          RTList<Event>::Iterator itNoteEvent;          RTList<Event>::Iterator itNoteEvent;
316          GetFirstEventOnKey(MIDIKey, itNoteEvent);          GetFirstEventOnKey(MIDIKey, itNoteEvent);
317    
318            RTList<Event>::Iterator itGroupEvent;
319            if (pGroupEvents) itGroupEvent = pGroupEvents->first();
320    
321          if (itTriggerEvent) { // skip events that happened before this voice was triggered          if (itTriggerEvent) { // skip events that happened before this voice was triggered
322              while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;              while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;
323                while (itGroupEvent && itGroupEvent->FragmentPos() <= Skip) ++itGroupEvent;
324    
325              // we can't simply compare the timestamp here, because note events              // we can't simply compare the timestamp here, because note events
326              // 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
327              // actual sequence the note events arrived instead (see bug #112)              // actual sequence the note events arrived instead (see bug #112)
# Line 362  namespace LinuxSampler { Line 368  namespace LinuxSampler {
368    
369              // process transition events (note on, note off & sustain pedal)              // process transition events (note on, note off & sustain pedal)
370              processTransitionEvents(itNoteEvent, iSubFragmentEnd);              processTransitionEvents(itNoteEvent, iSubFragmentEnd);
371                processGroupEvents(itGroupEvent, iSubFragmentEnd);
372    
373              // if the voice was killed in this subfragment, or if the              // if the voice was killed in this subfragment, or if the
374              // filter EG is finished, switch EG1 to fade out stage              // filter EG is finished, switch EG1 to fade out stage
375              if ((itKillEvent && killPos <= iSubFragmentEnd) ||              if ((itKillEvent && killPos <= iSubFragmentEnd) ||
376                  (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&                  (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&
377                   EG2.getSegmentType() == gig::EGADSR::segment_end)) {                   pEG2->getSegmentType() == EG::segment_end)) {
378                  pEG1->enterFadeOutStage();                  pEG1->enterFadeOutStage();
379                  itKillEvent = Pool<Event>::Iterator();                  itKillEvent = Pool<Event>::Iterator();
380              }              }
# Line 387  namespace LinuxSampler { Line 394  namespace LinuxSampler {
394                      fFinalVolume *= pEG1->processPow();                      fFinalVolume *= pEG1->processPow();
395                      break;                      break;
396              }              }
397              switch (EG2.getSegmentType()) {              switch (pEG2->getSegmentType()) {
398                  case gig::EGADSR::segment_lin:                  case EG::segment_lin:
399                      fFinalCutoff *= EG2.processLin();                      fFinalCutoff *= pEG2->processLin();
400                      break;                      break;
401                  case gig::EGADSR::segment_exp:                  case EG::segment_exp:
402                      fFinalCutoff *= EG2.processExp();                      fFinalCutoff *= pEG2->processExp();
403                      break;                      break;
404                  case gig::EGADSR::segment_end:                  case EG::segment_end:
405                      fFinalCutoff *= EG2.getLevel();                      fFinalCutoff *= pEG2->getLevel();
406                      break; // noop                      break; // noop
407                    case EG::segment_pow:
408                        fFinalCutoff *= pEG2->processPow();
409                        break;
410              }              }
411              if (EG3.active()) finalSynthesisParameters.fFinalPitch *= EG3.render();              if (EG3.active()) finalSynthesisParameters.fFinalPitch *= EG3.render();
412    
# Line 455  namespace LinuxSampler { Line 465  namespace LinuxSampler {
465                  pEG1->increment(1);                  pEG1->increment(1);
466                  if (!pEG1->toStageEndLeft()) pEG1->update(EG::event_stage_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  if (!pEG1->toStageEndLeft()) pEG1->update(EG::event_stage_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
467              }              }
468              if (EG2.active()) {              if (pEG2->active()) {
469                  EG2.increment(1);                  pEG2->increment(1);
470                  if (!EG2.toStageEndLeft()) EG2.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);
471              }              }
472              EG3.increment(1);              EG3.increment(1);
473              if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached              if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached
# Line 465  namespace LinuxSampler { Line 475  namespace LinuxSampler {
475              Pos = newPos;              Pos = newPos;
476              i = iSubFragmentEnd;              i = iSubFragmentEnd;
477          }          }
478    
479            if (bVoiceRequiresDedicatedRouting) {
480                optional<float> effectSendLevels[2] = {
481                    pMidiKeyInfo->ReverbSend,
482                    pMidiKeyInfo->ChorusSend
483                };
484                GetEngine()->RouteDedicatedVoiceChannels(pEngineChannel, effectSendLevels, Samples);
485            }
486      }      }
487    
488      /**      /**
# Line 529  namespace LinuxSampler { Line 547  namespace LinuxSampler {
547       */       */
548      void AbstractVoice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) {      void AbstractVoice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) {
549          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
550              if (itEvent->Type == Event::type_release) {              // some voice types ignore note off
551                  pEG1->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);              if (!(Type & (Voice::type_one_shot | Voice::type_release_trigger | Voice::type_controller_triggered))) {
552                  EG2.update(gig::EGADSR::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  if (itEvent->Type == Event::type_release) {
553              } else if (itEvent->Type == Event::type_cancel_release) {                      EnterReleaseStage();
554                  pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  } else if (itEvent->Type == Event::type_cancel_release) {
555                  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);
556                        pEG2->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
557                    }
558              }              }
559          }          }
560      }      }
561    
562        /**
563         * Process given list of events aimed at all voices in a key group.
564         *
565         * @param itEvent - iterator pointing to the next event to be processed
566         * @param End     - youngest time stamp where processing should be stopped
567         */
568        void AbstractVoice::processGroupEvents(RTList<Event>::Iterator& itEvent, uint End) {
569            for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
570                ProcessGroupEvent(itEvent);
571            }
572        }
573    
574      /** @brief Update current portamento position.      /** @brief Update current portamento position.
575       *       *
576       * 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 596  namespace LinuxSampler { Line 628  namespace LinuxSampler {
628          volume *= GetSampleAttenuation() * pEngineChannel->GlobalVolume * GLOBAL_VOLUME;          volume *= GetSampleAttenuation() * pEngineChannel->GlobalVolume * GLOBAL_VOLUME;
629    
630          // the volume of release triggered samples depends on note length          // the volume of release triggered samples depends on note length
631          if (Type == Voice::type_release_trigger) {          if (Type & Voice::type_release_trigger) {
632              float noteLength = float(GetEngine()->FrameTime + Delay -              float noteLength = float(GetEngine()->FrameTime + Delay -
633                  GetNoteOnTime(MIDIKey) ) / GetEngine()->SampleRate;                  GetNoteOnTime(MIDIKey) ) / GetEngine()->SampleRate;
634    
635              float attenuation = 1 - 0.01053 * (256 >> RgnInfo.ReleaseTriggerDecay) * noteLength;              volume *= GetReleaseTriggerAttenuation(noteLength);
             volume *= attenuation;  
636          }          }
637    
638          return volume;          return volume;
639      }      }
640    
641        float AbstractVoice::GetReleaseTriggerAttenuation(float noteLength) {
642            return 1 - RgnInfo.ReleaseTriggerDecay * noteLength;
643        }
644    
645        void AbstractVoice::EnterReleaseStage() {
646            pEG1->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
647            pEG2->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
648        }
649    
650  } // namespace LinuxSampler  } // namespace LinuxSampler

Legend:
Removed from v.2055  
changed lines
  Added in v.2175

  ViewVC Help
Powered by ViewVC