/[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 236 by schoenebeck, Thu Sep 9 18:44:18 2004 UTC revision 287 by schoenebeck, Sat Oct 16 17:38:03 2004 UTC
# Line 27  Line 27 
27    
28  namespace LinuxSampler { namespace gig {  namespace LinuxSampler { namespace gig {
29    
     // TODO: no support for crossfades yet  
   
30      const float Voice::FILTER_CUTOFF_COEFF(CalculateFilterCutoffCoeff());      const float Voice::FILTER_CUTOFF_COEFF(CalculateFilterCutoffCoeff());
31    
32      const int Voice::FILTER_UPDATE_MASK(CalculateFilterUpdateMask());      const int Voice::FILTER_UPDATE_MASK(CalculateFilterUpdateMask());
# Line 47  namespace LinuxSampler { namespace gig { Line 45  namespace LinuxSampler { namespace gig {
45      Voice::Voice() {      Voice::Voice() {
46          pEngine     = NULL;          pEngine     = NULL;
47          pDiskThread = NULL;          pDiskThread = NULL;
48          Active = false;          PlaybackState = playback_state_end;
49          pEG1   = NULL;          pEG1   = NULL;
50          pEG2   = NULL;          pEG2   = NULL;
51          pEG3   = NULL;          pEG3   = NULL;
# Line 57  namespace LinuxSampler { namespace gig { Line 55  namespace LinuxSampler { namespace gig {
55          pLFO1  = NULL;          pLFO1  = NULL;
56          pLFO2  = NULL;          pLFO2  = NULL;
57          pLFO3  = NULL;          pLFO3  = NULL;
58            KeyGroup = 0;
59      }      }
60    
61      Voice::~Voice() {      Voice::~Voice() {
# Line 104  namespace LinuxSampler { namespace gig { Line 103  namespace LinuxSampler { namespace gig {
103       *  Initializes and triggers the voice, a disk stream will be launched if       *  Initializes and triggers the voice, a disk stream will be launched if
104       *  needed.       *  needed.
105       *       *
106       *  @param pNoteOnEvent - event that caused triggering of this voice       *  @param itNoteOnEvent       - event that caused triggering of this voice
107       *  @param PitchBend    - MIDI detune factor (-8192 ... +8191)       *  @param PitchBend           - MIDI detune factor (-8192 ... +8191)
108       *  @param pInstrument  - points to the loaded instrument which provides sample wave(s) and articulation data       *  @param pInstrument         - points to the loaded instrument which provides sample wave(s) and articulation data
109       *  @param iLayer       - layer number this voice refers to (only if this is a layered sound of course)       *  @param iLayer              - layer number this voice refers to (only if this is a layered sound of course)
110       *  @returns            0 on success, a value < 0 if something failed       *  @param ReleaseTriggerVoice - if this new voice is a release trigger voice (optional, default = false)
111         *  @param VoiceStealing       - wether the voice is allowed to steal voices for further subvoices
112         *  @returns 0 on success, a value < 0 if something failed
113       */       */
114      int Voice::Trigger(Event* pNoteOnEvent, int PitchBend, ::gig::Instrument* pInstrument, int iLayer) {      int Voice::Trigger(Pool<Event>::Iterator& itNoteOnEvent, int PitchBend, ::gig::Instrument* pInstrument, int iLayer, bool ReleaseTriggerVoice, bool VoiceStealing) {
115          if (!pInstrument) {          if (!pInstrument) {
116             dmsg(1,("voice::trigger: !pInstrument\n"));             dmsg(1,("voice::trigger: !pInstrument\n"));
117             exit(EXIT_FAILURE);             exit(EXIT_FAILURE);
118          }          }
119    
120          Active          = true;          Type            = type_normal;
121          MIDIKey         = pNoteOnEvent->Key;          MIDIKey         = itNoteOnEvent->Param.Note.Key;
122          pRegion         = pInstrument->GetRegion(MIDIKey);          pRegion         = pInstrument->GetRegion(MIDIKey);
123          PlaybackState   = playback_state_ram; // we always start playback from RAM cache and switch then to disk if needed          PlaybackState   = playback_state_ram; // we always start playback from RAM cache and switch then to disk if needed
124          Delay           = pNoteOnEvent->FragmentPos();          Delay           = itNoteOnEvent->FragmentPos();
125          pTriggerEvent   = pNoteOnEvent;          itTriggerEvent  = itNoteOnEvent;
126            itKillEvent     = Pool<Event>::Iterator();
127            itChildVoice    = Pool<Voice>::Iterator();
128    
129          if (!pRegion) {          if (!pRegion) {
130              std::cerr << "gig::Voice: No Region defined for MIDI key " << MIDIKey << std::endl << std::flush;              std::cerr << "gig::Voice: No Region defined for MIDI key " << MIDIKey << std::endl << std::flush;
131              Kill();              KillImmediately();
132              return -1;              return -1;
133          }          }
134    
135            KeyGroup = pRegion->KeyGroup;
136    
137          // get current dimension values to select the right dimension region          // get current dimension values to select the right dimension region
138          //FIXME: controller values for selecting the dimension region here are currently not sample accurate          //FIXME: controller values for selecting the dimension region here are currently not sample accurate
139          uint DimValues[5] = {0,0,0,0,0};          uint DimValues[5] = {0,0,0,0,0};
# Line 142  namespace LinuxSampler { namespace gig { Line 147  namespace LinuxSampler { namespace gig {
147                      // if this is the 1st layer then spawn further voices for all the other layers                      // if this is the 1st layer then spawn further voices for all the other layers
148                      if (iLayer == 0)                      if (iLayer == 0)
149                          for (int iNewLayer = 1; iNewLayer < pRegion->pDimensionDefinitions[i].zones; iNewLayer++)                          for (int iNewLayer = 1; iNewLayer < pRegion->pDimensionDefinitions[i].zones; iNewLayer++)
150                              pEngine->LaunchVoice(pNoteOnEvent, iNewLayer);                              itChildVoice = pEngine->LaunchVoice(itNoteOnEvent, iNewLayer, ReleaseTriggerVoice, VoiceStealing);
151                      break;                      break;
152                  case ::gig::dimension_velocity:                  case ::gig::dimension_velocity:
153                      DimValues[i] = pNoteOnEvent->Velocity;                      DimValues[i] = itNoteOnEvent->Param.Note.Velocity;
154                      break;                      break;
155                  case ::gig::dimension_channelaftertouch:                  case ::gig::dimension_channelaftertouch:
156                      DimValues[i] = 0; //TODO: we currently ignore this dimension                      DimValues[i] = 0; //TODO: we currently ignore this dimension
157                      break;                      break;
158                  case ::gig::dimension_releasetrigger:                  case ::gig::dimension_releasetrigger:
159                      DimValues[i] = 0; //TODO: we currently ignore this dimension                      Type = (ReleaseTriggerVoice) ? type_release_trigger : (!iLayer) ? type_release_trigger_required : type_normal;
160                        DimValues[i] = (uint) ReleaseTriggerVoice;
161                      break;                      break;
162                  case ::gig::dimension_keyboard:                  case ::gig::dimension_keyboard:
163                      DimValues[i] = (uint) pNoteOnEvent->Key;                      DimValues[i] = (uint) itNoteOnEvent->Param.Note.Key;
164                      break;                      break;
165                  case ::gig::dimension_modwheel:                  case ::gig::dimension_modwheel:
166                      DimValues[i] = pEngine->ControllerTable[1];                      DimValues[i] = pEngine->ControllerTable[1];
# Line 240  namespace LinuxSampler { namespace gig { Line 246  namespace LinuxSampler { namespace gig {
246                  CrossfadeVolume = 1.0f; //TODO: aftertouch not supported yet                  CrossfadeVolume = 1.0f; //TODO: aftertouch not supported yet
247                  break;                  break;
248              case ::gig::attenuation_ctrl_t::type_velocity:              case ::gig::attenuation_ctrl_t::type_velocity:
249                  CrossfadeVolume = CrossfadeAttenuation(pNoteOnEvent->Velocity);                  CrossfadeVolume = CrossfadeAttenuation(itNoteOnEvent->Param.Note.Velocity);
250                  break;                  break;
251              case ::gig::attenuation_ctrl_t::type_controlchange: //FIXME: currently not sample accurate              case ::gig::attenuation_ctrl_t::type_controlchange: //FIXME: currently not sample accurate
252                  CrossfadeVolume = CrossfadeAttenuation(pEngine->ControllerTable[pDimRgn->AttenuationController.controller_number]);                  CrossfadeVolume = CrossfadeAttenuation(pEngine->ControllerTable[pDimRgn->AttenuationController.controller_number]);
# Line 250  namespace LinuxSampler { namespace gig { Line 256  namespace LinuxSampler { namespace gig {
256                  CrossfadeVolume = 1.0f;                  CrossfadeVolume = 1.0f;
257          }          }
258    
259            PanLeft  = 1.0f - float(RTMath::Max(pDimRgn->Pan, 0)) /  63.0f;
260            PanRight = 1.0f - float(RTMath::Min(pDimRgn->Pan, 0)) / -64.0f;
261    
262          pSample = pDimRgn->pSample; // sample won't change until the voice is finished          pSample = pDimRgn->pSample; // sample won't change until the voice is finished
263    
264          Pos = pDimRgn->SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)          Pos = pDimRgn->SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)
# Line 270  namespace LinuxSampler { namespace gig { Line 279  namespace LinuxSampler { namespace gig {
279    
280              if (pDiskThread->OrderNewStream(&DiskStreamRef, pSample, MaxRAMPos, !RAMLoop) < 0) {              if (pDiskThread->OrderNewStream(&DiskStreamRef, pSample, MaxRAMPos, !RAMLoop) < 0) {
281                  dmsg(1,("Disk stream order failed!\n"));                  dmsg(1,("Disk stream order failed!\n"));
282                  Kill();                  KillImmediately();
283                  return -1;                  return -1;
284              }              }
285              dmsg(4,("Disk voice launched (cached samples: %d, total Samples: %d, MaxRAMPos: %d, RAMLooping: %s)\n", cachedsamples, pSample->SamplesTotal, MaxRAMPos, (RAMLoop) ? "yes" : "no"));              dmsg(4,("Disk voice launched (cached samples: %d, total Samples: %d, MaxRAMPos: %d, RAMLooping: %s)\n", cachedsamples, pSample->SamplesTotal, MaxRAMPos, (RAMLoop) ? "yes" : "no"));
# Line 288  namespace LinuxSampler { namespace gig { Line 297  namespace LinuxSampler { namespace gig {
297    
298          // calculate initial pitch value          // calculate initial pitch value
299          {          {
300              double pitchbasecents = pDimRgn->FineTune * 10;              double pitchbasecents = pDimRgn->FineTune * 10 + (int) pEngine->ScaleTuning[MIDIKey % 12];
301              if (pDimRgn->PitchTrack) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;              if (pDimRgn->PitchTrack) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;
302              this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents) * (double(pSample->SamplesPerSecond) / double(pEngine->pAudioOutputDevice->SampleRate()));              this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents) * (double(pSample->SamplesPerSecond) / double(pEngine->pAudioOutputDevice->SampleRate()));
303              this->PitchBend = RTMath::CentsToFreqRatio(((double) PitchBend / 8192.0) * 200.0); // pitchbend wheel +-2 semitones = 200 cents              this->PitchBend = RTMath::CentsToFreqRatio(((double) PitchBend / 8192.0) * 200.0); // pitchbend wheel +-2 semitones = 200 cents
304          }          }
305    
306    
307          Volume = pDimRgn->GetVelocityAttenuation(pNoteOnEvent->Velocity) / 32768.0f; // we downscale by 32768 to convert from int16 value range to DSP value range (which is -1.0..1.0)          Volume = pDimRgn->GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity) / 32768.0f; // we downscale by 32768 to convert from int16 value range to DSP value range (which is -1.0..1.0)
308    
309    
310          // setup EG 1 (VCA EG)          // setup EG 1 (VCA EG)
# Line 310  namespace LinuxSampler { namespace gig { Line 319  namespace LinuxSampler { namespace gig {
319                      eg1controllervalue = 0; // TODO: aftertouch not yet supported                      eg1controllervalue = 0; // TODO: aftertouch not yet supported
320                      break;                      break;
321                  case ::gig::eg1_ctrl_t::type_velocity:                  case ::gig::eg1_ctrl_t::type_velocity:
322                      eg1controllervalue = pNoteOnEvent->Velocity;                      eg1controllervalue = itNoteOnEvent->Param.Note.Velocity;
323                      break;                      break;
324                  case ::gig::eg1_ctrl_t::type_controlchange: // MIDI control change controller                  case ::gig::eg1_ctrl_t::type_controlchange: // MIDI control change controller
325                      eg1controllervalue = pEngine->ControllerTable[pDimRgn->EG1Controller.controller_number];                      eg1controllervalue = pEngine->ControllerTable[pDimRgn->EG1Controller.controller_number];
# Line 349  namespace LinuxSampler { namespace gig { Line 358  namespace LinuxSampler { namespace gig {
358                      eg2controllervalue = 0; // TODO: aftertouch not yet supported                      eg2controllervalue = 0; // TODO: aftertouch not yet supported
359                      break;                      break;
360                  case ::gig::eg2_ctrl_t::type_velocity:                  case ::gig::eg2_ctrl_t::type_velocity:
361                      eg2controllervalue = pNoteOnEvent->Velocity;                      eg2controllervalue = itNoteOnEvent->Param.Note.Velocity;
362                      break;                      break;
363                  case ::gig::eg2_ctrl_t::type_controlchange: // MIDI control change controller                  case ::gig::eg2_ctrl_t::type_controlchange: // MIDI control change controller
364                      eg2controllervalue = pEngine->ControllerTable[pDimRgn->EG2Controller.controller_number];                      eg2controllervalue = pEngine->ControllerTable[pDimRgn->EG2Controller.controller_number];
# Line 577  namespace LinuxSampler { namespace gig { Line 586  namespace LinuxSampler { namespace gig {
586    
587              // calculate cutoff frequency              // calculate cutoff frequency
588              float cutoff = (!VCFCutoffCtrl.controller)              float cutoff = (!VCFCutoffCtrl.controller)
589                  ? exp((float) (127 - pNoteOnEvent->Velocity) * (float) pDimRgn->VCFVelocityScale * 6.2E-5f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX                  ? exp((float) (127 - itNoteOnEvent->Param.Note.Velocity) * (float) pDimRgn->VCFVelocityScale * 6.2E-5f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX
590                  : exp((float) VCFCutoffCtrl.value * 0.00787402f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX;                  : exp((float) VCFCutoffCtrl.value * 0.00787402f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX;
591    
592              // calculate resonance              // calculate resonance
593              float resonance = (float) VCFResonanceCtrl.value * 0.00787f;   // 0.0..1.0              float resonance = (float) VCFResonanceCtrl.value * 0.00787f;   // 0.0..1.0
594              if (pDimRgn->VCFKeyboardTracking) {              if (pDimRgn->VCFKeyboardTracking) {
595                  resonance += (float) (pNoteOnEvent->Key - pDimRgn->VCFKeyboardTrackingBreakpoint) * 0.00787f;                  resonance += (float) (itNoteOnEvent->Param.Note.Key - pDimRgn->VCFKeyboardTrackingBreakpoint) * 0.00787f;
596              }              }
597              Constrain(resonance, 0.0, 1.0); // correct resonance if outside allowed value range (0.0..1.0)              Constrain(resonance, 0.0, 1.0); // correct resonance if outside allowed value range (0.0..1.0)
598    
# Line 601  namespace LinuxSampler { namespace gig { Line 610  namespace LinuxSampler { namespace gig {
610          }          }
611      #endif // ENABLE_FILTER      #endif // ENABLE_FILTER
612    
         // ************************************************  
         // TODO: ARTICULATION DATA HANDLING IS MISSING HERE  
         // ************************************************  
   
613          return 0; // success          return 0; // success
614      }      }
615    
# Line 635  namespace LinuxSampler { namespace gig { Line 640  namespace LinuxSampler { namespace gig {
640    
641    
642          // Let all modulators write their parameter changes to the synthesis parameter matrix for the current audio fragment          // Let all modulators write their parameter changes to the synthesis parameter matrix for the current audio fragment
643          pEG1->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, pTriggerEvent, this->Pos, this->PitchBase * this->PitchBend);          pEG1->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, itTriggerEvent, this->Pos, this->PitchBase * this->PitchBend, itKillEvent);
644      #if ENABLE_FILTER      #if ENABLE_FILTER
645          pEG2->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, pTriggerEvent, this->Pos, this->PitchBase * this->PitchBend);          pEG2->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, itTriggerEvent, this->Pos, this->PitchBase * this->PitchBend);
646      #endif // ENABLE_FILTER      #endif // ENABLE_FILTER
647          pEG3->Process(Samples);          pEG3->Process(Samples);
648          pLFO1->Process(Samples);          pLFO1->Process(Samples);
# Line 656  namespace LinuxSampler { namespace gig { Line 661  namespace LinuxSampler { namespace gig {
661    
662              case playback_state_ram: {              case playback_state_ram: {
663                      if (RAMLoop) InterpolateAndLoop(Samples, (sample_t*) pSample->GetCache().pStart, Delay);                      if (RAMLoop) InterpolateAndLoop(Samples, (sample_t*) pSample->GetCache().pStart, Delay);
664                      else         Interpolate(Samples, (sample_t*) pSample->GetCache().pStart, Delay);                      else         InterpolateNoLoop(Samples, (sample_t*) pSample->GetCache().pStart, Delay);
665                      if (DiskVoice) {                      if (DiskVoice) {
666                          // check if we reached the allowed limit of the sample RAM cache                          // check if we reached the allowed limit of the sample RAM cache
667                          if (Pos > MaxRAMPos) {                          if (Pos > MaxRAMPos) {
# Line 676  namespace LinuxSampler { namespace gig { Line 681  namespace LinuxSampler { namespace gig {
681                          DiskStreamRef.pStream = pDiskThread->AskForCreatedStream(DiskStreamRef.OrderID);                          DiskStreamRef.pStream = pDiskThread->AskForCreatedStream(DiskStreamRef.OrderID);
682                          if (!DiskStreamRef.pStream) {                          if (!DiskStreamRef.pStream) {
683                              std::cout << stderr << "Disk stream not available in time!" << std::endl << std::flush;                              std::cout << stderr << "Disk stream not available in time!" << std::endl << std::flush;
684                              Kill();                              KillImmediately();
685                              return;                              return;
686                          }                          }
687                          DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (RTMath::DoubleToInt(Pos) - MaxRAMPos));                          DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (RTMath::DoubleToInt(Pos) - MaxRAMPos));
# Line 690  namespace LinuxSampler { namespace gig { Line 695  namespace LinuxSampler { namespace gig {
695                      }                      }
696    
697                      sample_t* ptr = DiskStreamRef.pStream->GetReadPtr(); // get the current read_ptr within the ringbuffer where we read the samples from                      sample_t* ptr = DiskStreamRef.pStream->GetReadPtr(); // get the current read_ptr within the ringbuffer where we read the samples from
698                      Interpolate(Samples, ptr, Delay);                      InterpolateNoLoop(Samples, ptr, Delay);
699                      DiskStreamRef.pStream->IncrementReadPos(RTMath::DoubleToInt(Pos) * pSample->Channels);                      DiskStreamRef.pStream->IncrementReadPos(RTMath::DoubleToInt(Pos) * pSample->Channels);
700                      Pos -= RTMath::DoubleToInt(Pos);                      Pos -= RTMath::DoubleToInt(Pos);
701                  }                  }
702                  break;                  break;
703    
704              case playback_state_end:              case playback_state_end:
705                  Kill(); // free voice                  std::cerr << "gig::Voice::Render(): entered with playback_state_end, this is a bug!\n" << std::flush;
706                  break;                  break;
707          }          }
708    
# Line 712  namespace LinuxSampler { namespace gig { Line 717  namespace LinuxSampler { namespace gig {
717          // Reset delay          // Reset delay
718          Delay = 0;          Delay = 0;
719    
720          pTriggerEvent = NULL;          itTriggerEvent = Pool<Event>::Iterator();
721    
722          // If release stage finished, let the voice be killed          // If sample stream or release stage finished, kill the voice
723          if (pEG1->GetStage() == EGADSR::stage_end) this->PlaybackState = playback_state_end;          if (PlaybackState == playback_state_end || pEG1->GetStage() == EGADSR::stage_end) KillImmediately();
724      }      }
725    
726      /**      /**
# Line 730  namespace LinuxSampler { namespace gig { Line 735  namespace LinuxSampler { namespace gig {
735          DiskStreamRef.hStream = 0;          DiskStreamRef.hStream = 0;
736          DiskStreamRef.State   = Stream::state_unused;          DiskStreamRef.State   = Stream::state_unused;
737          DiskStreamRef.OrderID = 0;          DiskStreamRef.OrderID = 0;
738          Active = false;          PlaybackState = playback_state_end;
739            itTriggerEvent = Pool<Event>::Iterator();
740            itKillEvent    = Pool<Event>::Iterator();
741      }      }
742    
743      /**      /**
# Line 743  namespace LinuxSampler { namespace gig { Line 750  namespace LinuxSampler { namespace gig {
750      void Voice::ProcessEvents(uint Samples) {      void Voice::ProcessEvents(uint Samples) {
751    
752          // dispatch control change events          // dispatch control change events
753          Event* pCCEvent = pEngine->pCCEvents->first();          RTList<Event>::Iterator itCCEvent = pEngine->pCCEvents->first();
754          if (Delay) { // skip events that happened before this voice was triggered          if (Delay) { // skip events that happened before this voice was triggered
755              while (pCCEvent && pCCEvent->FragmentPos() <= Delay) pCCEvent = pEngine->pCCEvents->next();              while (itCCEvent && itCCEvent->FragmentPos() <= Delay) ++itCCEvent;
756          }          }
757          while (pCCEvent) {          while (itCCEvent) {
758              if (pCCEvent->Controller) { // if valid MIDI controller              if (itCCEvent->Param.CC.Controller) { // if valid MIDI controller
759                  #if ENABLE_FILTER                  #if ENABLE_FILTER
760                  if (pCCEvent->Controller == VCFCutoffCtrl.controller) {                  if (itCCEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {
761                      pEngine->pSynthesisEvents[Event::destination_vcfc]->alloc_assign(*pCCEvent);                      *pEngine->pSynthesisEvents[Event::destination_vcfc]->allocAppend() = *itCCEvent;
762                  }                  }
763                  if (pCCEvent->Controller == VCFResonanceCtrl.controller) {                  if (itCCEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {
764                      pEngine->pSynthesisEvents[Event::destination_vcfr]->alloc_assign(*pCCEvent);                      *pEngine->pSynthesisEvents[Event::destination_vcfr]->allocAppend() = *itCCEvent;
765                  }                  }
766                  #endif // ENABLE_FILTER                  #endif // ENABLE_FILTER
767                  if (pCCEvent->Controller == pLFO1->ExtController) {                  if (itCCEvent->Param.CC.Controller == pLFO1->ExtController) {
768                      pLFO1->SendEvent(pCCEvent);                      pLFO1->SendEvent(itCCEvent);
769                  }                  }
770                  #if ENABLE_FILTER                  #if ENABLE_FILTER
771                  if (pCCEvent->Controller == pLFO2->ExtController) {                  if (itCCEvent->Param.CC.Controller == pLFO2->ExtController) {
772                      pLFO2->SendEvent(pCCEvent);                      pLFO2->SendEvent(itCCEvent);
773                  }                  }
774                  #endif // ENABLE_FILTER                  #endif // ENABLE_FILTER
775                  if (pCCEvent->Controller == pLFO3->ExtController) {                  if (itCCEvent->Param.CC.Controller == pLFO3->ExtController) {
776                      pLFO3->SendEvent(pCCEvent);                      pLFO3->SendEvent(itCCEvent);
777                  }                  }
778                  if (pDimRgn->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange &&                  if (pDimRgn->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange &&
779                      pCCEvent->Controller == pDimRgn->AttenuationController.controller_number) { // if crossfade event                      itCCEvent->Param.CC.Controller == pDimRgn->AttenuationController.controller_number) { // if crossfade event
780                      pEngine->pSynthesisEvents[Event::destination_vca]->alloc_assign(*pCCEvent);                      *pEngine->pSynthesisEvents[Event::destination_vca]->allocAppend() = *itCCEvent;
781                  }                  }
782              }              }
783    
784              pCCEvent = pEngine->pCCEvents->next();              ++itCCEvent;
785          }          }
786    
787    
788          // process pitch events          // process pitch events
789          {          {
790              RTEList<Event>* pVCOEventList = pEngine->pSynthesisEvents[Event::destination_vco];              RTList<Event>* pVCOEventList = pEngine->pSynthesisEvents[Event::destination_vco];
791              Event* pVCOEvent = pVCOEventList->first();              RTList<Event>::Iterator itVCOEvent = pVCOEventList->first();
792              if (Delay) { // skip events that happened before this voice was triggered              if (Delay) { // skip events that happened before this voice was triggered
793                  while (pVCOEvent && pVCOEvent->FragmentPos() <= Delay) pVCOEvent = pVCOEventList->next();                  while (itVCOEvent && itVCOEvent->FragmentPos() <= Delay) ++itVCOEvent;
794              }              }
795              // apply old pitchbend value until first pitch event occurs              // apply old pitchbend value until first pitch event occurs
796              if (this->PitchBend != 1.0) {              if (this->PitchBend != 1.0) {
797                  uint end = (pVCOEvent) ? pVCOEvent->FragmentPos() : Samples;                  uint end = (itVCOEvent) ? itVCOEvent->FragmentPos() : Samples;
798                  for (uint i = Delay; i < end; i++) {                  for (uint i = Delay; i < end; i++) {
799                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= this->PitchBend;                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= this->PitchBend;
800                  }                  }
801              }              }
802              float pitch;              float pitch;
803              while (pVCOEvent) {              while (itVCOEvent) {
804                  Event* pNextVCOEvent = pVCOEventList->next();                  RTList<Event>::Iterator itNextVCOEvent = itVCOEvent;
805                    ++itNextVCOEvent;
806    
807                  // calculate the influence length of this event (in sample points)                  // calculate the influence length of this event (in sample points)
808                  uint end = (pNextVCOEvent) ? pNextVCOEvent->FragmentPos() : Samples;                  uint end = (itNextVCOEvent) ? itNextVCOEvent->FragmentPos() : Samples;
809    
810                  pitch = RTMath::CentsToFreqRatio(((double) pVCOEvent->Pitch / 8192.0) * 200.0); // +-two semitones = +-200 cents                  pitch = RTMath::CentsToFreqRatio(((double) itVCOEvent->Param.Pitch.Pitch / 8192.0) * 200.0); // +-two semitones = +-200 cents
811    
812                  // apply pitch value to the pitch parameter sequence                  // apply pitch value to the pitch parameter sequence
813                  for (uint i = pVCOEvent->FragmentPos(); i < end; i++) {                  for (uint i = itVCOEvent->FragmentPos(); i < end; i++) {
814                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= pitch;                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= pitch;
815                  }                  }
816    
817                  pVCOEvent = pNextVCOEvent;                  itVCOEvent = itNextVCOEvent;
818              }              }
819              if (pVCOEventList->last()) this->PitchBend = pitch;              if (!pVCOEventList->isEmpty()) this->PitchBend = pitch;
820          }          }
821    
822          // process volume / attenuation events (TODO: we only handle and _expect_ crossfade events here ATM !)          // process volume / attenuation events (TODO: we only handle and _expect_ crossfade events here ATM !)
823          {          {
824              RTEList<Event>* pVCAEventList = pEngine->pSynthesisEvents[Event::destination_vca];              RTList<Event>* pVCAEventList = pEngine->pSynthesisEvents[Event::destination_vca];
825              Event* pVCAEvent = pVCAEventList->first();              RTList<Event>::Iterator itVCAEvent = pVCAEventList->first();
826              if (Delay) { // skip events that happened before this voice was triggered              if (Delay) { // skip events that happened before this voice was triggered
827                  while (pVCAEvent && pVCAEvent->FragmentPos() <= Delay) pVCAEvent = pVCAEventList->next();                  while (itVCAEvent && itVCAEvent->FragmentPos() <= Delay) ++itVCAEvent;
828              }              }
829              float crossfadevolume;              float crossfadevolume;
830              while (pVCAEvent) {              while (itVCAEvent) {
831                  Event* pNextVCAEvent = pVCAEventList->next();                  RTList<Event>::Iterator itNextVCAEvent = itVCAEvent;
832                    ++itNextVCAEvent;
833    
834                  // calculate the influence length of this event (in sample points)                  // calculate the influence length of this event (in sample points)
835                  uint end = (pNextVCAEvent) ? pNextVCAEvent->FragmentPos() : Samples;                  uint end = (itNextVCAEvent) ? itNextVCAEvent->FragmentPos() : Samples;
836    
837                  crossfadevolume = CrossfadeAttenuation(pVCAEvent->Value);                  crossfadevolume = CrossfadeAttenuation(itVCAEvent->Param.CC.Value);
838    
839                  float effective_volume = crossfadevolume * this->Volume * pEngine->GlobalVolume;                  float effective_volume = crossfadevolume * this->Volume * pEngine->GlobalVolume;
840    
841                  // apply volume value to the volume parameter sequence                  // apply volume value to the volume parameter sequence
842                  for (uint i = pVCAEvent->FragmentPos(); i < end; i++) {                  for (uint i = itVCAEvent->FragmentPos(); i < end; i++) {
843                      pEngine->pSynthesisParameters[Event::destination_vca][i] = effective_volume;                      pEngine->pSynthesisParameters[Event::destination_vca][i] = effective_volume;
844                  }                  }
845    
846                  pVCAEvent = pNextVCAEvent;                  itVCAEvent = itNextVCAEvent;
847              }              }
848              if (pVCAEventList->last()) this->CrossfadeVolume = crossfadevolume;              if (!pVCAEventList->isEmpty()) this->CrossfadeVolume = crossfadevolume;
849          }          }
850    
851      #if ENABLE_FILTER      #if ENABLE_FILTER
852          // process filter cutoff events          // process filter cutoff events
853          {          {
854              RTEList<Event>* pCutoffEventList = pEngine->pSynthesisEvents[Event::destination_vcfc];              RTList<Event>* pCutoffEventList = pEngine->pSynthesisEvents[Event::destination_vcfc];
855              Event* pCutoffEvent = pCutoffEventList->first();              RTList<Event>::Iterator itCutoffEvent = pCutoffEventList->first();
856              if (Delay) { // skip events that happened before this voice was triggered              if (Delay) { // skip events that happened before this voice was triggered
857                  while (pCutoffEvent && pCutoffEvent->FragmentPos() <= Delay) pCutoffEvent = pCutoffEventList->next();                  while (itCutoffEvent && itCutoffEvent->FragmentPos() <= Delay) ++itCutoffEvent;
858              }              }
859              float cutoff;              float cutoff;
860              while (pCutoffEvent) {              while (itCutoffEvent) {
861                  Event* pNextCutoffEvent = pCutoffEventList->next();                  RTList<Event>::Iterator itNextCutoffEvent = itCutoffEvent;
862                    ++itNextCutoffEvent;
863    
864                  // calculate the influence length of this event (in sample points)                  // calculate the influence length of this event (in sample points)
865                  uint end = (pNextCutoffEvent) ? pNextCutoffEvent->FragmentPos() : Samples;                  uint end = (itNextCutoffEvent) ? itNextCutoffEvent->FragmentPos() : Samples;
866    
867                  cutoff = exp((float) pCutoffEvent->Value * 0.00787402f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX - FILTER_CUTOFF_MIN;                  cutoff = exp((float) itCutoffEvent->Param.CC.Value * 0.00787402f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX - FILTER_CUTOFF_MIN;
868    
869                  // apply cutoff frequency to the cutoff parameter sequence                  // apply cutoff frequency to the cutoff parameter sequence
870                  for (uint i = pCutoffEvent->FragmentPos(); i < end; i++) {                  for (uint i = itCutoffEvent->FragmentPos(); i < end; i++) {
871                      pEngine->pSynthesisParameters[Event::destination_vcfc][i] = cutoff;                      pEngine->pSynthesisParameters[Event::destination_vcfc][i] = cutoff;
872                  }                  }
873    
874                  pCutoffEvent = pNextCutoffEvent;                  itCutoffEvent = itNextCutoffEvent;
875              }              }
876              if (pCutoffEventList->last()) VCFCutoffCtrl.fvalue = cutoff; // needed for initialization of parameter matrix next time              if (!pCutoffEventList->isEmpty()) VCFCutoffCtrl.fvalue = cutoff; // needed for initialization of parameter matrix next time
877          }          }
878    
879          // process filter resonance events          // process filter resonance events
880          {          {
881              RTEList<Event>* pResonanceEventList = pEngine->pSynthesisEvents[Event::destination_vcfr];              RTList<Event>* pResonanceEventList = pEngine->pSynthesisEvents[Event::destination_vcfr];
882              Event* pResonanceEvent = pResonanceEventList->first();              RTList<Event>::Iterator itResonanceEvent = pResonanceEventList->first();
883              if (Delay) { // skip events that happened before this voice was triggered              if (Delay) { // skip events that happened before this voice was triggered
884                  while (pResonanceEvent && pResonanceEvent->FragmentPos() <= Delay) pResonanceEvent = pResonanceEventList->next();                  while (itResonanceEvent && itResonanceEvent->FragmentPos() <= Delay) ++itResonanceEvent;
885              }              }
886              while (pResonanceEvent) {              while (itResonanceEvent) {
887                  Event* pNextResonanceEvent = pResonanceEventList->next();                  RTList<Event>::Iterator itNextResonanceEvent = itResonanceEvent;
888                    ++itNextResonanceEvent;
889    
890                  // calculate the influence length of this event (in sample points)                  // calculate the influence length of this event (in sample points)
891                  uint end = (pNextResonanceEvent) ? pNextResonanceEvent->FragmentPos() : Samples;                  uint end = (itNextResonanceEvent) ? itNextResonanceEvent->FragmentPos() : Samples;
892    
893                  // convert absolute controller value to differential                  // convert absolute controller value to differential
894                  int ctrldelta = pResonanceEvent->Value - VCFResonanceCtrl.value;                  int ctrldelta = itResonanceEvent->Param.CC.Value - VCFResonanceCtrl.value;
895                  VCFResonanceCtrl.value = pResonanceEvent->Value;                  VCFResonanceCtrl.value = itResonanceEvent->Param.CC.Value;
896    
897                  float resonancedelta = (float) ctrldelta * 0.00787f; // 0.0..1.0                  float resonancedelta = (float) ctrldelta * 0.00787f; // 0.0..1.0
898    
899                  // apply cutoff frequency to the cutoff parameter sequence                  // apply cutoff frequency to the cutoff parameter sequence
900                  for (uint i = pResonanceEvent->FragmentPos(); i < end; i++) {                  for (uint i = itResonanceEvent->FragmentPos(); i < end; i++) {
901                      pEngine->pSynthesisParameters[Event::destination_vcfr][i] += resonancedelta;                      pEngine->pSynthesisParameters[Event::destination_vcfr][i] += resonancedelta;
902                  }                  }
903    
904                  pResonanceEvent = pNextResonanceEvent;                  itResonanceEvent = itNextResonanceEvent;
905              }              }
906              if (pResonanceEventList->last()) VCFResonanceCtrl.fvalue = pResonanceEventList->last()->Value * 0.00787f; // needed for initialization of parameter matrix next time              if (!pResonanceEventList->isEmpty()) VCFResonanceCtrl.fvalue = pResonanceEventList->last()->Param.CC.Value * 0.00787f; // needed for initialization of parameter matrix next time
907          }          }
908      #endif // ENABLE_FILTER      #endif // ENABLE_FILTER
909      }      }
# Line 944  namespace LinuxSampler { namespace gig { Line 955  namespace LinuxSampler { namespace gig {
955      #endif // ENABLE_FILTER      #endif // ENABLE_FILTER
956    
957      /**      /**
958       *  Interpolates the input audio data (no loop).       *  Interpolates the input audio data (without looping).
959       *       *
960       *  @param Samples - number of sample points to be rendered in this audio       *  @param Samples - number of sample points to be rendered in this audio
961       *                   fragment cycle       *                   fragment cycle
962       *  @param pSrc    - pointer to input sample data       *  @param pSrc    - pointer to input sample data
963       *  @param Skip    - number of sample points to skip in output buffer       *  @param Skip    - number of sample points to skip in output buffer
964       */       */
965      void Voice::Interpolate(uint Samples, sample_t* pSrc, uint Skip) {      void Voice::InterpolateNoLoop(uint Samples, sample_t* pSrc, uint Skip) {
966          int i = Skip;          int i = Skip;
967    
968          // FIXME: assuming either mono or stereo          // FIXME: assuming either mono or stereo
969          if (this->pSample->Channels == 2) { // Stereo Sample          if (this->pSample->Channels == 2) { // Stereo Sample
970              while (i < Samples) {              while (i < Samples) InterpolateStereo(pSrc, i);
                 InterpolateOneStep_Stereo(pSrc, i,  
                                           pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                           pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                           pEngine->pBasicFilterParameters[i],  
                                           pEngine->pMainFilterParameters[i]);  
             }  
971          }          }
972          else { // Mono Sample          else { // Mono Sample
973              while (i < Samples) {              while (i < Samples) InterpolateMono(pSrc, i);
                 InterpolateOneStep_Mono(pSrc, i,  
                                         pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                         pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                         pEngine->pBasicFilterParameters[i],  
                                         pEngine->pMainFilterParameters[i]);  
             }  
974          }          }
975      }      }
976    
# Line 991  namespace LinuxSampler { namespace gig { Line 990  namespace LinuxSampler { namespace gig {
990              if (pSample->LoopPlayCount) {              if (pSample->LoopPlayCount) {
991                  // render loop (loop count limited)                  // render loop (loop count limited)
992                  while (i < Samples && LoopCyclesLeft) {                  while (i < Samples && LoopCyclesLeft) {
993                      InterpolateOneStep_Stereo(pSrc, i,                      InterpolateStereo(pSrc, i);
                                               pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                               pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                               pEngine->pBasicFilterParameters[i],  
                                               pEngine->pMainFilterParameters[i]);  
994                      if (Pos > pSample->LoopEnd) {                      if (Pos > pSample->LoopEnd) {
995                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;
996                          LoopCyclesLeft--;                          LoopCyclesLeft--;
997                      }                      }
998                  }                  }
999                  // render on without loop                  // render on without loop
1000                  while (i < Samples) {                  while (i < Samples) InterpolateStereo(pSrc, i);
                     InterpolateOneStep_Stereo(pSrc, i,  
                                               pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                               pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                               pEngine->pBasicFilterParameters[i],  
                                               pEngine->pMainFilterParameters[i]);  
                 }  
1001              }              }
1002              else { // render loop (endless loop)              else { // render loop (endless loop)
1003                  while (i < Samples) {                  while (i < Samples) {
1004                      InterpolateOneStep_Stereo(pSrc, i,                      InterpolateStereo(pSrc, i);
                                               pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                               pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                               pEngine->pBasicFilterParameters[i],  
                                               pEngine->pMainFilterParameters[i]);  
1005                      if (Pos > pSample->LoopEnd) {                      if (Pos > pSample->LoopEnd) {
1006                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);
1007                      }                      }
# Line 1027  namespace LinuxSampler { namespace gig { Line 1012  namespace LinuxSampler { namespace gig {
1012              if (pSample->LoopPlayCount) {              if (pSample->LoopPlayCount) {
1013                  // render loop (loop count limited)                  // render loop (loop count limited)
1014                  while (i < Samples && LoopCyclesLeft) {                  while (i < Samples && LoopCyclesLeft) {
1015                      InterpolateOneStep_Mono(pSrc, i,                      InterpolateMono(pSrc, i);
                                             pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                             pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                             pEngine->pBasicFilterParameters[i],  
                                             pEngine->pMainFilterParameters[i]);  
1016                      if (Pos > pSample->LoopEnd) {                      if (Pos > pSample->LoopEnd) {
1017                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;
1018                          LoopCyclesLeft--;                          LoopCyclesLeft--;
1019                      }                      }
1020                  }                  }
1021                  // render on without loop                  // render on without loop
1022                  while (i < Samples) {                  while (i < Samples) InterpolateMono(pSrc, i);
                     InterpolateOneStep_Mono(pSrc, i,  
                                             pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                             pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                             pEngine->pBasicFilterParameters[i],  
                                             pEngine->pMainFilterParameters[i]);  
                 }  
1023              }              }
1024              else { // render loop (endless loop)              else { // render loop (endless loop)
1025                  while (i < Samples) {                  while (i < Samples) {
1026                      InterpolateOneStep_Mono(pSrc, i,                      InterpolateMono(pSrc, i);
                                             pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                             pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                             pEngine->pBasicFilterParameters[i],  
                                             pEngine->pMainFilterParameters[i]);  
1027                      if (Pos > pSample->LoopEnd) {                      if (Pos > pSample->LoopEnd) {
1028                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;
1029                      }                      }
# Line 1062  namespace LinuxSampler { namespace gig { Line 1033  namespace LinuxSampler { namespace gig {
1033      }      }
1034    
1035      /**      /**
1036       *  Immediately kill the voice.       *  Immediately kill the voice. This method should not be used to kill
1037         *  a normal, active voice, because it doesn't take care of things like
1038         *  fading down the volume level to avoid clicks and regular processing
1039         *  until the kill event actually occured!
1040         *
1041         *  @see Kill()
1042       */       */
1043      void Voice::Kill() {      void Voice::KillImmediately() {
1044          if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {          if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {
1045              pDiskThread->OrderDeletionOfStream(&DiskStreamRef);              pDiskThread->OrderDeletionOfStream(&DiskStreamRef);
1046          }          }
1047          Reset();          Reset();
1048      }      }
1049    
1050        /**
1051         *  Kill the voice in regular sense. Let the voice render audio until
1052         *  the kill event actually occured and then fade down the volume level
1053         *  very quickly and let the voice die finally. Unlike a normal release
1054         *  of a voice, a kill process cannot be cancalled and is therefore
1055         *  usually used for voice stealing and key group conflicts.
1056         *
1057         *  @param itKillEvent - event which caused the voice to be killed
1058         */
1059        void Voice::Kill(Pool<Event>::Iterator& itKillEvent) {
1060            //FIXME: just two sanity checks for debugging, can be removed
1061            if (!itKillEvent) dmsg(1,("gig::Voice::Kill(): ERROR, !itKillEvent !!!\n"));
1062            if (itKillEvent && !itKillEvent.isValid()) dmsg(1,("gig::Voice::Kill(): ERROR, itKillEvent invalid !!!\n"));
1063    
1064            if (itTriggerEvent && itKillEvent->FragmentPos() <= itTriggerEvent->FragmentPos()) return;
1065            this->itKillEvent = itKillEvent;
1066        }
1067    
1068  }} // namespace LinuxSampler::gig  }} // namespace LinuxSampler::gig

Legend:
Removed from v.236  
changed lines
  Added in v.287

  ViewVC Help
Powered by ViewVC