/[svn]/linuxsampler/trunk/src/engines/gig/Voice.cpp
ViewVC logotype

Diff of /linuxsampler/trunk/src/engines/gig/Voice.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 877 by persson, Sun Jun 25 13:54:17 2006 UTC revision 1923 by persson, Sat Jun 27 16:55:41 2009 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, 2006 Christian Schoenebeck                        *   *   Copyright (C) 2005 - 2009 Christian Schoenebeck                       *
7   *                                                                         *   *                                                                         *
8   *   This program is free software; you can redistribute it and/or modify  *   *   This program is free software; you can redistribute it and/or modify  *
9   *   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 38  namespace LinuxSampler { namespace gig { Line 38  namespace LinuxSampler { namespace gig {
38          pLFO3 = new LFOSigned(1200.0f); // pitch EG (-1200..+1200 range)          pLFO3 = new LFOSigned(1200.0f); // pitch EG (-1200..+1200 range)
39          KeyGroup = 0;          KeyGroup = 0;
40          SynthesisMode = 0; // set all mode bits to 0 first          SynthesisMode = 0; // set all mode bits to 0 first
41          // select synthesis implementation (currently either pure C++ or MMX+SSE(1))          // select synthesis implementation (asm core is not supported ATM)
42          #if CONFIG_ASM && ARCH_X86          #if 0 // CONFIG_ASM && ARCH_X86
43          SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, Features::supportsMMX() && Features::supportsSSE());          SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, Features::supportsMMX() && Features::supportsSSE());
44          #else          #else
45          SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, false);          SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, false);
# Line 79  namespace LinuxSampler { namespace gig { Line 79  namespace LinuxSampler { namespace gig {
79      int Voice::Trigger(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent, int PitchBend, ::gig::DimensionRegion* pDimRgn, type_t VoiceType, int iKeyGroup) {      int Voice::Trigger(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent, int PitchBend, ::gig::DimensionRegion* pDimRgn, type_t VoiceType, int iKeyGroup) {
80          this->pEngineChannel = pEngineChannel;          this->pEngineChannel = pEngineChannel;
81          this->pDimRgn        = pDimRgn;          this->pDimRgn        = pDimRgn;
82            Orphan = false;
83    
84          #if CONFIG_DEVMODE          #if CONFIG_DEVMODE
85          if (itNoteOnEvent->FragmentPos() > pEngine->MaxSamplesPerCycle) { // just a sanity check for debugging          if (itNoteOnEvent->FragmentPos() > pEngine->MaxSamplesPerCycle) { // just a sanity check for debugging
# Line 98  namespace LinuxSampler { namespace gig { Line 99  namespace LinuxSampler { namespace gig {
99          // calculate volume          // calculate volume
100          const double velocityAttenuation = pDimRgn->GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity);          const double velocityAttenuation = pDimRgn->GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity);
101    
102          float volume = velocityAttenuation / 32768.0f; // we downscale by 32768 to convert from int16 value range to DSP value range (which is -1.0..1.0)          // For 16 bit samples, we downscale by 32768 to convert from
103            // int16 value range to DSP value range (which is
104            // -1.0..1.0). For 24 bit, we downscale from int32.
105            float volume = velocityAttenuation / (pSample->BitDepth == 16 ? 32768.0f : 32768.0f * 65536.0f);
106    
107          volume *= pDimRgn->SampleAttenuation;          volume *= pDimRgn->SampleAttenuation * pEngineChannel->GlobalVolume * GLOBAL_VOLUME;
108    
109          // the volume of release triggered samples depends on note length          // the volume of release triggered samples depends on note length
110          if (Type == type_release_trigger) {          if (Type == type_release_trigger) {
# Line 113  namespace LinuxSampler { namespace gig { Line 117  namespace LinuxSampler { namespace gig {
117    
118          // select channel mode (mono or stereo)          // select channel mode (mono or stereo)
119          SYNTHESIS_MODE_SET_CHANNELS(SynthesisMode, pSample->Channels == 2);          SYNTHESIS_MODE_SET_CHANNELS(SynthesisMode, pSample->Channels == 2);
120            // select bit depth (16 or 24)
121            SYNTHESIS_MODE_SET_BITDEPTH24(SynthesisMode, pSample->BitDepth == 24);
122    
123          // get starting crossfade volume level          // get starting crossfade volume level
124          float crossfadeVolume;          float crossfadeVolume;
125          switch (pDimRgn->AttenuationController.type) {          switch (pDimRgn->AttenuationController.type) {
126              case ::gig::attenuation_ctrl_t::type_channelaftertouch:              case ::gig::attenuation_ctrl_t::type_channelaftertouch:
127                  crossfadeVolume = 1.0f; //TODO: aftertouch not supported yet                  crossfadeVolume = Engine::CrossfadeCurve[CrossfadeAttenuation(pEngineChannel->ControllerTable[128])];
128                  break;                  break;
129              case ::gig::attenuation_ctrl_t::type_velocity:              case ::gig::attenuation_ctrl_t::type_velocity:
130                  crossfadeVolume = Engine::CrossfadeCurve[CrossfadeAttenuation(itNoteOnEvent->Param.Note.Velocity)];                  crossfadeVolume = Engine::CrossfadeCurve[CrossfadeAttenuation(itNoteOnEvent->Param.Note.Velocity)];
# Line 136  namespace LinuxSampler { namespace gig { Line 142  namespace LinuxSampler { namespace gig {
142    
143          float subfragmentRate = pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;          float subfragmentRate = pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;
144          CrossfadeSmoother.trigger(crossfadeVolume, subfragmentRate);          CrossfadeSmoother.trigger(crossfadeVolume, subfragmentRate);
145          VolumeSmoother.trigger(pEngineChannel->GlobalVolume, subfragmentRate);          VolumeSmoother.trigger(pEngineChannel->MidiVolume, subfragmentRate);
146          PanLeftSmoother.trigger(pEngineChannel->GlobalPanLeft, subfragmentRate);          PanLeftSmoother.trigger(pEngineChannel->GlobalPanLeft, subfragmentRate);
147          PanRightSmoother.trigger(pEngineChannel->GlobalPanRight, subfragmentRate);          PanRightSmoother.trigger(pEngineChannel->GlobalPanRight, subfragmentRate);
148    
# Line 150  namespace LinuxSampler { namespace gig { Line 156  namespace LinuxSampler { namespace gig {
156          const DLS::sample_loop_t& loopinfo = pDimRgn->pSampleLoops[0];          const DLS::sample_loop_t& loopinfo = pDimRgn->pSampleLoops[0];
157    
158          if (DiskVoice) { // voice to be streamed from disk          if (DiskVoice) { // voice to be streamed from disk
159              MaxRAMPos = cachedsamples - (pEngine->MaxSamplesPerCycle << CONFIG_MAX_PITCH) / pSample->Channels; //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)              if (cachedsamples > (pEngine->MaxSamplesPerCycle << CONFIG_MAX_PITCH)) {
160                    MaxRAMPos = cachedsamples - (pEngine->MaxSamplesPerCycle << CONFIG_MAX_PITCH) / pSample->Channels; //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)
161                } else {
162                    // The cache is too small to fit a max sample buffer.
163                    // Setting MaxRAMPos to 0 will probably cause a click
164                    // in the audio, but it's better than not handling
165                    // this case at all, which would have caused the
166                    // unsigned MaxRAMPos to be set to a negative number.
167                    MaxRAMPos = 0;
168                }
169    
170              // check if there's a loop defined which completely fits into the cached (RAM) part of the sample              // check if there's a loop defined which completely fits into the cached (RAM) part of the sample
171              RAMLoop = (pDimRgn->SampleLoops && (loopinfo.LoopStart + loopinfo.LoopLength) <= MaxRAMPos);              RAMLoop = (pDimRgn->SampleLoops && (loopinfo.LoopStart + loopinfo.LoopLength) <= MaxRAMPos);
# Line 177  namespace LinuxSampler { namespace gig { Line 192  namespace LinuxSampler { namespace gig {
192    
193          // calculate initial pitch value          // calculate initial pitch value
194          {          {
195              double pitchbasecents = pDimRgn->FineTune + (int) pEngine->ScaleTuning[MIDIKey % 12];              double pitchbasecents = pEngineChannel->pInstrument->FineTune + pDimRgn->FineTune + pEngine->ScaleTuning[MIDIKey % 12];
196              if (pDimRgn->PitchTrack) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;  
197              this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents) * (double(pSample->SamplesPerSecond) / double(pEngine->SampleRate));              // GSt behaviour: maximum transpose up is 40 semitones. If
198              this->PitchBend = RTMath::CentsToFreqRatio(((double) PitchBend / 8192.0) * 200.0); // pitchbend wheel +-2 semitones = 200 cents              // MIDI key is more than 40 semitones above unity note,
199                // the transpose is not done.
200                if (pDimRgn->PitchTrack && (MIDIKey - (int) pDimRgn->UnityNote) < 40) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;
201    
202                this->PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(pSample->SamplesPerSecond) / double(pEngine->SampleRate));
203                this->PitchBendRange = 1.0 / 8192.0 * 100.0 * pEngineChannel->pInstrument->PitchbendRange;
204                this->PitchBend = RTMath::CentsToFreqRatio(PitchBend * PitchBendRange);
205          }          }
206    
207          // 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
# Line 195  namespace LinuxSampler { namespace gig { Line 216  namespace LinuxSampler { namespace gig {
216                      eg1controllervalue = 0;                      eg1controllervalue = 0;
217                      break;                      break;
218                  case ::gig::eg1_ctrl_t::type_channelaftertouch:                  case ::gig::eg1_ctrl_t::type_channelaftertouch:
219                      eg1controllervalue = 0; // TODO: aftertouch not yet supported                      eg1controllervalue = pEngineChannel->ControllerTable[128];
220                      break;                      break;
221                  case ::gig::eg1_ctrl_t::type_velocity:                  case ::gig::eg1_ctrl_t::type_velocity:
222                      eg1controllervalue = itNoteOnEvent->Param.Note.Velocity;                      eg1controllervalue = itNoteOnEvent->Param.Note.Velocity;
# Line 236  namespace LinuxSampler { namespace gig { Line 257  namespace LinuxSampler { namespace gig {
257          else          else
258  #else  #else
259          {          {
260              float finalVolume = pEngineChannel->GlobalVolume * crossfadeVolume * EG1.getLevel();              float finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * EG1.getLevel();
261    
262              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * pEngineChannel->GlobalPanLeft;              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * pEngineChannel->GlobalPanLeft;
263              finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * pEngineChannel->GlobalPanRight;              finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * pEngineChannel->GlobalPanRight;
# Line 253  namespace LinuxSampler { namespace gig { Line 274  namespace LinuxSampler { namespace gig {
274                      eg2controllervalue = 0;                      eg2controllervalue = 0;
275                      break;                      break;
276                  case ::gig::eg2_ctrl_t::type_channelaftertouch:                  case ::gig::eg2_ctrl_t::type_channelaftertouch:
277                      eg2controllervalue = 0; // TODO: aftertouch not yet supported                      eg2controllervalue = pEngineChannel->ControllerTable[128];
278                      break;                      break;
279                  case ::gig::eg2_ctrl_t::type_velocity:                  case ::gig::eg2_ctrl_t::type_velocity:
280                      eg2controllervalue = itNoteOnEvent->Param.Note.Velocity;                      eg2controllervalue = itNoteOnEvent->Param.Note.Velocity;
# Line 333  namespace LinuxSampler { namespace gig { Line 354  namespace LinuxSampler { namespace gig {
354              }              }
355              if (bLFO1Enabled) {              if (bLFO1Enabled) {
356                  pLFO1->trigger(pDimRgn->LFO1Frequency,                  pLFO1->trigger(pDimRgn->LFO1Frequency,
357                                 start_level_max,                                 start_level_min,
358                                 lfo1_internal_depth,                                 lfo1_internal_depth,
359                                 pDimRgn->LFO1ControlDepth,                                 pDimRgn->LFO1ControlDepth,
360                                 pDimRgn->LFO1FlipPhase,                                 pDimRgn->LFO1FlipPhase,
# Line 405  namespace LinuxSampler { namespace gig { Line 426  namespace LinuxSampler { namespace gig {
426                      break;                      break;
427                  case ::gig::lfo3_ctrl_aftertouch:                  case ::gig::lfo3_ctrl_aftertouch:
428                      lfo3_internal_depth  = 0;                      lfo3_internal_depth  = 0;
429                      pLFO3->ExtController = 0; // TODO: aftertouch not implemented yet                      pLFO3->ExtController = 128;
430                      bLFO3Enabled         = false; // see TODO comment in line above                      bLFO3Enabled         = true;
431                      break;                      break;
432                  case ::gig::lfo3_ctrl_internal_modwheel:                  case ::gig::lfo3_ctrl_internal_modwheel:
433                      lfo3_internal_depth  = pDimRgn->LFO3InternalDepth;                      lfo3_internal_depth  = pDimRgn->LFO3InternalDepth;
# Line 415  namespace LinuxSampler { namespace gig { Line 436  namespace LinuxSampler { namespace gig {
436                      break;                      break;
437                  case ::gig::lfo3_ctrl_internal_aftertouch:                  case ::gig::lfo3_ctrl_internal_aftertouch:
438                      lfo3_internal_depth  = pDimRgn->LFO3InternalDepth;                      lfo3_internal_depth  = pDimRgn->LFO3InternalDepth;
439                      pLFO1->ExtController = 0; // TODO: aftertouch not implemented yet                      pLFO1->ExtController = 128;
440                      bLFO3Enabled         = (lfo3_internal_depth > 0 /*|| pDimRgn->LFO3ControlDepth > 0*/); // see TODO comment in line above                      bLFO3Enabled         = (lfo3_internal_depth > 0 || pDimRgn->LFO3ControlDepth > 0);
441                      break;                      break;
442                  default:                  default:
443                      lfo3_internal_depth  = 0;                      lfo3_internal_depth  = 0;
# Line 473  namespace LinuxSampler { namespace gig { Line 494  namespace LinuxSampler { namespace gig {
494                  case ::gig::vcf_cutoff_ctrl_genpurpose8:                  case ::gig::vcf_cutoff_ctrl_genpurpose8:
495                      VCFCutoffCtrl.controller = 83;                      VCFCutoffCtrl.controller = 83;
496                      break;                      break;
497                  case ::gig::vcf_cutoff_ctrl_aftertouch: //TODO: not implemented yet                  case ::gig::vcf_cutoff_ctrl_aftertouch:
498                        VCFCutoffCtrl.controller = 128;
499                        break;
500                  case ::gig::vcf_cutoff_ctrl_none:                  case ::gig::vcf_cutoff_ctrl_none:
501                  default:                  default:
502                      VCFCutoffCtrl.controller = 0;                      VCFCutoffCtrl.controller = 0;
# Line 507  namespace LinuxSampler { namespace gig { Line 530  namespace LinuxSampler { namespace gig {
530              finalSynthesisParameters.filterLeft.SetType(pDimRgn->VCFType);              finalSynthesisParameters.filterLeft.SetType(pDimRgn->VCFType);
531              finalSynthesisParameters.filterRight.SetType(pDimRgn->VCFType);              finalSynthesisParameters.filterRight.SetType(pDimRgn->VCFType);
532              #else // override filter type              #else // override filter type
533              FilterLeft.SetType(CONFIG_OVERRIDE_FILTER_TYPE);              finalSynthesisParameters.filterLeft.SetType(CONFIG_OVERRIDE_FILTER_TYPE);
534              FilterRight.SetType(CONFIG_OVERRIDE_FILTER_TYPE);              finalSynthesisParameters.filterRight.SetType(CONFIG_OVERRIDE_FILTER_TYPE);
535              #endif // CONFIG_OVERRIDE_FILTER_TYPE              #endif // CONFIG_OVERRIDE_FILTER_TYPE
536    
537              VCFCutoffCtrl.value    = pEngineChannel->ControllerTable[VCFCutoffCtrl.controller];              VCFCutoffCtrl.value    = pEngineChannel->ControllerTable[VCFCutoffCtrl.controller];
# Line 614  namespace LinuxSampler { namespace gig { Line 637  namespace LinuxSampler { namespace gig {
637                          }                          }
638                      }                      }
639    
640                      sample_t* ptr = DiskStreamRef.pStream->GetReadPtr(); // get the current read_ptr within the ringbuffer where we read the samples from                      sample_t* ptr = (sample_t*)DiskStreamRef.pStream->GetReadPtr(); // get the current read_ptr within the ringbuffer where we read the samples from
641    
642                      // render current audio fragment                      // render current audio fragment
643                      Synthesize(Samples, ptr, Delay);                      Synthesize(Samples, ptr, Delay);
# Line 712  namespace LinuxSampler { namespace gig { Line 735  namespace LinuxSampler { namespace gig {
735                      CrossfadeSmoother.update(Engine::CrossfadeCurve[CrossfadeAttenuation(itEvent->Param.CC.Value)]);                      CrossfadeSmoother.update(Engine::CrossfadeCurve[CrossfadeAttenuation(itEvent->Param.CC.Value)]);
736                  }                  }
737                  if (itEvent->Param.CC.Controller == 7) { // volume                  if (itEvent->Param.CC.Controller == 7) { // volume
738                      VolumeSmoother.update(Engine::VolumeCurve[itEvent->Param.CC.Value] * CONFIG_GLOBAL_ATTENUATION);                      VolumeSmoother.update(Engine::VolumeCurve[itEvent->Param.CC.Value]);
739                  } else if (itEvent->Param.CC.Controller == 10) { // panpot                  } else if (itEvent->Param.CC.Controller == 10) { // panpot
740                      PanLeftSmoother.update(Engine::PanCurve[128 - itEvent->Param.CC.Value]);                      PanLeftSmoother.update(Engine::PanCurve[128 - itEvent->Param.CC.Value]);
741                      PanRightSmoother.update(Engine::PanCurve[itEvent->Param.CC.Value]);                      PanRightSmoother.update(Engine::PanCurve[itEvent->Param.CC.Value]);
# Line 724  namespace LinuxSampler { namespace gig { Line 747  namespace LinuxSampler { namespace gig {
747      }      }
748    
749      void Voice::processPitchEvent(RTList<Event>::Iterator& itEvent) {      void Voice::processPitchEvent(RTList<Event>::Iterator& itEvent) {
750          const float pitch = RTMath::CentsToFreqRatio(((double) itEvent->Param.Pitch.Pitch / 8192.0) * 200.0); // +-two semitones = +-200 cents          PitchBend = RTMath::CentsToFreqRatio(itEvent->Param.Pitch.Pitch * PitchBendRange);
         finalSynthesisParameters.fFinalPitch *= pitch;  
         PitchBend = pitch;  
751      }      }
752    
753      void Voice::processCutoffEvent(RTList<Event>::Iterator& itEvent) {      void Voice::processCutoffEvent(RTList<Event>::Iterator& itEvent) {
# Line 761  namespace LinuxSampler { namespace gig { Line 782  namespace LinuxSampler { namespace gig {
782       *  @param Skip    - number of sample points to skip in output buffer       *  @param Skip    - number of sample points to skip in output buffer
783       */       */
784      void Voice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {      void Voice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {
785          finalSynthesisParameters.pOutLeft  = &pEngineChannel->pOutputLeft[Skip];          finalSynthesisParameters.pOutLeft  = &pEngineChannel->pChannelLeft->Buffer()[Skip];
786          finalSynthesisParameters.pOutRight = &pEngineChannel->pOutputRight[Skip];          finalSynthesisParameters.pOutRight = &pEngineChannel->pChannelRight->Buffer()[Skip];
787          finalSynthesisParameters.pSrc      = pSrc;          finalSynthesisParameters.pSrc      = pSrc;
788    
789          RTList<Event>::Iterator itCCEvent = pEngineChannel->pEvents->first();          RTList<Event>::Iterator itCCEvent = pEngineChannel->pEvents->first();
790          RTList<Event>::Iterator itNoteEvent = pEngineChannel->pMIDIKeyInfo[MIDIKey].pEvents->first();          RTList<Event>::Iterator itNoteEvent = pEngineChannel->pMIDIKeyInfo[MIDIKey].pEvents->first();
791    
792          if (Skip) { // skip events that happened before this voice was triggered          if (itTriggerEvent) { // skip events that happened before this voice was triggered
793              while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;              while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;
794              while (itNoteEvent && itNoteEvent->FragmentPos() <= Skip) ++itNoteEvent;              // we can't simply compare the timestamp here, because note events
795                // might happen on the same time stamp, so we have to deal on the
796                // actual sequence the note events arrived instead (see bug #112)
797                for (; itNoteEvent; ++itNoteEvent) {
798                    if (itTriggerEvent == itNoteEvent) {
799                        ++itNoteEvent;
800                        break;
801                    }
802                }
803          }          }
804    
805          uint killPos;          uint killPos;
806          if (itKillEvent) killPos = RTMath::Min(itKillEvent->FragmentPos(), pEngine->MaxFadeOutPos);          if (itKillEvent) {
807                int maxFadeOutPos = Samples - pEngine->MinFadeOutSamples;
808                if (maxFadeOutPos < 0) {
809                    // There's not enough space in buffer to do a fade out
810                    // from max volume (this can only happen for audio
811                    // drivers that use Samples < MaxSamplesPerCycle).
812                    // End the EG1 here, at pos 0, with a shorter max fade
813                    // out time.
814                    EG1.enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
815                    itKillEvent = Pool<Event>::Iterator();
816                } else {
817                    killPos = RTMath::Min(itKillEvent->FragmentPos(), maxFadeOutPos);
818                }
819            }
820    
821          uint i = Skip;          uint i = Skip;
822          while (i < Samples) {          while (i < Samples) {
823              int iSubFragmentEnd = RTMath::Min(i + CONFIG_DEFAULT_SUBFRAGMENT_SIZE, Samples);              int iSubFragmentEnd = RTMath::Min(i + CONFIG_DEFAULT_SUBFRAGMENT_SIZE, Samples);
824    
825              // initialize all final synthesis parameters              // initialize all final synthesis parameters
             finalSynthesisParameters.fFinalPitch = PitchBase * PitchBend;  
826              fFinalCutoff    = VCFCutoffCtrl.fvalue;              fFinalCutoff    = VCFCutoffCtrl.fvalue;
827              fFinalResonance = VCFResonanceCtrl.fvalue;              fFinalResonance = VCFResonanceCtrl.fvalue;
828    
829              // process MIDI control change and pitchbend events for this subfragment              // process MIDI control change and pitchbend events for this subfragment
830              processCCEvents(itCCEvent, iSubFragmentEnd);              processCCEvents(itCCEvent, iSubFragmentEnd);
831    
832                finalSynthesisParameters.fFinalPitch = PitchBase * PitchBend;
833              float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render();              float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render();
834  #ifdef CONFIG_PROCESS_MUTED_CHANNELS  #ifdef CONFIG_PROCESS_MUTED_CHANNELS
835              if (pEngineChannel->GetMute()) fFinalVolume = 0;              if (pEngineChannel->GetMute()) fFinalVolume = 0;
# Line 796  namespace LinuxSampler { namespace gig { Line 838  namespace LinuxSampler { namespace gig {
838              // process transition events (note on, note off & sustain pedal)              // process transition events (note on, note off & sustain pedal)
839              processTransitionEvents(itNoteEvent, iSubFragmentEnd);              processTransitionEvents(itNoteEvent, iSubFragmentEnd);
840    
841              // if the voice was killed in this subfragment switch EG1 to fade out stage              // if the voice was killed in this subfragment, or if the
842              if (itKillEvent && killPos <= iSubFragmentEnd) {              // filter EG is finished, switch EG1 to fade out stage
843                if ((itKillEvent && killPos <= iSubFragmentEnd) ||
844                    (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&
845                     EG2.getSegmentType() == EGADSR::segment_end)) {
846                  EG1.enterFadeOutStage();                  EG1.enterFadeOutStage();
847                  itKillEvent = Pool<Event>::Iterator();                  itKillEvent = Pool<Event>::Iterator();
848              }              }
# Line 828  namespace LinuxSampler { namespace gig { Line 873  namespace LinuxSampler { namespace gig {
873              if (EG3.active()) finalSynthesisParameters.fFinalPitch *= EG3.render();              if (EG3.active()) finalSynthesisParameters.fFinalPitch *= EG3.render();
874    
875              // process low frequency oscillators              // process low frequency oscillators
876              if (bLFO1Enabled) fFinalVolume *= pLFO1->render();              if (bLFO1Enabled) fFinalVolume *= (1.0f - pLFO1->render());
877              if (bLFO2Enabled) fFinalCutoff *= pLFO2->render();              if (bLFO2Enabled) fFinalCutoff *= pLFO2->render();
878              if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());              if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());
879    
880                // limit the pitch so we don't read outside the buffer
881                finalSynthesisParameters.fFinalPitch = RTMath::Min(finalSynthesisParameters.fFinalPitch, float(1 << CONFIG_MAX_PITCH));
882    
883              // if filter enabled then update filter coefficients              // if filter enabled then update filter coefficients
884              if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode)) {              if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode)) {
885                  finalSynthesisParameters.filterLeft.SetParameters(fFinalCutoff, fFinalResonance, pEngine->SampleRate);                  finalSynthesisParameters.filterLeft.SetParameters(fFinalCutoff, fFinalResonance, pEngine->SampleRate);
# Line 910  namespace LinuxSampler { namespace gig { Line 958  namespace LinuxSampler { namespace gig {
958       *  fading down the volume level to avoid clicks and regular processing       *  fading down the volume level to avoid clicks and regular processing
959       *  until the kill event actually occured!       *  until the kill event actually occured!
960       *       *
961       *  @see Kill()       * If it's necessary to know when the voice's disk stream was actually
962         * deleted, then one can set the optional @a bRequestNotification
963         * parameter and this method will then return the handle of the disk
964         * stream (unique identifier) and one can use this handle to poll the
965         * disk thread if this stream has been deleted. In any case this method
966         * will return immediately and will not block until the stream actually
967         * was deleted.
968         *
969         * @param bRequestNotification - (optional) whether the disk thread shall
970         *                                provide a notification once it deleted
971         *                               the respective disk stream
972         *                               (default=false)
973         * @returns handle to the voice's disk stream or @c Stream::INVALID_HANDLE
974         *          if the voice did not use a disk stream at all
975         * @see Kill()
976       */       */
977      void Voice::KillImmediately() {      Stream::Handle Voice::KillImmediately(bool bRequestNotification) {
978            Stream::Handle hStream = Stream::INVALID_HANDLE;
979          if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {          if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {
980              pDiskThread->OrderDeletionOfStream(&DiskStreamRef);              pDiskThread->OrderDeletionOfStream(&DiskStreamRef, bRequestNotification);
981                hStream = DiskStreamRef.hStream;
982          }          }
983          Reset();          Reset();
984            return hStream;
985      }      }
986    
987      /**      /**

Legend:
Removed from v.877  
changed lines
  Added in v.1923

  ViewVC Help
Powered by ViewVC