/[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 1321 by schoenebeck, Tue Sep 4 01:12:49 2007 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 - 2007 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 156  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 183  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 732  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 776  namespace LinuxSampler { namespace gig { Line 789  namespace LinuxSampler { namespace gig {
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 843  namespace LinuxSampler { namespace gig { Line 877  namespace LinuxSampler { namespace gig {
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);

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

  ViewVC Help
Powered by ViewVC