/[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 3054 by schoenebeck, Thu Dec 15 12:47:45 2016 UTC revision 3724 by schoenebeck, Thu Jan 23 18:15:37 2020 UTC
# Line 3  Line 3 
3   *   LinuxSampler - modular, streaming capable sampler                     *   *   LinuxSampler - modular, streaming capable sampler                     *
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-2020 Christian Schoenebeck                         *
7   *   Copyright (C) 2009-2012 Christian Schoenebeck and Grigor Iliev        *   *   Copyright (C) 2009-2012 Grigor Iliev                                  *
8   *   Copyright (C) 2013-2016 Christian Schoenebeck and Andreas Persson     *   *   Copyright (C) 2013-2017 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 29  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 118  namespace LinuxSampler { Line 118  namespace LinuxSampler {
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;          // when editing key groups with an instrument editor while sound was
122            // already loaded, ActiveKeyGroups may not have the KeyGroup in question
123            // so use find() here instead of array subscript operator[] to avoid an
124            // implied creation of a NULL entry, to prevent a crash while editing
125            // instruments
126            {
127                AbstractEngineChannel::ActiveKeyGroupMap::const_iterator it =
128                    pEngineChannel->ActiveKeyGroups.find(iKeyGroup);
129                pGroupEvents =
130                    (iKeyGroup && it != pEngineChannel->ActiveKeyGroups.end()) ?
131                        it->second : NULL;
132            }
133    
134          SmplInfo   = GetSampleInfo();          SmplInfo   = GetSampleInfo();
135          RgnInfo    = GetRegionInfo();          RgnInfo    = GetRegionInfo();
# Line 129  namespace LinuxSampler { Line 140  namespace LinuxSampler {
140          AboutToTrigger();          AboutToTrigger();
141    
142          // calculate volume          // calculate volume
143          const double velocityAttenuation = GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity);          const double velocityAttenuation = GetVelocityAttenuation(MIDIVelocity());
144          float volume = CalculateVolume(velocityAttenuation) * pKeyInfo->Volume;          float volume = CalculateVolume(velocityAttenuation) * pKeyInfo->Volume;
145          if (volume <= 0) return -1;          if (volume <= 0) return -1;
146    
# Line 139  namespace LinuxSampler { Line 150  namespace LinuxSampler {
150          SYNTHESIS_MODE_SET_BITDEPTH24(SynthesisMode, SmplInfo.BitDepth == 24);          SYNTHESIS_MODE_SET_BITDEPTH24(SynthesisMode, SmplInfo.BitDepth == 24);
151    
152          // get starting crossfade volume level          // get starting crossfade volume level
153          float crossfadeVolume = CalculateCrossfadeVolume(itNoteOnEvent->Param.Note.Velocity);          float crossfadeVolume = CalculateCrossfadeVolume(MIDIVelocity());
154    
155          VolumeLeft  = volume * pKeyInfo->PanLeft;          VolumeLeft  = volume * pKeyInfo->PanLeft;
156          VolumeRight = volume * pKeyInfo->PanRight;          VolumeRight = volume * pKeyInfo->PanRight;
# Line 147  namespace LinuxSampler { Line 158  namespace LinuxSampler {
158          // this rate is used for rather mellow volume fades          // this rate is used for rather mellow volume fades
159          const float subfragmentRate = GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;          const float subfragmentRate = GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;
160          // this rate is used for very fast volume fades          // this rate is used for very fast volume fades
161          const float quickRampRate = RTMath::Min(subfragmentRate, GetEngine()->SampleRate * 0.001f /* 1ms */);          const float quickRampRate = RTMath::Min(subfragmentRate, GetEngine()->SampleRate * 0.001f /* approx. 13ms */);
162          CrossfadeSmoother.trigger(crossfadeVolume, subfragmentRate);          CrossfadeSmoother.trigger(crossfadeVolume, subfragmentRate);
163    
164          VolumeSmoother.trigger(pEngineChannel->MidiVolume, subfragmentRate);          VolumeSmoother.trigger(pEngineChannel->MidiVolume, subfragmentRate);
165          NoteVolumeSmoother.trigger(pNote ? pNote->Override.Volume : 1.f, quickRampRate);          NoteVolume.setCurveOnly(pNote ? pNote->Override.VolumeCurve : DEFAULT_FADE_CURVE);
166            NoteVolume.setCurrentValue(pNote ? pNote->Override.Volume.Value : 1.f);
167            NoteVolume.setDefaultDuration(pNote ? pNote->Override.VolumeTime : DEFAULT_NOTE_VOLUME_TIME_S);
168            NoteVolume.setFinal(pNote ? pNote->Override.Volume.Final : false);
169    
170          // 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
171          long cachedsamples = GetSampleCacheSize() / SmplInfo.FrameSize;          long cachedsamples = GetSampleCacheSize() / SmplInfo.FrameSize;
# Line 191  namespace LinuxSampler { Line 205  namespace LinuxSampler {
205          }          }
206    
207          Pitch = CalculatePitchInfo(PitchBend);          Pitch = CalculatePitchInfo(PitchBend);
208          NotePitch = (pNote) ? pNote->Override.Pitch : 1.0f;          NotePitch.setCurveOnly(pNote ? pNote->Override.PitchCurve : DEFAULT_FADE_CURVE);
209          NoteCutoff = (pNote) ? pNote->Override.Cutoff : 1.0f;          NotePitch.setCurrentValue(pNote ? pNote->Override.Pitch.Value : 1.0f);
210          NoteResonance = (pNote) ? pNote->Override.Resonance : 1.0f;          NotePitch.setFinal(pNote ? pNote->Override.Pitch.Final : false);
211            NotePitch.setDefaultDuration(pNote ? pNote->Override.PitchTime : DEFAULT_NOTE_PITCH_TIME_S);
212            NoteCutoff.Value = (pNote) ? pNote->Override.Cutoff.Value : 1.0f;
213            NoteCutoff.Final = (pNote) ? pNote->Override.Cutoff.isFinal() : false;
214            NoteResonance.Value = (pNote) ? pNote->Override.Resonance.Value : 1.0f;
215            NoteResonance.Final = (pNote) ? pNote->Override.Resonance.Final : false;
216    
217          // 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
218          const double velrelease = 1 / GetVelocityRelease(itNoteOnEvent->Param.Note.Velocity);          const double velrelease = 1 / GetVelocityRelease(MIDIVelocity());
219    
220          if (pSignalUnitRack == NULL) { // setup EG 1 (VCA EG)          if (pSignalUnitRack == NULL) { // setup EG 1 (VCA EG)
221              // get current value of EG1 controller              // get current value of EG1 controller
222              double eg1controllervalue = GetEG1ControllerValue(itNoteOnEvent->Param.Note.Velocity);              double eg1controllervalue = GetEG1ControllerValue(MIDIVelocity());
223    
224              // calculate influence of EG1 controller on EG1's parameters              // calculate influence of EG1 controller on EG1's parameters
225              EGInfo egInfo = CalculateEG1ControllerInfluence(eg1controllervalue);              EGInfo egInfo = CalculateEG1ControllerInfluence(eg1controllervalue);
226    
227              if (pNote) {              if (pNote) {
228                  egInfo.Attack  *= pNote->Override.Attack;                  pNote->Override.Attack.applyTo(egInfo.Attack);
229                  egInfo.Decay   *= pNote->Override.Decay;                  pNote->Override.Decay.applyTo(egInfo.Decay);
230                  egInfo.Release *= pNote->Override.Release;                  pNote->Override.Release.applyTo(egInfo.Release);
231              }              }
232    
233              TriggerEG1(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity);              TriggerEG1(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, MIDIVelocity());
234          } else {          } else {
235              pSignalUnitRack->Trigger();              pSignalUnitRack->Trigger();
236          }          }
237    
238          const uint8_t pan = (pSignalUnitRack) ? pSignalUnitRack->GetEndpointUnit()->CalculatePan(MIDIPan) : MIDIPan;          const uint8_t pan = (pSignalUnitRack) ? pSignalUnitRack->GetEndpointUnit()->CalculatePan(MIDIPan) : MIDIPan;
239          NotePanLeft  = (pNote) ? AbstractEngine::PanCurveValueNorm(pNote->Override.Pan, 0 /*left*/ ) : 1.f;          for (int c = 0; c < 2; ++c) {
240          NotePanRight = (pNote) ? AbstractEngine::PanCurveValueNorm(pNote->Override.Pan, 1 /*right*/) : 1.f;              float value = (pNote) ? AbstractEngine::PanCurveValueNorm(pNote->Override.Pan.Value, c) : 1.f;
241                NotePan[c].setCurveOnly(pNote ? pNote->Override.PanCurve : DEFAULT_FADE_CURVE);
242                NotePan[c].setCurrentValue(value);
243                NotePan[c].setFinal(pNote ? pNote->Override.Pan.Final : false);
244                NotePan[c].setDefaultDuration(pNote ? pNote->Override.PanTime : DEFAULT_NOTE_PAN_TIME_S);
245            }
246    
247          PanLeftSmoother.trigger(          PanLeftSmoother.trigger(
248              AbstractEngine::PanCurve[128 - pan] * NotePanLeft,              AbstractEngine::PanCurve[128 - pan],
249              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)              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)
250          );          );
251          PanRightSmoother.trigger(          PanRightSmoother.trigger(
252              AbstractEngine::PanCurve[pan] * NotePanRight,              AbstractEngine::PanCurve[pan],
253              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)              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)
254          );          );
255    
256  #ifdef CONFIG_INTERPOLATE_VOLUME  #if CONFIG_INTERPOLATE_VOLUME
257          // setup initial volume in synthesis parameters          // setup initial volume in synthesis parameters
258      #ifdef CONFIG_PROCESS_MUTED_CHANNELS      #if CONFIG_PROCESS_MUTED_CHANNELS
259          if (pEngineChannel->GetMute()) {          if (pEngineChannel->GetMute()) {
260              finalSynthesisParameters.fFinalVolumeLeft  = 0;              finalSynthesisParameters.fFinalVolumeLeft  = 0;
261              finalSynthesisParameters.fFinalVolumeRight = 0;              finalSynthesisParameters.fFinalVolumeRight = 0;
# Line 238  namespace LinuxSampler { Line 263  namespace LinuxSampler {
263          else          else
264      #else      #else
265          {          {
266              float finalVolume;              float finalVolume = pEngineChannel->MidiVolume * crossfadeVolume;
267                float fModVolume;
268              if (pSignalUnitRack == NULL) {              if (pSignalUnitRack == NULL) {
269                  finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pEG1->getLevel();                  fModVolume = pEG1->getLevel();
270              } else {              } else {
271                  finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pSignalUnitRack->GetEndpointUnit()->GetVolume();                  fModVolume = pSignalUnitRack->GetEndpointUnit()->GetVolume();
272              }              }
273                NoteVolume.applyCurrentValueTo(fModVolume);
274                finalVolume *= fModVolume;
275    
276              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * PanLeftSmoother.render();              float panL = PanLeftSmoother.render();
277              finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * PanRightSmoother.render();              float panR = PanRightSmoother.render();
278                NotePan[0].applyCurrentValueTo(panL);
279                NotePan[1].applyCurrentValueTo(panR);
280    
281                finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * panL;
282                finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * panR;
283          }          }
284      #endif      #endif
285  #endif  #endif
# Line 255  namespace LinuxSampler { Line 288  namespace LinuxSampler {
288              // setup EG 2 (VCF Cutoff EG)              // setup EG 2 (VCF Cutoff EG)
289              {              {
290                  // get current value of EG2 controller                  // get current value of EG2 controller
291                  double eg2controllervalue = GetEG2ControllerValue(itNoteOnEvent->Param.Note.Velocity);                  double eg2controllervalue = GetEG2ControllerValue(MIDIVelocity());
292    
293                  // calculate influence of EG2 controller on EG2's parameters                  // calculate influence of EG2 controller on EG2's parameters
294                  EGInfo egInfo = CalculateEG2ControllerInfluence(eg2controllervalue);                  EGInfo egInfo = CalculateEG2ControllerInfluence(eg2controllervalue);
295    
296                  TriggerEG2(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity);                  if (pNote) {
297                        pNote->Override.CutoffAttack.applyTo(egInfo.Attack);
298                        pNote->Override.CutoffDecay.applyTo(egInfo.Decay);
299                        pNote->Override.CutoffRelease.applyTo(egInfo.Release);
300                    }
301    
302                    TriggerEG2(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, MIDIVelocity());
303              }              }
304    
305    
# Line 319  namespace LinuxSampler { Line 358  namespace LinuxSampler {
358              VCFResonanceCtrl.value = pEngineChannel->ControllerTable[VCFResonanceCtrl.controller];              VCFResonanceCtrl.value = pEngineChannel->ControllerTable[VCFResonanceCtrl.controller];
359    
360              // calculate cutoff frequency              // calculate cutoff frequency
361              CutoffBase = CalculateCutoffBase(itNoteOnEvent->Param.Note.Velocity);              CutoffBase = CalculateCutoffBase(MIDIVelocity());
362    
363              VCFCutoffCtrl.fvalue = CalculateFinalCutoff(CutoffBase);              VCFCutoffCtrl.fvalue = CalculateFinalCutoff(CutoffBase);
364    
# Line 344  namespace LinuxSampler { Line 383  namespace LinuxSampler {
383      }      }
384            
385      void AbstractVoice::SetSampleStartOffset() {      void AbstractVoice::SetSampleStartOffset() {
386          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
387          Pos = RgnInfo.SampleStartOffset;  
388            // if another sample playback start position was requested by instrument
389            // script (built-in script function play_note())
390            if (pNote && pNote->Override.SampleOffset >= 0) {
391                double overridePos =
392                    double(SmplInfo.SampleRate) * double(pNote->Override.SampleOffset) / 1000000.0;
393                if (overridePos < SmplInfo.TotalFrameCount)
394                    pos = overridePos;
395            }
396    
397            finalSynthesisParameters.dPos = pos;
398            Pos = pos;
399      }      }
400    
401      /**      /**
# Line 453  namespace LinuxSampler { Line 503  namespace LinuxSampler {
503              uint8_t pan = MIDIPan;              uint8_t pan = MIDIPan;
504              if (pSignalUnitRack != NULL) pan = pSignalUnitRack->GetEndpointUnit()->CalculatePan(MIDIPan);              if (pSignalUnitRack != NULL) pan = pSignalUnitRack->GetEndpointUnit()->CalculatePan(MIDIPan);
505    
506              PanLeftSmoother.update(AbstractEngine::PanCurve[128 - pan] * NotePanLeft);              PanLeftSmoother.update(AbstractEngine::PanCurve[128 - pan]);
507              PanRightSmoother.update(AbstractEngine::PanCurve[pan]      * NotePanRight);              PanRightSmoother.update(AbstractEngine::PanCurve[pan]);
508    
509              finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend * NotePitch;              finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend;
510    
511              float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render() * NoteVolumeSmoother.render();              float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render();
512  #ifdef CONFIG_PROCESS_MUTED_CHANNELS  #if CONFIG_PROCESS_MUTED_CHANNELS
513              if (pChannel->GetMute()) fFinalVolume = 0;              if (pChannel->GetMute()) fFinalVolume = 0;
514  #endif  #endif
515    
516              // process transition events (note on, note off & sustain pedal)              // process transition events (note on, note off & sustain pedal)
517              processTransitionEvents(itNoteEvent, iSubFragmentEnd);              processTransitionEvents(itNoteEvent, iSubFragmentEnd);
518              processGroupEvents(itGroupEvent, iSubFragmentEnd);              processGroupEvents(itGroupEvent, iSubFragmentEnd);
519                
520                float fModVolume = 1;
521                float fModPitch  = 1;
522    
523              if (pSignalUnitRack == NULL) {              if (pSignalUnitRack == NULL) {
524                  // if the voice was killed in this subfragment, or if the                  // if the voice was killed in this subfragment, or if the
525                  // filter EG is finished, switch EG1 to fade out stage                  // filter EG is finished, switch EG1 to fade out stage
# Line 480  namespace LinuxSampler { Line 533  namespace LinuxSampler {
533                  // process envelope generators                  // process envelope generators
534                  switch (pEG1->getSegmentType()) {                  switch (pEG1->getSegmentType()) {
535                      case EG::segment_lin:                      case EG::segment_lin:
536                          fFinalVolume *= pEG1->processLin();                          fModVolume *= pEG1->processLin();
537                          break;                          break;
538                      case EG::segment_exp:                      case EG::segment_exp:
539                          fFinalVolume *= pEG1->processExp();                          fModVolume *= pEG1->processExp();
540                          break;                          break;
541                      case EG::segment_end:                      case EG::segment_end:
542                          fFinalVolume *= pEG1->getLevel();                          fModVolume *= pEG1->getLevel();
543                          break; // noop                          break; // noop
544                      case EG::segment_pow:                      case EG::segment_pow:
545                          fFinalVolume *= pEG1->processPow();                          fModVolume *= pEG1->processPow();
546                          break;                          break;
547                  }                  }
548                  switch (pEG2->getSegmentType()) {                  switch (pEG2->getSegmentType()) {
# Line 506  namespace LinuxSampler { Line 559  namespace LinuxSampler {
559                          fFinalCutoff *= pEG2->processPow();                          fFinalCutoff *= pEG2->processPow();
560                          break;                          break;
561                  }                  }
562                  if (EG3.active()) finalSynthesisParameters.fFinalPitch *= EG3.render();                  if (EG3.active()) fModPitch *= EG3.render();
563    
564                  // process low frequency oscillators                  // process low frequency oscillators
565                  if (bLFO1Enabled) fFinalVolume *= (1.0f - pLFO1->render());                  if (bLFO1Enabled) fModVolume   *= (1.0f - pLFO1->render());
566                  if (bLFO2Enabled) fFinalCutoff *= (1.0f - pLFO2->render());                  if (bLFO2Enabled) fFinalCutoff *= (1.0f - pLFO2->render());
567                  if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());                  if (bLFO3Enabled) fModPitch *= RTMath::CentsToFreqRatio(pLFO3->render());
568              } else {              } else {
569                  // if the voice was killed in this subfragment, enter fade out stage                  // if the voice was killed in this subfragment, enter fade out stage
570                  if (itKillEvent && killPos <= iSubFragmentEnd) {                  if (itKillEvent && killPos <= iSubFragmentEnd) {
# Line 531  namespace LinuxSampler { Line 584  namespace LinuxSampler {
584                  fFinalCutoff    = pSignalUnitRack->GetEndpointUnit()->CalculateFilterCutoff(fFinalCutoff);                  fFinalCutoff    = pSignalUnitRack->GetEndpointUnit()->CalculateFilterCutoff(fFinalCutoff);
585                  fFinalResonance = pSignalUnitRack->GetEndpointUnit()->CalculateResonance(fFinalResonance);                  fFinalResonance = pSignalUnitRack->GetEndpointUnit()->CalculateResonance(fFinalResonance);
586                                    
587                  finalSynthesisParameters.fFinalPitch =                  fModPitch = pSignalUnitRack->GetEndpointUnit()->CalculatePitch(fModPitch);
                     pSignalUnitRack->GetEndpointUnit()->CalculatePitch(finalSynthesisParameters.fFinalPitch);  
                       
588              }              }
589    
590              fFinalCutoff    *= NoteCutoff;              NoteVolume.renderApplyTo(fModVolume);
591              fFinalResonance *= NoteResonance;              NotePitch.renderApplyTo(fModPitch);
592                NoteCutoff.applyTo(fFinalCutoff);
593                NoteResonance.applyTo(fFinalResonance);
594    
595                fFinalVolume *= fModVolume;
596    
597                finalSynthesisParameters.fFinalPitch *= fModPitch;
598    
599              // limit the pitch so we don't read outside the buffer              // limit the pitch so we don't read outside the buffer
600              finalSynthesisParameters.fFinalPitch = RTMath::Min(finalSynthesisParameters.fFinalPitch, float(1 << CONFIG_MAX_PITCH));              finalSynthesisParameters.fFinalPitch = RTMath::Min(finalSynthesisParameters.fFinalPitch, float(1 << CONFIG_MAX_PITCH));
# Line 557  namespace LinuxSampler { Line 614  namespace LinuxSampler {
614    
615              // prepare final synthesis parameters structure              // prepare final synthesis parameters structure
616              finalSynthesisParameters.uiToGo            = iSubFragmentEnd - i;              finalSynthesisParameters.uiToGo            = iSubFragmentEnd - i;
617  #ifdef CONFIG_INTERPOLATE_VOLUME  
618                float panL = PanLeftSmoother.render();
619                float panR = PanRightSmoother.render();
620                NotePan[0].renderApplyTo(panL);
621                NotePan[1].renderApplyTo(panR);
622    
623    #if CONFIG_INTERPOLATE_VOLUME
624              finalSynthesisParameters.fFinalVolumeDeltaLeft  =              finalSynthesisParameters.fFinalVolumeDeltaLeft  =
625                  (fFinalVolume * VolumeLeft  * PanLeftSmoother.render() -                  (fFinalVolume * VolumeLeft  * panL -
626                   finalSynthesisParameters.fFinalVolumeLeft) / finalSynthesisParameters.uiToGo;                   finalSynthesisParameters.fFinalVolumeLeft) / finalSynthesisParameters.uiToGo;
627              finalSynthesisParameters.fFinalVolumeDeltaRight =              finalSynthesisParameters.fFinalVolumeDeltaRight =
628                  (fFinalVolume * VolumeRight * PanRightSmoother.render() -                  (fFinalVolume * VolumeRight * panR -
629                   finalSynthesisParameters.fFinalVolumeRight) / finalSynthesisParameters.uiToGo;                   finalSynthesisParameters.fFinalVolumeRight) / finalSynthesisParameters.uiToGo;
630  #else  #else
631              finalSynthesisParameters.fFinalVolumeLeft  =              finalSynthesisParameters.fFinalVolumeLeft  =
632                  fFinalVolume * VolumeLeft  * PanLeftSmoother.render();                  fFinalVolume * VolumeLeft  * panL;
633              finalSynthesisParameters.fFinalVolumeRight =              finalSynthesisParameters.fFinalVolumeRight =
634                  fFinalVolume * VolumeRight * PanRightSmoother.render();                  fFinalVolume * VolumeRight * panR;
635  #endif  #endif
636              // render audio for one subfragment              // render audio for one subfragment
637              if (!delay) RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);              if (!delay) RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);
# Line 660  namespace LinuxSampler { Line 723  namespace LinuxSampler {
723                  }                  }
724                  if (pSignalUnitRack == NULL) {                  if (pSignalUnitRack == NULL) {
725                      if (itEvent->Param.CC.Controller == pLFO1->ExtController) {                      if (itEvent->Param.CC.Controller == pLFO1->ExtController) {
726                          pLFO1->update(itEvent->Param.CC.Value);                          pLFO1->updateByMIDICtrlValue(itEvent->Param.CC.Value);
727                      }                      }
728                      if (itEvent->Param.CC.Controller == pLFO2->ExtController) {                      if (itEvent->Param.CC.Controller == pLFO2->ExtController) {
729                          pLFO2->update(itEvent->Param.CC.Value);                          pLFO2->updateByMIDICtrlValue(itEvent->Param.CC.Value);
730                      }                      }
731                      if (itEvent->Param.CC.Controller == pLFO3->ExtController) {                      if (itEvent->Param.CC.Controller == pLFO3->ExtController) {
732                          pLFO3->update(itEvent->Param.CC.Value);                          pLFO3->updateByMIDICtrlValue(itEvent->Param.CC.Value);
733                      }                      }
734                  }                  }
735                  if (itEvent->Param.CC.Controller == 7) { // volume                  if (itEvent->Param.CC.Controller == 7) { // volume
# Line 729  namespace LinuxSampler { Line 792  namespace LinuxSampler {
792              {              {
793                  EnterReleaseStage();                  EnterReleaseStage();
794              }              }
795                // process kill-note events (caused by built-in instrument script function fade_out())
796                if (itEvent->Type == Event::type_kill_note && pNote &&
797                    pEngineChannel->pEngine->NoteByID( itEvent->Param.Note.ID ) == pNote)
798                {
799                    Kill(itEvent);
800                }
801              // process synthesis parameter events (caused by built-in realt-time instrument script functions)              // process synthesis parameter events (caused by built-in realt-time instrument script functions)
802              if (itEvent->Type == Event::type_note_synth_param && pNote &&              if (itEvent->Type == Event::type_note_synth_param && pNote &&
803                  pEngineChannel->pEngine->NoteByID( itEvent->Param.NoteSynthParam.NoteID ) == pNote)                  pEngineChannel->pEngine->NoteByID( itEvent->Param.NoteSynthParam.NoteID ) == pNote)
804              {              {
805                  switch (itEvent->Param.NoteSynthParam.Type) {                  switch (itEvent->Param.NoteSynthParam.Type) {
806                      case Event::synth_param_volume:                      case Event::synth_param_volume:
807                          NoteVolumeSmoother.update(itEvent->Param.NoteSynthParam.AbsValue);                          NoteVolume.fadeTo(itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
808                            NoteVolume.setFinal(itEvent->Param.NoteSynthParam.isFinal());
809                            break;
810                        case Event::synth_param_volume_time:
811                            NoteVolume.setDefaultDuration(itEvent->Param.NoteSynthParam.AbsValue);
812                            break;
813                        case Event::synth_param_volume_curve:
814                            NoteVolume.setCurve((fade_curve_t)itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
815                          break;                          break;
816                      case Event::synth_param_pitch:                      case Event::synth_param_pitch:
817                          NotePitch = itEvent->Param.NoteSynthParam.AbsValue;                          NotePitch.fadeTo(itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
818                            NotePitch.setFinal(itEvent->Param.NoteSynthParam.isFinal());
819                            break;
820                        case Event::synth_param_pitch_time:
821                            NotePitch.setDefaultDuration(itEvent->Param.NoteSynthParam.AbsValue);
822                            break;
823                        case Event::synth_param_pitch_curve:
824                            NotePitch.setCurve((fade_curve_t)itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
825                          break;                          break;
826                      case Event::synth_param_pan:                      case Event::synth_param_pan:
827                          NotePanLeft  = AbstractEngine::PanCurveValueNorm(itEvent->Param.NoteSynthParam.AbsValue, 0 /*left*/);                          NotePan[0].fadeTo(
828                          NotePanRight = AbstractEngine::PanCurveValueNorm(itEvent->Param.NoteSynthParam.AbsValue, 1 /*right*/);                              AbstractEngine::PanCurveValueNorm(itEvent->Param.NoteSynthParam.AbsValue, 0 /*left*/),
829                                GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE
830                            );
831                            NotePan[1].fadeTo(
832                                AbstractEngine::PanCurveValueNorm(itEvent->Param.NoteSynthParam.AbsValue, 1 /*right*/),
833                                GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE
834                            );
835                            NotePan[0].setFinal(itEvent->Param.NoteSynthParam.isFinal());
836                            NotePan[1].setFinal(itEvent->Param.NoteSynthParam.isFinal());
837                            break;
838                        case Event::synth_param_pan_time:
839                            NotePan[0].setDefaultDuration(itEvent->Param.NoteSynthParam.AbsValue);
840                            NotePan[1].setDefaultDuration(itEvent->Param.NoteSynthParam.AbsValue);
841                            break;
842                        case Event::synth_param_pan_curve:
843                            NotePan[0].setCurve((fade_curve_t)itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
844                            NotePan[1].setCurve((fade_curve_t)itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
845                          break;                          break;
846                      case Event::synth_param_cutoff:                      case Event::synth_param_cutoff:
847                          NoteCutoff = itEvent->Param.NoteSynthParam.AbsValue;                          NoteCutoff.Value = itEvent->Param.NoteSynthParam.AbsValue;
848                            NoteCutoff.Final = itEvent->Param.NoteSynthParam.isFinal();
849                          break;                          break;
850                      case Event::synth_param_resonance:                      case Event::synth_param_resonance:
851                          NoteResonance = itEvent->Param.NoteSynthParam.AbsValue;                          NoteResonance.Value = itEvent->Param.NoteSynthParam.AbsValue;
852                            NoteResonance.Final = itEvent->Param.NoteSynthParam.isFinal();
853                            break;
854                        case Event::synth_param_amp_lfo_depth:
855                            pLFO1->setScriptDepthFactor(
856                                itEvent->Param.NoteSynthParam.AbsValue,
857                                itEvent->Param.NoteSynthParam.isFinal()
858                            );
859                            break;
860                        case Event::synth_param_amp_lfo_freq:
861                            if (itEvent->Param.NoteSynthParam.isFinal())
862                                pLFO1->setScriptFrequencyFinal(itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
863                            else
864                                pLFO1->setScriptFrequencyFactor(itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
865                            break;
866                        case Event::synth_param_cutoff_lfo_depth:
867                            pLFO2->setScriptDepthFactor(
868                                itEvent->Param.NoteSynthParam.AbsValue,
869                                itEvent->Param.NoteSynthParam.isFinal()
870                            );
871                            break;
872                        case Event::synth_param_cutoff_lfo_freq:
873                            if (itEvent->Param.NoteSynthParam.isFinal())
874                                pLFO2->setScriptFrequencyFinal(itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
875                            else
876                                pLFO2->setScriptFrequencyFactor(itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
877                            break;
878                        case Event::synth_param_pitch_lfo_depth:
879                            pLFO3->setScriptDepthFactor(
880                                itEvent->Param.NoteSynthParam.AbsValue,
881                                itEvent->Param.NoteSynthParam.isFinal()
882                            );
883                            break;
884                        case Event::synth_param_pitch_lfo_freq:
885                            pLFO3->setScriptFrequencyFactor(itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
886                          break;                          break;
887    
888                      case Event::synth_param_attack:                      case Event::synth_param_attack:
889                      case Event::synth_param_decay:                      case Event::synth_param_decay:
890                        case Event::synth_param_sustain:
891                      case Event::synth_param_release:                      case Event::synth_param_release:
892                        case Event::synth_param_cutoff_attack:
893                        case Event::synth_param_cutoff_decay:
894                        case Event::synth_param_cutoff_sustain:
895                        case Event::synth_param_cutoff_release:
896                          break; // noop                          break; // noop
897                  }                  }
898              }              }
# Line 815  namespace LinuxSampler { Line 954  namespace LinuxSampler {
954          // GSt behaviour: maximum transpose up is 40 semitones. If          // GSt behaviour: maximum transpose up is 40 semitones. If
955          // MIDI key is more than 40 semitones above unity note,          // MIDI key is more than 40 semitones above unity note,
956          // the transpose is not done.          // the transpose is not done.
957          if (!SmplInfo.Unpitched && (MIDIKey() - (int) RgnInfo.UnityNote) < 40) pitchbasecents += (MIDIKey() - (int) RgnInfo.UnityNote) * 100;          //
958            // Update: Removed this GSt misbehavior. I don't think that any stock
959            // gig sound requires it to resemble its original sound.
960            // -- Christian, 2017-07-09
961            if (!SmplInfo.Unpitched /* && (MIDIKey() - (int) RgnInfo.UnityNote) < 40*/)
962                pitchbasecents += (MIDIKey() - (int) RgnInfo.UnityNote) * 100;
963    
964          pitch.PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(SmplInfo.SampleRate) / double(GetEngine()->SampleRate));          pitch.PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(SmplInfo.SampleRate) / double(GetEngine()->SampleRate));
965          pitch.PitchBendRange = 1.0 / 8192.0 * 100.0 * InstrInfo.PitchbendRange;          pitch.PitchBendRange = 1.0 / 8192.0 * 100.0 * InstrInfo.PitchbendRange;
# Line 831  namespace LinuxSampler { Line 975  namespace LinuxSampler {
975          // GSt behaviour: maximum transpose up is 40 semitones. If          // GSt behaviour: maximum transpose up is 40 semitones. If
976          // MIDI key is more than 40 semitones above unity note,          // MIDI key is more than 40 semitones above unity note,
977          // the transpose is not done.          // the transpose is not done.
978          if (!SmplInfo.Unpitched && (MIDIKey() - (int) RgnInfo.UnityNote) < 40) pitchbasecents += (MIDIKey() - (int) RgnInfo.UnityNote) * 100;          //
979            // Update: Removed this GSt misbehavior. I don't think that any stock
980            // gig sound requires it to resemble its original sound.
981            // -- Christian, 2017-07-09
982            if (!SmplInfo.Unpitched /* && (MIDIKey() - (int) RgnInfo.UnityNote) < 40*/)
983                pitchbasecents += (MIDIKey() - (int) RgnInfo.UnityNote) * 100;
984                    
985          pitch.PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(SmplInfo.SampleRate) / double(GetEngine()->SampleRate));          pitch.PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(SmplInfo.SampleRate) / double(GetEngine()->SampleRate));
986          this->Pitch = pitch;          this->Pitch = pitch;

Legend:
Removed from v.3054  
changed lines
  Added in v.3724

  ViewVC Help
Powered by ViewVC