/[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 3638 by schoenebeck, Fri Oct 25 17:08:46 2019 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 28  namespace LinuxSampler { Line 29  namespace LinuxSampler {
29    
30      AbstractVoice::AbstractVoice(SignalUnitRack* pRack): pSignalUnitRack(pRack) {      AbstractVoice::AbstractVoice(SignalUnitRack* pRack): pSignalUnitRack(pRack) {
31          pEngineChannel = NULL;          pEngineChannel = NULL;
32          pLFO1 = new LFOUnsigned(1.0f);  // amplitude LFO (0..1 range)          pLFO1 = new LFOClusterUnsigned(1.0f);  // amplitude LFO (0..1 range)
33          pLFO2 = new LFOUnsigned(1.0f);  // filter LFO (0..1 range)          pLFO2 = new LFOClusterUnsigned(1.0f);  // filter LFO (0..1 range)
34          pLFO3 = new LFOSigned(1200.0f); // pitch LFO (-1200..+1200 range)          pLFO3 = new LFOClusterSigned(1200.0f); // pitch LFO (-1200..+1200 range)
35          PlaybackState = playback_state_end;          PlaybackState = playback_state_end;
36          SynthesisMode = 0; // set all mode bits to 0 first          SynthesisMode = 0; // set all mode bits to 0 first
37          // select synthesis implementation (asm core is not supported ATM)          // select synthesis implementation (asm core is not supported ATM)
# 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.Value : 1.f);
156            NoteVolume.setDefaultDuration(pNote ? pNote->Override.VolumeTime : DEFAULT_NOTE_VOLUME_TIME_S);
157            NoteVolume.setFinal(pNote ? pNote->Override.Volume.Final : false);
158    
159          // 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
160          long cachedsamples = GetSampleCacheSize() / SmplInfo.FrameSize;          long cachedsamples = GetSampleCacheSize() / SmplInfo.FrameSize;
# Line 170  namespace LinuxSampler { Line 178  namespace LinuxSampler {
178              RAMLoop = (SmplInfo.HasLoops && (SmplInfo.LoopStart + SmplInfo.LoopLength) <= MaxRAMPos);              RAMLoop = (SmplInfo.HasLoops && (SmplInfo.LoopStart + SmplInfo.LoopLength) <= MaxRAMPos);
179    
180              if (OrderNewStream()) return -1;              if (OrderNewStream()) return -1;
181              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"));
182          }          }
183          else { // RAM only voice          else { // RAM only voice
184              MaxRAMPos = cachedsamples;              MaxRAMPos = cachedsamples;
# Line 186  namespace LinuxSampler { Line 194  namespace LinuxSampler {
194          }          }
195    
196          Pitch = CalculatePitchInfo(PitchBend);          Pitch = CalculatePitchInfo(PitchBend);
197            NotePitch.setCurveOnly(pNote ? pNote->Override.PitchCurve : DEFAULT_FADE_CURVE);
198            NotePitch.setCurrentValue(pNote ? pNote->Override.Pitch.Value : 1.0f);
199            NotePitch.setFinal(pNote ? pNote->Override.Pitch.Final : false);
200            NotePitch.setDefaultDuration(pNote ? pNote->Override.PitchTime : DEFAULT_NOTE_PITCH_TIME_S);
201            NoteCutoff.Value = (pNote) ? pNote->Override.Cutoff.Value : 1.0f;
202            NoteCutoff.Final = (pNote) ? pNote->Override.Cutoff.isFinal() : false;
203            NoteResonance.Value = (pNote) ? pNote->Override.Resonance.Value : 1.0f;
204            NoteResonance.Final = (pNote) ? pNote->Override.Resonance.Final : false;
205    
206          // 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
207          const double velrelease = 1 / GetVelocityRelease(itNoteOnEvent->Param.Note.Velocity);          const double velrelease = 1 / GetVelocityRelease(MIDIVelocity());
208    
209          if (pSignalUnitRack == NULL) { // setup EG 1 (VCA EG)          if (pSignalUnitRack == NULL) { // setup EG 1 (VCA EG)
210              // get current value of EG1 controller              // get current value of EG1 controller
211              double eg1controllervalue = GetEG1ControllerValue(itNoteOnEvent->Param.Note.Velocity);              double eg1controllervalue = GetEG1ControllerValue(MIDIVelocity());
212    
213              // calculate influence of EG1 controller on EG1's parameters              // calculate influence of EG1 controller on EG1's parameters
214              EGInfo egInfo = CalculateEG1ControllerInfluence(eg1controllervalue);              EGInfo egInfo = CalculateEG1ControllerInfluence(eg1controllervalue);
215    
216              TriggerEG1(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity);              if (pNote) {
217                    pNote->Override.Attack.applyTo(egInfo.Attack);
218                    pNote->Override.Decay.applyTo(egInfo.Decay);
219                    pNote->Override.Release.applyTo(egInfo.Release);
220                }
221    
222                TriggerEG1(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, MIDIVelocity());
223          } else {          } else {
224              pSignalUnitRack->Trigger();              pSignalUnitRack->Trigger();
225          }          }
226    
227          uint8_t pan = MIDIPan;          const uint8_t pan = (pSignalUnitRack) ? pSignalUnitRack->GetEndpointUnit()->CalculatePan(MIDIPan) : MIDIPan;
228          if (pSignalUnitRack) pan = pSignalUnitRack->GetEndpointUnit()->CalculatePan(MIDIPan);          for (int c = 0; c < 2; ++c) {
229          PanLeftSmoother.trigger(AbstractEngine::PanCurve[128 - pan], subfragmentRate);              float value = (pNote) ? AbstractEngine::PanCurveValueNorm(pNote->Override.Pan.Value, c) : 1.f;
230          PanRightSmoother.trigger(AbstractEngine::PanCurve[pan], subfragmentRate);              NotePan[c].setCurveOnly(pNote ? pNote->Override.PanCurve : DEFAULT_FADE_CURVE);
231                NotePan[c].setCurrentValue(value);
232                NotePan[c].setFinal(pNote ? pNote->Override.Pan.Final : false);
233                NotePan[c].setDefaultDuration(pNote ? pNote->Override.PanTime : DEFAULT_NOTE_PAN_TIME_S);
234            }
235    
236            PanLeftSmoother.trigger(
237                AbstractEngine::PanCurve[128 - pan],
238                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)
239            );
240            PanRightSmoother.trigger(
241                AbstractEngine::PanCurve[pan],
242                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)
243            );
244    
245  #ifdef CONFIG_INTERPOLATE_VOLUME  #if CONFIG_INTERPOLATE_VOLUME
246          // setup initial volume in synthesis parameters          // setup initial volume in synthesis parameters
247      #ifdef CONFIG_PROCESS_MUTED_CHANNELS      #if CONFIG_PROCESS_MUTED_CHANNELS
248          if (pEngineChannel->GetMute()) {          if (pEngineChannel->GetMute()) {
249              finalSynthesisParameters.fFinalVolumeLeft  = 0;              finalSynthesisParameters.fFinalVolumeLeft  = 0;
250              finalSynthesisParameters.fFinalVolumeRight = 0;              finalSynthesisParameters.fFinalVolumeRight = 0;
# Line 217  namespace LinuxSampler { Line 252  namespace LinuxSampler {
252          else          else
253      #else      #else
254          {          {
255              float finalVolume;              float finalVolume = pEngineChannel->MidiVolume * crossfadeVolume;
256                float fModVolume;
257              if (pSignalUnitRack == NULL) {              if (pSignalUnitRack == NULL) {
258                  finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pEG1->getLevel();                  fModVolume = pEG1->getLevel();
259              } else {              } else {
260                  finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pSignalUnitRack->GetEndpointUnit()->GetVolume();                  fModVolume = pSignalUnitRack->GetEndpointUnit()->GetVolume();
261              }              }
262                NoteVolume.applyCurrentValueTo(fModVolume);
263                finalVolume *= fModVolume;
264    
265                float panL = PanLeftSmoother.render();
266                float panR = PanRightSmoother.render();
267                NotePan[0].applyCurrentValueTo(panL);
268                NotePan[1].applyCurrentValueTo(panR);
269    
270              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * PanLeftSmoother.render();              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * panL;
271              finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * PanRightSmoother.render();              finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * panR;
272          }          }
273      #endif      #endif
274  #endif  #endif
# Line 234  namespace LinuxSampler { Line 277  namespace LinuxSampler {
277              // setup EG 2 (VCF Cutoff EG)              // setup EG 2 (VCF Cutoff EG)
278              {              {
279                  // get current value of EG2 controller                  // get current value of EG2 controller
280                  double eg2controllervalue = GetEG2ControllerValue(itNoteOnEvent->Param.Note.Velocity);                  double eg2controllervalue = GetEG2ControllerValue(MIDIVelocity());
281    
282                  // calculate influence of EG2 controller on EG2's parameters                  // calculate influence of EG2 controller on EG2's parameters
283                  EGInfo egInfo = CalculateEG2ControllerInfluence(eg2controllervalue);                  EGInfo egInfo = CalculateEG2ControllerInfluence(eg2controllervalue);
284    
285                  TriggerEG2(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity);                  if (pNote) {
286                        pNote->Override.CutoffAttack.applyTo(egInfo.Attack);
287                        pNote->Override.CutoffDecay.applyTo(egInfo.Decay);
288                        pNote->Override.CutoffRelease.applyTo(egInfo.Release);
289                    }
290    
291                    TriggerEG2(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, MIDIVelocity());
292              }              }
293    
294    
# Line 248  namespace LinuxSampler { Line 297  namespace LinuxSampler {
297                  // 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
298                  bool  bPortamento = pEngineChannel->PortamentoMode && pEngineChannel->PortamentoPos >= 0.0f;                  bool  bPortamento = pEngineChannel->PortamentoMode && pEngineChannel->PortamentoPos >= 0.0f;
299                  float eg3depth = (bPortamento)                  float eg3depth = (bPortamento)
300                               ? RTMath::CentsToFreqRatio((pEngineChannel->PortamentoPos - (float) MIDIKey) * 100)                               ? RTMath::CentsToFreqRatio((pEngineChannel->PortamentoPos - (float) MIDIKey()) * 100)
301                               : RTMath::CentsToFreqRatio(RgnInfo.EG3Depth);                               : RTMath::CentsToFreqRatio(RgnInfo.EG3Depth);
302                  float eg3time = (bPortamento)                  float eg3time = (bPortamento)
303                              ? pEngineChannel->PortamentoTime                              ? pEngineChannel->PortamentoTime
# Line 298  namespace LinuxSampler { Line 347  namespace LinuxSampler {
347              VCFResonanceCtrl.value = pEngineChannel->ControllerTable[VCFResonanceCtrl.controller];              VCFResonanceCtrl.value = pEngineChannel->ControllerTable[VCFResonanceCtrl.controller];
348    
349              // calculate cutoff frequency              // calculate cutoff frequency
350              CutoffBase = CalculateCutoffBase(itNoteOnEvent->Param.Note.Velocity);              CutoffBase = CalculateCutoffBase(MIDIVelocity());
351    
352              VCFCutoffCtrl.fvalue = CalculateFinalCutoff(CutoffBase);              VCFCutoffCtrl.fvalue = CalculateFinalCutoff(CutoffBase);
353    
# Line 323  namespace LinuxSampler { Line 372  namespace LinuxSampler {
372      }      }
373            
374      void AbstractVoice::SetSampleStartOffset() {      void AbstractVoice::SetSampleStartOffset() {
375          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
376          Pos = RgnInfo.SampleStartOffset;  
377            // if another sample playback start position was requested by instrument
378            // script (built-in script function play_note())
379            if (pNote && pNote->Override.SampleOffset >= 0) {
380                double overridePos =
381                    double(SmplInfo.SampleRate) * double(pNote->Override.SampleOffset) / 1000000.0;
382                if (overridePos < SmplInfo.TotalFrameCount)
383                    pos = overridePos;
384            }
385    
386            finalSynthesisParameters.dPos = pos;
387            Pos = pos;
388      }      }
389    
390      /**      /**
# Line 353  namespace LinuxSampler { Line 413  namespace LinuxSampler {
413          }          }
414                    
415          AbstractEngineChannel* pChannel = pEngineChannel;          AbstractEngineChannel* pChannel = pEngineChannel;
416          MidiKeyBase* pMidiKeyInfo = GetMidiKeyInfo(MIDIKey);          MidiKeyBase* pMidiKeyInfo = GetMidiKeyInfo(MIDIKey());
417    
418          const bool bVoiceRequiresDedicatedRouting =          const bool bVoiceRequiresDedicatedRouting =
419              pEngineChannel->GetFxSendCount() > 0 &&              pEngineChannel->GetFxSendCount() > 0 &&
# Line 379  namespace LinuxSampler { Line 439  namespace LinuxSampler {
439    
440          RTList<Event>::Iterator itCCEvent = pChannel->pEvents->first();          RTList<Event>::Iterator itCCEvent = pChannel->pEvents->first();
441          RTList<Event>::Iterator itNoteEvent;          RTList<Event>::Iterator itNoteEvent;
442          GetFirstEventOnKey(MIDIKey, itNoteEvent);          GetFirstEventOnKey(HostKey(), itNoteEvent);
443    
444          RTList<Event>::Iterator itGroupEvent;          RTList<Event>::Iterator itGroupEvent;
445          if (pGroupEvents && !Orphan) itGroupEvent = pGroupEvents->first();          if (pGroupEvents && !Orphan) itGroupEvent = pGroupEvents->first();
# Line 399  namespace LinuxSampler { Line 459  namespace LinuxSampler {
459              }              }
460          }          }
461    
462          uint killPos;          uint killPos = 0;
463          if (itKillEvent) {          if (itKillEvent) {
464              int maxFadeOutPos = Samples - GetEngine()->GetMinFadeOutSamples();              int maxFadeOutPos = Samples - GetEngine()->GetMinFadeOutSamples();
465              if (maxFadeOutPos < 0) {              if (maxFadeOutPos < 0) {
# Line 427  namespace LinuxSampler { Line 487  namespace LinuxSampler {
487              fFinalCutoff    = VCFCutoffCtrl.fvalue;              fFinalCutoff    = VCFCutoffCtrl.fvalue;
488              fFinalResonance = VCFResonanceCtrl.fvalue;              fFinalResonance = VCFResonanceCtrl.fvalue;
489    
490              // process MIDI control change and pitchbend events for this subfragment              // process MIDI control change, aftertouch and pitchbend events for this subfragment
491              processCCEvents(itCCEvent, iSubFragmentEnd);              processCCEvents(itCCEvent, iSubFragmentEnd);
492              uint8_t pan = MIDIPan;              uint8_t pan = MIDIPan;
493              if (pSignalUnitRack != NULL) pan = pSignalUnitRack->GetEndpointUnit()->CalculatePan(MIDIPan);              if (pSignalUnitRack != NULL) pan = pSignalUnitRack->GetEndpointUnit()->CalculatePan(MIDIPan);
494                
495              PanLeftSmoother.update(AbstractEngine::PanCurve[128 - pan]);              PanLeftSmoother.update(AbstractEngine::PanCurve[128 - pan]);
496              PanRightSmoother.update(AbstractEngine::PanCurve[pan]);              PanRightSmoother.update(AbstractEngine::PanCurve[pan]);
497    
498              finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend;              finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend;
499    
500              float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render();              float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render();
501  #ifdef CONFIG_PROCESS_MUTED_CHANNELS  #if CONFIG_PROCESS_MUTED_CHANNELS
502              if (pChannel->GetMute()) fFinalVolume = 0;              if (pChannel->GetMute()) fFinalVolume = 0;
503  #endif  #endif
504    
505              // process transition events (note on, note off & sustain pedal)              // process transition events (note on, note off & sustain pedal)
506              processTransitionEvents(itNoteEvent, iSubFragmentEnd);              processTransitionEvents(itNoteEvent, iSubFragmentEnd);
507              processGroupEvents(itGroupEvent, iSubFragmentEnd);              processGroupEvents(itGroupEvent, iSubFragmentEnd);
508                
509                float fModVolume = 1;
510                float fModPitch  = 1;
511    
512              if (pSignalUnitRack == NULL) {              if (pSignalUnitRack == NULL) {
513                  // if the voice was killed in this subfragment, or if the                  // if the voice was killed in this subfragment, or if the
514                  // filter EG is finished, switch EG1 to fade out stage                  // filter EG is finished, switch EG1 to fade out stage
# Line 458  namespace LinuxSampler { Line 522  namespace LinuxSampler {
522                  // process envelope generators                  // process envelope generators
523                  switch (pEG1->getSegmentType()) {                  switch (pEG1->getSegmentType()) {
524                      case EG::segment_lin:                      case EG::segment_lin:
525                          fFinalVolume *= pEG1->processLin();                          fModVolume *= pEG1->processLin();
526                          break;                          break;
527                      case EG::segment_exp:                      case EG::segment_exp:
528                          fFinalVolume *= pEG1->processExp();                          fModVolume *= pEG1->processExp();
529                          break;                          break;
530                      case EG::segment_end:                      case EG::segment_end:
531                          fFinalVolume *= pEG1->getLevel();                          fModVolume *= pEG1->getLevel();
532                          break; // noop                          break; // noop
533                      case EG::segment_pow:                      case EG::segment_pow:
534                          fFinalVolume *= pEG1->processPow();                          fModVolume *= pEG1->processPow();
535                          break;                          break;
536                  }                  }
537                  switch (pEG2->getSegmentType()) {                  switch (pEG2->getSegmentType()) {
# Line 484  namespace LinuxSampler { Line 548  namespace LinuxSampler {
548                          fFinalCutoff *= pEG2->processPow();                          fFinalCutoff *= pEG2->processPow();
549                          break;                          break;
550                  }                  }
551                  if (EG3.active()) finalSynthesisParameters.fFinalPitch *= EG3.render();                  if (EG3.active()) fModPitch *= EG3.render();
552    
553                  // process low frequency oscillators                  // process low frequency oscillators
554                  if (bLFO1Enabled) fFinalVolume *= (1.0f - pLFO1->render());                  if (bLFO1Enabled) fModVolume   *= (1.0f - pLFO1->render());
555                  if (bLFO2Enabled) fFinalCutoff *= pLFO2->render();                  if (bLFO2Enabled) fFinalCutoff *= (1.0f - pLFO2->render());
556                  if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());                  if (bLFO3Enabled) fModPitch *= RTMath::CentsToFreqRatio(pLFO3->render());
557              } else {              } else {
558                  // if the voice was killed in this subfragment, enter fade out stage                  // if the voice was killed in this subfragment, enter fade out stage
559                  if (itKillEvent && killPos <= iSubFragmentEnd) {                  if (itKillEvent && killPos <= iSubFragmentEnd) {
# Line 509  namespace LinuxSampler { Line 573  namespace LinuxSampler {
573                  fFinalCutoff    = pSignalUnitRack->GetEndpointUnit()->CalculateFilterCutoff(fFinalCutoff);                  fFinalCutoff    = pSignalUnitRack->GetEndpointUnit()->CalculateFilterCutoff(fFinalCutoff);
574                  fFinalResonance = pSignalUnitRack->GetEndpointUnit()->CalculateResonance(fFinalResonance);                  fFinalResonance = pSignalUnitRack->GetEndpointUnit()->CalculateResonance(fFinalResonance);
575                                    
576                  finalSynthesisParameters.fFinalPitch =                  fModPitch = pSignalUnitRack->GetEndpointUnit()->CalculatePitch(fModPitch);
                     pSignalUnitRack->GetEndpointUnit()->CalculatePitch(finalSynthesisParameters.fFinalPitch);  
                       
577              }              }
578                
579                NoteVolume.renderApplyTo(fModVolume);
580                NotePitch.renderApplyTo(fModPitch);
581                NoteCutoff.applyTo(fFinalCutoff);
582                NoteResonance.applyTo(fFinalResonance);
583    
584                fFinalVolume *= fModVolume;
585    
586                finalSynthesisParameters.fFinalPitch *= fModPitch;
587    
588              // limit the pitch so we don't read outside the buffer              // limit the pitch so we don't read outside the buffer
589              finalSynthesisParameters.fFinalPitch = RTMath::Min(finalSynthesisParameters.fFinalPitch, float(1 << CONFIG_MAX_PITCH));              finalSynthesisParameters.fFinalPitch = RTMath::Min(finalSynthesisParameters.fFinalPitch, float(1 << CONFIG_MAX_PITCH));
590    
# Line 532  namespace LinuxSampler { Line 603  namespace LinuxSampler {
603    
604              // prepare final synthesis parameters structure              // prepare final synthesis parameters structure
605              finalSynthesisParameters.uiToGo            = iSubFragmentEnd - i;              finalSynthesisParameters.uiToGo            = iSubFragmentEnd - i;
606  #ifdef CONFIG_INTERPOLATE_VOLUME  
607                float panL = PanLeftSmoother.render();
608                float panR = PanRightSmoother.render();
609                NotePan[0].renderApplyTo(panL);
610                NotePan[1].renderApplyTo(panR);
611    
612    #if CONFIG_INTERPOLATE_VOLUME
613              finalSynthesisParameters.fFinalVolumeDeltaLeft  =              finalSynthesisParameters.fFinalVolumeDeltaLeft  =
614                  (fFinalVolume * VolumeLeft  * PanLeftSmoother.render() -                  (fFinalVolume * VolumeLeft  * panL -
615                   finalSynthesisParameters.fFinalVolumeLeft) / finalSynthesisParameters.uiToGo;                   finalSynthesisParameters.fFinalVolumeLeft) / finalSynthesisParameters.uiToGo;
616              finalSynthesisParameters.fFinalVolumeDeltaRight =              finalSynthesisParameters.fFinalVolumeDeltaRight =
617                  (fFinalVolume * VolumeRight * PanRightSmoother.render() -                  (fFinalVolume * VolumeRight * panR -
618                   finalSynthesisParameters.fFinalVolumeRight) / finalSynthesisParameters.uiToGo;                   finalSynthesisParameters.fFinalVolumeRight) / finalSynthesisParameters.uiToGo;
619  #else  #else
620              finalSynthesisParameters.fFinalVolumeLeft  =              finalSynthesisParameters.fFinalVolumeLeft  =
621                  fFinalVolume * VolumeLeft  * PanLeftSmoother.render();                  fFinalVolume * VolumeLeft  * panL;
622              finalSynthesisParameters.fFinalVolumeRight =              finalSynthesisParameters.fFinalVolumeRight =
623                  fFinalVolume * VolumeRight * PanRightSmoother.render();                  fFinalVolume * VolumeRight * panR;
624  #endif  #endif
625              // render audio for one subfragment              // render audio for one subfragment
626              if (!delay) RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);              if (!delay) RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);
# Line 611  namespace LinuxSampler { Line 688  namespace LinuxSampler {
688      }      }
689    
690      /**      /**
691       * Process given list of MIDI control change and pitch bend events for       * Process given list of MIDI control change, aftertouch and pitch bend
692       * the given time.       * events for the given time.
693       *       *
694       * @param itEvent - iterator pointing to the next event to be processed       * @param itEvent - iterator pointing to the next event to be processed
695       * @param End     - youngest time stamp where processing should be stopped       * @param End     - youngest time stamp where processing should be stopped
696       */       */
697      void AbstractVoice::processCCEvents(RTList<Event>::Iterator& itEvent, uint End) {      void AbstractVoice::processCCEvents(RTList<Event>::Iterator& itEvent, uint End) {
698          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
699              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)
700                    && itEvent->Param.CC.Controller) // if (valid) MIDI control change event
701                {
702                  if (itEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {                  if (itEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {
703                      ProcessCutoffEvent(itEvent);                      ProcessCutoffEvent(itEvent);
704                  }                  }
705                  if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {                  if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {
706                      processResonanceEvent(itEvent);                      processResonanceEvent(itEvent);
707                  }                  }
708                    if (itEvent->Param.CC.Controller == CTRL_TABLE_IDX_AFTERTOUCH ||
709                        itEvent->Type == Event::type_channel_pressure)
710                    {
711                        ProcessChannelPressureEvent(itEvent);
712                    }
713                  if (pSignalUnitRack == NULL) {                  if (pSignalUnitRack == NULL) {
714                      if (itEvent->Param.CC.Controller == pLFO1->ExtController) {                      if (itEvent->Param.CC.Controller == pLFO1->ExtController) {
715                          pLFO1->update(itEvent->Param.CC.Value);                          pLFO1->updateByMIDICtrlValue(itEvent->Param.CC.Value);
716                      }                      }
717                      if (itEvent->Param.CC.Controller == pLFO2->ExtController) {                      if (itEvent->Param.CC.Controller == pLFO2->ExtController) {
718                          pLFO2->update(itEvent->Param.CC.Value);                          pLFO2->updateByMIDICtrlValue(itEvent->Param.CC.Value);
719                      }                      }
720                      if (itEvent->Param.CC.Controller == pLFO3->ExtController) {                      if (itEvent->Param.CC.Controller == pLFO3->ExtController) {
721                          pLFO3->update(itEvent->Param.CC.Value);                          pLFO3->updateByMIDICtrlValue(itEvent->Param.CC.Value);
722                      }                      }
723                  }                  }
724                  if (itEvent->Param.CC.Controller == 7) { // volume                  if (itEvent->Param.CC.Controller == 7) { // volume
# Line 644  namespace LinuxSampler { Line 728  namespace LinuxSampler {
728                  }                  }
729              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event
730                  processPitchEvent(itEvent);                  processPitchEvent(itEvent);
731                } else if (itEvent->Type == Event::type_note_pressure) {
732                    ProcessPolyphonicKeyPressureEvent(itEvent);
733              }              }
734    
735              ProcessCCEvent(itEvent);              ProcessCCEvent(itEvent);
# Line 668  namespace LinuxSampler { Line 754  namespace LinuxSampler {
754      }      }
755    
756      /**      /**
757       * 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
758       * for the given time.       * note synthesis parameter events for the given time.
759       *       *
760       * @param itEvent - iterator pointing to the next event to be processed       * @param itEvent - iterator pointing to the next event to be processed
761       * @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 764  namespace LinuxSampler {
764          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
765              // some voice types ignore note off              // some voice types ignore note off
766              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))) {
767                  if (itEvent->Type == Event::type_release) {                  if (itEvent->Type == Event::type_release_key) {
768                      EnterReleaseStage();                      EnterReleaseStage();
769                  } else if (itEvent->Type == Event::type_cancel_release) {                  } else if (itEvent->Type == Event::type_cancel_release_key) {
770                      if (pSignalUnitRack == NULL) {                      if (pSignalUnitRack == NULL) {
771                          pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                          pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
772                          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 775  namespace LinuxSampler {
775                      }                      }
776                  }                  }
777              }              }
778                // process stop-note events (caused by built-in instrument script function note_off())
779                if (itEvent->Type == Event::type_release_note && pNote &&
780                    pEngineChannel->pEngine->NoteByID( itEvent->Param.Note.ID ) == pNote)
781                {
782                    EnterReleaseStage();
783                }
784                // process kill-note events (caused by built-in instrument script function fade_out())
785                if (itEvent->Type == Event::type_kill_note && pNote &&
786                    pEngineChannel->pEngine->NoteByID( itEvent->Param.Note.ID ) == pNote)
787                {
788                    Kill(itEvent);
789                }
790                // process synthesis parameter events (caused by built-in realt-time instrument script functions)
791                if (itEvent->Type == Event::type_note_synth_param && pNote &&
792                    pEngineChannel->pEngine->NoteByID( itEvent->Param.NoteSynthParam.NoteID ) == pNote)
793                {
794                    switch (itEvent->Param.NoteSynthParam.Type) {
795                        case Event::synth_param_volume:
796                            NoteVolume.fadeTo(itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
797                            NoteVolume.setFinal(itEvent->Param.NoteSynthParam.isFinal());
798                            break;
799                        case Event::synth_param_volume_time:
800                            NoteVolume.setDefaultDuration(itEvent->Param.NoteSynthParam.AbsValue);
801                            break;
802                        case Event::synth_param_volume_curve:
803                            NoteVolume.setCurve((fade_curve_t)itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
804                            break;
805                        case Event::synth_param_pitch:
806                            NotePitch.fadeTo(itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
807                            NotePitch.setFinal(itEvent->Param.NoteSynthParam.isFinal());
808                            break;
809                        case Event::synth_param_pitch_time:
810                            NotePitch.setDefaultDuration(itEvent->Param.NoteSynthParam.AbsValue);
811                            break;
812                        case Event::synth_param_pitch_curve:
813                            NotePitch.setCurve((fade_curve_t)itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
814                            break;
815                        case Event::synth_param_pan:
816                            NotePan[0].fadeTo(
817                                AbstractEngine::PanCurveValueNorm(itEvent->Param.NoteSynthParam.AbsValue, 0 /*left*/),
818                                GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE
819                            );
820                            NotePan[1].fadeTo(
821                                AbstractEngine::PanCurveValueNorm(itEvent->Param.NoteSynthParam.AbsValue, 1 /*right*/),
822                                GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE
823                            );
824                            NotePan[0].setFinal(itEvent->Param.NoteSynthParam.isFinal());
825                            NotePan[1].setFinal(itEvent->Param.NoteSynthParam.isFinal());
826                            break;
827                        case Event::synth_param_pan_time:
828                            NotePan[0].setDefaultDuration(itEvent->Param.NoteSynthParam.AbsValue);
829                            NotePan[1].setDefaultDuration(itEvent->Param.NoteSynthParam.AbsValue);
830                            break;
831                        case Event::synth_param_pan_curve:
832                            NotePan[0].setCurve((fade_curve_t)itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
833                            NotePan[1].setCurve((fade_curve_t)itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
834                            break;
835                        case Event::synth_param_cutoff:
836                            NoteCutoff.Value = itEvent->Param.NoteSynthParam.AbsValue;
837                            NoteCutoff.Final = itEvent->Param.NoteSynthParam.isFinal();
838                            break;
839                        case Event::synth_param_resonance:
840                            NoteResonance.Value = itEvent->Param.NoteSynthParam.AbsValue;
841                            NoteResonance.Final = itEvent->Param.NoteSynthParam.isFinal();
842                            break;
843                        case Event::synth_param_amp_lfo_depth:
844                            pLFO1->setScriptDepthFactor(
845                                itEvent->Param.NoteSynthParam.AbsValue,
846                                itEvent->Param.NoteSynthParam.isFinal()
847                            );
848                            break;
849                        case Event::synth_param_amp_lfo_freq:
850                            if (itEvent->Param.NoteSynthParam.isFinal())
851                                pLFO1->setScriptFrequencyFinal(itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
852                            else
853                                pLFO1->setScriptFrequencyFactor(itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
854                            break;
855                        case Event::synth_param_cutoff_lfo_depth:
856                            pLFO2->setScriptDepthFactor(
857                                itEvent->Param.NoteSynthParam.AbsValue,
858                                itEvent->Param.NoteSynthParam.isFinal()
859                            );
860                            break;
861                        case Event::synth_param_cutoff_lfo_freq:
862                            if (itEvent->Param.NoteSynthParam.isFinal())
863                                pLFO2->setScriptFrequencyFinal(itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
864                            else
865                                pLFO2->setScriptFrequencyFactor(itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
866                            break;
867                        case Event::synth_param_pitch_lfo_depth:
868                            pLFO3->setScriptDepthFactor(
869                                itEvent->Param.NoteSynthParam.AbsValue,
870                                itEvent->Param.NoteSynthParam.isFinal()
871                            );
872                            break;
873                        case Event::synth_param_pitch_lfo_freq:
874                            pLFO3->setScriptFrequencyFactor(itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
875                            break;
876    
877                        case Event::synth_param_attack:
878                        case Event::synth_param_decay:
879                        case Event::synth_param_sustain:
880                        case Event::synth_param_release:
881                            break; // noop
882                    }
883                }
884          }          }
885      }      }
886    
# Line 715  namespace LinuxSampler { Line 907  namespace LinuxSampler {
907      void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {      void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {
908          if (pSignalUnitRack == NULL) {          if (pSignalUnitRack == NULL) {
909              const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());              const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());
910              pEngineChannel->PortamentoPos = (float) MIDIKey + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;              pEngineChannel->PortamentoPos = (float) MIDIKey() + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;
911          } else {          } else {
912              // TODO:              // TODO:
913          }          }
# Line 742  namespace LinuxSampler { Line 934  namespace LinuxSampler {
934    
935      Voice::PitchInfo AbstractVoice::CalculatePitchInfo(int PitchBend) {      Voice::PitchInfo AbstractVoice::CalculatePitchInfo(int PitchBend) {
936          PitchInfo pitch;          PitchInfo pitch;
937          double pitchbasecents = InstrInfo.FineTune + RgnInfo.FineTune + GetEngine()->ScaleTuning[MIDIKey % 12];          double pitchbasecents = InstrInfo.FineTune + RgnInfo.FineTune + GetEngine()->ScaleTuning[MIDIKey() % 12];
938    
939          // GSt behaviour: maximum transpose up is 40 semitones. If          // GSt behaviour: maximum transpose up is 40 semitones. If
940          // MIDI key is more than 40 semitones above unity note,          // MIDI key is more than 40 semitones above unity note,
941          // the transpose is not done.          // the transpose is not done.
942          if (!SmplInfo.Unpitched && (MIDIKey - (int) RgnInfo.UnityNote) < 40) pitchbasecents += (MIDIKey - (int) RgnInfo.UnityNote) * 100;          //
943            // Update: Removed this GSt misbehavior. I don't think that any stock
944            // gig sound requires it to resemble its original sound.
945            // -- Christian, 2017-07-09
946            if (!SmplInfo.Unpitched /* && (MIDIKey() - (int) RgnInfo.UnityNote) < 40*/)
947                pitchbasecents += (MIDIKey() - (int) RgnInfo.UnityNote) * 100;
948    
949          pitch.PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(SmplInfo.SampleRate) / double(GetEngine()->SampleRate));          pitch.PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(SmplInfo.SampleRate) / double(GetEngine()->SampleRate));
950          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 952  namespace LinuxSampler {
952    
953          return pitch;          return pitch;
954      }      }
955        
956        void AbstractVoice::onScaleTuningChanged() {
957            PitchInfo pitch = this->Pitch;
958            double pitchbasecents = InstrInfo.FineTune + RgnInfo.FineTune + GetEngine()->ScaleTuning[MIDIKey() % 12];
959            
960            // GSt behaviour: maximum transpose up is 40 semitones. If
961            // MIDI key is more than 40 semitones above unity note,
962            // the transpose is not done.
963            //
964            // Update: Removed this GSt misbehavior. I don't think that any stock
965            // gig sound requires it to resemble its original sound.
966            // -- Christian, 2017-07-09
967            if (!SmplInfo.Unpitched /* && (MIDIKey() - (int) RgnInfo.UnityNote) < 40*/)
968                pitchbasecents += (MIDIKey() - (int) RgnInfo.UnityNote) * 100;
969            
970            pitch.PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(SmplInfo.SampleRate) / double(GetEngine()->SampleRate));
971            this->Pitch = pitch;
972        }
973    
974      double AbstractVoice::CalculateVolume(double velocityAttenuation) {      double AbstractVoice::CalculateVolume(double velocityAttenuation) {
975          // 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 982  namespace LinuxSampler {
982          // the volume of release triggered samples depends on note length          // the volume of release triggered samples depends on note length
983          if (Type & Voice::type_release_trigger) {          if (Type & Voice::type_release_trigger) {
984              float noteLength = float(GetEngine()->FrameTime + Delay -              float noteLength = float(GetEngine()->FrameTime + Delay -
985                  GetNoteOnTime(MIDIKey) ) / GetEngine()->SampleRate;                  GetNoteOnTime(MIDIKey()) ) / GetEngine()->SampleRate;
986    
987              volume *= GetReleaseTriggerAttenuation(noteLength);              volume *= GetReleaseTriggerAttenuation(noteLength);
988          }          }

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

  ViewVC Help
Powered by ViewVC