/[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 2217 by iliev, Tue Jul 26 15:51:30 2011 UTC revision 3054 by schoenebeck, Thu Dec 15 12:47:45 2016 UTC
# Line 4  Line 4 
4   *                                                                         *   *                                                                         *
5   *   Copyright (C) 2003,2004 by Benno Senoner and Christian Schoenebeck    *   *   Copyright (C) 2003,2004 by Benno Senoner and Christian Schoenebeck    *
6   *   Copyright (C) 2005-2008 Christian Schoenebeck                         *   *   Copyright (C) 2005-2008 Christian Schoenebeck                         *
7   *   Copyright (C) 2009-2011 Christian Schoenebeck and Grigor Iliev        *   *   Copyright (C) 2009-2012 Christian Schoenebeck and Grigor Iliev        *
8     *   Copyright (C) 2013-2016 Christian Schoenebeck and Andreas Persson     *
9   *                                                                         *   *                                                                         *
10   *   This program is free software; you can redistribute it and/or modify  *   *   This program is free software; you can redistribute it and/or modify  *
11   *   it under the terms of the GNU General Public License as published by  *   *   it under the terms of the GNU General Public License as published by  *
# Line 43  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      /**      /**
# Line 98  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          MidiKeyBase* pKeyInfo = GetMidiKeyInfo(MIDIKey);          MidiKeyBase* pKeyInfo = GetMidiKeyInfo(MIDIKey());
120    
121          pGroupEvents = iKeyGroup ? pEngineChannel->ActiveKeyGroups[iKeyGroup] : 0;          pGroupEvents = iKeyGroup ? pEngineChannel->ActiveKeyGroups[iKeyGroup] : 0;
122    
# Line 111  namespace LinuxSampler { Line 124  namespace LinuxSampler {
124          RgnInfo    = GetRegionInfo();          RgnInfo    = GetRegionInfo();
125          InstrInfo  = GetInstrumentInfo();          InstrInfo  = GetInstrumentInfo();
126                    
127            MIDIPan    = CalculatePan(pEngineChannel->iLastPanRequest);
128    
129          AboutToTrigger();          AboutToTrigger();
130    
131          // calculate volume          // calculate volume
# Line 126  namespace LinuxSampler { Line 141  namespace LinuxSampler {
141          // get starting crossfade volume level          // get starting crossfade volume level
142          float crossfadeVolume = CalculateCrossfadeVolume(itNoteOnEvent->Param.Note.Velocity);          float crossfadeVolume = CalculateCrossfadeVolume(itNoteOnEvent->Param.Note.Velocity);
143    
144          VolumeLeft  = volume * pKeyInfo->PanLeft  * AbstractEngine::PanCurve[64 - RgnInfo.Pan];          VolumeLeft  = volume * pKeyInfo->PanLeft;
145          VolumeRight = volume * pKeyInfo->PanRight * AbstractEngine::PanCurve[64 + RgnInfo.Pan];          VolumeRight = volume * pKeyInfo->PanRight;
146    
147          float subfragmentRate = GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;          // this rate is used for rather mellow volume fades
148            const float subfragmentRate = GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;
149            // this rate is used for very fast volume fades
150            const float quickRampRate = RTMath::Min(subfragmentRate, GetEngine()->SampleRate * 0.001f /* 1ms */);
151          CrossfadeSmoother.trigger(crossfadeVolume, subfragmentRate);          CrossfadeSmoother.trigger(crossfadeVolume, subfragmentRate);
152    
153          VolumeSmoother.trigger(pEngineChannel->MidiVolume, subfragmentRate);          VolumeSmoother.trigger(pEngineChannel->MidiVolume, subfragmentRate);
154          PanLeftSmoother.trigger(pEngineChannel->GlobalPanLeft, subfragmentRate);          NoteVolumeSmoother.trigger(pNote ? pNote->Override.Volume : 1.f, quickRampRate);
         PanRightSmoother.trigger(pEngineChannel->GlobalPanRight, subfragmentRate);  
155    
156          // 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
157          long cachedsamples = GetSampleCacheSize() / SmplInfo.FrameSize;          long cachedsamples = GetSampleCacheSize() / SmplInfo.FrameSize;
# Line 157  namespace LinuxSampler { Line 175  namespace LinuxSampler {
175              RAMLoop = (SmplInfo.HasLoops && (SmplInfo.LoopStart + SmplInfo.LoopLength) <= MaxRAMPos);              RAMLoop = (SmplInfo.HasLoops && (SmplInfo.LoopStart + SmplInfo.LoopLength) <= MaxRAMPos);
176    
177              if (OrderNewStream()) return -1;              if (OrderNewStream()) return -1;
178              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"));
179          }          }
180          else { // RAM only voice          else { // RAM only voice
181              MaxRAMPos = cachedsamples;              MaxRAMPos = cachedsamples;
# Line 173  namespace LinuxSampler { Line 191  namespace LinuxSampler {
191          }          }
192    
193          Pitch = CalculatePitchInfo(PitchBend);          Pitch = CalculatePitchInfo(PitchBend);
194            NotePitch = (pNote) ? pNote->Override.Pitch : 1.0f;
195            NoteCutoff = (pNote) ? pNote->Override.Cutoff : 1.0f;
196            NoteResonance = (pNote) ? pNote->Override.Resonance : 1.0f;
197    
198          // 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
199          const double velrelease = 1 / GetVelocityRelease(itNoteOnEvent->Param.Note.Velocity);          const double velrelease = 1 / GetVelocityRelease(itNoteOnEvent->Param.Note.Velocity);
# Line 184  namespace LinuxSampler { Line 205  namespace LinuxSampler {
205              // calculate influence of EG1 controller on EG1's parameters              // calculate influence of EG1 controller on EG1's parameters
206              EGInfo egInfo = CalculateEG1ControllerInfluence(eg1controllervalue);              EGInfo egInfo = CalculateEG1ControllerInfluence(eg1controllervalue);
207    
208                if (pNote) {
209                    egInfo.Attack  *= pNote->Override.Attack;
210                    egInfo.Decay   *= pNote->Override.Decay;
211                    egInfo.Release *= pNote->Override.Release;
212                }
213    
214              TriggerEG1(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity);              TriggerEG1(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity);
215          } else {          } else {
216              pSignalUnitRack->Trigger();              pSignalUnitRack->Trigger();
217          }          }
218    
219            const uint8_t pan = (pSignalUnitRack) ? pSignalUnitRack->GetEndpointUnit()->CalculatePan(MIDIPan) : MIDIPan;
220            NotePanLeft  = (pNote) ? AbstractEngine::PanCurveValueNorm(pNote->Override.Pan, 0 /*left*/ ) : 1.f;
221            NotePanRight = (pNote) ? AbstractEngine::PanCurveValueNorm(pNote->Override.Pan, 1 /*right*/) : 1.f;
222            PanLeftSmoother.trigger(
223                AbstractEngine::PanCurve[128 - pan] * NotePanLeft,
224                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)
225            );
226            PanRightSmoother.trigger(
227                AbstractEngine::PanCurve[pan] * NotePanRight,
228                quickRampRate //NOTE: maybe we should have 2 separate pan smoothers, one for MIDI CC10 (with slow rate) and one for instrument script change_pan() calls (with fast rate)
229            );
230    
231  #ifdef CONFIG_INTERPOLATE_VOLUME  #ifdef CONFIG_INTERPOLATE_VOLUME
232          // setup initial volume in synthesis parameters          // setup initial volume in synthesis parameters
233      #ifdef CONFIG_PROCESS_MUTED_CHANNELS      #ifdef CONFIG_PROCESS_MUTED_CHANNELS
# Line 206  namespace LinuxSampler { Line 245  namespace LinuxSampler {
245                  finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pSignalUnitRack->GetEndpointUnit()->GetVolume();                  finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pSignalUnitRack->GetEndpointUnit()->GetVolume();
246              }              }
247    
248              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * pEngineChannel->GlobalPanLeft;              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * PanLeftSmoother.render();
249              finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * pEngineChannel->GlobalPanRight;              finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * PanRightSmoother.render();
250          }          }
251      #endif      #endif
252  #endif  #endif
# Line 230  namespace LinuxSampler { Line 269  namespace LinuxSampler {
269                  // 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
270                  bool  bPortamento = pEngineChannel->PortamentoMode && pEngineChannel->PortamentoPos >= 0.0f;                  bool  bPortamento = pEngineChannel->PortamentoMode && pEngineChannel->PortamentoPos >= 0.0f;
271                  float eg3depth = (bPortamento)                  float eg3depth = (bPortamento)
272                               ? RTMath::CentsToFreqRatio((pEngineChannel->PortamentoPos - (float) MIDIKey) * 100)                               ? RTMath::CentsToFreqRatio((pEngineChannel->PortamentoPos - (float) MIDIKey()) * 100)
273                               : RTMath::CentsToFreqRatio(RgnInfo.EG3Depth);                               : RTMath::CentsToFreqRatio(RgnInfo.EG3Depth);
274                  float eg3time = (bPortamento)                  float eg3time = (bPortamento)
275                              ? pEngineChannel->PortamentoTime                              ? pEngineChannel->PortamentoTime
# Line 291  namespace LinuxSampler { Line 330  namespace LinuxSampler {
330              VCFCutoffCtrl.controller    = 0;              VCFCutoffCtrl.controller    = 0;
331              VCFResonanceCtrl.controller = 0;              VCFResonanceCtrl.controller = 0;
332          }          }
333            
334            const bool bEq =
335                pSignalUnitRack != NULL && pSignalUnitRack->HasEq() && pEq->HasSupport();
336    
337            if (bEq) {
338                pEq->GetInChannelLeft()->Clear();
339                pEq->GetInChannelRight()->Clear();
340                pEq->RenderAudio(GetEngine()->pAudioOutputDevice->MaxSamplesPerCycle());
341            }
342    
343          return 0; // success          return 0; // success
344      }      }
# Line 309  namespace LinuxSampler { Line 357  namespace LinuxSampler {
357       *  @param Skip    - number of sample points to skip in output buffer       *  @param Skip    - number of sample points to skip in output buffer
358       */       */
359      void AbstractVoice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {      void AbstractVoice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {
360            bool delay = false; // Whether the voice playback should be delayed for this call
361            
362            if (pSignalUnitRack != NULL) {
363                uint delaySteps = pSignalUnitRack->GetEndpointUnit()->DelayTrigger();
364                if (delaySteps > 0) { // delay on the endpoint unit means delay of the voice playback
365                    if (delaySteps >= Samples) {
366                        pSignalUnitRack->GetEndpointUnit()->DecreaseDelay(Samples);
367                        delay = true;
368                    } else {
369                        pSignalUnitRack->GetEndpointUnit()->DecreaseDelay(delaySteps);
370                        Samples -= delaySteps;
371                        Skip += delaySteps;
372                    }
373                }
374            }
375            
376          AbstractEngineChannel* pChannel = pEngineChannel;          AbstractEngineChannel* pChannel = pEngineChannel;
377          MidiKeyBase* pMidiKeyInfo = GetMidiKeyInfo(MIDIKey);          MidiKeyBase* pMidiKeyInfo = GetMidiKeyInfo(MIDIKey());
378    
379          const bool bVoiceRequiresDedicatedRouting =          const bool bVoiceRequiresDedicatedRouting =
380              pEngineChannel->GetFxSendCount() > 0 &&              pEngineChannel->GetFxSendCount() > 0 &&
381              (pMidiKeyInfo->ReverbSend || pMidiKeyInfo->ChorusSend);              (pMidiKeyInfo->ReverbSend || pMidiKeyInfo->ChorusSend);
382            
383            const bool bEq =
384                pSignalUnitRack != NULL && pSignalUnitRack->HasEq() && pEq->HasSupport();
385    
386          if (bVoiceRequiresDedicatedRouting) {          if (bEq) {
387                pEq->GetInChannelLeft()->Clear();
388                pEq->GetInChannelRight()->Clear();
389                finalSynthesisParameters.pOutLeft  = &pEq->GetInChannelLeft()->Buffer()[Skip];
390                finalSynthesisParameters.pOutRight = &pEq->GetInChannelRight()->Buffer()[Skip];
391                pSignalUnitRack->UpdateEqSettings(pEq);
392            } else if (bVoiceRequiresDedicatedRouting) {
393              finalSynthesisParameters.pOutLeft  = &GetEngine()->pDedicatedVoiceChannelLeft->Buffer()[Skip];              finalSynthesisParameters.pOutLeft  = &GetEngine()->pDedicatedVoiceChannelLeft->Buffer()[Skip];
394              finalSynthesisParameters.pOutRight = &GetEngine()->pDedicatedVoiceChannelRight->Buffer()[Skip];              finalSynthesisParameters.pOutRight = &GetEngine()->pDedicatedVoiceChannelRight->Buffer()[Skip];
395          } else {          } else {
# Line 327  namespace LinuxSampler { Line 400  namespace LinuxSampler {
400    
401          RTList<Event>::Iterator itCCEvent = pChannel->pEvents->first();          RTList<Event>::Iterator itCCEvent = pChannel->pEvents->first();
402          RTList<Event>::Iterator itNoteEvent;          RTList<Event>::Iterator itNoteEvent;
403          GetFirstEventOnKey(MIDIKey, itNoteEvent);          GetFirstEventOnKey(HostKey(), itNoteEvent);
404    
405          RTList<Event>::Iterator itGroupEvent;          RTList<Event>::Iterator itGroupEvent;
406          if (pGroupEvents) itGroupEvent = pGroupEvents->first();          if (pGroupEvents && !Orphan) itGroupEvent = pGroupEvents->first();
407    
408          if (itTriggerEvent) { // skip events that happened before this voice was triggered          if (itTriggerEvent) { // skip events that happened before this voice was triggered
409              while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;              while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;
# Line 347  namespace LinuxSampler { Line 420  namespace LinuxSampler {
420              }              }
421          }          }
422    
423          uint killPos;          uint killPos = 0;
424          if (itKillEvent) {          if (itKillEvent) {
425              int maxFadeOutPos = Samples - GetEngine()->GetMinFadeOutSamples();              int maxFadeOutPos = Samples - GetEngine()->GetMinFadeOutSamples();
426              if (maxFadeOutPos < 0) {              if (maxFadeOutPos < 0) {
# Line 359  namespace LinuxSampler { Line 432  namespace LinuxSampler {
432                  if (pSignalUnitRack == NULL) {                  if (pSignalUnitRack == NULL) {
433                      pEG1->enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                      pEG1->enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
434                  } else {                  } else {
435                      // TODO:                      pSignalUnitRack->EnterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
436                  }                  }
437                  itKillEvent = Pool<Event>::Iterator();                  itKillEvent = Pool<Event>::Iterator();
438              } else {              } else {
# Line 375  namespace LinuxSampler { Line 448  namespace LinuxSampler {
448              fFinalCutoff    = VCFCutoffCtrl.fvalue;              fFinalCutoff    = VCFCutoffCtrl.fvalue;
449              fFinalResonance = VCFResonanceCtrl.fvalue;              fFinalResonance = VCFResonanceCtrl.fvalue;
450    
451              // process MIDI control change and pitchbend events for this subfragment              // process MIDI control change, aftertouch and pitchbend events for this subfragment
452              processCCEvents(itCCEvent, iSubFragmentEnd);              processCCEvents(itCCEvent, iSubFragmentEnd);
453                uint8_t pan = MIDIPan;
454                if (pSignalUnitRack != NULL) pan = pSignalUnitRack->GetEndpointUnit()->CalculatePan(MIDIPan);
455    
456                PanLeftSmoother.update(AbstractEngine::PanCurve[128 - pan] * NotePanLeft);
457                PanRightSmoother.update(AbstractEngine::PanCurve[pan]      * NotePanRight);
458    
459                finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend * NotePitch;
460    
461              finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend;              float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render() * NoteVolumeSmoother.render();
             float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render();  
462  #ifdef CONFIG_PROCESS_MUTED_CHANNELS  #ifdef CONFIG_PROCESS_MUTED_CHANNELS
463              if (pChannel->GetMute()) fFinalVolume = 0;              if (pChannel->GetMute()) fFinalVolume = 0;
464  #endif  #endif
# Line 387  namespace LinuxSampler { Line 466  namespace LinuxSampler {
466              // process transition events (note on, note off & sustain pedal)              // process transition events (note on, note off & sustain pedal)
467              processTransitionEvents(itNoteEvent, iSubFragmentEnd);              processTransitionEvents(itNoteEvent, iSubFragmentEnd);
468              processGroupEvents(itGroupEvent, iSubFragmentEnd);              processGroupEvents(itGroupEvent, iSubFragmentEnd);
469                
470              if (pSignalUnitRack == NULL) {              if (pSignalUnitRack == NULL) {
471                  // if the voice was killed in this subfragment, or if the                  // if the voice was killed in this subfragment, or if the
472                  // filter EG is finished, switch EG1 to fade out stage                  // filter EG is finished, switch EG1 to fade out stage
# Line 431  namespace LinuxSampler { Line 510  namespace LinuxSampler {
510    
511                  // process low frequency oscillators                  // process low frequency oscillators
512                  if (bLFO1Enabled) fFinalVolume *= (1.0f - pLFO1->render());                  if (bLFO1Enabled) fFinalVolume *= (1.0f - pLFO1->render());
513                  if (bLFO2Enabled) fFinalCutoff *= pLFO2->render();                  if (bLFO2Enabled) fFinalCutoff *= (1.0f - pLFO2->render());
514                  if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());                  if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());
515              } else {              } else {
516                  // if the voice was killed in this subfragment, or if the                  // if the voice was killed in this subfragment, enter fade out stage
517                  // filter EG is finished, switch EG1 to fade out stage                  if (itKillEvent && killPos <= iSubFragmentEnd) {
518                  /*if ((itKillEvent && killPos <= iSubFragmentEnd) ||                      pSignalUnitRack->EnterFadeOutStage();
519                      (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&                      itKillEvent = Pool<Event>::Iterator();
520                      pEG2->getSegmentType() == EG::segment_end)) {                  }
521                    
522                    // if the filter EG is finished, switch EG1 to fade out stage
523                    /*if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&
524                        pEG2->getSegmentType() == EG::segment_end) {
525                      pEG1->enterFadeOutStage();                      pEG1->enterFadeOutStage();
526                      itKillEvent = Pool<Event>::Iterator();                      itKillEvent = Pool<Event>::Iterator();
527                  }*/                  }*/
# Line 452  namespace LinuxSampler { Line 535  namespace LinuxSampler {
535                      pSignalUnitRack->GetEndpointUnit()->CalculatePitch(finalSynthesisParameters.fFinalPitch);                      pSignalUnitRack->GetEndpointUnit()->CalculatePitch(finalSynthesisParameters.fFinalPitch);
536                                            
537              }              }
538                
539                fFinalCutoff    *= NoteCutoff;
540                fFinalResonance *= NoteResonance;
541    
542              // limit the pitch so we don't read outside the buffer              // limit the pitch so we don't read outside the buffer
543              finalSynthesisParameters.fFinalPitch = RTMath::Min(finalSynthesisParameters.fFinalPitch, float(1 << CONFIG_MAX_PITCH));              finalSynthesisParameters.fFinalPitch = RTMath::Min(finalSynthesisParameters.fFinalPitch, float(1 << CONFIG_MAX_PITCH));
544    
# Line 485  namespace LinuxSampler { Line 571  namespace LinuxSampler {
571                  fFinalVolume * VolumeRight * PanRightSmoother.render();                  fFinalVolume * VolumeRight * PanRightSmoother.render();
572  #endif  #endif
573              // render audio for one subfragment              // render audio for one subfragment
574              RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);              if (!delay) RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);
575    
576              if (pSignalUnitRack == NULL) {              if (pSignalUnitRack == NULL) {
577                  // stop the rendering if volume EG is finished                  // stop the rendering if volume EG is finished
# Line 522  namespace LinuxSampler { Line 608  namespace LinuxSampler {
608                      }*/                      }*/
609                  // TODO: ^^^                  // TODO: ^^^
610                                    
611                  pSignalUnitRack->Increment();                  if (!delay) pSignalUnitRack->Increment();
612              }              }
613    
614              Pos = newPos;              Pos = newPos;
615              i = iSubFragmentEnd;              i = iSubFragmentEnd;
616          }          }
617            
618            if (delay) return;
619    
620          if (bVoiceRequiresDedicatedRouting) {          if (bVoiceRequiresDedicatedRouting) {
621                if (bEq) {
622                    pEq->RenderAudio(Samples);
623                    pEq->GetOutChannelLeft()->CopyTo(GetEngine()->pDedicatedVoiceChannelLeft, Samples);
624                    pEq->GetOutChannelRight()->CopyTo(GetEngine()->pDedicatedVoiceChannelRight, Samples);
625                }
626              optional<float> effectSendLevels[2] = {              optional<float> effectSendLevels[2] = {
627                  pMidiKeyInfo->ReverbSend,                  pMidiKeyInfo->ReverbSend,
628                  pMidiKeyInfo->ChorusSend                  pMidiKeyInfo->ChorusSend
629              };              };
630              GetEngine()->RouteDedicatedVoiceChannels(pEngineChannel, effectSendLevels, Samples);              GetEngine()->RouteDedicatedVoiceChannels(pEngineChannel, effectSendLevels, Samples);
631            } else if (bEq) {
632                pEq->RenderAudio(Samples);
633                pEq->GetOutChannelLeft()->MixTo(pChannel->pChannelLeft, Samples);
634                pEq->GetOutChannelRight()->MixTo(pChannel->pChannelRight, Samples);
635          }          }
636      }      }
637    
638      /**      /**
639       * Process given list of MIDI control change and pitch bend events for       * Process given list of MIDI control change, aftertouch and pitch bend
640       * the given time.       * events for the given time.
641       *       *
642       * @param itEvent - iterator pointing to the next event to be processed       * @param itEvent - iterator pointing to the next event to be processed
643       * @param End     - youngest time stamp where processing should be stopped       * @param End     - youngest time stamp where processing should be stopped
644       */       */
645      void AbstractVoice::processCCEvents(RTList<Event>::Iterator& itEvent, uint End) {      void AbstractVoice::processCCEvents(RTList<Event>::Iterator& itEvent, uint End) {
646          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
647              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)
648                    && itEvent->Param.CC.Controller) // if (valid) MIDI control change event
649                {
650                  if (itEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {                  if (itEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {
651                      ProcessCutoffEvent(itEvent);                      ProcessCutoffEvent(itEvent);
652                  }                  }
653                  if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {                  if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {
654                      processResonanceEvent(itEvent);                      processResonanceEvent(itEvent);
655                  }                  }
656                    if (itEvent->Param.CC.Controller == CTRL_TABLE_IDX_AFTERTOUCH ||
657                        itEvent->Type == Event::type_channel_pressure)
658                    {
659                        ProcessChannelPressureEvent(itEvent);
660                    }
661                  if (pSignalUnitRack == NULL) {                  if (pSignalUnitRack == NULL) {
662                      if (itEvent->Param.CC.Controller == pLFO1->ExtController) {                      if (itEvent->Param.CC.Controller == pLFO1->ExtController) {
663                          pLFO1->update(itEvent->Param.CC.Value);                          pLFO1->update(itEvent->Param.CC.Value);
# Line 568  namespace LinuxSampler { Line 672  namespace LinuxSampler {
672                  if (itEvent->Param.CC.Controller == 7) { // volume                  if (itEvent->Param.CC.Controller == 7) { // volume
673                      VolumeSmoother.update(AbstractEngine::VolumeCurve[itEvent->Param.CC.Value]);                      VolumeSmoother.update(AbstractEngine::VolumeCurve[itEvent->Param.CC.Value]);
674                  } else if (itEvent->Param.CC.Controller == 10) { // panpot                  } else if (itEvent->Param.CC.Controller == 10) { // panpot
675                      PanLeftSmoother.update(AbstractEngine::PanCurve[128 - itEvent->Param.CC.Value]);                      MIDIPan = CalculatePan(itEvent->Param.CC.Value);
                     PanRightSmoother.update(AbstractEngine::PanCurve[itEvent->Param.CC.Value]);  
676                  }                  }
677              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event
678                  processPitchEvent(itEvent);                  processPitchEvent(itEvent);
679                } else if (itEvent->Type == Event::type_note_pressure) {
680                    ProcessPolyphonicKeyPressureEvent(itEvent);
681              }              }
682    
683              ProcessCCEvent(itEvent);              ProcessCCEvent(itEvent);
# Line 597  namespace LinuxSampler { Line 702  namespace LinuxSampler {
702      }      }
703    
704      /**      /**
705       * 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
706       * for the given time.       * note synthesis parameter events for the given time.
707       *       *
708       * @param itEvent - iterator pointing to the next event to be processed       * @param itEvent - iterator pointing to the next event to be processed
709       * @param End     - youngest time stamp where processing should be stopped       * @param End     - youngest time stamp where processing should be stopped
# Line 607  namespace LinuxSampler { Line 712  namespace LinuxSampler {
712          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
713              // some voice types ignore note off              // some voice types ignore note off
714              if (!(Type & (Voice::type_one_shot | Voice::type_release_trigger | Voice::type_controller_triggered))) {              if (!(Type & (Voice::type_one_shot | Voice::type_release_trigger | Voice::type_controller_triggered))) {
715                  if (itEvent->Type == Event::type_release) {                  if (itEvent->Type == Event::type_release_key) {
716                      EnterReleaseStage();                      EnterReleaseStage();
717                  } else if (itEvent->Type == Event::type_cancel_release) {                  } else if (itEvent->Type == Event::type_cancel_release_key) {
718                      if (pSignalUnitRack == NULL) {                      if (pSignalUnitRack == NULL) {
719                          pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                          pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
720                          pEG2->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                          pEG2->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
# Line 618  namespace LinuxSampler { Line 723  namespace LinuxSampler {
723                      }                      }
724                  }                  }
725              }              }
726                // process stop-note events (caused by built-in instrument script function note_off())
727                if (itEvent->Type == Event::type_release_note && pNote &&
728                    pEngineChannel->pEngine->NoteByID( itEvent->Param.Note.ID ) == pNote)
729                {
730                    EnterReleaseStage();
731                }
732                // process synthesis parameter events (caused by built-in realt-time instrument script functions)
733                if (itEvent->Type == Event::type_note_synth_param && pNote &&
734                    pEngineChannel->pEngine->NoteByID( itEvent->Param.NoteSynthParam.NoteID ) == pNote)
735                {
736                    switch (itEvent->Param.NoteSynthParam.Type) {
737                        case Event::synth_param_volume:
738                            NoteVolumeSmoother.update(itEvent->Param.NoteSynthParam.AbsValue);
739                            break;
740                        case Event::synth_param_pitch:
741                            NotePitch = itEvent->Param.NoteSynthParam.AbsValue;
742                            break;
743                        case Event::synth_param_pan:
744                            NotePanLeft  = AbstractEngine::PanCurveValueNorm(itEvent->Param.NoteSynthParam.AbsValue, 0 /*left*/);
745                            NotePanRight = AbstractEngine::PanCurveValueNorm(itEvent->Param.NoteSynthParam.AbsValue, 1 /*right*/);
746                            break;
747                        case Event::synth_param_cutoff:
748                            NoteCutoff = itEvent->Param.NoteSynthParam.AbsValue;
749                            break;
750                        case Event::synth_param_resonance:
751                            NoteResonance = itEvent->Param.NoteSynthParam.AbsValue;
752                            break;
753    
754                        case Event::synth_param_attack:
755                        case Event::synth_param_decay:
756                        case Event::synth_param_release:
757                            break; // noop
758                    }
759                }
760          }          }
761      }      }
762    
# Line 644  namespace LinuxSampler { Line 783  namespace LinuxSampler {
783      void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {      void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {
784          if (pSignalUnitRack == NULL) {          if (pSignalUnitRack == NULL) {
785              const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());              const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());
786              pEngineChannel->PortamentoPos = (float) MIDIKey + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;              pEngineChannel->PortamentoPos = (float) MIDIKey() + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;
787          } else {          } else {
788              // TODO:              // TODO:
789          }          }
# Line 671  namespace LinuxSampler { Line 810  namespace LinuxSampler {
810    
811      Voice::PitchInfo AbstractVoice::CalculatePitchInfo(int PitchBend) {      Voice::PitchInfo AbstractVoice::CalculatePitchInfo(int PitchBend) {
812          PitchInfo pitch;          PitchInfo pitch;
813          double pitchbasecents = InstrInfo.FineTune + RgnInfo.FineTune + GetEngine()->ScaleTuning[MIDIKey % 12];          double pitchbasecents = InstrInfo.FineTune + RgnInfo.FineTune + GetEngine()->ScaleTuning[MIDIKey() % 12];
814    
815          // GSt behaviour: maximum transpose up is 40 semitones. If          // GSt behaviour: maximum transpose up is 40 semitones. If
816          // MIDI key is more than 40 semitones above unity note,          // MIDI key is more than 40 semitones above unity note,
817          // the transpose is not done.          // the transpose is not done.
818          if (!SmplInfo.Unpitched && (MIDIKey - (int) RgnInfo.UnityNote) < 40) pitchbasecents += (MIDIKey - (int) RgnInfo.UnityNote) * 100;          if (!SmplInfo.Unpitched && (MIDIKey() - (int) RgnInfo.UnityNote) < 40) pitchbasecents += (MIDIKey() - (int) RgnInfo.UnityNote) * 100;
819    
820          pitch.PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(SmplInfo.SampleRate) / double(GetEngine()->SampleRate));          pitch.PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(SmplInfo.SampleRate) / double(GetEngine()->SampleRate));
821          pitch.PitchBendRange = 1.0 / 8192.0 * 100.0 * InstrInfo.PitchbendRange;          pitch.PitchBendRange = 1.0 / 8192.0 * 100.0 * InstrInfo.PitchbendRange;
# Line 684  namespace LinuxSampler { Line 823  namespace LinuxSampler {
823    
824          return pitch;          return pitch;
825      }      }
826        
827        void AbstractVoice::onScaleTuningChanged() {
828            PitchInfo pitch = this->Pitch;
829            double pitchbasecents = InstrInfo.FineTune + RgnInfo.FineTune + GetEngine()->ScaleTuning[MIDIKey() % 12];
830            
831            // GSt behaviour: maximum transpose up is 40 semitones. If
832            // MIDI key is more than 40 semitones above unity note,
833            // the transpose is not done.
834            if (!SmplInfo.Unpitched && (MIDIKey() - (int) RgnInfo.UnityNote) < 40) pitchbasecents += (MIDIKey() - (int) RgnInfo.UnityNote) * 100;
835            
836            pitch.PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(SmplInfo.SampleRate) / double(GetEngine()->SampleRate));
837            this->Pitch = pitch;
838        }
839    
840      double AbstractVoice::CalculateVolume(double velocityAttenuation) {      double AbstractVoice::CalculateVolume(double velocityAttenuation) {
841          // For 16 bit samples, we downscale by 32768 to convert from          // For 16 bit samples, we downscale by 32768 to convert from
# Line 696  namespace LinuxSampler { Line 848  namespace LinuxSampler {
848          // the volume of release triggered samples depends on note length          // the volume of release triggered samples depends on note length
849          if (Type & Voice::type_release_trigger) {          if (Type & Voice::type_release_trigger) {
850              float noteLength = float(GetEngine()->FrameTime + Delay -              float noteLength = float(GetEngine()->FrameTime + Delay -
851                  GetNoteOnTime(MIDIKey) ) / GetEngine()->SampleRate;                  GetNoteOnTime(MIDIKey()) ) / GetEngine()->SampleRate;
852    
853              volume *= GetReleaseTriggerAttenuation(noteLength);              volume *= GetReleaseTriggerAttenuation(noteLength);
854          }          }

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

  ViewVC Help
Powered by ViewVC