/[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 2061 by persson, Tue Feb 23 18:32:31 2010 UTC revision 2121 by schoenebeck, Tue Sep 14 17:09:08 2010 UTC
# 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 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 306  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 362  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
# Line 465  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      /**      /**
# Line 529  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                  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))) {
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                  pEG1->update(EG::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 596  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    
# Line 609  namespace LinuxSampler { Line 649  namespace LinuxSampler {
649      float AbstractVoice::GetReleaseTriggerAttenuation(float noteLength) {      float AbstractVoice::GetReleaseTriggerAttenuation(float noteLength) {
650          return 1 - RgnInfo.ReleaseTriggerDecay * noteLength;          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.2061  
changed lines
  Added in v.2121

  ViewVC Help
Powered by ViewVC