/[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 830 by persson, Sun Jan 15 18:23:11 2006 UTC revision 865 by persson, Sun May 14 07:15:52 2006 UTC
# Line 104  namespace LinuxSampler { namespace gig { Line 104  namespace LinuxSampler { namespace gig {
104          // calculate volume          // calculate volume
105          const double velocityAttenuation = pDimRgn->GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity);          const double velocityAttenuation = pDimRgn->GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity);
106    
107          Volume = velocityAttenuation / 32768.0f; // we downscale by 32768 to convert from int16 value range to DSP value range (which is -1.0..1.0)          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)
108    
109          Volume *= pDimRgn->SampleAttenuation;          volume *= pDimRgn->SampleAttenuation;
110    
111          // the volume of release triggered samples depends on note length          // the volume of release triggered samples depends on note length
112          if (Type == type_release_trigger) {          if (Type == type_release_trigger) {
# Line 114  namespace LinuxSampler { namespace gig { Line 114  namespace LinuxSampler { namespace gig {
114                                       pEngineChannel->pMIDIKeyInfo[MIDIKey].NoteOnTime) / pEngine->SampleRate;                                       pEngineChannel->pMIDIKeyInfo[MIDIKey].NoteOnTime) / pEngine->SampleRate;
115              float attenuation = 1 - 0.01053 * (256 >> pDimRgn->ReleaseTriggerDecay) * noteLength;              float attenuation = 1 - 0.01053 * (256 >> pDimRgn->ReleaseTriggerDecay) * noteLength;
116              if (attenuation <= 0) return -1;              if (attenuation <= 0) return -1;
117              Volume *= attenuation;              volume *= attenuation;
118          }          }
119    
120          // select channel mode (mono or stereo)          // select channel mode (mono or stereo)
121          SYNTHESIS_MODE_SET_CHANNELS(SynthesisMode, pSample->Channels == 2);          SYNTHESIS_MODE_SET_CHANNELS(SynthesisMode, pSample->Channels == 2);
122    
123          // get starting crossfade volume level          // get starting crossfade volume level
124            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 = 1.0f; //TODO: aftertouch not supported yet
128                  break;                  break;
129              case ::gig::attenuation_ctrl_t::type_velocity:              case ::gig::attenuation_ctrl_t::type_velocity:
130                  CrossfadeVolume = CrossfadeAttenuation(itNoteOnEvent->Param.Note.Velocity);                  crossfadeVolume = Engine::CrossfadeCurve[CrossfadeAttenuation(itNoteOnEvent->Param.Note.Velocity)];
131                  break;                  break;
132              case ::gig::attenuation_ctrl_t::type_controlchange: //FIXME: currently not sample accurate              case ::gig::attenuation_ctrl_t::type_controlchange: //FIXME: currently not sample accurate
133                  CrossfadeVolume = CrossfadeAttenuation(pEngineChannel->ControllerTable[pDimRgn->AttenuationController.controller_number]);                  crossfadeVolume = Engine::CrossfadeCurve[CrossfadeAttenuation(pEngineChannel->ControllerTable[pDimRgn->AttenuationController.controller_number])];
134                  break;                  break;
135              case ::gig::attenuation_ctrl_t::type_none: // no crossfade defined              case ::gig::attenuation_ctrl_t::type_none: // no crossfade defined
136              default:              default:
137                  CrossfadeVolume = 1.0f;                  crossfadeVolume = 1.0f;
138          }          }
139    
140          PanLeft  = 1.0f - float(RTMath::Max(pDimRgn->Pan, 0)) /  63.0f;          VolumeLeft  = volume * Engine::PanCurve[64 - pDimRgn->Pan];
141          PanRight = 1.0f - float(RTMath::Min(pDimRgn->Pan, 0)) / -64.0f;          VolumeRight = volume * Engine::PanCurve[64 + pDimRgn->Pan];
142    
143            float subfragmentRate = pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;
144            CrossfadeSmoother.trigger(crossfadeVolume, subfragmentRate);
145            VolumeSmoother.trigger(pEngineChannel->GlobalVolume, subfragmentRate);
146            PanLeftSmoother.trigger(pEngineChannel->GlobalPanLeft, subfragmentRate);
147            PanRightSmoother.trigger(pEngineChannel->GlobalPanRight, subfragmentRate);
148    
149          finalSynthesisParameters.dPos = pDimRgn->SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)          finalSynthesisParameters.dPos = pDimRgn->SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)
150          Pos = pDimRgn->SampleStartOffset;          Pos = pDimRgn->SampleStartOffset;
# Line 146  namespace LinuxSampler { namespace gig { Line 153  namespace LinuxSampler { namespace gig {
153          long cachedsamples = pSample->GetCache().Size / pSample->FrameSize;          long cachedsamples = pSample->GetCache().Size / pSample->FrameSize;
154          DiskVoice          = cachedsamples < pSample->SamplesTotal;          DiskVoice          = cachedsamples < pSample->SamplesTotal;
155    
156            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)              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)
160    
161              // 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
162              RAMLoop = (pSample->Loops && pSample->LoopEnd <= MaxRAMPos);              RAMLoop = (pDimRgn->SampleLoops && (loopinfo.LoopStart + loopinfo.LoopLength) <= MaxRAMPos);
163    
164              if (pDiskThread->OrderNewStream(&DiskStreamRef, pSample, MaxRAMPos, !RAMLoop) < 0) {              if (pDiskThread->OrderNewStream(&DiskStreamRef, pDimRgn, MaxRAMPos, !RAMLoop) < 0) {
165                  dmsg(1,("Disk stream order failed!\n"));                  dmsg(1,("Disk stream order failed!\n"));
166                  KillImmediately();                  KillImmediately();
167                  return -1;                  return -1;
# Line 161  namespace LinuxSampler { namespace gig { Line 170  namespace LinuxSampler { namespace gig {
170          }          }
171          else { // RAM only voice          else { // RAM only voice
172              MaxRAMPos = cachedsamples;              MaxRAMPos = cachedsamples;
173              RAMLoop = (pSample->Loops != 0);              RAMLoop = (pDimRgn->SampleLoops != 0);
174              dmsg(4,("RAM only voice launched (Looping: %s)\n", (RAMLoop) ? "yes" : "no"));              dmsg(4,("RAM only voice launched (Looping: %s)\n", (RAMLoop) ? "yes" : "no"));
175          }          }
176          if (RAMLoop) {          if (RAMLoop) {
177              loop.uiTotalCycles = pSample->LoopPlayCount;              loop.uiTotalCycles = pSample->LoopPlayCount;
178              loop.uiCyclesLeft  = pSample->LoopPlayCount;              loop.uiCyclesLeft  = pSample->LoopPlayCount;
179              loop.uiStart       = pSample->LoopStart;              loop.uiStart       = loopinfo.LoopStart;
180              loop.uiEnd         = pSample->LoopEnd;              loop.uiEnd         = loopinfo.LoopStart + loopinfo.LoopLength;
181              loop.uiSize        = pSample->LoopSize;              loop.uiSize        = loopinfo.LoopLength;
182          }          }
183    
184          // calculate initial pitch value          // calculate initial pitch value
# Line 223  namespace LinuxSampler { namespace gig { Line 232  namespace LinuxSampler { namespace gig {
232                          pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                          pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
233          }          }
234    
235    #ifdef CONFIG_INTERPOLATE_VOLUME
236          // setup initial volume in synthesis parameters          // setup initial volume in synthesis parameters
237          fFinalVolume = getVolume() * EG1.getLevel();  #ifdef CONFIG_PROCESS_MUTED_CHANNELS
238          finalSynthesisParameters.fFinalVolumeLeft  = fFinalVolume * PanLeft;          if (pEngineChannel->GetMute()) {
239          finalSynthesisParameters.fFinalVolumeRight = fFinalVolume * PanRight;              finalSynthesisParameters.fFinalVolumeLeft  = 0;
240                finalSynthesisParameters.fFinalVolumeRight = 0;
241            }
242            else
243    #else
244            {
245                float finalVolume = pEngineChannel->GlobalVolume * crossfadeVolume * EG1.getLevel();
246    
247                finalSynthesisParameters.fFinalVolumeLeft  = finalVolume * VolumeLeft  * pEngineChannel->GlobalPanLeft;
248                finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * pEngineChannel->GlobalPanRight;
249            }
250    #endif
251    #endif
252    
253          // setup EG 2 (VCF Cutoff EG)          // setup EG 2 (VCF Cutoff EG)
254          {          {
# Line 316  namespace LinuxSampler { namespace gig { Line 337  namespace LinuxSampler { namespace gig {
337                      pLFO1->ExtController = 0; // no external controller                      pLFO1->ExtController = 0; // no external controller
338                      bLFO1Enabled         = false;                      bLFO1Enabled         = false;
339              }              }
340              if (bLFO1Enabled) pLFO1->trigger(pDimRgn->LFO1Frequency,              if (bLFO1Enabled) {
341                                               start_level_max,                  pLFO1->trigger(pDimRgn->LFO1Frequency,
342                                               lfo1_internal_depth,                                 start_level_max,
343                                               pDimRgn->LFO1ControlDepth,                                 lfo1_internal_depth,
344                                               pDimRgn->LFO1FlipPhase,                                 pDimRgn->LFO1ControlDepth,
345                                               pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                                 pDimRgn->LFO1FlipPhase,
346                                   pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
347                    pLFO1->update(pLFO1->ExtController ? pEngineChannel->ControllerTable[pLFO1->ExtController] : 0);
348                }
349          }          }
350    
351    
# Line 359  namespace LinuxSampler { namespace gig { Line 383  namespace LinuxSampler { namespace gig {
383                      pLFO2->ExtController = 0; // no external controller                      pLFO2->ExtController = 0; // no external controller
384                      bLFO2Enabled         = false;                      bLFO2Enabled         = false;
385              }              }
386              if (bLFO2Enabled) pLFO2->trigger(pDimRgn->LFO2Frequency,              if (bLFO2Enabled) {
387                                               start_level_max,                  pLFO2->trigger(pDimRgn->LFO2Frequency,
388                                               lfo2_internal_depth,                                 start_level_max,
389                                               pDimRgn->LFO2ControlDepth,                                 lfo2_internal_depth,
390                                               pDimRgn->LFO2FlipPhase,                                 pDimRgn->LFO2ControlDepth,
391                                               pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                                 pDimRgn->LFO2FlipPhase,
392                                   pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
393                    pLFO2->update(pLFO2->ExtController ? pEngineChannel->ControllerTable[pLFO2->ExtController] : 0);
394                }
395          }          }
396    
397    
# Line 402  namespace LinuxSampler { namespace gig { Line 429  namespace LinuxSampler { namespace gig {
429                      pLFO3->ExtController = 0; // no external controller                      pLFO3->ExtController = 0; // no external controller
430                      bLFO3Enabled         = false;                      bLFO3Enabled         = false;
431              }              }
432              if (bLFO3Enabled) pLFO3->trigger(pDimRgn->LFO3Frequency,              if (bLFO3Enabled) {
433                                               start_level_mid,                  pLFO3->trigger(pDimRgn->LFO3Frequency,
434                                               lfo3_internal_depth,                                 start_level_mid,
435                                               pDimRgn->LFO3ControlDepth,                                 lfo3_internal_depth,
436                                               false,                                 pDimRgn->LFO3ControlDepth,
437                                               pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                                 false,
438                                   pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
439                    pLFO3->update(pLFO3->ExtController ? pEngineChannel->ControllerTable[pLFO3->ExtController] : 0);
440                }
441          }          }
442    
443    
# Line 645  namespace LinuxSampler { namespace gig { Line 675  namespace LinuxSampler { namespace gig {
675       * for the given time.       * for the given time.
676       *       *
677       * @param itEvent - iterator pointing to the next event to be processed       * @param itEvent - iterator pointing to the next event to be processed
678       * @param End     - youngest time stamp where processing should be stopped       * @param End     - youngest time stamp where processing should be stopped
679       */       */
680      void Voice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) {      void Voice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) {
681          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
# Line 664  namespace LinuxSampler { namespace gig { Line 694  namespace LinuxSampler { namespace gig {
694       * the given time.       * the given time.
695       *       *
696       * @param itEvent - iterator pointing to the next event to be processed       * @param itEvent - iterator pointing to the next event to be processed
697       * @param End     - youngest time stamp where processing should be stopped       * @param End     - youngest time stamp where processing should be stopped
698       */       */
699      void Voice::processCCEvents(RTList<Event>::Iterator& itEvent, uint End) {      void Voice::processCCEvents(RTList<Event>::Iterator& itEvent, uint End) {
700          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
# Line 687  namespace LinuxSampler { namespace gig { Line 717  namespace LinuxSampler { namespace gig {
717                  }                  }
718                  if (pDimRgn->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange &&                  if (pDimRgn->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange &&
719                      itEvent->Param.CC.Controller == pDimRgn->AttenuationController.controller_number) {                      itEvent->Param.CC.Controller == pDimRgn->AttenuationController.controller_number) {
720                      processCrossFadeEvent(itEvent);                      CrossfadeSmoother.update(Engine::CrossfadeCurve[CrossfadeAttenuation(itEvent->Param.CC.Value)]);
721                    }
722                    if (itEvent->Param.CC.Controller == 7) { // volume
723                        VolumeSmoother.update(Engine::VolumeCurve[itEvent->Param.CC.Value] * CONFIG_GLOBAL_ATTENUATION);
724                    } else if (itEvent->Param.CC.Controller == 10) { // panpot
725                        PanLeftSmoother.update(Engine::PanCurve[128 - itEvent->Param.CC.Value]);
726                        PanRightSmoother.update(Engine::PanCurve[itEvent->Param.CC.Value]);
727                  }                  }
728              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event
729                  processPitchEvent(itEvent);                  processPitchEvent(itEvent);
# Line 701  namespace LinuxSampler { namespace gig { Line 737  namespace LinuxSampler { namespace gig {
737          PitchBend = pitch;          PitchBend = pitch;
738      }      }
739    
     void Voice::processCrossFadeEvent(RTList<Event>::Iterator& itEvent) {  
         CrossfadeVolume = CrossfadeAttenuation(itEvent->Param.CC.Value);  
         fFinalVolume = getVolume();  
     }  
   
     float Voice::getVolume() {  
         #if CONFIG_PROCESS_MUTED_CHANNELS  
         return pEngineChannel->GetMute() ? 0 : (Volume * CrossfadeVolume * pEngineChannel->GlobalVolume);  
         #else  
         return Volume * CrossfadeVolume * pEngineChannel->GlobalVolume;  
         #endif  
     }  
   
