/[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 2219 by iliev, Thu Jul 28 12:35:49 2011 UTC revision 2938 by schoenebeck, Mon Jul 11 17:10:40 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-2015 Christian Schoenebeck and Grigor Iliev        *
8   *                                                                         *   *                                                                         *
9   *   This program is free software; you can redistribute it and/or modify  *   *   This program is free software; you can redistribute it and/or modify  *
10   *   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 43  namespace LinuxSampler {
43    
44          finalSynthesisParameters.filterLeft.Reset();          finalSynthesisParameters.filterLeft.Reset();
45          finalSynthesisParameters.filterRight.Reset();          finalSynthesisParameters.filterRight.Reset();
46            
47            pEq          = NULL;
48            bEqSupport   = false;
49      }      }
50    
51      AbstractVoice::~AbstractVoice() {      AbstractVoice::~AbstractVoice() {
52          if (pLFO1) delete pLFO1;          if (pLFO1) delete pLFO1;
53          if (pLFO2) delete pLFO2;          if (pLFO2) delete pLFO2;
54          if (pLFO3) delete pLFO3;          if (pLFO3) delete pLFO3;
55            
56            if(pEq != NULL) delete pEq;
57        }
58                
59        void AbstractVoice::CreateEq() {
60            if(!bEqSupport) return;
61            if(pEq != NULL) delete pEq;
62            pEq = new EqSupport;
63            pEq->InitEffect(GetEngine()->pAudioOutputDevice);
64      }      }
65    
66      /**      /**
# Line 98  namespace LinuxSampler { Line 110  namespace LinuxSampler {
110          #endif // CONFIG_DEVMODE          #endif // CONFIG_DEVMODE
111    
112          Type            = VoiceType;          Type            = VoiceType;
113          MIDIKey         = itNoteOnEvent->Param.Note.Key;          pNote           = pEngineChannel->pEngine->NoteByID( itNoteOnEvent->Param.Note.ID );
         MIDIVelocity    = itNoteOnEvent->Param.Note.Velocity;  
         MIDIPan         = pEngineChannel->ControllerTable[10];  
         if (MIDIPan == 0 && pEngineChannel->GlobalPanRight == 1) MIDIPan = 64; // workaround used to determine whether the MIDI pan has not been set  
114          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
115          Delay           = itNoteOnEvent->FragmentPos();          Delay           = itNoteOnEvent->FragmentPos();
116          itTriggerEvent  = itNoteOnEvent;          itTriggerEvent  = itNoteOnEvent;
117          itKillEvent     = Pool<Event>::Iterator();          itKillEvent     = Pool<Event>::Iterator();
118          MidiKeyBase* pKeyInfo = GetMidiKeyInfo(MIDIKey);          MidiKeyBase* pKeyInfo = GetMidiKeyInfo(MIDIKey());
119    
120          pGroupEvents = iKeyGroup ? pEngineChannel->ActiveKeyGroups[iKeyGroup] : 0;          pGroupEvents = iKeyGroup ? pEngineChannel->ActiveKeyGroups[iKeyGroup] : 0;
121    
# Line 114  namespace LinuxSampler { Line 123  namespace LinuxSampler {
123          RgnInfo    = GetRegionInfo();          RgnInfo    = GetRegionInfo();
124          InstrInfo  = GetInstrumentInfo();          InstrInfo  = GetInstrumentInfo();
125                    
126            MIDIPan    = CalculatePan(pEngineChannel->iLastPanRequest);
127    
128          AboutToTrigger();          AboutToTrigger();
129    
130          // calculate volume          // calculate volume
# Line 129  namespace LinuxSampler { Line 140  namespace LinuxSampler {
140          // get starting crossfade volume level          // get starting crossfade volume level
141          float crossfadeVolume = CalculateCrossfadeVolume(itNoteOnEvent->Param.Note.Velocity);          float crossfadeVolume = CalculateCrossfadeVolume(itNoteOnEvent->Param.Note.Velocity);
142    
143          VolumeLeft  = volume * pKeyInfo->PanLeft  * AbstractEngine::PanCurve[64 - RgnInfo.Pan];          VolumeLeft  = volume * pKeyInfo->PanLeft;
144          VolumeRight = volume * pKeyInfo->PanRight * AbstractEngine::PanCurve[64 + RgnInfo.Pan];          VolumeRight = volume * pKeyInfo->PanRight;
145    
146          float subfragmentRate = GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;          float subfragmentRate = GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;
147          CrossfadeSmoother.trigger(crossfadeVolume, subfragmentRate);          CrossfadeSmoother.trigger(crossfadeVolume, subfragmentRate);
148          VolumeSmoother.trigger(pEngineChannel->MidiVolume, subfragmentRate);          VolumeSmoother.trigger(pEngineChannel->MidiVolume, subfragmentRate);
149          PanLeftSmoother.trigger(pEngineChannel->GlobalPanLeft, subfragmentRate);          NoteVolumeSmoother.trigger(pNote ? pNote->Override.Volume : 1.f, subfragmentRate);
         PanRightSmoother.trigger(pEngineChannel->GlobalPanRight, subfragmentRate);  
150    
151          // 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
152          long cachedsamples = GetSampleCacheSize() / SmplInfo.FrameSize;          long cachedsamples = GetSampleCacheSize() / SmplInfo.FrameSize;
# Line 160  namespace LinuxSampler { Line 170  namespace LinuxSampler {
170              RAMLoop = (SmplInfo.HasLoops && (SmplInfo.LoopStart + SmplInfo.LoopLength) <= MaxRAMPos);              RAMLoop = (SmplInfo.HasLoops && (SmplInfo.LoopStart + SmplInfo.LoopLength) <= MaxRAMPos);
171    
172              if (OrderNewStream()) return -1;              if (OrderNewStream()) return -1;
173              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"));
174          }          }
175          else { // RAM only voice          else { // RAM only voice
176              MaxRAMPos = cachedsamples;              MaxRAMPos = cachedsamples;
# Line 176  namespace LinuxSampler { Line 186  namespace LinuxSampler {
186          }          }
187    
188          Pitch = CalculatePitchInfo(PitchBend);          Pitch = CalculatePitchInfo(PitchBend);
189            NotePitch = (pNote) ? pNote->Override.Pitch : 1.0f;
190            NoteCutoff = (pNote) ? pNote->Override.Cutoff : 1.0f;
191            NoteResonance = (pNote) ? pNote->Override.Resonance : 1.0f;
192    
193          // 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
194          const double velrelease = 1 / GetVelocityRelease(itNoteOnEvent->Param.Note.Velocity);          const double velrelease = 1 / GetVelocityRelease(itNoteOnEvent->Param.Note.Velocity);
# Line 192  namespace LinuxSampler { Line 205  namespace LinuxSampler {
205              pSignalUnitRack->Trigger();              pSignalUnitRack->Trigger();
206          }          }
207    
208            const uint8_t pan = (pSignalUnitRack) ? pSignalUnitRack->GetEndpointUnit()->CalculatePan(MIDIPan) : MIDIPan;
209            NotePanLeft  = (pNote) ? AbstractEngine::PanCurveValueNorm(pNote->Override.Pan, 0 /*left*/ ) : 1.f;
210            NotePanRight = (pNote) ? AbstractEngine::PanCurveValueNorm(pNote->Override.Pan, 1 /*right*/) : 1.f;
211            PanLeftSmoother.trigger(
212                AbstractEngine::PanCurve[128 - pan] * NotePanLeft,
213                subfragmentRate
214            );
215            PanRightSmoother.trigger(
216                AbstractEngine::PanCurve[pan] * NotePanRight,
217                subfragmentRate
218            );
219    
220  #ifdef CONFIG_INTERPOLATE_VOLUME  #ifdef CONFIG_INTERPOLATE_VOLUME
221          // setup initial volume in synthesis parameters          // setup initial volume in synthesis parameters
222      #ifdef CONFIG_PROCESS_MUTED_CHANNELS      #ifdef CONFIG_PROCESS_MUTED_CHANNELS
# Line 209  namespace LinuxSampler { Line 234  namespace LinuxSampler {
234                  finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pSignalUnitRack->GetEndpointUnit()->GetVolume();                  finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pSignalUnitRack->GetEndpointUnit()->GetVolume();
235              }              }
236    
237              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * pEngineChannel->GlobalPanLeft;              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * PanLeftSmoother.render();
238              finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * pEngineChannel->GlobalPanRight;              finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * PanRightSmoother.render();
239          }          }
240      #endif      #endif
241  #endif  #endif
# Line 233  namespace LinuxSampler { Line 258  namespace LinuxSampler {
258                  // 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
259                  bool  bPortamento = pEngineChannel->PortamentoMode && pEngineChannel->PortamentoPos >= 0.0f;                  bool  bPortamento = pEngineChannel->PortamentoMode && pEngineChannel->PortamentoPos >= 0.0f;
260                  float eg3depth = (bPortamento)                  float eg3depth = (bPortamento)
261                               ? RTMath::CentsToFreqRatio((pEngineChannel->PortamentoPos - (float) MIDIKey) * 100)                               ? RTMath::CentsToFreqRatio((pEngineChannel->PortamentoPos - (float) MIDIKey()) * 100)
262                               : RTMath::CentsToFreqRatio(RgnInfo.EG3Depth);                               : RTMath::CentsToFreqRatio(RgnInfo.EG3Depth);
263                  float eg3time = (bPortamento)                  float eg3time = (bPortamento)
264                              ? pEngineChannel->PortamentoTime                              ? pEngineChannel->PortamentoTime
# Line 294  namespace LinuxSampler { Line 319  namespace LinuxSampler {
319              VCFCutoffCtrl.controller    = 0;              VCFCutoffCtrl.controller    = 0;
320              VCFResonanceCtrl.controller = 0;              VCFResonanceCtrl.controller = 0;
321          }          }
322            
323            const bool bEq =
324                pSignalUnitRack != NULL && pSignalUnitRack->HasEq() && pEq->HasSupport();
325    
326            if (bEq) {
327                pEq->GetInChannelLeft()->Clear();
328                pEq->GetInChannelRight()->Clear();
329                pEq->RenderAudio(GetEngine()->pAudioOutputDevice->MaxSamplesPerCycle());
330            }
331    
332          return 0; // success          return 0; // success
333      }      }
# Line 312  namespace LinuxSampler { Line 346  namespace LinuxSampler {
346       *  @param Skip    - number of sample points to skip in output buffer       *  @param Skip    - number of sample points to skip in output buffer
347       */       */
348      void AbstractVoice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {      void AbstractVoice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {
349            bool delay = false; // Whether the voice playback should be delayed for this call
350            
351            if (pSignalUnitRack != NULL) {
352                uint delaySteps = pSignalUnitRack->GetEndpointUnit()->DelayTrigger();
353                if (delaySteps > 0) { // delay on the endpoint unit means delay of the voice playback
354                    if (delaySteps >= Samples) {
355                        pSignalUnitRack->GetEndpointUnit()->DecreaseDelay(Samples);
356                        delay = true;
357                    } else {
358                        pSignalUnitRack->GetEndpointUnit()->DecreaseDelay(delaySteps);
359                        Samples -= delaySteps;
360                        Skip += delaySteps;
361                    }
362                }
363            }
364            
365          AbstractEngineChannel* pChannel = pEngineChannel;          AbstractEngineChannel* pChannel = pEngineChannel;
366          MidiKeyBase* pMidiKeyInfo = GetMidiKeyInfo(MIDIKey);          MidiKeyBase* pMidiKeyInfo = GetMidiKeyInfo(MIDIKey());
367    
368          const bool bVoiceRequiresDedicatedRouting =          const bool bVoiceRequiresDedicatedRouting =
369              pEngineChannel->GetFxSendCount() > 0 &&              pEngineChannel->GetFxSendCount() > 0 &&
370              (pMidiKeyInfo->ReverbSend || pMidiKeyInfo->ChorusSend);              (pMidiKeyInfo->ReverbSend || pMidiKeyInfo->ChorusSend);
371            
372            const bool bEq =
373                pSignalUnitRack != NULL && pSignalUnitRack->HasEq() && pEq->HasSupport();
374    
375          if (bVoiceRequiresDedicatedRouting) {          if (bEq) {
376                pEq->GetInChannelLeft()->Clear();
377                pEq->GetInChannelRight()->Clear();
378                finalSynthesisParameters.pOutLeft  = &pEq->GetInChannelLeft()->Buffer()[Skip];
379                finalSynthesisParameters.pOutRight = &pEq->GetInChannelRight()->Buffer()[Skip];
380                pSignalUnitRack->UpdateEqSettings(pEq);
381            } else if (bVoiceRequiresDedicatedRouting) {
382              finalSynthesisParameters.pOutLeft  = &GetEngine()->pDedicatedVoiceChannelLeft->Buffer()[Skip];              finalSynthesisParameters.pOutLeft  = &GetEngine()->pDedicatedVoiceChannelLeft->Buffer()[Skip];
383              finalSynthesisParameters.pOutRight = &GetEngine()->pDedicatedVoiceChannelRight->Buffer()[Skip];              finalSynthesisParameters.pOutRight = &GetEngine()->pDedicatedVoiceChannelRight->Buffer()[Skip];
384          } else {          } else {
# Line 330  namespace LinuxSampler { Line 389  namespace LinuxSampler {
389    
390          RTList<Event>::Iterator itCCEvent = pChannel->pEvents->first();          RTList<Event>::Iterator itCCEvent = pChannel->pEvents->first();
391          RTList<Event>::Iterator itNoteEvent;          RTList<Event>::Iterator itNoteEvent;
392          GetFirstEventOnKey(MIDIKey, itNoteEvent);          GetFirstEventOnKey(HostKey(), itNoteEvent);
393    
394          RTList<Event>::Iterator itGroupEvent;          RTList<Event>::Iterator itGroupEvent;
395          if (pGroupEvents) itGroupEvent = pGroupEvents->first();          if (pGroupEvents && !Orphan) itGroupEvent = pGroupEvents->first();
396    
397          if (itTriggerEvent) { // skip events that happened before this voice was triggered          if (itTriggerEvent) { // skip events that happened before this voice was triggered
398              while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;              while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;
# Line 362  namespace LinuxSampler { Line 421  namespace LinuxSampler {
421                  if (pSignalUnitRack == NULL) {                  if (pSignalUnitRack == NULL) {
422                      pEG1->enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                      pEG1->enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
423                  } else {                  } else {
424                      // TODO:                      pSignalUnitRack->EnterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
425                  }                  }
426                  itKillEvent = Pool<Event>::Iterator();                  itKillEvent = Pool<Event>::Iterator();
427              } else {              } else {
# Line 378  namespace LinuxSampler { Line 437  namespace LinuxSampler {
437              fFinalCutoff    = VCFCutoffCtrl.fvalue;              fFinalCutoff    = VCFCutoffCtrl.fvalue;
438              fFinalResonance = VCFResonanceCtrl.fvalue;              fFinalResonance = VCFResonanceCtrl.fvalue;
439    
440              // process MIDI control change and pitchbend events for this subfragment              // process MIDI control change, aftertouch and pitchbend events for this subfragment
441              processCCEvents(itCCEvent, iSubFragmentEnd);              processCCEvents(itCCEvent, iSubFragmentEnd);
442              uint8_t pan = MIDIPan;              uint8_t pan = MIDIPan;
443              if (pSignalUnitRack != NULL) pan = pSignalUnitRack->GetEndpointUnit()->CaluclatePan(pan);              if (pSignalUnitRack != NULL) pan = pSignalUnitRack->GetEndpointUnit()->CalculatePan(MIDIPan);
444                
445              PanLeftSmoother.update(AbstractEngine::PanCurve[128 - pan]);              PanLeftSmoother.update(AbstractEngine::PanCurve[128 - pan] * NotePanLeft);
446              PanRightSmoother.update(AbstractEngine::PanCurve[pan]);              PanRightSmoother.update(AbstractEngine::PanCurve[pan]      * NotePanRight);
447    
448                finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend * NotePitch;
449    
450              finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend;              float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render() * NoteVolumeSmoother.render();
             float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render();  
451  #ifdef CONFIG_PROCESS_MUTED_CHANNELS  #ifdef CONFIG_PROCESS_MUTED_CHANNELS
452              if (pChannel->GetMute()) fFinalVolume = 0;              if (pChannel->GetMute()) fFinalVolume = 0;
453  #endif  #endif
# Line 395  namespace LinuxSampler { Line 455  namespace LinuxSampler {
455              // process transition events (note on, note off & sustain pedal)              // process transition events (note on, note off & sustain pedal)
456              processTransitionEvents(itNoteEvent, iSubFragmentEnd);              processTransitionEvents(itNoteEvent, iSubFragmentEnd);
457              processGroupEvents(itGroupEvent, iSubFragmentEnd);              processGroupEvents(itGroupEvent, iSubFragmentEnd);
458                
459              if (pSignalUnitRack == NULL) {              if (pSignalUnitRack == NULL) {
460                  // if the voice was killed in this subfragment, or if the                  // if the voice was killed in this subfragment, or if the
461                  // filter EG is finished, switch EG1 to fade out stage                  // filter EG is finished, switch EG1 to fade out stage
# Line 439  namespace LinuxSampler { Line 499  namespace LinuxSampler {
499    
500                  // process low frequency oscillators                  // process low frequency oscillators
501                  if (bLFO1Enabled) fFinalVolume *= (1.0f - pLFO1->render());                  if (bLFO1Enabled) fFinalVolume *= (1.0f - pLFO1->render());
502                  if (bLFO2Enabled) fFinalCutoff *= pLFO2->render();                  if (bLFO2Enabled) fFinalCutoff *= (1.0f - pLFO2->render());
503                  if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());                  if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());
504              } else {              } else {
505                  // if the voice was killed in this subfragment, or if the                  // if the voice was killed in this subfragment, enter fade out stage
506                  // filter EG is finished, switch EG1 to fade out stage                  if (itKillEvent && killPos <= iSubFragmentEnd) {
507                  /*if ((itKillEvent && killPos <= iSubFragmentEnd) ||                      pSignalUnitRack->EnterFadeOutStage();
508                      (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&                      itKillEvent = Pool<Event>::Iterator();
509                      pEG2->getSegmentType() == EG::segment_end)) {                  }
510                    
511                    // if the filter EG is finished, switch EG1 to fade out stage
512                    /*if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&
513                        pEG2->getSegmentType() == EG::segment_end) {
514                      pEG1->enterFadeOutStage();                      pEG1->enterFadeOutStage();
515                      itKillEvent = Pool<Event>::Iterator();                      itKillEvent = Pool<Event>::Iterator();
516                  }*/                  }*/
# Line 460  namespace LinuxSampler { Line 524  namespace LinuxSampler {
524                      pSignalUnitRack->GetEndpointUnit()->CalculatePitch(finalSynthesisParameters.fFinalPitch);                      pSignalUnitRack->GetEndpointUnit()->CalculatePitch(finalSynthesisParameters.fFinalPitch);
525                                            
526              }              }
527                
528                fFinalCutoff    *= NoteCutoff;
529                fFinalResonance *= NoteResonance;
530    
531              // limit the pitch so we don't read outside the buffer              // limit the pitch so we don't read outside the buffer
532              finalSynthesisParameters.fFinalPitch = RTMath::Min(finalSynthesisParameters.fFinalPitch, float(1 << CONFIG_MAX_PITCH));              finalSynthesisParameters.fFinalPitch = RTMath::Min(finalSynthesisParameters.fFinalPitch, float(1 << CONFIG_MAX_PITCH));
533    
# Line 493  namespace LinuxSampler { Line 560  namespace LinuxSampler {
560                  fFinalVolume * VolumeRight * PanRightSmoother.render();                  fFinalVolume * VolumeRight * PanRightSmoother.render();
561  #endif  #endif
562              // render audio for one subfragment              // render audio for one subfragment
563              RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);              if (!delay) RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);
564    
565              if (pSignalUnitRack == NULL) {              if (pSignalUnitRack == NULL) {
566                  // stop the rendering if volume EG is finished                  // stop the rendering if volume EG is finished
# Line 530  namespace LinuxSampler { Line 597  namespace LinuxSampler {
597                      }*/                      }*/
598                  // TODO: ^^^                  // TODO: ^^^
599                                    
600                  pSignalUnitRack->Increment();                  if (!delay) pSignalUnitRack->Increment();
601              }              }
602    
603              Pos = newPos;              Pos = newPos;
604              i = iSubFragmentEnd;              i = iSubFragmentEnd;
605          }          }
606            
607            if (delay) return;
608    
609          if (bVoiceRequiresDedicatedRouting) {          if (bVoiceRequiresDedicatedRouting) {
610                if (bEq) {
611                    pEq->RenderAudio(Samples);
612                    pEq->GetOutChannelLeft()->CopyTo(GetEngine()->pDedicatedVoiceChannelLeft, Samples);
613                    pEq->GetOutChannelRight()->CopyTo(GetEngine()->pDedicatedVoiceChannelRight, Samples);
614                }
615              optional<float> effectSendLevels[2] = {              optional<float> effectSendLevels[2] = {
616                  pMidiKeyInfo->ReverbSend,                  pMidiKeyInfo->ReverbSend,
617                  pMidiKeyInfo->ChorusSend                  pMidiKeyInfo->ChorusSend
618              };              };
619              GetEngine()->RouteDedicatedVoiceChannels(pEngineChannel, effectSendLevels, Samples);              GetEngine()->RouteDedicatedVoiceChannels(pEngineChannel, effectSendLevels, Samples);
620            } else if (bEq) {
621                pEq->RenderAudio(Samples);
622                pEq->GetOutChannelLeft()->MixTo(pChannel->pChannelLeft, Samples);
623                pEq->GetOutChannelRight()->MixTo(pChannel->pChannelRight, Samples);
624          }          }
625      }      }
626    
627      /**      /**
628       * Process given list of MIDI control change and pitch bend events for       * Process given list of MIDI control change, aftertouch and pitch bend
629       * the given time.       * events for the given time.
630       *       *
631       * @param itEvent - iterator pointing to the next event to be processed       * @param itEvent - iterator pointing to the next event to be processed
632       * @param End     - youngest time stamp where processing should be stopped       * @param End     - youngest time stamp where processing should be stopped
# Line 576  namespace LinuxSampler { Line 654  namespace LinuxSampler {
654                  if (itEvent->Param.CC.Controller == 7) { // volume                  if (itEvent->Param.CC.Controller == 7) { // volume
655                      VolumeSmoother.update(AbstractEngine::VolumeCurve[itEvent->Param.CC.Value]);                      VolumeSmoother.update(AbstractEngine::VolumeCurve[itEvent->Param.CC.Value]);
656                  } else if (itEvent->Param.CC.Controller == 10) { // panpot                  } else if (itEvent->Param.CC.Controller == 10) { // panpot
657                      MIDIPan = itEvent->Param.CC.Value;                      MIDIPan = CalculatePan(itEvent->Param.CC.Value);
658                  }                  }
659              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event
660                  processPitchEvent(itEvent);                  processPitchEvent(itEvent);
661                } else if (itEvent->Type == Event::type_channel_pressure) {
662                    ProcessChannelPressureEvent(itEvent);
663                } else if (itEvent->Type == Event::type_note_pressure) {
664                    ProcessPolyphonicKeyPressureEvent(itEvent);
665              }              }
666    
667              ProcessCCEvent(itEvent);              ProcessCCEvent(itEvent);
# Line 604  namespace LinuxSampler { Line 686  namespace LinuxSampler {
686      }      }
687    
688      /**      /**
689       * 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
690       * for the given time.       * note synthesis parameter events for the given time.
691       *       *
692       * @param itEvent - iterator pointing to the next event to be processed       * @param itEvent - iterator pointing to the next event to be processed
693       * @param End     - youngest time stamp where processing should be stopped       * @param End     - youngest time stamp where processing should be stopped
# Line 614  namespace LinuxSampler { Line 696  namespace LinuxSampler {
696          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
697              // some voice types ignore note off              // some voice types ignore note off
698              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))) {
699                  if (itEvent->Type == Event::type_release) {                  if (itEvent->Type == Event::type_release_key) {
700                      EnterReleaseStage();                      EnterReleaseStage();
701                  } else if (itEvent->Type == Event::type_cancel_release) {                  } else if (itEvent->Type == Event::type_cancel_release_key) {
702                      if (pSignalUnitRack == NULL) {                      if (pSignalUnitRack == NULL) {
703                          pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                          pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
704                          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 625  namespace LinuxSampler { Line 707  namespace LinuxSampler {
707                      }                      }
708                  }                  }
709              }              }
710                // process stop-note events (caused by built-in instrument script function note_off())
711                if (itEvent->Type == Event::type_release_note && pNote &&
712                    pEngineChannel->pEngine->NoteByID( itEvent->Param.Note.ID ) == pNote)
713                {
714                    EnterReleaseStage();
715                }
716                // process synthesis parameter events (caused by built-in realt-time instrument script functions)
717                if (itEvent->Type == Event::type_note_synth_param && pNote &&
718                    pEngineChannel->pEngine->NoteByID( itEvent->Param.NoteSynthParam.NoteID ) == pNote)
719                {
720                    switch (itEvent->Param.NoteSynthParam.Type) {
721                        case Event::synth_param_volume:
722                            NoteVolumeSmoother.update(itEvent->Param.NoteSynthParam.AbsValue);
723                            break;
724                        case Event::synth_param_pitch:
725                            NotePitch = itEvent->Param.NoteSynthParam.AbsValue;
726                            break;
727                        case Event::synth_param_pan:
728                            NotePanLeft  = AbstractEngine::PanCurveValueNorm(itEvent->Param.NoteSynthParam.AbsValue, 0 /*left*/);
729                            NotePanRight = AbstractEngine::PanCurveValueNorm(itEvent->Param.NoteSynthParam.AbsValue, 1 /*right*/);
730                            break;
731                        case Event::synth_param_cutoff:
732                            NoteCutoff = itEvent->Param.NoteSynthParam.AbsValue;
733                            break;
734                        case Event::synth_param_resonance:
735                            NoteResonance = itEvent->Param.NoteSynthParam.AbsValue;
736                            break;
737                    }
738                }
739          }          }
740      }      }
741    
# Line 651  namespace LinuxSampler { Line 762  namespace LinuxSampler {
762      void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {      void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {
763          if (pSignalUnitRack == NULL) {          if (pSignalUnitRack == NULL) {
764              const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());              const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());
765              pEngineChannel->PortamentoPos = (float) MIDIKey + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;              pEngineChannel->PortamentoPos = (float) MIDIKey() + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;
766          } else {          } else {
767              // TODO:              // TODO:
768          }          }
# Line 678  namespace LinuxSampler { Line 789  namespace LinuxSampler {
789    
790      Voice::PitchInfo AbstractVoice::CalculatePitchInfo(int PitchBend) {      Voice::PitchInfo AbstractVoice::CalculatePitchInfo(int PitchBend) {
791          PitchInfo pitch;          PitchInfo pitch;
792          double pitchbasecents = InstrInfo.FineTune + RgnInfo.FineTune + GetEngine()->ScaleTuning[MIDIKey % 12];          double pitchbasecents = InstrInfo.FineTune + RgnInfo.FineTune + GetEngine()->ScaleTuning[MIDIKey() % 12];
793    
794          // GSt behaviour: maximum transpose up is 40 semitones. If          // GSt behaviour: maximum transpose up is 40 semitones. If
795          // MIDI key is more than 40 semitones above unity note,          // MIDI key is more than 40 semitones above unity note,
796          // the transpose is not done.          // the transpose is not done.
797          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;
798    
799          pitch.PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(SmplInfo.SampleRate) / double(GetEngine()->SampleRate));          pitch.PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(SmplInfo.SampleRate) / double(GetEngine()->SampleRate));
800          pitch.PitchBendRange = 1.0 / 8192.0 * 100.0 * InstrInfo.PitchbendRange;          pitch.PitchBendRange = 1.0 / 8192.0 * 100.0 * InstrInfo.PitchbendRange;
# Line 691  namespace LinuxSampler { Line 802  namespace LinuxSampler {
802    
803          return pitch;          return pitch;
804      }      }
805        
806        void AbstractVoice::onScaleTuningChanged() {
807            PitchInfo pitch = this->Pitch;
808            double pitchbasecents = InstrInfo.FineTune + RgnInfo.FineTune + GetEngine()->ScaleTuning[MIDIKey() % 12];
809            
810            // GSt behaviour: maximum transpose up is 40 semitones. If
811            // MIDI key is more than 40 semitones above unity note,
812            // the transpose is not done.
813            if (!SmplInfo.Unpitched && (MIDIKey() - (int) RgnInfo.UnityNote) < 40) pitchbasecents += (MIDIKey() - (int) RgnInfo.UnityNote) * 100;
814            
815            pitch.PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(SmplInfo.SampleRate) / double(GetEngine()->SampleRate));
816            this->Pitch = pitch;
817        }
818    
819      double AbstractVoice::CalculateVolume(double velocityAttenuation) {      double AbstractVoice::CalculateVolume(double velocityAttenuation) {
820          // For 16 bit samples, we downscale by 32768 to convert from          // For 16 bit samples, we downscale by 32768 to convert from
# Line 703  namespace LinuxSampler { Line 827  namespace LinuxSampler {
827          // the volume of release triggered samples depends on note length          // the volume of release triggered samples depends on note length
828          if (Type & Voice::type_release_trigger) {          if (Type & Voice::type_release_trigger) {
829              float noteLength = float(GetEngine()->FrameTime + Delay -              float noteLength = float(GetEngine()->FrameTime + Delay -
830                  GetNoteOnTime(MIDIKey) ) / GetEngine()->SampleRate;                  GetNoteOnTime(MIDIKey()) ) / GetEngine()->SampleRate;
831    
832              volume *= GetReleaseTriggerAttenuation(noteLength);              volume *= GetReleaseTriggerAttenuation(noteLength);
833          }          }

Legend:
Removed from v.2219  
changed lines
  Added in v.2938

  ViewVC Help
Powered by ViewVC