/[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 2015 by iliev, Sun Oct 25 22:22:52 2009 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-2009 Christian Schoenebeck                         *   *   Copyright (C) 2005-2020 Christian Schoenebeck                         *
7   *   Copyright (C) 2009 Grigor Iliev                                       *   *   Copyright (C) 2009-2012 Grigor Iliev                                  *
8     *   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 26  Line 27 
27    
28  namespace LinuxSampler {  namespace LinuxSampler {
29    
30      AbstractVoice::AbstractVoice() {      AbstractVoice::AbstractVoice(SignalUnitRack* pRack): pSignalUnitRack(pRack) {
31          pEngineChannel = NULL;          pEngineChannel = NULL;
32          pLFO1 = new LFOUnsigned(1.0f);  // amplitude EG (0..1 range)          pLFO1 = new LFOClusterUnsigned(1.0f);  // amplitude LFO (0..1 range)
33          pLFO2 = new LFOUnsigned(1.0f);  // filter EG (0..1 range)          pLFO2 = new LFOClusterUnsigned(1.0f);  // filter LFO (0..1 range)
34          pLFO3 = new LFOSigned(1200.0f); // pitch EG (-1200..+1200 range)          pLFO3 = new LFOClusterSigned(1200.0f); // pitch LFO (-1200..+1200 range)
35          PlaybackState = playback_state_end;          PlaybackState = playback_state_end;
         KeyGroup = 0;  
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)
38          #if 0 // CONFIG_ASM && ARCH_X86          #if 0 // CONFIG_ASM && ARCH_X86
# Line 44  namespace LinuxSampler { Line 44  namespace LinuxSampler {
44    
45          finalSynthesisParameters.filterLeft.Reset();          finalSynthesisParameters.filterLeft.Reset();
46          finalSynthesisParameters.filterRight.Reset();          finalSynthesisParameters.filterRight.Reset();
47            
48            pEq          = NULL;
49            bEqSupport   = false;
50      }      }
51    
52      AbstractVoice::~AbstractVoice() {      AbstractVoice::~AbstractVoice() {
53          if (pLFO1) delete pLFO1;          if (pLFO1) delete pLFO1;
54          if (pLFO2) delete pLFO2;          if (pLFO2) delete pLFO2;
55          if (pLFO3) delete pLFO3;          if (pLFO3) delete pLFO3;
56            
57            if(pEq != NULL) delete pEq;
58      }      }
59                    
60        void AbstractVoice::CreateEq() {
61            if(!bEqSupport) return;
62            if(pEq != NULL) delete pEq;
63            pEq = new EqSupport;
64            pEq->InitEffect(GetEngine()->pAudioOutputDevice);
65        }
66    
67      /**      /**
68       *  Resets voice variables. Should only be called if rendering process is       *  Resets voice variables. Should only be called if rendering process is
69       *  suspended / not running.       *  suspended / not running.
# Line 99  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 );
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          KeyGroup        = iKeyGroup;          MidiKeyBase* pKeyInfo = GetMidiKeyInfo(MIDIKey());
120    
121            // 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();
136          InstrInfo  = GetInstrumentInfo();          InstrInfo  = GetInstrumentInfo();
137            
138            MIDIPan    = CalculatePan(pEngineChannel->iLastPanRequest);
139    
140            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);          float volume = CalculateVolume(velocityAttenuation) * pKeyInfo->Volume;
145            if (volume <= 0) return -1;
146    
147          // select channel mode (mono or stereo)          // select channel mode (mono or stereo)
148          SYNTHESIS_MODE_SET_CHANNELS(SynthesisMode, SmplInfo.ChannelCount == 2);          SYNTHESIS_MODE_SET_CHANNELS(SynthesisMode, SmplInfo.ChannelCount == 2);
# Line 120  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 * AbstractEngine::PanCurve[64 - RgnInfo.Pan];          VolumeLeft  = volume * pKeyInfo->PanLeft;
156          VolumeRight = volume * AbstractEngine::PanCurve[64 + RgnInfo.Pan];          VolumeRight = volume * pKeyInfo->PanRight;
157    
158          float subfragmentRate = GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;          // this rate is used for rather mellow volume fades
159            const float subfragmentRate = GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;
160            // this rate is used for very fast volume fades
161            const float quickRampRate = RTMath::Min(subfragmentRate, GetEngine()->SampleRate * 0.001f /* approx. 13ms */);
162          CrossfadeSmoother.trigger(crossfadeVolume, subfragmentRate);          CrossfadeSmoother.trigger(crossfadeVolume, subfragmentRate);
         VolumeSmoother.trigger(pEngineChannel->MidiVolume, subfragmentRate);  
         PanLeftSmoother.trigger(pEngineChannel->GlobalPanLeft, subfragmentRate);  
         PanRightSmoother.trigger(pEngineChannel->GlobalPanRight, subfragmentRate);  
163    
164          finalSynthesisParameters.dPos = RgnInfo.SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)          VolumeSmoother.trigger(pEngineChannel->MidiVolume, subfragmentRate);
165          Pos = RgnInfo.SampleStartOffset;          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;
172          DiskVoice          = cachedsamples < SmplInfo.TotalFrameCount;          DiskVoice          = cachedsamples < SmplInfo.TotalFrameCount;
173    
174            SetSampleStartOffset();
175    
176          if (DiskVoice) { // voice to be streamed from disk          if (DiskVoice) { // voice to be streamed from disk
177              if (cachedsamples > (GetEngine()->MaxSamplesPerCycle << CONFIG_MAX_PITCH)) {              if (cachedsamples > (GetEngine()->MaxSamplesPerCycle << CONFIG_MAX_PITCH)) {
178                  MaxRAMPos = cachedsamples - (GetEngine()->MaxSamplesPerCycle << CONFIG_MAX_PITCH) / SmplInfo.ChannelCount; //TODO: this calculation is too pessimistic and may better be moved to Render() method, so it calculates MaxRAMPos dependent to the current demand of sample points to be rendered (e.g. in case of JACK)                  MaxRAMPos = cachedsamples - (GetEngine()->MaxSamplesPerCycle << CONFIG_MAX_PITCH) / SmplInfo.ChannelCount; //TODO: this calculation is too pessimistic and may better be moved to Render() method, so it calculates MaxRAMPos dependent to the current demand of sample points to be rendered (e.g. in case of JACK)
# Line 154  namespace LinuxSampler { Line 189  namespace LinuxSampler {
189              RAMLoop = (SmplInfo.HasLoops && (SmplInfo.LoopStart + SmplInfo.LoopLength) <= MaxRAMPos);              RAMLoop = (SmplInfo.HasLoops && (SmplInfo.LoopStart + SmplInfo.LoopLength) <= MaxRAMPos);
190    
191              if (OrderNewStream()) return -1;              if (OrderNewStream()) return -1;
192              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"));
193          }          }
194          else { // RAM only voice          else { // RAM only voice
195              MaxRAMPos = cachedsamples;              MaxRAMPos = cachedsamples;
# Line 170  namespace LinuxSampler { Line 205  namespace LinuxSampler {
205          }          }
206    
207          Pitch = CalculatePitchInfo(PitchBend);          Pitch = CalculatePitchInfo(PitchBend);
208            NotePitch.setCurveOnly(pNote ? pNote->Override.PitchCurve : DEFAULT_FADE_CURVE);
209            NotePitch.setCurrentValue(pNote ? pNote->Override.Pitch.Value : 1.0f);
210            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          // 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              EG1.trigger (              if (pNote) {
228                  RgnInfo.EG1PreAttack,                  pNote->Override.Attack.applyTo(egInfo.Attack);
229                  RgnInfo.EG1Attack * egInfo.Attack,                  pNote->Override.Decay.applyTo(egInfo.Decay);
230                  RgnInfo.EG1Hold,                  pNote->Override.Release.applyTo(egInfo.Release);
231                  RgnInfo.EG1Decay1 * egInfo.Decay * velrelease,              }
232                  RgnInfo.EG1Decay2 * egInfo.Decay * velrelease,  
233                  RgnInfo.EG1InfiniteSustain,              TriggerEG1(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, MIDIVelocity());
234                  RgnInfo.EG1Sustain,          } else {
235                  RgnInfo.EG1Release * egInfo.Release * velrelease,              pSignalUnitRack->Trigger();
236                  velocityAttenuation,          }
237                  GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE  
238              );          const uint8_t pan = (pSignalUnitRack) ? pSignalUnitRack->GetEndpointUnit()->CalculatePan(MIDIPan) : MIDIPan;
239            for (int c = 0; c < 2; ++c) {
240                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  #ifdef CONFIG_INTERPOLATE_VOLUME          PanLeftSmoother.trigger(
248                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)
250            );
251            PanRightSmoother.trigger(
252                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)
254            );
255    
256    #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 206  namespace LinuxSampler { Line 263  namespace LinuxSampler {
263          else          else
264      #else      #else
265          {          {
266              float finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * EG1.getLevel();              float finalVolume = pEngineChannel->MidiVolume * crossfadeVolume;
267                float fModVolume;
268                if (pSignalUnitRack == NULL) {
269                    fModVolume = pEG1->getLevel();
270                } else {
271                    fModVolume = pSignalUnitRack->GetEndpointUnit()->GetVolume();
272                }
273                NoteVolume.applyCurrentValueTo(fModVolume);
274                finalVolume *= fModVolume;
275    
276                float panL = PanLeftSmoother.render();
277                float panR = PanRightSmoother.render();
278                NotePan[0].applyCurrentValueTo(panL);
279                NotePan[1].applyCurrentValueTo(panR);
280    
281              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * pEngineChannel->GlobalPanLeft;              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * panL;
282              finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * pEngineChannel->GlobalPanRight;              finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * panR;
283          }          }
284      #endif      #endif
285  #endif  #endif
286    
287          // setup EG 2 (VCF Cutoff EG)          if (pSignalUnitRack == NULL) {
288          {              // setup EG 2 (VCF Cutoff EG)
289              // get current value of EG2 controller              {
290              double eg2controllervalue = GetEG2ControllerValue(itNoteOnEvent->Param.Note.Velocity);                  // get current value of EG2 controller
291                    double eg2controllervalue = GetEG2ControllerValue(MIDIVelocity());
292              // calculate influence of EG2 controller on EG2's parameters  
293              EGInfo egInfo = CalculateEG2ControllerInfluence(eg2controllervalue);                  // calculate influence of EG2 controller on EG2's parameters
294                    EGInfo egInfo = CalculateEG2ControllerInfluence(eg2controllervalue);
295    
296                    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              EG2.trigger (                  TriggerEG2(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, MIDIVelocity());
303                  RgnInfo.EG2PreAttack,              }
                 RgnInfo.EG2Attack * egInfo.Attack,  
                 false,  
                 RgnInfo.EG2Decay1 * egInfo.Decay * velrelease,  
                 RgnInfo.EG2Decay2 * egInfo.Decay * velrelease,  
                 RgnInfo.EG2InfiniteSustain,  
                 RgnInfo.EG2Sustain,  
                 RgnInfo.EG2Release * egInfo.Release * velrelease,  
                 velocityAttenuation,  
                 GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE  
             );  
         }  
