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) { |
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; |
230 |
pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
231 |
} |
} |
232 |
|
|
233 |
|
#ifdef CONFIG_INTERPOLATE_VOLUME |
234 |
|
// setup initial volume in synthesis parameters |
235 |
|
#ifdef CONFIG_PROCESS_MUTED_CHANNELS |
236 |
|
if (pEngineChannel->GetMute()) { |
237 |
|
finalSynthesisParameters.fFinalVolumeLeft = 0; |
238 |
|
finalSynthesisParameters.fFinalVolumeRight = 0; |
239 |
|
} |
240 |
|
else |
241 |
|
#else |
242 |
|
{ |
243 |
|
float finalVolume = pEngineChannel->GlobalVolume * crossfadeVolume * EG1.getLevel(); |
244 |
|
|
245 |
|
finalSynthesisParameters.fFinalVolumeLeft = finalVolume * VolumeLeft * pEngineChannel->GlobalPanLeft; |
246 |
|
finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * pEngineChannel->GlobalPanRight; |
247 |
|
} |
248 |
|
#endif |
249 |
|
#endif |
250 |
|
|
251 |
// setup EG 2 (VCF Cutoff EG) |
// setup EG 2 (VCF Cutoff EG) |
252 |
{ |
{ |
335 |
pLFO1->ExtController = 0; // no external controller |
pLFO1->ExtController = 0; // no external controller |
336 |
bLFO1Enabled = false; |
bLFO1Enabled = false; |
337 |
} |
} |
338 |
if (bLFO1Enabled) pLFO1->trigger(pDimRgn->LFO1Frequency, |
if (bLFO1Enabled) { |
339 |
start_level_max, |
pLFO1->trigger(pDimRgn->LFO1Frequency, |
340 |
lfo1_internal_depth, |
start_level_max, |
341 |
pDimRgn->LFO1ControlDepth, |
lfo1_internal_depth, |
342 |
pDimRgn->LFO1FlipPhase, |
pDimRgn->LFO1ControlDepth, |
343 |
pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
pDimRgn->LFO1FlipPhase, |
344 |
|
pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
345 |
|
pLFO1->update(pLFO1->ExtController ? pEngineChannel->ControllerTable[pLFO1->ExtController] : 0); |
346 |
|
} |
347 |
} |
} |
348 |
|
|
349 |
|
|
381 |
pLFO2->ExtController = 0; // no external controller |
pLFO2->ExtController = 0; // no external controller |
382 |
bLFO2Enabled = false; |
bLFO2Enabled = false; |
383 |
} |
} |
384 |
if (bLFO2Enabled) pLFO2->trigger(pDimRgn->LFO2Frequency, |
if (bLFO2Enabled) { |
385 |
start_level_max, |
pLFO2->trigger(pDimRgn->LFO2Frequency, |
386 |
lfo2_internal_depth, |
start_level_max, |
387 |
pDimRgn->LFO2ControlDepth, |
lfo2_internal_depth, |
388 |
pDimRgn->LFO2FlipPhase, |
pDimRgn->LFO2ControlDepth, |
389 |
pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
pDimRgn->LFO2FlipPhase, |
390 |
|
pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
391 |
|
pLFO2->update(pLFO2->ExtController ? pEngineChannel->ControllerTable[pLFO2->ExtController] : 0); |
392 |
|
} |
393 |
} |
} |
394 |
|
|
395 |
|
|
427 |
pLFO3->ExtController = 0; // no external controller |
pLFO3->ExtController = 0; // no external controller |
428 |
bLFO3Enabled = false; |
bLFO3Enabled = false; |
429 |
} |
} |
430 |
if (bLFO3Enabled) pLFO3->trigger(pDimRgn->LFO3Frequency, |
if (bLFO3Enabled) { |
431 |
start_level_mid, |
pLFO3->trigger(pDimRgn->LFO3Frequency, |
432 |
lfo3_internal_depth, |
start_level_mid, |
433 |
pDimRgn->LFO3ControlDepth, |
lfo3_internal_depth, |
434 |
false, |
pDimRgn->LFO3ControlDepth, |
435 |
pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
false, |
436 |
|
pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
437 |
|
pLFO3->update(pLFO3->ExtController ? pEngineChannel->ControllerTable[pLFO3->ExtController] : 0); |
438 |
|
} |
439 |
} |
} |
440 |
|
|
441 |
|
|
673 |
* for the given time. |
* for the given time. |
674 |
* |
* |
675 |
* @param itEvent - iterator pointing to the next event to be processed |
* @param itEvent - iterator pointing to the next event to be processed |
676 |
* @param End - youngest time stamp where processing should be stopped |
* @param End - youngest time stamp where processing should be stopped |
677 |
*/ |
*/ |
678 |
void Voice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) { |
void Voice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) { |
679 |
for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) { |
for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) { |
692 |
* the given time. |
* the given time. |
693 |
* |
* |
694 |
* @param itEvent - iterator pointing to the next event to be processed |
* @param itEvent - iterator pointing to the next event to be processed |
695 |
* @param End - youngest time stamp where processing should be stopped |
* @param End - youngest time stamp where processing should be stopped |
696 |
*/ |
*/ |
697 |
void Voice::processCCEvents(RTList<Event>::Iterator& itEvent, uint End) { |
void Voice::processCCEvents(RTList<Event>::Iterator& itEvent, uint End) { |
698 |
for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) { |
for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) { |
715 |
} |
} |
716 |
if (pDimRgn->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange && |
if (pDimRgn->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange && |
717 |
itEvent->Param.CC.Controller == pDimRgn->AttenuationController.controller_number) { |
itEvent->Param.CC.Controller == pDimRgn->AttenuationController.controller_number) { |
718 |
processCrossFadeEvent(itEvent); |
CrossfadeSmoother.update(Engine::CrossfadeCurve[CrossfadeAttenuation(itEvent->Param.CC.Value)]); |
719 |
|
} |
720 |
|
if (itEvent->Param.CC.Controller == 7) { // volume |
721 |
|
VolumeSmoother.update(Engine::VolumeCurve[itEvent->Param.CC.Value] * CONFIG_GLOBAL_ATTENUATION); |
722 |
|
} else if (itEvent->Param.CC.Controller == 10) { // panpot |
723 |
|
PanLeftSmoother.update(Engine::PanCurve[128 - itEvent->Param.CC.Value]); |
724 |
|
PanRightSmoother.update(Engine::PanCurve[itEvent->Param.CC.Value]); |
725 |
} |
} |
726 |
} else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event |
} else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event |
727 |
processPitchEvent(itEvent); |
processPitchEvent(itEvent); |
735 |
PitchBend = pitch; |
PitchBend = pitch; |
736 |
} |
} |
737 |
|
|
|
void Voice::processCrossFadeEvent(RTList<Event>::Iterator& itEvent) { |
|
|
CrossfadeVolume = CrossfadeAttenuation(itEvent->Param.CC.Value); |
|
|
#if CONFIG_PROCESS_MUTED_CHANNELS |
|
|
const float effectiveVolume = CrossfadeVolume * Volume * (pEngineChannel->GetMute() ? 0 : pEngineChannel->GlobalVolume); |
|
|
#else |
|
|
const float effectiveVolume = CrossfadeVolume * Volume * pEngineChannel->GlobalVolume; |
|
|
#endif |
|
|
fFinalVolume = effectiveVolume; |
|
|
} |
|
|
|
|
738 |
void Voice::processCutoffEvent(RTList<Event>::Iterator& itEvent) { |
void Voice::processCutoffEvent(RTList<Event>::Iterator& itEvent) { |
739 |
int ccvalue = itEvent->Param.CC.Value; |
int ccvalue = itEvent->Param.CC.Value; |
740 |
if (VCFCutoffCtrl.value == ccvalue) return; |
if (VCFCutoffCtrl.value == ccvalue) return; |
790 |
|
|
791 |
// initialize all final synthesis parameters |
// initialize all final synthesis parameters |
792 |
finalSynthesisParameters.fFinalPitch = PitchBase * PitchBend; |
finalSynthesisParameters.fFinalPitch = PitchBase * PitchBend; |
|
#if CONFIG_PROCESS_MUTED_CHANNELS |
|
|
fFinalVolume = this->Volume * this->CrossfadeVolume * (pEngineChannel->GetMute() ? 0 : pEngineChannel->GlobalVolume); |
|
|
#else |
|
|
fFinalVolume = this->Volume * this->CrossfadeVolume * pEngineChannel->GlobalVolume; |
|
|
#endif |
|
793 |
fFinalCutoff = VCFCutoffCtrl.fvalue; |
fFinalCutoff = VCFCutoffCtrl.fvalue; |
794 |
fFinalResonance = VCFResonanceCtrl.fvalue; |
fFinalResonance = VCFResonanceCtrl.fvalue; |
795 |
|
|
796 |
// process MIDI control change and pitchbend events for this subfragment |
// process MIDI control change and pitchbend events for this subfragment |
797 |
processCCEvents(itCCEvent, iSubFragmentEnd); |
processCCEvents(itCCEvent, iSubFragmentEnd); |
798 |
|
|
799 |
|
float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render(); |
800 |
|
#ifdef CONFIG_PROCESS_MUTED_CHANNELS |
801 |
|
if (pEngineChannel->GetMute()) fFinalVolume = 0; |
802 |
|
#endif |
803 |
|
|
804 |
// process transition events (note on, note off & sustain pedal) |
// process transition events (note on, note off & sustain pedal) |
805 |
processTransitionEvents(itNoteEvent, iSubFragmentEnd); |
processTransitionEvents(itNoteEvent, iSubFragmentEnd); |
806 |
|
|
854 |
SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, bResamplingRequired); |
SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, bResamplingRequired); |
855 |
|
|
856 |
// prepare final synthesis parameters structure |
// prepare final synthesis parameters structure |
|
finalSynthesisParameters.fFinalVolumeLeft = fFinalVolume * PanLeft; |
|
|
finalSynthesisParameters.fFinalVolumeRight = fFinalVolume * PanRight; |
|
857 |
finalSynthesisParameters.uiToGo = iSubFragmentEnd - i; |
finalSynthesisParameters.uiToGo = iSubFragmentEnd - i; |
858 |
|
#ifdef CONFIG_INTERPOLATE_VOLUME |
859 |
|
finalSynthesisParameters.fFinalVolumeDeltaLeft = |
860 |
|
(fFinalVolume * VolumeLeft * PanLeftSmoother.render() - |
861 |
|
finalSynthesisParameters.fFinalVolumeLeft) / finalSynthesisParameters.uiToGo; |
862 |
|
finalSynthesisParameters.fFinalVolumeDeltaRight = |
863 |
|
(fFinalVolume * VolumeRight * PanRightSmoother.render() - |
864 |
|
finalSynthesisParameters.fFinalVolumeRight) / finalSynthesisParameters.uiToGo; |
865 |
|
#else |
866 |
|
finalSynthesisParameters.fFinalVolumeLeft = |
867 |
|
fFinalVolume * VolumeLeft * PanLeftSmoother.render(); |
868 |
|
finalSynthesisParameters.fFinalVolumeRight = |
869 |
|
fFinalVolume * VolumeRight * PanRightSmoother.render(); |
870 |
|
#endif |
871 |
// render audio for one subfragment |
// render audio for one subfragment |
872 |
RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop); |
RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop); |
873 |
|
|
874 |
|
// stop the rendering if volume EG is finished |
875 |
|
if (EG1.getSegmentType() == EGADSR::segment_end) break; |
876 |
|
|
877 |
const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch; |
const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch; |
878 |
|
|
879 |
// increment envelopes' positions |
// increment envelopes' positions |