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 Christian Schoenebeck * |
* Copyright (C) 2005, 2006 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 * |
223 |
pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
224 |
} |
} |
225 |
|
|
226 |
|
// setup initial volume in synthesis parameters |
227 |
|
fFinalVolume = getVolume() * EG1.getLevel(); |
228 |
|
finalSynthesisParameters.fFinalVolumeLeft = fFinalVolume * PanLeft; |
229 |
|
finalSynthesisParameters.fFinalVolumeRight = fFinalVolume * PanRight; |
230 |
|
|
231 |
|
|
232 |
// setup EG 2 (VCF Cutoff EG) |
// setup EG 2 (VCF Cutoff EG) |
233 |
{ |
{ |
269 |
|
|
270 |
// setup EG 3 (VCO EG) |
// setup EG 3 (VCO EG) |
271 |
{ |
{ |
272 |
double eg3depth = RTMath::CentsToFreqRatio(pDimRgn->EG3Depth); |
// if portamento mode is on, we dedicate EG3 purely for portamento, otherwise if portamento is off we do as told by the patch |
273 |
EG3.trigger(eg3depth, pDimRgn->EG3Attack, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
bool bPortamento = pEngineChannel->PortamentoMode && pEngineChannel->PortamentoPos >= 0.0f; |
274 |
|
float eg3depth = (bPortamento) |
275 |
|
? RTMath::CentsToFreqRatio((pEngineChannel->PortamentoPos - (float) MIDIKey) * 100) |
276 |
|
: RTMath::CentsToFreqRatio(pDimRgn->EG3Depth); |
277 |
|
float eg3time = (bPortamento) |
278 |
|
? pEngineChannel->PortamentoTime |
279 |
|
: pDimRgn->EG3Attack; |
280 |
|
EG3.trigger(eg3depth, eg3time, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
281 |
|
dmsg(5,("PortamentoPos=%f, depth=%f, time=%f\n", pEngineChannel->PortamentoPos, eg3depth, eg3time)); |
282 |
} |
} |
283 |
|
|
284 |
|
|
703 |
|
|
704 |
void Voice::processCrossFadeEvent(RTList<Event>::Iterator& itEvent) { |
void Voice::processCrossFadeEvent(RTList<Event>::Iterator& itEvent) { |
705 |
CrossfadeVolume = CrossfadeAttenuation(itEvent->Param.CC.Value); |
CrossfadeVolume = CrossfadeAttenuation(itEvent->Param.CC.Value); |
706 |
|
fFinalVolume = getVolume(); |
707 |
|
} |
708 |
|
|
709 |
|
float Voice::getVolume() { |
710 |
#if CONFIG_PROCESS_MUTED_CHANNELS |
#if CONFIG_PROCESS_MUTED_CHANNELS |
711 |
const float effectiveVolume = CrossfadeVolume * Volume * (pEngineChannel->GetMute() ? 0 : pEngineChannel->GlobalVolume); |
return pEngineChannel->GetMute() ? 0 : (Volume * CrossfadeVolume * pEngineChannel->GlobalVolume); |
712 |
#else |
#else |
713 |
const float effectiveVolume = CrossfadeVolume * Volume * pEngineChannel->GlobalVolume; |
return Volume * CrossfadeVolume * pEngineChannel->GlobalVolume; |
714 |
#endif |
#endif |
|
fFinalVolume = effectiveVolume; |
|
715 |
} |
} |
716 |
|
|
717 |
void Voice::processCutoffEvent(RTList<Event>::Iterator& itEvent) { |
void Voice::processCutoffEvent(RTList<Event>::Iterator& itEvent) { |
769 |
|
|
770 |
// initialize all final synthesis parameters |
// initialize all final synthesis parameters |
771 |
finalSynthesisParameters.fFinalPitch = PitchBase * PitchBend; |
finalSynthesisParameters.fFinalPitch = PitchBase * PitchBend; |
772 |
#if CONFIG_PROCESS_MUTED_CHANNELS |
fFinalVolume = getVolume(); |
|
fFinalVolume = this->Volume * this->CrossfadeVolume * (pEngineChannel->GetMute() ? 0 : pEngineChannel->GlobalVolume); |
|
|
#else |
|
|
fFinalVolume = this->Volume * this->CrossfadeVolume * pEngineChannel->GlobalVolume; |
|
|
#endif |
|
773 |
fFinalCutoff = VCFCutoffCtrl.fvalue; |
fFinalCutoff = VCFCutoffCtrl.fvalue; |
774 |
fFinalResonance = VCFResonanceCtrl.fvalue; |
fFinalResonance = VCFResonanceCtrl.fvalue; |
775 |
|
|
808 |
fFinalCutoff *= EG2.getLevel(); |
fFinalCutoff *= EG2.getLevel(); |
809 |
break; // noop |
break; // noop |
810 |
} |
} |
811 |
if (EG3.active()) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(EG3.render()); |
if (EG3.active()) finalSynthesisParameters.fFinalPitch *= EG3.render(); |
812 |
|
|
813 |
// process low frequency oscillators |
// process low frequency oscillators |
814 |
if (bLFO1Enabled) fFinalVolume *= pLFO1->render(); |
if (bLFO1Enabled) fFinalVolume *= pLFO1->render(); |
829 |
SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, bResamplingRequired); |
SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, bResamplingRequired); |
830 |
|
|
831 |
// prepare final synthesis parameters structure |
// prepare final synthesis parameters structure |
832 |
|
finalSynthesisParameters.uiToGo = iSubFragmentEnd - i; |
833 |
|
#ifdef CONFIG_INTERPOLATE_VOLUME |
834 |
|
finalSynthesisParameters.fFinalVolumeDeltaLeft = |
835 |
|
(fFinalVolume * PanLeft - finalSynthesisParameters.fFinalVolumeLeft) / finalSynthesisParameters.uiToGo; |
836 |
|
finalSynthesisParameters.fFinalVolumeDeltaRight = |
837 |
|
(fFinalVolume * PanRight - finalSynthesisParameters.fFinalVolumeRight) / finalSynthesisParameters.uiToGo; |
838 |
|
#else |
839 |
finalSynthesisParameters.fFinalVolumeLeft = fFinalVolume * PanLeft; |
finalSynthesisParameters.fFinalVolumeLeft = fFinalVolume * PanLeft; |
840 |
finalSynthesisParameters.fFinalVolumeRight = fFinalVolume * PanRight; |
finalSynthesisParameters.fFinalVolumeRight = fFinalVolume * PanRight; |
841 |
finalSynthesisParameters.uiToGo = iSubFragmentEnd - i; |
#endif |
|
|
|
842 |
// render audio for one subfragment |
// render audio for one subfragment |
843 |
RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop); |
RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop); |
844 |
|
|
845 |
|
// stop the rendering if volume EG is finished |
846 |
|
if (EG1.getSegmentType() == EGADSR::segment_end) break; |
847 |
|
|
848 |
const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch; |
const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch; |
849 |
|
|
850 |
// increment envelopes' positions |
// increment envelopes' positions |
870 |
} |
} |
871 |
} |
} |
872 |
|
|
873 |
|
/** @brief Update current portamento position. |
874 |
|
* |
875 |
|
* Will be called when portamento mode is enabled to get the final |
876 |
|
* portamento position of this active voice from where the next voice(s) |
877 |
|
* might continue to slide on. |
878 |
|
* |
879 |
|
* @param itNoteOffEvent - event which causes this voice to die soon |
880 |
|
*/ |
881 |
|
void Voice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) { |
882 |
|
const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos()); |
883 |
|
pEngineChannel->PortamentoPos = (float) MIDIKey + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f; |
884 |
|
} |
885 |
|
|
886 |
/** |
/** |
887 |
* Immediately kill the voice. This method should not be used to kill |
* Immediately kill the voice. This method should not be used to kill |
888 |
* a normal, active voice, because it doesn't take care of things like |
* a normal, active voice, because it doesn't take care of things like |