304    
305    
306          // setup EG 3 (VCO EG)              // setup EG 3 (VCO EG)
307          {              {
308              // 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
309              bool  bPortamento = pEngineChannel->PortamentoMode && pEngineChannel->PortamentoPos >= 0.0f;                  bool  bPortamento = pEngineChannel->PortamentoMode && pEngineChannel->PortamentoPos >= 0.0f;
310              float eg3depth = (bPortamento)                  float eg3depth = (bPortamento)
311                           ? RTMath::CentsToFreqRatio((pEngineChannel->PortamentoPos - (float) MIDIKey) * 100)                               ? RTMath::CentsToFreqRatio((pEngineChannel->PortamentoPos - (float) MIDIKey()) * 100)
312                           : RTMath::CentsToFreqRatio(RgnInfo.EG3Depth);                               : RTMath::CentsToFreqRatio(RgnInfo.EG3Depth);
313              float eg3time = (bPortamento)                  float eg3time = (bPortamento)
314                          ? pEngineChannel->PortamentoTime                              ? pEngineChannel->PortamentoTime
315                          : RgnInfo.EG3Attack;                              : RgnInfo.EG3Attack;
316              EG3.trigger(eg3depth, eg3time, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  EG3.trigger(eg3depth, eg3time, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
317              dmsg(5,("PortamentoPos=%f, depth=%f, time=%f\n", pEngineChannel->PortamentoPos, eg3depth, eg3time));                  dmsg(5,("PortamentoPos=%f, depth=%f, time=%f\n", pEngineChannel->PortamentoPos, eg3depth, eg3time));
318          }              }
319    
320    
321          // setup LFO 1 (VCA LFO)              // setup LFO 1 (VCA LFO)
322          InitLFO1();              InitLFO1();
323          // setup LFO 2 (VCF Cutoff LFO)              // setup LFO 2 (VCF Cutoff LFO)
324          InitLFO2();              InitLFO2();
325          // setup LFO 3 (VCO LFO)              // setup LFO 3 (VCO LFO)
326          InitLFO3();              InitLFO3();
327            }
328    
329    
330          #if CONFIG_FORCE_FILTER          #if CONFIG_FORCE_FILTER
# Line 291  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 302  namespace LinuxSampler { Line 369  namespace LinuxSampler {
369              VCFCutoffCtrl.controller    = 0;              VCFCutoffCtrl.controller    = 0;
370              VCFResonanceCtrl.controller = 0;              VCFResonanceCtrl.controller = 0;
371          }          }
372            
373            const bool bEq =
374                pSignalUnitRack != NULL && pSignalUnitRack->HasEq() && pEq->HasSupport();
375    
376            if (bEq) {
377                pEq->GetInChannelLeft()->Clear();
378                pEq->GetInChannelRight()->Clear();
379                pEq->RenderAudio(GetEngine()->pAudioOutputDevice->MaxSamplesPerCycle());
380            }
381    
382          return 0; // success          return 0; // success
383      }      }
384        
385        void AbstractVoice::SetSampleStartOffset() {
386            double pos = RgnInfo.SampleStartOffset; // offset where we should start playback of sample
387    
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      /**      /**
402       *  Synthesizes the current audio fragment for this voice.       *  Synthesizes the current audio fragment for this voice.
# Line 315  namespace LinuxSampler { Line 407  namespace LinuxSampler {
407       *  @param Skip    - number of sample points to skip in output buffer       *  @param Skip    - number of sample points to skip in output buffer
408       */       */
409      void AbstractVoice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {      void AbstractVoice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {
410            bool delay = false; // Whether the voice playback should be delayed for this call
411            
412            if (pSignalUnitRack != NULL) {
413                uint delaySteps = pSignalUnitRack->GetEndpointUnit()->DelayTrigger();
414                if (delaySteps > 0) { // delay on the endpoint unit means delay of the voice playback
415                    if (delaySteps >= Samples) {
416                        pSignalUnitRack->GetEndpointUnit()->DecreaseDelay(Samples);
417                        delay = true;
418                    } else {
419                        pSignalUnitRack->GetEndpointUnit()->DecreaseDelay(delaySteps);
420                        Samples -= delaySteps;
421                        Skip += delaySteps;
422                    }
423                }
424            }
425            
426          AbstractEngineChannel* pChannel = pEngineChannel;          AbstractEngineChannel* pChannel = pEngineChannel;
427          finalSynthesisParameters.pOutLeft  = &pChannel->pChannelLeft->Buffer()[Skip];          MidiKeyBase* pMidiKeyInfo = GetMidiKeyInfo(MIDIKey());
428          finalSynthesisParameters.pOutRight = &pChannel->pChannelRight->Buffer()[Skip];  
429          finalSynthesisParameters.pSrc      = pSrc;          const bool bVoiceRequiresDedicatedRouting =
430                pEngineChannel->GetFxSendCount() > 0 &&
431                (pMidiKeyInfo->ReverbSend || pMidiKeyInfo->ChorusSend);
432            
433            const bool bEq =
434                pSignalUnitRack != NULL && pSignalUnitRack->HasEq() && pEq->HasSupport();
435    
436            if (bEq) {
437                pEq->GetInChannelLeft()->Clear();
438                pEq->GetInChannelRight()->Clear();
439                finalSynthesisParameters.pOutLeft  = &pEq->GetInChannelLeft()->Buffer()[Skip];
440                finalSynthesisParameters.pOutRight = &pEq->GetInChannelRight()->Buffer()[Skip];
441                pSignalUnitRack->UpdateEqSettings(pEq);
442            } else if (bVoiceRequiresDedicatedRouting) {
443                finalSynthesisParameters.pOutLeft  = &GetEngine()->pDedicatedVoiceChannelLeft->Buffer()[Skip];
444                finalSynthesisParameters.pOutRight = &GetEngine()->pDedicatedVoiceChannelRight->Buffer()[Skip];
445            } else {
446                finalSynthesisParameters.pOutLeft  = &pChannel->pChannelLeft->Buffer()[Skip];
447                finalSynthesisParameters.pOutRight = &pChannel->pChannelRight->Buffer()[Skip];
448            }
449            finalSynthesisParameters.pSrc = pSrc;
450    
451          RTList<Event>::Iterator itCCEvent = pChannel->pEvents->first();          RTList<Event>::Iterator itCCEvent = pChannel->pEvents->first();
452          RTList<Event>::Iterator itNoteEvent;          RTList<Event>::Iterator itNoteEvent;
453          GetFirstEventOnKey(MIDIKey, itNoteEvent);          GetFirstEventOnKey(HostKey(), itNoteEvent);
454    
455            RTList<Event>::Iterator itGroupEvent;
456            if (pGroupEvents && !Orphan) itGroupEvent = pGroupEvents->first();
457    
458          if (itTriggerEvent) { // skip events that happened before this voice was triggered          if (itTriggerEvent) { // skip events that happened before this voice was triggered
459              while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;              while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;
460                while (itGroupEvent && itGroupEvent->FragmentPos() <= Skip) ++itGroupEvent;
461    
462              // we can't simply compare the timestamp here, because note events              // we can't simply compare the timestamp here, because note events
463              // might happen on the same time stamp, so we have to deal on the              // might happen on the same time stamp, so we have to deal on the
464              // actual sequence the note events arrived instead (see bug #112)              // actual sequence the note events arrived instead (see bug #112)
# Line 337  namespace LinuxSampler { Line 470  namespace LinuxSampler {
470              }              }
471          }          }
472    
473          uint killPos;          uint killPos = 0;
474          if (itKillEvent) {          if (itKillEvent) {
475              int maxFadeOutPos = Samples - GetEngine()->GetMinFadeOutSamples();              int maxFadeOutPos = Samples - GetEngine()->GetMinFadeOutSamples();
476              if (maxFadeOutPos < 0) {              if (maxFadeOutPos < 0) {
# Line 346  namespace LinuxSampler { Line 479  namespace LinuxSampler {
479                  // drivers that use Samples < MaxSamplesPerCycle).                  // drivers that use Samples < MaxSamplesPerCycle).
480                  // End the EG1 here, at pos 0, with a shorter max fade                  // End the EG1 here, at pos 0, with a shorter max fade
481                  // out time.                  // out time.
482                  EG1.enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  if (pSignalUnitRack == NULL) {
483                        pEG1->enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
484                    } else {
485                        pSignalUnitRack->EnterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
486                    }
487                  itKillEvent = Pool<Event>::Iterator();                  itKillEvent = Pool<Event>::Iterator();
488              } else {              } else {
489                  killPos = RTMath::Min(itKillEvent->FragmentPos(), maxFadeOutPos);                  killPos = RTMath::Min(itKillEvent->FragmentPos(), maxFadeOutPos);
# Line 361  namespace LinuxSampler { Line 498  namespace LinuxSampler {
498              fFinalCutoff    = VCFCutoffCtrl.fvalue;              fFinalCutoff    = VCFCutoffCtrl.fvalue;
499              fFinalResonance = VCFResonanceCtrl.fvalue;              fFinalResonance = VCFResonanceCtrl.fvalue;
500    
501              // process MIDI control change and pitchbend events for this subfragment              // process MIDI control change, aftertouch and pitchbend events for this subfragment
502              processCCEvents(itCCEvent, iSubFragmentEnd);              processCCEvents(itCCEvent, iSubFragmentEnd);
503                uint8_t pan = MIDIPan;
504                if (pSignalUnitRack != NULL) pan = pSignalUnitRack->GetEndpointUnit()->CalculatePan(MIDIPan);
505    
506                PanLeftSmoother.update(AbstractEngine::PanCurve[128 - pan]);
507                PanRightSmoother.update(AbstractEngine::PanCurve[pan]);
508    
509              finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend;              finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend;
510    
511              float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.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);
519    
520              // if the voice was killed in this subfragment, or if the              float fModVolume = 1;
521              // filter EG is finished, switch EG1 to fade out stage              float fModPitch  = 1;
522              if ((itKillEvent && killPos <= iSubFragmentEnd) ||  
523                  (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&              if (pSignalUnitRack == NULL) {
524                   EG2.getSegmentType() == gig::EGADSR::segment_end)) {                  // if the voice was killed in this subfragment, or if the
525                  EG1.enterFadeOutStage();                  // filter EG is finished, switch EG1 to fade out stage
526                  itKillEvent = Pool<Event>::Iterator();                  if ((itKillEvent && killPos <= iSubFragmentEnd) ||
527                        (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&
528                        pEG2->getSegmentType() == EG::segment_end)) {
529                        pEG1->enterFadeOutStage();
530                        itKillEvent = Pool<Event>::Iterator();
531                    }
532    
533                    // process envelope generators
534                    switch (pEG1->getSegmentType()) {
535                        case EG::segment_lin:
536                            fModVolume *= pEG1->processLin();
537                            break;
538                        case EG::segment_exp:
539                            fModVolume *= pEG1->processExp();
540                            break;
541                        case EG::segment_end:
542                            fModVolume *= pEG1->getLevel();
543                            break; // noop
544                        case EG::segment_pow:
545                            fModVolume *= pEG1->processPow();
546                            break;
547                    }
548                    switch (pEG2->getSegmentType()) {
549                        case EG::segment_lin:
550                            fFinalCutoff *= pEG2->processLin();
551                            break;
552                        case EG::segment_exp:
553                            fFinalCutoff *= pEG2->processExp();
554                            break;
555                        case EG::segment_end:
556                            fFinalCutoff *= pEG2->getLevel();
557                            break; // noop
558                        case EG::segment_pow:
559                            fFinalCutoff *= pEG2->processPow();
560                            break;
561                    }
562                    if (EG3.active()) fModPitch *= EG3.render();
563    
564                    // process low frequency oscillators
565                    if (bLFO1Enabled) fModVolume   *= (1.0f - pLFO1->render());
566                    if (bLFO2Enabled) fFinalCutoff *= (1.0f - pLFO2->render());
567                    if (bLFO3Enabled) fModPitch *= RTMath::CentsToFreqRatio(pLFO3->render());
568                } else {
569                    // if the voice was killed in this subfragment, enter fade out stage
570                    if (itKillEvent && killPos <= iSubFragmentEnd) {
571                        pSignalUnitRack->EnterFadeOutStage();
572                        itKillEvent = Pool<Event>::Iterator();
573                    }
574                    
575                    // if the filter EG is finished, switch EG1 to fade out stage
576                    /*if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&
577                        pEG2->getSegmentType() == EG::segment_end) {
578                        pEG1->enterFadeOutStage();
579                        itKillEvent = Pool<Event>::Iterator();
580                    }*/
581                    // TODO: ^^^
582    
583                    fFinalVolume   *= pSignalUnitRack->GetEndpointUnit()->GetVolume();
584                    fFinalCutoff    = pSignalUnitRack->GetEndpointUnit()->CalculateFilterCutoff(fFinalCutoff);
585                    fFinalResonance = pSignalUnitRack->GetEndpointUnit()->CalculateResonance(fFinalResonance);
586                    
587                    fModPitch = pSignalUnitRack->GetEndpointUnit()->CalculatePitch(fModPitch);
588              }              }
589    
590              // process envelope generators              NoteVolume.renderApplyTo(fModVolume);
591              switch (EG1.getSegmentType()) {              NotePitch.renderApplyTo(fModPitch);
592                  case gig::EGADSR::segment_lin:              NoteCutoff.applyTo(fFinalCutoff);
593                      fFinalVolume *= EG1.processLin();              NoteResonance.applyTo(fFinalResonance);
594                      break;  
595                  case gig::EGADSR::segment_exp:              fFinalVolume *= fModVolume;
596                      fFinalVolume *= EG1.processExp();  
597                      break;              finalSynthesisParameters.fFinalPitch *= fModPitch;
                 case gig::EGADSR::segment_end:  
                     fFinalVolume *= EG1.getLevel();  
                     break; // noop  
             }  
             switch (EG2.getSegmentType()) {  
                 case gig::EGADSR::segment_lin:  
                     fFinalCutoff *= EG2.processLin();  
                     break;  
                 case gig::EGADSR::segment_exp:  
                     fFinalCutoff *= EG2.processExp();  
                     break;  
                 case gig::EGADSR::segment_end:  
                     fFinalCutoff *= EG2.getLevel();  
                     break; // noop  
             }  
             if (EG3.active()) finalSynthesisParameters.fFinalPitch *= EG3.render();  
   
             // process low frequency oscillators  
             if (bLFO1Enabled) fFinalVolume *= (1.0f - pLFO1->render());  
             if (bLFO2Enabled) fFinalCutoff *= pLFO2->render();  
             if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());  
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 430  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              RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);              if (!delay) RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);
638    
639              // stop the rendering if volume EG is finished              if (pSignalUnitRack == NULL) {
640              if (EG1.getSegmentType() == gig::EGADSR::segment_end) break;                  // stop the rendering if volume EG is finished
641                    if (pEG1->getSegmentType() == EG::segment_end) break;
642                } else {
643                    // stop the rendering if the endpoint unit is not active
644                    if (!pSignalUnitRack->GetEndpointUnit()->Active()) break;
645                }
646    
647              const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;              const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;
648    
649              // increment envelopes' positions              if (pSignalUnitRack == NULL) {
650              if (EG1.active()) {                  // increment envelopes' positions
651                    if (pEG1->active()) {
652    
653                        // if sample has a loop and loop start has been reached in this subfragment, send a special event to EG1 to let it finish the attack hold stage
654                        if (SmplInfo.HasLoops && Pos <= SmplInfo.LoopStart && SmplInfo.LoopStart < newPos) {
655                            pEG1->update(EG::event_hold_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
656                        }
657    
658                  // if sample has a loop and loop start has been reached in this subfragment, send a special event to EG1 to let it finish the attack hold stage                      pEG1->increment(1);
659                  if (SmplInfo.HasLoops && Pos <= SmplInfo.LoopStart && SmplInfo.LoopStart < newPos) {                      if (!pEG1->toStageEndLeft()) pEG1->update(EG::event_stage_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
                     EG1.update(gig::EGADSR::event_hold_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);  
660                  }                  }
661                    if (pEG2->active()) {
662                  EG1.increment(1);                      pEG2->increment(1);
663                  if (!EG1.toStageEndLeft()) EG1.update(gig::EGADSR::event_stage_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                      if (!pEG2->toStageEndLeft()) pEG2->update(EG::event_stage_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
664              }                  }
665              if (EG2.active()) {                  EG3.increment(1);
666                  EG2.increment(1);                  if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached
667                  if (!EG2.toStageEndLeft()) EG2.update(gig::EGADSR::event_stage_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);              } else {
668                        // if sample has a loop and loop start has been reached in this subfragment, send a special event to EG1 to let it finish the attack hold stage
669                        /*if (SmplInfo.HasLoops && Pos <= SmplInfo.LoopStart && SmplInfo.LoopStart < newPos) {
670                            pEG1->update(EG::event_hold_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
671                        }*/
672                    // TODO: ^^^
673                    
674                    if (!delay) pSignalUnitRack->Increment();
675              }              }
             EG3.increment(1);  
             if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached  
676    
677              Pos = newPos;              Pos = newPos;
678              i = iSubFragmentEnd;              i = iSubFragmentEnd;
679          }          }
680            
681            if (delay) return;
682    
683            if (bVoiceRequiresDedicatedRouting) {
684                if (bEq) {
685                    pEq->RenderAudio(Samples);
686                    pEq->GetOutChannelLeft()->CopyTo(GetEngine()->pDedicatedVoiceChannelLeft, Samples);
687                    pEq->GetOutChannelRight()->CopyTo(GetEngine()->pDedicatedVoiceChannelRight, Samples);
688                }
689                optional<float> effectSendLevels[2] = {
690                    pMidiKeyInfo->ReverbSend,
691                    pMidiKeyInfo->ChorusSend
692                };
693                GetEngine()->RouteDedicatedVoiceChannels(pEngineChannel, effectSendLevels, Samples);
694            } else if (bEq) {
695                pEq->RenderAudio(Samples);
696                pEq->GetOutChannelLeft()->MixTo(pChannel->pChannelLeft, Samples);
697                pEq->GetOutChannelRight()->MixTo(pChannel->pChannelRight, Samples);
698            }
699      }      }
700        
701      /**      /**
702       * Process given list of MIDI control change and pitch bend events for       * Process given list of MIDI control change, aftertouch and pitch bend
703       * the given time.       * events for the given time.
704       *       *
705       * @param itEvent - iterator pointing to the next event to be processed       * @param itEvent - iterator pointing to the next event to be processed
706       * @param End     - youngest time stamp where processing should be stopped       * @param End     - youngest time stamp where processing should be stopped
707       */       */
708      void AbstractVoice::processCCEvents(RTList<Event>::Iterator& itEvent, uint End) {      void AbstractVoice::processCCEvents(RTList<Event>::Iterator& itEvent, uint End) {
709          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
710              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)
711                    && itEvent->Param.CC.Controller) // if (valid) MIDI control change event
712                {
713                  if (itEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {                  if (itEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {
714                      ProcessCutoffEvent(itEvent);                      ProcessCutoffEvent(itEvent);
715                  }                  }
716                  if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {                  if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {
717                      processResonanceEvent(itEvent);                      processResonanceEvent(itEvent);
718                  }                  }
719                  if (itEvent->Param.CC.Controller == pLFO1->ExtController) {                  if (itEvent->Param.CC.Controller == CTRL_TABLE_IDX_AFTERTOUCH ||
720                      pLFO1->update(itEvent->Param.CC.Value);                      itEvent->Type == Event::type_channel_pressure)
721                  }                  {
722                  if (itEvent->Param.CC.Controller == pLFO2->ExtController) {                      ProcessChannelPressureEvent(itEvent);
                     pLFO2->update(itEvent->Param.CC.Value);  
723                  }                  }
724                  if (itEvent->Param.CC.Controller == pLFO3->ExtController) {                  if (pSignalUnitRack == NULL) {
725                      pLFO3->update(itEvent->Param.CC.Value);                      if (itEvent->Param.CC.Controller == pLFO1->ExtController) {
726                            pLFO1->updateByMIDICtrlValue(itEvent->Param.CC.Value);
727                        }
728                        if (itEvent->Param.CC.Controller == pLFO2->ExtController) {
729                            pLFO2->updateByMIDICtrlValue(itEvent->Param.CC.Value);
730                        }
731                        if (itEvent->Param.CC.Controller == pLFO3->ExtController) {
732                            pLFO3->updateByMIDICtrlValue(itEvent->Param.CC.Value);
733                        }
734                  }                  }
735                  if (itEvent->Param.CC.Controller == 7) { // volume                  if (itEvent->Param.CC.Controller == 7) { // volume
736                      VolumeSmoother.update(AbstractEngine::VolumeCurve[itEvent->Param.CC.Value]);                      VolumeSmoother.update(AbstractEngine::VolumeCurve[itEvent->Param.CC.Value]);
737                  } else if (itEvent->Param.CC.Controller == 10) { // panpot                  } else if (itEvent->Param.CC.Controller == 10) { // panpot
738                      PanLeftSmoother.update(AbstractEngine::PanCurve[128 - itEvent->Param.CC.Value]);                      MIDIPan = CalculatePan(itEvent->Param.CC.Value);
                     PanRightSmoother.update(AbstractEngine::PanCurve[itEvent->Param.CC.Value]);  
739                  }                  }
740              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event
741                  processPitchEvent(itEvent);                  processPitchEvent(itEvent);
742                } else if (itEvent->Type == Event::type_note_pressure) {
743                    ProcessPolyphonicKeyPressureEvent(itEvent);
744              }              }
745    
746              ProcessCCEvent(itEvent);              ProcessCCEvent(itEvent);
747                if (pSignalUnitRack != NULL) {
748                    pSignalUnitRack->ProcessCCEvent(itEvent);
749                }
750          }          }
751      }      }
752    
# Line 528  namespace LinuxSampler { Line 765  namespace LinuxSampler {
765      }      }
766    
767      /**      /**
768       * 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
769       * for the given time.       * note synthesis parameter events for the given time.
770       *       *
771       * @param itEvent - iterator pointing to the next event to be processed       * @param itEvent - iterator pointing to the next event to be processed
772       * @param End     - youngest time stamp where processing should be stopped       * @param End     - youngest time stamp where processing should be stopped
773       */       */
774      void AbstractVoice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) {      void AbstractVoice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) {
775          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
776              if (itEvent->Type == Event::type_release) {              // some voice types ignore note off
777                  EG1.update(gig::EGADSR::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);              if (!(Type & (Voice::type_one_shot | Voice::type_release_trigger | Voice::type_controller_triggered))) {
778                  EG2.update(gig::EGADSR::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  if (itEvent->Type == Event::type_release_key) {
779              } else if (itEvent->Type == Event::type_cancel_release) {                      EnterReleaseStage();
780                  EG1.update(gig::EGADSR::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                  } else if (itEvent->Type == Event::type_cancel_release_key) {
781                  EG2.update(gig::EGADSR::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                      if (pSignalUnitRack == NULL) {
782                            pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
783                            pEG2->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
784                        } else {
785                            pSignalUnitRack->CancelRelease();
786                        }
787                    }
788                }
789                // process stop-note events (caused by built-in instrument script function note_off())
790                if (itEvent->Type == Event::type_release_note && pNote &&
791                    pEngineChannel->pEngine->NoteByID( itEvent->Param.Note.ID ) == pNote)
792                {
793                    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)
802                if (itEvent->Type == Event::type_note_synth_param && pNote &&
803                    pEngineChannel->pEngine->NoteByID( itEvent->Param.NoteSynthParam.NoteID ) == pNote)
804                {
805                    switch (itEvent->Param.NoteSynthParam.Type) {
806                        case Event::synth_param_volume:
807                            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;
816                        case Event::synth_param_pitch:
817                            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;
826                        case Event::synth_param_pan:
827                            NotePan[0].fadeTo(
828                                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;
846                        case Event::synth_param_cutoff:
847                            NoteCutoff.Value = itEvent->Param.NoteSynthParam.AbsValue;
848                            NoteCutoff.Final = itEvent->Param.NoteSynthParam.isFinal();
849                            break;
850                        case Event::synth_param_resonance:
851                            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;
887    
888                        case Event::synth_param_attack:
889                        case Event::synth_param_decay:
890                        case Event::synth_param_sustain:
891                        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
897                    }
898                }
899            }
900        }
901    
902        /**
903         * Process given list of events aimed at all voices in a key group.
904         *
905         * @param itEvent - iterator pointing to the next event to be processed
906         * @param End     - youngest time stamp where processing should be stopped
907         */
908        void AbstractVoice::processGroupEvents(RTList<Event>::Iterator& itEvent, uint End) {
909            for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
910                ProcessGroupEvent(itEvent);
911          }          }
912      }      }
913    
# Line 555  namespace LinuxSampler { Line 920  namespace LinuxSampler {
920       * @param itNoteOffEvent - event which causes this voice to die soon       * @param itNoteOffEvent - event which causes this voice to die soon
921       */       */
922      void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {      void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {
923          const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());          if (pSignalUnitRack == NULL) {
924          pEngineChannel->PortamentoPos = (float) MIDIKey + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;              const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());
925                pEngineChannel->PortamentoPos = (float) MIDIKey() + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;
926            } else {
927                // TODO:
928            }
929      }      }
930    
931      /**      /**
# Line 580  namespace LinuxSampler { Line 949  namespace LinuxSampler {
949    
950      Voice::PitchInfo AbstractVoice::CalculatePitchInfo(int PitchBend) {      Voice::PitchInfo AbstractVoice::CalculatePitchInfo(int PitchBend) {
951          PitchInfo pitch;          PitchInfo pitch;
952          double pitchbasecents = InstrInfo.FineTune + RgnInfo.FineTune + GetEngine()->ScaleTuning[MIDIKey % 12];          double pitchbasecents = InstrInfo.FineTune + RgnInfo.FineTune + GetEngine()->ScaleTuning[MIDIKey() % 12];
953    
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 593  namespace LinuxSampler { Line 967  namespace LinuxSampler {
967    
968          return pitch;          return pitch;
969      }      }
970        
971        void AbstractVoice::onScaleTuningChanged() {
972            PitchInfo pitch = this->Pitch;
973            double pitchbasecents = InstrInfo.FineTune + RgnInfo.FineTune + GetEngine()->ScaleTuning[MIDIKey() % 12];
974            
975            // GSt behaviour: maximum transpose up is 40 semitones. If
976            // MIDI key is more than 40 semitones above unity note,
977            // the transpose is not done.
978            //
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));
986            this->Pitch = pitch;
987        }
988    
989      double AbstractVoice::CalculateVolume(double velocityAttenuation) {      double AbstractVoice::CalculateVolume(double velocityAttenuation) {
990          // For 16 bit samples, we downscale by 32768 to convert from          // For 16 bit samples, we downscale by 32768 to convert from
# Line 603  namespace LinuxSampler { Line 995  namespace LinuxSampler {
995          volume *= GetSampleAttenuation() * pEngineChannel->GlobalVolume * GLOBAL_VOLUME;          volume *= GetSampleAttenuation() * pEngineChannel->GlobalVolume * GLOBAL_VOLUME;
996    
997          // the volume of release triggered samples depends on note length          // the volume of release triggered samples depends on note length
998          if (Type == Voice::type_release_trigger) {          if (Type & Voice::type_release_trigger) {
999              float noteLength = float(GetEngine()->FrameTime + Delay -              float noteLength = float(GetEngine()->FrameTime + Delay -
1000                  GetNoteOnTime(MIDIKey) ) / GetEngine()->SampleRate;                  GetNoteOnTime(MIDIKey()) ) / GetEngine()->SampleRate;
1001    
1002              float attenuation = 1 - 0.01053 * (256 >> RgnInfo.ReleaseTriggerDecay) * noteLength;              volume *= GetReleaseTriggerAttenuation(noteLength);
             if (attenuation <= 0) return -1;  
             volume *= attenuation;  
1003          }          }
1004    
1005          return volume;          return volume;
1006      }      }
1007    
1008        float AbstractVoice::GetReleaseTriggerAttenuation(float noteLength) {
1009            return 1 - RgnInfo.ReleaseTriggerDecay * noteLength;
1010        }
1011    
1012        void AbstractVoice::EnterReleaseStage() {
1013            if (pSignalUnitRack == NULL) {
1014                pEG1->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
1015                pEG2->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
1016            } else {
1017                pSignalUnitRack->EnterReleaseStage();
1018            }
1019        }
1020    
1021        bool AbstractVoice::EG1Finished() {
1022            if (pSignalUnitRack == NULL) {
1023                return pEG1->getSegmentType() == EG::segment_end;
1024            } else {
1025                return !pSignalUnitRack->GetEndpointUnit()->Active();
1026            }
1027        }
1028    
1029  } // namespace LinuxSampler  } // namespace LinuxSampler

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

  ViewVC Help
Powered by ViewVC