/[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 2559 by schoenebeck, Sun May 18 17:38:25 2014 UTC revision 2931 by schoenebeck, Sat Jul 9 14:38:33 2016 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-2012 Christian Schoenebeck and Grigor Iliev        *   *   Copyright (C) 2009-2015 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 110  namespace LinuxSampler { Line 110  namespace LinuxSampler {
110          #endif // CONFIG_DEVMODE          #endif // CONFIG_DEVMODE
111    
112          Type            = VoiceType;          Type            = VoiceType;
113          MIDIKey         = itNoteOnEvent->Param.Note.Key;          pNote           = pEngineChannel->pEngine->NoteByID( itNoteOnEvent->Param.Note.ID );
         MIDIVelocity    = itNoteOnEvent->Param.Note.Velocity;  
114          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
115          Delay           = itNoteOnEvent->FragmentPos();          Delay           = itNoteOnEvent->FragmentPos();
116          itTriggerEvent  = itNoteOnEvent;          itTriggerEvent  = itNoteOnEvent;
117          itKillEvent     = Pool<Event>::Iterator();          itKillEvent     = Pool<Event>::Iterator();
118          MidiKeyBase* pKeyInfo = GetMidiKeyInfo(MIDIKey);          MidiKeyBase* pKeyInfo = GetMidiKeyInfo(MIDIKey());
119    
120          pGroupEvents = iKeyGroup ? pEngineChannel->ActiveKeyGroups[iKeyGroup] : 0;          pGroupEvents = iKeyGroup ? pEngineChannel->ActiveKeyGroups[iKeyGroup] : 0;
121    
# Line 147  namespace LinuxSampler { Line 146  namespace LinuxSampler {
146          float subfragmentRate = GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;          float subfragmentRate = GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;
147          CrossfadeSmoother.trigger(crossfadeVolume, subfragmentRate);          CrossfadeSmoother.trigger(crossfadeVolume, subfragmentRate);
148          VolumeSmoother.trigger(pEngineChannel->MidiVolume, subfragmentRate);          VolumeSmoother.trigger(pEngineChannel->MidiVolume, subfragmentRate);
149            NoteVolumeSmoother.trigger(pNote ? pNote->Override.Volume : 1.f, subfragmentRate);
150    
151          // 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
152          long cachedsamples = GetSampleCacheSize() / SmplInfo.FrameSize;          long cachedsamples = GetSampleCacheSize() / SmplInfo.FrameSize;
# Line 170  namespace LinuxSampler { Line 170  namespace LinuxSampler {
170              RAMLoop = (SmplInfo.HasLoops && (SmplInfo.LoopStart + SmplInfo.LoopLength) <= MaxRAMPos);              RAMLoop = (SmplInfo.HasLoops && (SmplInfo.LoopStart + SmplInfo.LoopLength) <= MaxRAMPos);
171    
172              if (OrderNewStream()) return -1;              if (OrderNewStream()) return -1;
173              dmsg(4,("Disk voice launched (cached samples: %d, total Samples: %d, MaxRAMPos: %d, RAMLooping: %s)\n", cachedsamples, SmplInfo.TotalFrameCount, MaxRAMPos, (RAMLoop) ? "yes" : "no"));              dmsg(4,("Disk voice launched (cached samples: %ld, total Samples: %d, MaxRAMPos: %lu, RAMLooping: %s)\n", cachedsamples, SmplInfo.TotalFrameCount, MaxRAMPos, (RAMLoop) ? "yes" : "no"));
174          }          }
175          else { // RAM only voice          else { // RAM only voice
176              MaxRAMPos = cachedsamples;              MaxRAMPos = cachedsamples;
# Line 186  namespace LinuxSampler { Line 186  namespace LinuxSampler {
186          }          }
187    
188          Pitch = CalculatePitchInfo(PitchBend);          Pitch = CalculatePitchInfo(PitchBend);
189            NotePitch = (pNote) ? pNote->Override.Pitch : 1.0f;
190    
191          // 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
192          const double velrelease = 1 / GetVelocityRelease(itNoteOnEvent->Param.Note.Velocity);          const double velrelease = 1 / GetVelocityRelease(itNoteOnEvent->Param.Note.Velocity);
# Line 202  namespace LinuxSampler { Line 203  namespace LinuxSampler {
203              pSignalUnitRack->Trigger();              pSignalUnitRack->Trigger();
204          }          }
205    
206          uint8_t pan = MIDIPan;          const uint8_t pan = (pSignalUnitRack) ? pSignalUnitRack->GetEndpointUnit()->CalculatePan(MIDIPan) : MIDIPan;
207          if (pSignalUnitRack) pan = pSignalUnitRack->GetEndpointUnit()->CalculatePan(MIDIPan);          NotePanLeft  = (pNote) ? AbstractEngine::PanCurveValueNorm(pNote->Override.Pan, 0 /*left*/ ) : 1.f;
208          PanLeftSmoother.trigger(AbstractEngine::PanCurve[128 - pan], subfragmentRate);          NotePanRight = (pNote) ? AbstractEngine::PanCurveValueNorm(pNote->Override.Pan, 1 /*right*/) : 1.f;
209          PanRightSmoother.trigger(AbstractEngine::PanCurve[pan], subfragmentRate);          PanLeftSmoother.trigger(
210                AbstractEngine::PanCurve[128 - pan] * NotePanLeft,
211                subfragmentRate
212            );
213            PanRightSmoother.trigger(
214                AbstractEngine::PanCurve[pan] * NotePanRight,
215                subfragmentRate
216            );
217    
218  #ifdef CONFIG_INTERPOLATE_VOLUME  #ifdef CONFIG_INTERPOLATE_VOLUME
219          // setup initial volume in synthesis parameters          // setup initial volume in synthesis parameters
# Line 248  namespace LinuxSampler { Line 256  namespace LinuxSampler {
256                  // if portamento mode is on, we dedicate EG3 purely for portamento, otherwise if portamento is off we do as told by the patch                  // if portamento mode is on, we dedicate EG3 purely for portamento, otherwise if portamento is off we do as told by the patch
257                  bool  bPortamento = pEngineChannel->PortamentoMode && pEngineChannel->PortamentoPos >= 0.0f;                  bool  bPortamento = pEngineChannel->PortamentoMode && pEngineChannel->PortamentoPos >= 0.0f;
258                  float eg3depth = (bPortamento)                  float eg3depth = (bPortamento)
259                               ? RTMath::CentsToFreqRatio((pEngineChannel->PortamentoPos - (float) MIDIKey) * 100)                               ? RTMath::CentsToFreqRatio((pEngineChannel->PortamentoPos - (float) MIDIKey()) * 100)
260                               : RTMath::CentsToFreqRatio(RgnInfo.EG3Depth);                               : RTMath::CentsToFreqRatio(RgnInfo.EG3Depth);
261                  float eg3time = (bPortamento)                  float eg3time = (bPortamento)
262                              ? pEngineChannel->PortamentoTime                              ? pEngineChannel->PortamentoTime
# Line 353  namespace LinuxSampler { Line 361  namespace LinuxSampler {
361          }          }
362                    
363          AbstractEngineChannel* pChannel = pEngineChannel;          AbstractEngineChannel* pChannel = pEngineChannel;
364          MidiKeyBase* pMidiKeyInfo = GetMidiKeyInfo(MIDIKey);          MidiKeyBase* pMidiKeyInfo = GetMidiKeyInfo(MIDIKey());
365    
366          const bool bVoiceRequiresDedicatedRouting =          const bool bVoiceRequiresDedicatedRouting =
367              pEngineChannel->GetFxSendCount() > 0 &&              pEngineChannel->GetFxSendCount() > 0 &&
# Line 379  namespace LinuxSampler { Line 387  namespace LinuxSampler {
387    
388          RTList<Event>::Iterator itCCEvent = pChannel->pEvents->first();          RTList<Event>::Iterator itCCEvent = pChannel->pEvents->first();
389          RTList<Event>::Iterator itNoteEvent;          RTList<Event>::Iterator itNoteEvent;
390          GetFirstEventOnKey(MIDIKey, itNoteEvent);          GetFirstEventOnKey(HostKey(), itNoteEvent);
391    
392          RTList<Event>::Iterator itGroupEvent;          RTList<Event>::Iterator itGroupEvent;
393          if (pGroupEvents && !Orphan) itGroupEvent = pGroupEvents->first();          if (pGroupEvents && !Orphan) itGroupEvent = pGroupEvents->first();
# Line 431  namespace LinuxSampler { Line 439  namespace LinuxSampler {
439              processCCEvents(itCCEvent, iSubFragmentEnd);              processCCEvents(itCCEvent, iSubFragmentEnd);
440              uint8_t pan = MIDIPan;              uint8_t pan = MIDIPan;
441              if (pSignalUnitRack != NULL) pan = pSignalUnitRack->GetEndpointUnit()->CalculatePan(MIDIPan);              if (pSignalUnitRack != NULL) pan = pSignalUnitRack->GetEndpointUnit()->CalculatePan(MIDIPan);
               
             PanLeftSmoother.update(AbstractEngine::PanCurve[128 - pan]);  
             PanRightSmoother.update(AbstractEngine::PanCurve[pan]);  
