/[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 2382 by persson, Sun Dec 2 16:30:42 2012 UTC revision 3251 by schoenebeck, Mon May 29 22:19:19 2017 UTC
# Line 5  Line 5 
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-2012 Christian Schoenebeck and Grigor Iliev        *
8     *   Copyright (C) 2013-2017 Christian Schoenebeck and Andreas Persson     *
9   *                                                                         *   *                                                                         *
10   *   This program is free software; you can redistribute it and/or modify  *   *   This program is free software; you can redistribute it and/or modify  *
11   *   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 111  namespace LinuxSampler {
111          #endif // CONFIG_DEVMODE          #endif // CONFIG_DEVMODE
112    
113          Type            = VoiceType;          Type            = VoiceType;
114          MIDIKey         = itNoteOnEvent->Param.Note.Key;          pNote           = pEngineChannel->pEngine->NoteByID( itNoteOnEvent->Param.Note.ID );
         MIDIVelocity    = itNoteOnEvent->Param.Note.Velocity;  
115          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
116          Delay           = itNoteOnEvent->FragmentPos();          Delay           = itNoteOnEvent->FragmentPos();
117          itTriggerEvent  = itNoteOnEvent;          itTriggerEvent  = itNoteOnEvent;
118          itKillEvent     = Pool<Event>::Iterator();          itKillEvent     = Pool<Event>::Iterator();
119          MidiKeyBase* pKeyInfo = GetMidiKeyInfo(MIDIKey);          MidiKeyBase* pKeyInfo = GetMidiKeyInfo(MIDIKey());
120    
121          pGroupEvents = iKeyGroup ? pEngineChannel->ActiveKeyGroups[iKeyGroup] : 0;          pGroupEvents = iKeyGroup ? pEngineChannel->ActiveKeyGroups[iKeyGroup] : 0;
122    
# Line 129  namespace LinuxSampler { Line 129  namespace LinuxSampler {
129          AboutToTrigger();          AboutToTrigger();
130    
131          // calculate volume          // calculate volume
132          const double velocityAttenuation = GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity);          const double velocityAttenuation = GetVelocityAttenuation(MIDIVelocity());
133          float volume = CalculateVolume(velocityAttenuation) * pKeyInfo->Volume;          float volume = CalculateVolume(velocityAttenuation) * pKeyInfo->Volume;
134          if (volume <= 0) return -1;          if (volume <= 0) return -1;
135    
# Line 139  namespace LinuxSampler { Line 139  namespace LinuxSampler {
139          SYNTHESIS_MODE_SET_BITDEPTH24(SynthesisMode, SmplInfo.BitDepth == 24);          SYNTHESIS_MODE_SET_BITDEPTH24(SynthesisMode, SmplInfo.BitDepth == 24);
140    
141          // get starting crossfade volume level          // get starting crossfade volume level
142          float crossfadeVolume = CalculateCrossfadeVolume(itNoteOnEvent->Param.Note.Velocity);          float crossfadeVolume = CalculateCrossfadeVolume(MIDIVelocity());
143    
144          VolumeLeft  = volume * pKeyInfo->PanLeft;          VolumeLeft  = volume * pKeyInfo->PanLeft;
145          VolumeRight = volume * pKeyInfo->PanRight;          VolumeRight = volume * pKeyInfo->PanRight;
146    
147          float subfragmentRate = GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;          // this rate is used for rather mellow volume fades
148            const float subfragmentRate = GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;
149            // this rate is used for very fast volume fades
150            const float quickRampRate = RTMath::Min(subfragmentRate, GetEngine()->SampleRate * 0.001f /* approx. 13ms */);
151          CrossfadeSmoother.trigger(crossfadeVolume, subfragmentRate);          CrossfadeSmoother.trigger(crossfadeVolume, subfragmentRate);
152    
153          VolumeSmoother.trigger(pEngineChannel->MidiVolume, subfragmentRate);          VolumeSmoother.trigger(pEngineChannel->MidiVolume, subfragmentRate);
154            NoteVolume.setCurveOnly(pNote ? pNote->Override.VolumeCurve : DEFAULT_FADE_CURVE);
155            NoteVolume.setCurrentValue(pNote ? pNote->Override.Volume : 1.f);
156            NoteVolume.setDefaultDuration(pNote ? pNote->Override.VolumeTime : DEFAULT_NOTE_VOLUME_TIME_S);
157    
158          // 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
159          long cachedsamples = GetSampleCacheSize() / SmplInfo.FrameSize;          long cachedsamples = GetSampleCacheSize() / SmplInfo.FrameSize;
# Line 170  namespace LinuxSampler { Line 177  namespace LinuxSampler {
177              RAMLoop = (SmplInfo.HasLoops && (SmplInfo.LoopStart + SmplInfo.LoopLength) <= MaxRAMPos);              RAMLoop = (SmplInfo.HasLoops && (SmplInfo.LoopStart + SmplInfo.LoopLength) <= MaxRAMPos);
178    
179              if (OrderNewStream()) return -1;              if (OrderNewStream()) return -1;
180              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"));
181          }          }
182          else { // RAM only voice          else { // RAM only voice
183              MaxRAMPos = cachedsamples;              MaxRAMPos = cachedsamples;
# Line 186  namespace LinuxSampler { Line 193  namespace LinuxSampler {
193          }          }
194    
195          Pitch = CalculatePitchInfo(PitchBend);          Pitch = CalculatePitchInfo(PitchBend);
196            NotePitch.setCurveOnly(pNote ? pNote->Override.PitchCurve : DEFAULT_FADE_CURVE);
197            NotePitch.setCurrentValue(pNote ? pNote->Override.Pitch : 1.0f);
198            NotePitch.setDefaultDuration(pNote ? pNote->Override.PitchTime : DEFAULT_NOTE_PITCH_TIME_S);
199            NoteCutoff = (pNote) ? pNote->Override.Cutoff : 1.0f;
200            NoteResonance = (pNote) ? pNote->Override.Resonance : 1.0f;
201    
202          // 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
203          const double velrelease = 1 / GetVelocityRelease(itNoteOnEvent->Param.Note.Velocity);          const double velrelease = 1 / GetVelocityRelease(MIDIVelocity());
204    
205          if (pSignalUnitRack == NULL) { // setup EG 1 (VCA EG)          if (pSignalUnitRack == NULL) { // setup EG 1 (VCA EG)
206              // get current value of EG1 controller              // get current value of EG1 controller
207              double eg1controllervalue = GetEG1ControllerValue(itNoteOnEvent->Param.Note.Velocity);              double eg1controllervalue = GetEG1ControllerValue(MIDIVelocity());
208    
209              // calculate influence of EG1 controller on EG1's parameters              // calculate influence of EG1 controller on EG1's parameters
210              EGInfo egInfo = CalculateEG1ControllerInfluence(eg1controllervalue);              EGInfo egInfo = CalculateEG1ControllerInfluence(eg1controllervalue);
211    
212              TriggerEG1(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity);              if (pNote) {
213                    egInfo.Attack  *= pNote->Override.Attack;
214                    egInfo.Decay   *= pNote->Override.Decay;
215                    egInfo.Release *= pNote->Override.Release;
216                }
217    
218                TriggerEG1(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, MIDIVelocity());
219          } else {          } else {
220              pSignalUnitRack->Trigger();              pSignalUnitRack->Trigger();
221          }          }
222    
223          uint8_t pan = MIDIPan;          const uint8_t pan = (pSignalUnitRack) ? pSignalUnitRack->GetEndpointUnit()->CalculatePan(MIDIPan) : MIDIPan;
224          if (pSignalUnitRack) pan = pSignalUnitRack->GetEndpointUnit()->CalculatePan(MIDIPan);          NotePanLeft  = (pNote) ? AbstractEngine::PanCurveValueNorm(pNote->Override.Pan, 0 /*left*/ ) : 1.f;
225          PanLeftSmoother.trigger(AbstractEngine::PanCurve[128 - pan], subfragmentRate);          NotePanRight = (pNote) ? AbstractEngine::PanCurveValueNorm(pNote->Override.Pan, 1 /*right*/) : 1.f;
226          PanRightSmoother.trigger(AbstractEngine::PanCurve[pan], subfragmentRate);          PanLeftSmoother.trigger(
227                AbstractEngine::PanCurve[128 - pan] * NotePanLeft,
228                quickRampRate //NOTE: maybe we should have 2 separate pan smoothers, one for MIDI CC10 (with slow rate) and one for instrument script change_pan() calls (with fast rate)
229            );
230            PanRightSmoother.trigger(
231                AbstractEngine::PanCurve[pan] * NotePanRight,
232                quickRampRate //NOTE: maybe we should have 2 separate pan smoothers, one for MIDI CC10 (with slow rate) and one for instrument script change_pan() calls (with fast rate)
233            );
234    
235  #ifdef CONFIG_INTERPOLATE_VOLUME  #ifdef CONFIG_INTERPOLATE_VOLUME
236          // setup initial volume in synthesis parameters          // setup initial volume in synthesis parameters
# Line 234  namespace LinuxSampler { Line 259  namespace LinuxSampler {
259              // setup EG 2 (VCF Cutoff EG)              // setup EG 2 (VCF Cutoff EG)
260              {              {
261                  // get current value of EG2 controller                  // get current value of EG2 controller
262                  double eg2controllervalue = GetEG2ControllerValue(itNoteOnEvent->Param.Note.Velocity);                  double eg2controllervalue = GetEG2ControllerValue(MIDIVelocity());
263    
264                  // calculate influence of EG2 controller on EG2's parameters                  // calculate influence of EG2 controller on EG2's parameters
265                  EGInfo egInfo = CalculateEG2ControllerInfluence(eg2controllervalue);                  EGInfo egInfo = CalculateEG2ControllerInfluence(eg2controllervalue);
266    
267                  TriggerEG2(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity);                  TriggerEG2(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, MIDIVelocity());
268              }              }
269    
270    
# Line 248  namespace LinuxSampler { Line 273  namespace LinuxSampler {
273                  // 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
274                  bool  bPortamento = pEngineChannel->PortamentoMode && pEngineChannel->PortamentoPos >= 0.0f;                  bool  bPortamento = pEngineChannel->PortamentoMode && pEngineChannel->PortamentoPos >= 0.0f;
275                  float eg3depth = (bPortamento)                  float eg3depth = (bPortamento)
276                               ? RTMath::CentsToFreqRatio((pEngineChannel->PortamentoPos - (float) MIDIKey) * 100)                               ? RTMath::CentsToFreqRatio((pEngineChannel->PortamentoPos - (float) MIDIKey()) * 100)
277                               : RTMath::CentsToFreqRatio(RgnInfo.EG3Depth);                               : RTMath::CentsToFreqRatio(RgnInfo.EG3Depth);
278                  float eg3time = (bPortamento)                  float eg3time = (bPortamento)
279                              ? pEngineChannel->PortamentoTime                              ? pEngineChannel->PortamentoTime
# Line 298  namespace LinuxSampler { Line 323  namespace LinuxSampler {
323              VCFResonanceCtrl.value = pEngineChannel->ControllerTable[VCFResonanceCtrl.controller];              VCFResonanceCtrl.value = pEngineChannel->ControllerTable[VCFResonanceCtrl.controller];
324    
325              // calculate cutoff frequency              // calculate cutoff frequency
326              CutoffBase = CalculateCutoffBase(itNoteOnEvent->Param.Note.Velocity);              CutoffBase = CalculateCutoffBase(MIDIVelocity());
327    
328              VCFCutoffCtrl.fvalue = CalculateFinalCutoff(CutoffBase);              VCFCutoffCtrl.fvalue = CalculateFinalCutoff(CutoffBase);
329    
# Line 323  namespace LinuxSampler { Line 348  namespace LinuxSampler {
348      }      }
349            
350      void AbstractVoice::SetSampleStartOffset() {      void AbstractVoice::SetSampleStartOffset() {
351          finalSynthesisParameters.dPos = RgnInfo.SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)          double pos = RgnInfo.SampleStartOffset; // offset where we should start playback of sample
352          Pos = RgnInfo.SampleStartOffset;  
353            // if another sample playback start position was requested by instrument
354            // script (built-in script function play_note())
355            if (pNote && pNote->Override.SampleOffset >= 0) {
356                double overridePos =
357                    double(SmplInfo.SampleRate) * double(pNote->Override.SampleOffset) / 1000000.0;
358                if (overridePos < SmplInfo.TotalFrameCount)
359                    pos = overridePos;
360            }
361    
362            finalSynthesisParameters.dPos = pos;
363            Pos = pos;
364      }      }
365    
366      /**      /**
# Line 353  namespace LinuxSampler { Line 389  namespace LinuxSampler {
389          }          }
390                    
391          AbstractEngineChannel* pChannel = pEngineChannel;          AbstractEngineChannel* pChannel = pEngineChannel;
392          MidiKeyBase* pMidiKeyInfo = GetMidiKeyInfo(MIDIKey);          MidiKeyBase* pMidiKeyInfo = GetMidiKeyInfo(MIDIKey());
393    
394          const bool bVoiceRequiresDedicatedRouting =          const bool bVoiceRequiresDedicatedRouting =
395              pEngineChannel->GetFxSendCount() > 0 &&              pEngineChannel->GetFxSendCount() > 0 &&
# Line 379  namespace LinuxSampler { Line 415  namespace LinuxSampler {
415    
416          RTList<Event>::Iterator itCCEvent = pChannel->pEvents->first();          RTList<Event>::Iterator itCCEvent = pChannel->pEvents->first();
417          RTList<Event>::Iterator itNoteEvent;          RTList<Event>::Iterator itNoteEvent;
418          GetFirstEventOnKey(MIDIKey, itNoteEvent);          GetFirstEventOnKey(HostKey(), itNoteEvent);
419    
420          RTList<Event>::Iterator itGroupEvent;          RTList<Event>::Iterator itGroupEvent;
421          if (pGroupEvents && !Orphan) itGroupEvent = pGroupEvents->first();          if (pGroupEvents && !Orphan) itGroupEvent = pGroupEvents->first();
# Line 399  namespace LinuxSampler { Line 435  namespace LinuxSampler {
435              }              }
436          }          }
437    
438          uint killPos;          uint killPos = 0;
439          if (itKillEvent) {          if (itKillEvent) {
440              int maxFadeOutPos = Samples - GetEngine()->GetMinFadeOutSamples();              int maxFadeOutPos = Samples - GetEngine()->GetMinFadeOutSamples();
441              if (maxFadeOutPos < 0) {              if (maxFadeOutPos < 0) {
# Line 427  namespace LinuxSampler { Line 463  namespace LinuxSampler {
463              fFinalCutoff    = VCFCutoffCtrl.fvalue;              fFinalCutoff    = VCFCutoffCtrl.fvalue;
464              fFinalResonance = VCFResonanceCtrl.fvalue;              fFinalResonance = VCFResonanceCtrl.fvalue;
465    
466              // process MIDI control change and pitchbend events for this subfragment              // process MIDI control change, aftertouch and pitchbend events for this subfragment
467              processCCEvents(itCCEvent, iSubFragmentEnd);              processCCEvents(itCCEvent, iSubFragmentEnd);
468              uint8_t pan = MIDIPan;              uint8_t pan = MIDIPan;
469              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]);  
470    
471              finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend;              PanLeftSmoother.update(AbstractEngine::PanCurve[128 - pan] * NotePanLeft);
472              float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render();              PanRightSmoother.update(AbstractEngine::PanCurve[pan]      * NotePanRight);
473    
474                finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend * NotePitch.render();
475    
476                float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render() * NoteVolume.render();
477  #ifdef CONFIG_PROCESS_MUTED_CHANNELS  #ifdef CONFIG_PROCESS_MUTED_CHANNELS
478              if (pChannel->GetMute()) fFinalVolume = 0;              if (pChannel->GetMute()) fFinalVolume = 0;
479  #endif  #endif
# Line 488  namespace LinuxSampler { Line 525  namespace LinuxSampler {
525    
526                  // process low frequency oscillators                  // process low frequency oscillators
527                  if (bLFO1Enabled) fFinalVolume *= (1.0f - pLFO1->render());                  if (bLFO1Enabled) fFinalVolume *= (1.0f - pLFO1->render());
528                  if (bLFO2Enabled) fFinalCutoff *= pLFO2->render();                  if (bLFO2Enabled) fFinalCutoff *= (1.0f - pLFO2->render());
529                  if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());                  if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());
530              } else {              } else {
531                  // 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 513  namespace LinuxSampler { Line 550  namespace LinuxSampler {
550                      pSignalUnitRack->GetEndpointUnit()->CalculatePitch(finalSynthesisParameters.fFinalPitch);                      pSignalUnitRack->GetEndpointUnit()->CalculatePitch(finalSynthesisParameters.fFinalPitch);
551                                            
552              }              }
553                
554                fFinalCutoff    *= NoteCutoff;
555                fFinalResonance *= NoteResonance;
556    
557              // limit the pitch so we don't read outside the buffer              // limit the pitch so we don't read outside the buffer
558              finalSynthesisParameters.fFinalPitch = RTMath::Min(finalSynthesisParameters.fFinalPitch, float(1 << CONFIG_MAX_PITCH));              finalSynthesisParameters.fFinalPitch = RTMath::Min(finalSynthesisParameters.fFinalPitch, float(1 << CONFIG_MAX_PITCH));
559    
# Line 611  namespace LinuxSampler { Line 651  namespace LinuxSampler {
651      }      }
652    
653      /**      /**
654       * Process given list of MIDI control change and pitch bend events for       * Process given list of MIDI control change, aftertouch and pitch bend
655       * the given time.       * events for the given time.
656       *       *
657       * @param itEvent - iterator pointing to the next event to be processed       * @param itEvent - iterator pointing to the next event to be processed
658       * @param End     - youngest time stamp where processing should be stopped       * @param End     - youngest time stamp where processing should be stopped
659       */       */
660      void AbstractVoice::processCCEvents(RTList<Event>::Iterator& itEvent, uint End) {      void AbstractVoice::processCCEvents(RTList<Event>::Iterator& itEvent, uint End) {
661          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
662              if (itEvent->Type == Event::type_control_change && itEvent->Param.CC.Controller) { // if (valid) MIDI control change event              if ((itEvent->Type == Event::type_control_change || itEvent->Type == Event::type_channel_pressure)
663                    && itEvent->Param.CC.Controller) // if (valid) MIDI control change event
664                {
665                  if (itEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {                  if (itEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {
666                      ProcessCutoffEvent(itEvent);                      ProcessCutoffEvent(itEvent);
667                  }                  }
668                  if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {                  if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {
669                      processResonanceEvent(itEvent);                      processResonanceEvent(itEvent);
670                  }                  }
671                    if (itEvent->Param.CC.Controller == CTRL_TABLE_IDX_AFTERTOUCH ||
672                        itEvent->Type == Event::type_channel_pressure)
673                    {
674                        ProcessChannelPressureEvent(itEvent);
675                    }
676                  if (pSignalUnitRack == NULL) {                  if (pSignalUnitRack == NULL) {
677                      if (itEvent->Param.CC.Controller == pLFO1->ExtController) {                      if (itEvent->Param.CC.Controller == pLFO1->ExtController) {
678                          pLFO1->update(itEvent->Param.CC.Value);                          pLFO1->updateByMIDICtrlValue(itEvent->Param.CC.Value);
679                      }                      }
680                      if (itEvent->Param.CC.Controller == pLFO2->ExtController) {                      if (itEvent->Param.CC.Controller == pLFO2->ExtController) {
681                          pLFO2->update(itEvent->Param.CC.Value);                          pLFO2->updateByMIDICtrlValue(itEvent->Param.CC.Value);
682                      }                      }
683                      if (itEvent->Param.CC.Controller == pLFO3->ExtController) {                      if (itEvent->Param.CC.Controller == pLFO3->ExtController) {
684                          pLFO3->update(itEvent->Param.CC.Value);                          pLFO3->updateByMIDICtrlValue(itEvent->Param.CC.Value);
685                      }                      }
686                  }                  }
687                  if (itEvent->Param.CC.Controller == 7) { // volume                  if (itEvent->Param.CC.Controller == 7) { // volume
# Line 644  namespace LinuxSampler { Line 691  namespace LinuxSampler {
691                  }                  }
692              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event
693                  processPitchEvent(itEvent);                  processPitchEvent(itEvent);
694                } else if (itEvent->Type == Event::type_note_pressure) {
695                    ProcessPolyphonicKeyPressureEvent(itEvent);
696              }              }
697    
698              ProcessCCEvent(itEvent);              ProcessCCEvent(itEvent);
# Line 668  namespace LinuxSampler { Line 717  namespace LinuxSampler {
717      }      }
718    
719      /**      /**
720       * 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
721       * for the given time.       * note synthesis parameter events for the given time.
722       *       *
723       * @param itEvent - iterator pointing to the next event to be processed       * @param itEvent - iterator pointing to the next event to be processed
724       * @param End     - youngest time stamp where processing should be stopped       * @param End     - youngest time stamp where processing should be stopped
# Line 678  namespace LinuxSampler { Line 727  namespace LinuxSampler {
727          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
728              // some voice types ignore note off              // some voice types ignore note off
729              if (!(Type & (Voice::type_one_shot | Voice::type_release_trigger | Voice::type_controller_triggered))) {              if (!(Type & (Voice::type_one_shot | Voice::type_release_trigger | Voice::type_controller_triggered))) {
730                  if (itEvent->Type == Event::type_release) {                  if (itEvent->Type == Event::type_release_key) {
731                      EnterReleaseStage();                      EnterReleaseStage();
732                  } else if (itEvent->Type == Event::type_cancel_release) {                  } else if (itEvent->Type == Event::type_cancel_release_key) {
733                      if (pSignalUnitRack == NULL) {                      if (pSignalUnitRack == NULL) {
734                          pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                          pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
735                          pEG2->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                          pEG2->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
# Line 689  namespace LinuxSampler { Line 738  namespace LinuxSampler {
738                      }                      }
739                  }                  }
740              }              }
741                // process stop-note events (caused by built-in instrument script function note_off())
742                if (itEvent->Type == Event::type_release_note && pNote &&
743                    pEngineChannel->pEngine->NoteByID( itEvent->Param.Note.ID ) == pNote)
744                {
745                    EnterReleaseStage();
746                }
747                // process kill-note events (caused by built-in instrument script function fade_out())
748                if (itEvent->Type == Event::type_kill_note && pNote &&
749                    pEngineChannel->pEngine->NoteByID( itEvent->Param.Note.ID ) == pNote)
750                {
751                    Kill(itEvent);
752                }
753                // process synthesis parameter events (caused by built-in realt-time instrument script functions)
754                if (itEvent->Type == Event::type_note_synth_param && pNote &&
755                    pEngineChannel->pEngine->NoteByID( itEvent->Param.NoteSynthParam.NoteID ) == pNote)
756                {
757                    switch (itEvent->Param.NoteSynthParam.Type) {
758                        case Event::synth_param_volume:
759                            NoteVolume.fadeTo(itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
760                            break;
761                        case Event::synth_param_volume_time:
762                            NoteVolume.setDefaultDuration(itEvent->Param.NoteSynthParam.AbsValue);
763                            break;
764                        case Event::synth_param_volume_curve:
765                            NoteVolume.setCurve((fade_curve_t)itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
766                            break;
767                        case Event::synth_param_pitch:
768                            NotePitch.fadeTo(itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
769                            break;
770                        case Event::synth_param_pitch_time:
771                            NotePitch.setDefaultDuration(itEvent->Param.NoteSynthParam.AbsValue);
772                            break;
773                        case Event::synth_param_pitch_curve:
774                            NotePitch.setCurve((fade_curve_t)itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
775                            break;
776                        case Event::synth_param_pan:
777                            NotePanLeft  = AbstractEngine::PanCurveValueNorm(itEvent->Param.NoteSynthParam.AbsValue, 0 /*left*/);
778                            NotePanRight = AbstractEngine::PanCurveValueNorm(itEvent->Param.NoteSynthParam.AbsValue, 1 /*right*/);
779                            break;
780                        case Event::synth_param_cutoff:
781                            NoteCutoff = itEvent->Param.NoteSynthParam.AbsValue;
782                            break;
783                        case Event::synth_param_resonance:
784                            NoteResonance = itEvent->Param.NoteSynthParam.AbsValue;
785                            break;
786                        case Event::synth_param_amp_lfo_depth:
787                            pLFO1->setScriptDepthFactor(itEvent->Param.NoteSynthParam.AbsValue);
788                            break;
789                        case Event::synth_param_amp_lfo_freq:
790                            pLFO1->setScriptFrequencyFactor(itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
791                            break;
792                        case Event::synth_param_pitch_lfo_depth:
793                            pLFO3->setScriptDepthFactor(itEvent->Param.NoteSynthParam.AbsValue);
794                            break;
795                        case Event::synth_param_pitch_lfo_freq:
796                            pLFO3->setScriptFrequencyFactor(itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
797                            break;
798    
799                        case Event::synth_param_attack:
800                        case Event::synth_param_decay:
801                        case Event::synth_param_release:
802                            break; // noop
803                    }
804                }
805          }          }
806      }      }
807    
# Line 715  namespace LinuxSampler { Line 828  namespace LinuxSampler {
828      void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {      void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {
829          if (pSignalUnitRack == NULL) {          if (pSignalUnitRack == NULL) {
830              const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());              const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());
831              pEngineChannel->PortamentoPos = (float) MIDIKey + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;              pEngineChannel->PortamentoPos = (float) MIDIKey() + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;
832          } else {          } else {
833              // TODO:              // TODO:
834          }          }
# Line 742  namespace LinuxSampler { Line 855  namespace LinuxSampler {
855    
856      Voice::PitchInfo AbstractVoice::CalculatePitchInfo(int PitchBend) {      Voice::PitchInfo AbstractVoice::CalculatePitchInfo(int PitchBend) {
857          PitchInfo pitch;          PitchInfo pitch;
858          double pitchbasecents = InstrInfo.FineTune + RgnInfo.FineTune + GetEngine()->ScaleTuning[MIDIKey % 12];          double pitchbasecents = InstrInfo.FineTune + RgnInfo.FineTune + GetEngine()->ScaleTuning[MIDIKey() % 12];
859    
860          // GSt behaviour: maximum transpose up is 40 semitones. If          // GSt behaviour: maximum transpose up is 40 semitones. If
861          // MIDI key is more than 40 semitones above unity note,          // MIDI key is more than 40 semitones above unity note,
862          // the transpose is not done.          // the transpose is not done.
863          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;
864    
865          pitch.PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(SmplInfo.SampleRate) / double(GetEngine()->SampleRate));          pitch.PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(SmplInfo.SampleRate) / double(GetEngine()->SampleRate));
866          pitch.PitchBendRange = 1.0 / 8192.0 * 100.0 * InstrInfo.PitchbendRange;          pitch.PitchBendRange = 1.0 / 8192.0 * 100.0 * InstrInfo.PitchbendRange;
# Line 755  namespace LinuxSampler { Line 868  namespace LinuxSampler {
868    
869          return pitch;          return pitch;
870      }      }
871        
872        void AbstractVoice::onScaleTuningChanged() {
873            PitchInfo pitch = this->Pitch;
874            double pitchbasecents = InstrInfo.FineTune + RgnInfo.FineTune + GetEngine()->ScaleTuning[MIDIKey() % 12];
875            
876            // GSt behaviour: maximum transpose up is 40 semitones. If
877            // MIDI key is more than 40 semitones above unity note,
878            // the transpose is not done.
879            if (!SmplInfo.Unpitched && (MIDIKey() - (int) RgnInfo.UnityNote) < 40) pitchbasecents += (MIDIKey() - (int) RgnInfo.UnityNote) * 100;
880            
881            pitch.PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(SmplInfo.SampleRate) / double(GetEngine()->SampleRate));
882            this->Pitch = pitch;
883        }
884    
885      double AbstractVoice::CalculateVolume(double velocityAttenuation) {      double AbstractVoice::CalculateVolume(double velocityAttenuation) {
886          // For 16 bit samples, we downscale by 32768 to convert from          // For 16 bit samples, we downscale by 32768 to convert from
# Line 767  namespace LinuxSampler { Line 893  namespace LinuxSampler {
893          // the volume of release triggered samples depends on note length          // the volume of release triggered samples depends on note length
894          if (Type & Voice::type_release_trigger) {          if (Type & Voice::type_release_trigger) {
895              float noteLength = float(GetEngine()->FrameTime + Delay -              float noteLength = float(GetEngine()->FrameTime + Delay -
896                  GetNoteOnTime(MIDIKey) ) / GetEngine()->SampleRate;                  GetNoteOnTime(MIDIKey()) ) / GetEngine()->SampleRate;
897    
898              volume *= GetReleaseTriggerAttenuation(noteLength);              volume *= GetReleaseTriggerAttenuation(noteLength);
899          }          }

Legend:
Removed from v.2382  
changed lines
  Added in v.3251

  ViewVC Help
Powered by ViewVC