/[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 1001 by schoenebeck, Wed Dec 27 16:17:08 2006 UTC revision 1862 by persson, Wed Mar 11 19:03:37 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 103  namespace LinuxSampler { namespace gig { Line 104  namespace LinuxSampler { namespace gig {
104          // -1.0..1.0). For 24 bit, we downscale from int32.          // -1.0..1.0). For 24 bit, we downscale from int32.
105          float volume = velocityAttenuation / (pSample->BitDepth == 16 ? 32768.0f : 32768.0f * 65536.0f);          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 141  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 * pEngineChannel->MidiVolume, 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 182  namespace LinuxSampler { namespace gig { Line 183  namespace LinuxSampler { namespace gig {
183    
184          // calculate initial pitch value          // calculate initial pitch value
185          {          {
186              double pitchbasecents = pDimRgn->FineTune + (int) pEngine->ScaleTuning[MIDIKey % 12];              double pitchbasecents = pEngineChannel->pInstrument->FineTune + pDimRgn->FineTune + pEngine->ScaleTuning[MIDIKey % 12];
187              if (pDimRgn->PitchTrack) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;  
188              this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents) * (double(pSample->SamplesPerSecond) / double(pEngine->SampleRate));              // GSt behaviour: maximum transpose up is 40 semitones. If
189              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,
190                // the transpose is not done.
191                if (pDimRgn->PitchTrack && (MIDIKey - (int) pDimRgn->UnityNote) < 40) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;
192    
193                this->PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(pSample->SamplesPerSecond) / double(pEngine->SampleRate));
194                this->PitchBend = RTMath::CentsToFreqRatio(PitchBend / 8192.0 * 100.0 * pEngineChannel->pInstrument->PitchbendRange);
195          }          }
196    
197          // 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 241  namespace LinuxSampler { namespace gig { Line 247  namespace LinuxSampler { namespace gig {
247          else          else
248  #else  #else
249          {          {
250              float finalVolume = pEngineChannel->GlobalVolume * pEngineChannel->MidiVolume * crossfadeVolume * EG1.getLevel();              float finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * EG1.getLevel();
251    
252              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * pEngineChannel->GlobalPanLeft;              finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * pEngineChannel->GlobalPanLeft;
253              finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * pEngineChannel->GlobalPanRight;              finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * pEngineChannel->GlobalPanRight;
# Line 514  namespace LinuxSampler { namespace gig { Line 520  namespace LinuxSampler { namespace gig {
520              finalSynthesisParameters.filterLeft.SetType(pDimRgn->VCFType);              finalSynthesisParameters.filterLeft.SetType(pDimRgn->VCFType);
521              finalSynthesisParameters.filterRight.SetType(pDimRgn->VCFType);              finalSynthesisParameters.filterRight.SetType(pDimRgn->VCFType);
522              #else // override filter type              #else // override filter type
523              FilterLeft.SetType(CONFIG_OVERRIDE_FILTER_TYPE);              finalSynthesisParameters.filterLeft.SetType(CONFIG_OVERRIDE_FILTER_TYPE);
524              FilterRight.SetType(CONFIG_OVERRIDE_FILTER_TYPE);              finalSynthesisParameters.filterRight.SetType(CONFIG_OVERRIDE_FILTER_TYPE);
525              #endif // CONFIG_OVERRIDE_FILTER_TYPE              #endif // CONFIG_OVERRIDE_FILTER_TYPE
526    
527              VCFCutoffCtrl.value    = pEngineChannel->ControllerTable[VCFCutoffCtrl.controller];              VCFCutoffCtrl.value    = pEngineChannel->ControllerTable[VCFCutoffCtrl.controller];
# Line 731  namespace LinuxSampler { namespace gig { Line 737  namespace LinuxSampler { namespace gig {
737      }      }
738    
739      void Voice::processPitchEvent(RTList<Event>::Iterator& itEvent) {      void Voice::processPitchEvent(RTList<Event>::Iterator& itEvent) {
740          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 / 8192.0 * 100.0 * pEngineChannel->pInstrument->PitchbendRange);
         finalSynthesisParameters.fFinalPitch *= pitch;  
         PitchBend = pitch;  
741      }      }
742    
743      void Voice::processCutoffEvent(RTList<Event>::Iterator& itEvent) {      void Voice::processCutoffEvent(RTList<Event>::Iterator& itEvent) {
# Line 775  namespace LinuxSampler { namespace gig { Line 779  namespace LinuxSampler { namespace gig {
779          RTList<Event>::Iterator itCCEvent = pEngineChannel->pEvents->first();          RTList<Event>::Iterator itCCEvent = pEngineChannel->pEvents->first();
780          RTList<Event>::Iterator itNoteEvent = pEngineChannel->pMIDIKeyInfo[MIDIKey].pEvents->first();          RTList<Event>::Iterator itNoteEvent = pEngineChannel->pMIDIKeyInfo[MIDIKey].pEvents->first();
781    
782          if (Skip) { // skip events that happened before this voice was triggered          if (itTriggerEvent) { // skip events that happened before this voice was triggered
783              while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;              while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;
784              while (itNoteEvent && itNoteEvent->FragmentPos() <= Skip) ++itNoteEvent;              // we can't simply compare the timestamp here, because note events
785                // might happen on the same time stamp, so we have to deal on the
786                // actual sequence the note events arrived instead (see bug #112)
787                for (; itNoteEvent; ++itNoteEvent) {
788                    if (itTriggerEvent == itNoteEvent) {
789                        ++itNoteEvent;
790                        break;
791                    }
792                }
793          }          }
794    
795          uint killPos;          uint killPos;
796          if (itKillEvent) killPos = RTMath::Min(itKillEvent->FragmentPos(), pEngine->MaxFadeOutPos);          if (itKillEvent) {
797                int maxFadeOutPos = Samples - pEngine->MinFadeOutSamples;
798                if (maxFadeOutPos < 0) {
799                    // There's not enough space in buffer to do a fade out
800                    // from max volume (this can only happen for audio
801                    // drivers that use Samples < MaxSamplesPerCycle).
802                    // End the EG1 here, at pos 0, with a shorter max fade
803                    // out time.
804                    EG1.enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
805                    itKillEvent = Pool<Event>::Iterator();
806                } else {
807                    killPos = RTMath::Min(itKillEvent->FragmentPos(), maxFadeOutPos);
808                }
809            }
810    
811          uint i = Skip;          uint i = Skip;
812          while (i < Samples) {          while (i < Samples) {
813              int iSubFragmentEnd = RTMath::Min(i + CONFIG_DEFAULT_SUBFRAGMENT_SIZE, Samples);              int iSubFragmentEnd = RTMath::Min(i + CONFIG_DEFAULT_SUBFRAGMENT_SIZE, Samples);
814    
815              // initialize all final synthesis parameters              // initialize all final synthesis parameters
             finalSynthesisParameters.fFinalPitch = PitchBase * PitchBend;  
816              fFinalCutoff    = VCFCutoffCtrl.fvalue;              fFinalCutoff    = VCFCutoffCtrl.fvalue;
817              fFinalResonance = VCFResonanceCtrl.fvalue;              fFinalResonance = VCFResonanceCtrl.fvalue;
818    
819              // process MIDI control change and pitchbend events for this subfragment              // process MIDI control change and pitchbend events for this subfragment
820              processCCEvents(itCCEvent, iSubFragmentEnd);              processCCEvents(itCCEvent, iSubFragmentEnd);
821    
822                finalSynthesisParameters.fFinalPitch = PitchBase * PitchBend;
823              float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render();              float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render();
824  #ifdef CONFIG_PROCESS_MUTED_CHANNELS  #ifdef CONFIG_PROCESS_MUTED_CHANNELS
825              if (pEngineChannel->GetMute()) fFinalVolume = 0;              if (pEngineChannel->GetMute()) fFinalVolume = 0;
# Line 842  namespace LinuxSampler { namespace gig { Line 867  namespace LinuxSampler { namespace gig {
867              if (bLFO2Enabled) fFinalCutoff *= pLFO2->render();              if (bLFO2Enabled) fFinalCutoff *= pLFO2->render();
868              if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());              if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());
869    
870                // limit the pitch so we don't read outside the buffer
871                finalSynthesisParameters.fFinalPitch = RTMath::Min(finalSynthesisParameters.fFinalPitch, float(1 << CONFIG_MAX_PITCH));
872    
873              // if filter enabled then update filter coefficients              // if filter enabled then update filter coefficients
874              if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode)) {              if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode)) {
875                  finalSynthesisParameters.filterLeft.SetParameters(fFinalCutoff, fFinalResonance, pEngine->SampleRate);                  finalSynthesisParameters.filterLeft.SetParameters(fFinalCutoff, fFinalResonance, pEngine->SampleRate);
# Line 920  namespace LinuxSampler { namespace gig { Line 948  namespace LinuxSampler { namespace gig {
948       *  fading down the volume level to avoid clicks and regular processing       *  fading down the volume level to avoid clicks and regular processing
949       *  until the kill event actually occured!       *  until the kill event actually occured!
950       *       *
951       *  @see Kill()       * If it's necessary to know when the voice's disk stream was actually
952         * deleted, then one can set the optional @a bRequestNotification
953         * parameter and this method will then return the handle of the disk
954         * stream (unique identifier) and one can use this handle to poll the
955         * disk thread if this stream has been deleted. In any case this method
956         * will return immediately and will not block until the stream actually
957         * was deleted.
958         *
959         * @param bRequestNotification - (optional) whether the disk thread shall
960         *                                provide a notification once it deleted
961         *                               the respective disk stream
962         *                               (default=false)
963         * @returns handle to the voice's disk stream or @c Stream::INVALID_HANDLE
964         *          if the voice did not use a disk stream at all
965         * @see Kill()
966       */       */
967      void Voice::KillImmediately() {      Stream::Handle Voice::KillImmediately(bool bRequestNotification) {
968            Stream::Handle hStream = Stream::INVALID_HANDLE;
969          if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {          if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {
970              pDiskThread->OrderDeletionOfStream(&DiskStreamRef);              pDiskThread->OrderDeletionOfStream(&DiskStreamRef, bRequestNotification);
971                hStream = DiskStreamRef.hStream;
972          }          }
973          Reset();          Reset();
974            return hStream;
975      }      }
976    
977      /**      /**

Legend:
Removed from v.1001  
changed lines
  Added in v.1862

  ViewVC Help
Powered by ViewVC