442    
443              finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend;              PanLeftSmoother.update(AbstractEngine::PanCurve[128 - pan] * NotePanLeft);
444              float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render();              PanRightSmoother.update(AbstractEngine::PanCurve[pan]      * NotePanRight);
445    
446                finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend * NotePitch;
447    
448                float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render() * NoteVolumeSmoother.render();
449  #ifdef CONFIG_PROCESS_MUTED_CHANNELS  #ifdef CONFIG_PROCESS_MUTED_CHANNELS
450              if (pChannel->GetMute()) fFinalVolume = 0;              if (pChannel->GetMute()) fFinalVolume = 0;
451  #endif  #endif
# Line 488  namespace LinuxSampler { Line 497  namespace LinuxSampler {
497    
498                  // process low frequency oscillators                  // process low frequency oscillators
499                  if (bLFO1Enabled) fFinalVolume *= (1.0f - pLFO1->render());                  if (bLFO1Enabled) fFinalVolume *= (1.0f - pLFO1->render());
500                  if (bLFO2Enabled) fFinalCutoff *= pLFO2->render();                  if (bLFO2Enabled) fFinalCutoff *= (1.0f - pLFO2->render());
501                  if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());                  if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());
502              } else {              } else {
503                  // if the voice was killed in this subfragment, enter fade out stage                  // if the voice was killed in this subfragment, enter fade out stage
# Line 672  namespace LinuxSampler { Line 681  namespace LinuxSampler {
681      }      }
682    
683      /**      /**
684       * Process given list of MIDI note on, note off and sustain pedal events       * Process given list of MIDI note on, note off, sustain pedal events and
685       * for the given time.       * note synthesis parameter events for the given time.
686       *       *
687       * @param itEvent - iterator pointing to the next event to be processed       * @param itEvent - iterator pointing to the next event to be processed
688       * @param End     - youngest time stamp where processing should be stopped       * @param End     - youngest time stamp where processing should be stopped
# Line 693  namespace LinuxSampler { Line 702  namespace LinuxSampler {
702                      }                      }
703                  }                  }
704              }              }
705                // process synthesis parameter events (caused by built-in realt-time instrument script functions)
706                if (itEvent->Type == Event::type_note_synth_param && pNote &&
707                    pEngineChannel->pEngine->NoteByID( itEvent->Param.NoteSynthParam.NoteID ) == pNote)
708                {
709                    switch (itEvent->Param.NoteSynthParam.Type) {
710                        case Event::synth_param_volume:
711                            NoteVolumeSmoother.update(itEvent->Param.NoteSynthParam.AbsValue);
712                            break;
713                        case Event::synth_param_pitch:
714                            NotePitch = itEvent->Param.NoteSynthParam.AbsValue;
715                            break;
716                        case Event::synth_param_pan:
717                            NotePanLeft  = AbstractEngine::PanCurveValueNorm(itEvent->Param.NoteSynthParam.AbsValue, 0 /*left*/);
718                            NotePanRight = AbstractEngine::PanCurveValueNorm(itEvent->Param.NoteSynthParam.AbsValue, 1 /*right*/);
719                            break;
720                    }
721                }
722          }          }
723      }      }
724    
# Line 719  namespace LinuxSampler { Line 745  namespace LinuxSampler {
745      void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {      void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {
746          if (pSignalUnitRack == NULL) {          if (pSignalUnitRack == NULL) {
747              const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());              const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());
748              pEngineChannel->PortamentoPos = (float) MIDIKey + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;              pEngineChannel->PortamentoPos = (float) MIDIKey() + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;
749          } else {          } else {
750              // TODO:              // TODO:
751          }          }
# Line 746  namespace LinuxSampler { Line 772  namespace LinuxSampler {
772    
773      Voice::PitchInfo AbstractVoice::CalculatePitchInfo(int PitchBend) {      Voice::PitchInfo AbstractVoice::CalculatePitchInfo(int PitchBend) {
774          PitchInfo pitch;          PitchInfo pitch;
775          double pitchbasecents = InstrInfo.FineTune + RgnInfo.FineTune + GetEngine()->ScaleTuning[MIDIKey % 12];          double pitchbasecents = InstrInfo.FineTune + RgnInfo.FineTune + GetEngine()->ScaleTuning[MIDIKey() % 12];
776    
777          // GSt behaviour: maximum transpose up is 40 semitones. If          // GSt behaviour: maximum transpose up is 40 semitones. If
778          // MIDI key is more than 40 semitones above unity note,          // MIDI key is more than 40 semitones above unity note,
779          // the transpose is not done.          // the transpose is not done.
780          if (!SmplInfo.Unpitched && (MIDIKey - (int) RgnInfo.UnityNote) < 40) pitchbasecents += (MIDIKey - (int) RgnInfo.UnityNote) * 100;          if (!SmplInfo.Unpitched && (MIDIKey() - (int) RgnInfo.UnityNote) < 40) pitchbasecents += (MIDIKey() - (int) RgnInfo.UnityNote) * 100;
781    
782          pitch.PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(SmplInfo.SampleRate) / double(GetEngine()->SampleRate));          pitch.PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(SmplInfo.SampleRate) / double(GetEngine()->SampleRate));
783          pitch.PitchBendRange = 1.0 / 8192.0 * 100.0 * InstrInfo.PitchbendRange;          pitch.PitchBendRange = 1.0 / 8192.0 * 100.0 * InstrInfo.PitchbendRange;
# Line 762  namespace LinuxSampler { Line 788  namespace LinuxSampler {
788            
789      void AbstractVoice::onScaleTuningChanged() {      void AbstractVoice::onScaleTuningChanged() {
790          PitchInfo pitch = this->Pitch;          PitchInfo pitch = this->Pitch;
791          double pitchbasecents = InstrInfo.FineTune + RgnInfo.FineTune + GetEngine()->ScaleTuning[MIDIKey % 12];          double pitchbasecents = InstrInfo.FineTune + RgnInfo.FineTune + GetEngine()->ScaleTuning[MIDIKey() % 12];
792                    
793          // GSt behaviour: maximum transpose up is 40 semitones. If          // GSt behaviour: maximum transpose up is 40 semitones. If
794          // MIDI key is more than 40 semitones above unity note,          // MIDI key is more than 40 semitones above unity note,
795          // the transpose is not done.          // the transpose is not done.
796          if (!SmplInfo.Unpitched && (MIDIKey - (int) RgnInfo.UnityNote) < 40) pitchbasecents += (MIDIKey - (int) RgnInfo.UnityNote) * 100;          if (!SmplInfo.Unpitched && (MIDIKey() - (int) RgnInfo.UnityNote) < 40) pitchbasecents += (MIDIKey() - (int) RgnInfo.UnityNote) * 100;
797                    
798          pitch.PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(SmplInfo.SampleRate) / double(GetEngine()->SampleRate));          pitch.PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(SmplInfo.SampleRate) / double(GetEngine()->SampleRate));
799          this->Pitch = pitch;          this->Pitch = pitch;
# Line 784  namespace LinuxSampler { Line 810  namespace LinuxSampler {
810          // the volume of release triggered samples depends on note length          // the volume of release triggered samples depends on note length
811          if (Type & Voice::type_release_trigger) {          if (Type & Voice::type_release_trigger) {
812              float noteLength = float(GetEngine()->FrameTime + Delay -              float noteLength = float(GetEngine()->FrameTime + Delay -
813                  GetNoteOnTime(MIDIKey) ) / GetEngine()->SampleRate;                  GetNoteOnTime(MIDIKey()) ) / GetEngine()->SampleRate;
814    
815              volume *= GetReleaseTriggerAttenuation(noteLength);              volume *= GetReleaseTriggerAttenuation(noteLength);
816          }          }

Legend:
Removed from v.2559  
changed lines
  Added in v.2931

  ViewVC Help
Powered by ViewVC