740      void Voice::processCutoffEvent(RTList<Event>::Iterator& itEvent) {      void Voice::processCutoffEvent(RTList<Event>::Iterator& itEvent) {
741          int ccvalue = itEvent->Param.CC.Value;          int ccvalue = itEvent->Param.CC.Value;
742          if (VCFCutoffCtrl.value == ccvalue) return;          if (VCFCutoffCtrl.value == ccvalue) return;
# Line 769  namespace LinuxSampler { namespace gig { Line 792  namespace LinuxSampler { namespace gig {
792    
793              // initialize all final synthesis parameters              // initialize all final synthesis parameters
794              finalSynthesisParameters.fFinalPitch = PitchBase * PitchBend;              finalSynthesisParameters.fFinalPitch = PitchBase * PitchBend;
             fFinalVolume    = getVolume();  
795              fFinalCutoff    = VCFCutoffCtrl.fvalue;              fFinalCutoff    = VCFCutoffCtrl.fvalue;
796              fFinalResonance = VCFResonanceCtrl.fvalue;              fFinalResonance = VCFResonanceCtrl.fvalue;
797    
798              // process MIDI control change and pitchbend events for this subfragment              // process MIDI control change and pitchbend events for this subfragment
799              processCCEvents(itCCEvent, iSubFragmentEnd);              processCCEvents(itCCEvent, iSubFragmentEnd);
800    
801                float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render();
802    #ifdef CONFIG_PROCESS_MUTED_CHANNELS
803                if (pEngineChannel->GetMute()) fFinalVolume = 0;
804    #endif
805    
806              // process transition events (note on, note off & sustain pedal)              // process transition events (note on, note off & sustain pedal)
807              processTransitionEvents(itNoteEvent, iSubFragmentEnd);              processTransitionEvents(itNoteEvent, iSubFragmentEnd);
808    
# Line 832  namespace LinuxSampler { namespace gig { Line 859  namespace LinuxSampler { namespace gig {
859              finalSynthesisParameters.uiToGo            = iSubFragmentEnd - i;              finalSynthesisParameters.uiToGo            = iSubFragmentEnd - i;
860  #ifdef CONFIG_INTERPOLATE_VOLUME  #ifdef CONFIG_INTERPOLATE_VOLUME
861              finalSynthesisParameters.fFinalVolumeDeltaLeft  =              finalSynthesisParameters.fFinalVolumeDeltaLeft  =
862                  (fFinalVolume * PanLeft - finalSynthesisParameters.fFinalVolumeLeft) / finalSynthesisParameters.uiToGo;                  (fFinalVolume * VolumeLeft  * PanLeftSmoother.render() -
863                     finalSynthesisParameters.fFinalVolumeLeft) / finalSynthesisParameters.uiToGo;
864              finalSynthesisParameters.fFinalVolumeDeltaRight =              finalSynthesisParameters.fFinalVolumeDeltaRight =
865                  (fFinalVolume * PanRight - finalSynthesisParameters.fFinalVolumeRight) / finalSynthesisParameters.uiToGo;                  (fFinalVolume * VolumeRight * PanRightSmoother.render() -
866                     finalSynthesisParameters.fFinalVolumeRight) / finalSynthesisParameters.uiToGo;
867  #else  #else
868              finalSynthesisParameters.fFinalVolumeLeft  = fFinalVolume * PanLeft;              finalSynthesisParameters.fFinalVolumeLeft  =
869              finalSynthesisParameters.fFinalVolumeRight = fFinalVolume * PanRight;                  fFinalVolume * VolumeLeft  * PanLeftSmoother.render();
870                finalSynthesisParameters.fFinalVolumeRight =
871                    fFinalVolume * VolumeRight * PanRightSmoother.render();
872  #endif  #endif
873              // render audio for one subfragment              // render audio for one subfragment
874              RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);              RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);
# Line 851  namespace LinuxSampler { namespace gig { Line 882  namespace LinuxSampler { namespace gig {
882              if (EG1.active()) {              if (EG1.active()) {
883    
884                  // if sample has a loop and loop start has been reached in this subfragment, send a special event to EG1 to let it finish the attack hold stage                  // if sample has a loop and loop start has been reached in this subfragment, send a special event to EG1 to let it finish the attack hold stage
885                  if (pSample->Loops && Pos <= pSample->LoopStart && pSample->LoopStart < newPos) {                  if (pDimRgn->SampleLoops && Pos <= pDimRgn->pSampleLoops[0].LoopStart && pDimRgn->pSampleLoops[0].LoopStart < newPos) {
886                      EG1.update(EGADSR::event_hold_end, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);                      EG1.update(EGADSR::event_hold_end, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
887                  }                  }
888    

Legend:
Removed from v.830  
changed lines
  Added in v.865

  ViewVC Help
Powered by ViewVC