140 |
PanRight = 1.0f - float(RTMath::Min(pDimRgn->Pan, 0)) / -64.0f; |
PanRight = 1.0f - float(RTMath::Min(pDimRgn->Pan, 0)) / -64.0f; |
141 |
|
|
142 |
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) |
143 |
|
Pos = pDimRgn->SampleStartOffset; |
144 |
|
|
145 |
// Check if the sample needs disk streaming or is too short for that |
// Check if the sample needs disk streaming or is too short for that |
146 |
long cachedsamples = pSample->GetCache().Size / pSample->FrameSize; |
long cachedsamples = pSample->GetCache().Size / pSample->FrameSize; |
220 |
EG1.trigger(pDimRgn->EG1PreAttack, |
EG1.trigger(pDimRgn->EG1PreAttack, |
221 |
pDimRgn->EG1Attack * eg1attack, |
pDimRgn->EG1Attack * eg1attack, |
222 |
pDimRgn->EG1Hold, |
pDimRgn->EG1Hold, |
|
pSample->LoopStart, |
|
223 |
pDimRgn->EG1Decay1 * eg1decay * velrelease, |
pDimRgn->EG1Decay1 * eg1decay * velrelease, |
224 |
pDimRgn->EG1Decay2 * eg1decay * velrelease, |
pDimRgn->EG1Decay2 * eg1decay * velrelease, |
225 |
pDimRgn->EG1InfiniteSustain, |
pDimRgn->EG1InfiniteSustain, |
258 |
EG2.trigger(pDimRgn->EG2PreAttack, |
EG2.trigger(pDimRgn->EG2PreAttack, |
259 |
pDimRgn->EG2Attack * eg2attack, |
pDimRgn->EG2Attack * eg2attack, |
260 |
false, |
false, |
|
pSample->LoopStart, |
|
261 |
pDimRgn->EG2Decay1 * eg2decay * velrelease, |
pDimRgn->EG2Decay1 * eg2decay * velrelease, |
262 |
pDimRgn->EG2Decay2 * eg2decay * velrelease, |
pDimRgn->EG2Decay2 * eg2decay * velrelease, |
263 |
pDimRgn->EG2InfiniteSustain, |
pDimRgn->EG2InfiniteSustain, |
494 |
if (VCFCutoffCtrl.controller) { |
if (VCFCutoffCtrl.controller) { |
495 |
cvalue = pEngineChannel->ControllerTable[VCFCutoffCtrl.controller]; |
cvalue = pEngineChannel->ControllerTable[VCFCutoffCtrl.controller]; |
496 |
if (pDimRgn->VCFCutoffControllerInvert) cvalue = 127 - cvalue; |
if (pDimRgn->VCFCutoffControllerInvert) cvalue = 127 - cvalue; |
497 |
|
// VCFVelocityScale in this case means Minimum cutoff |
498 |
if (cvalue < pDimRgn->VCFVelocityScale) cvalue = pDimRgn->VCFVelocityScale; |
if (cvalue < pDimRgn->VCFVelocityScale) cvalue = pDimRgn->VCFVelocityScale; |
499 |
} |
} |
500 |
else { |
else { |
502 |
} |
} |
503 |
cutoff *= float(cvalue) * 0.00787402f; // (1 / 127) |
cutoff *= float(cvalue) * 0.00787402f; // (1 / 127) |
504 |
if (cutoff > 1.0) cutoff = 1.0; |
if (cutoff > 1.0) cutoff = 1.0; |
505 |
cutoff = exp(cutoff * FILTER_CUTOFF_COEFF) * CONFIG_FILTER_CUTOFF_MIN; |
cutoff = (cutoff < 0.5 ? cutoff * 4826 - 1 : cutoff * 5715 - 449); |
506 |
|
if (cutoff < 1.0) cutoff = 1.0; |
507 |
|
|
508 |
// calculate resonance |
// calculate resonance |
509 |
float resonance = (float) VCFResonanceCtrl.value * 0.00787f; // 0.0..1.0 |
float resonance = (float) (VCFResonanceCtrl.controller ? VCFResonanceCtrl.value : pDimRgn->VCFResonance) * 0.00787f; // 0.0..1.0 |
|
if (pDimRgn->VCFKeyboardTracking) { |
|
|
resonance += (float) (itNoteOnEvent->Param.Note.Key - pDimRgn->VCFKeyboardTrackingBreakpoint) * 0.00787f; |
|
|
} |
|
|
Constrain(resonance, 0.0, 1.0); // correct resonance if outside allowed value range (0.0..1.0) |
|
510 |
|
|
511 |
VCFCutoffCtrl.fvalue = cutoff - CONFIG_FILTER_CUTOFF_MIN; |
VCFCutoffCtrl.fvalue = cutoff - 1.0; |
512 |
VCFResonanceCtrl.fvalue = resonance; |
VCFResonanceCtrl.fvalue = resonance; |
513 |
} |
} |
514 |
else { |
else { |
608 |
break; |
break; |
609 |
} |
} |
610 |
|
|
|
// Reset synthesis event lists |
|
|
pEngineChannel->pEvents->clear(); |
|
|
|
|
611 |
// Reset delay |
// Reset delay |
612 |
Delay = 0; |
Delay = 0; |
613 |
|
|
643 |
void Voice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) { |
void Voice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) { |
644 |
for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) { |
for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) { |
645 |
if (itEvent->Type == Event::type_release) { |
if (itEvent->Type == Event::type_release) { |
646 |
EG1.update(EGADSR::event_release, finalSynthesisParameters.dPos, finalSynthesisParameters.fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
EG1.update(EGADSR::event_release, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
647 |
EG2.update(EGADSR::event_release, finalSynthesisParameters.dPos, finalSynthesisParameters.fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
EG2.update(EGADSR::event_release, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
648 |
} else if (itEvent->Type == Event::type_cancel_release) { |
} else if (itEvent->Type == Event::type_cancel_release) { |
649 |
EG1.update(EGADSR::event_cancel_release, finalSynthesisParameters.dPos, finalSynthesisParameters.fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
EG1.update(EGADSR::event_cancel_release, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
650 |
EG2.update(EGADSR::event_cancel_release, finalSynthesisParameters.dPos, finalSynthesisParameters.fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
EG2.update(EGADSR::event_cancel_release, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
651 |
} |
} |
652 |
} |
} |
653 |
} |
} |
712 |
if (ccvalue < pDimRgn->VCFVelocityScale) ccvalue = pDimRgn->VCFVelocityScale; |
if (ccvalue < pDimRgn->VCFVelocityScale) ccvalue = pDimRgn->VCFVelocityScale; |
713 |
float cutoff = CutoffBase * float(ccvalue) * 0.00787402f; // (1 / 127) |
float cutoff = CutoffBase * float(ccvalue) * 0.00787402f; // (1 / 127) |
714 |
if (cutoff > 1.0) cutoff = 1.0; |
if (cutoff > 1.0) cutoff = 1.0; |
715 |
cutoff = exp(cutoff * FILTER_CUTOFF_COEFF) * CONFIG_FILTER_CUTOFF_MIN - CONFIG_FILTER_CUTOFF_MIN; |
cutoff = (cutoff < 0.5 ? cutoff * 4826 - 1 : cutoff * 5715 - 449); |
716 |
VCFCutoffCtrl.fvalue = cutoff; // needed for initialization of fFinalCutoff next time |
if (cutoff < 1.0) cutoff = 1.0; |
717 |
|
|
718 |
|
VCFCutoffCtrl.fvalue = cutoff - 1.0; // needed for initialization of fFinalCutoff next time |
719 |
fFinalCutoff = cutoff; |
fFinalCutoff = cutoff; |
720 |
} |
} |
721 |
|
|
750 |
while (itNoteEvent && itNoteEvent->FragmentPos() <= Skip) ++itNoteEvent; |
while (itNoteEvent && itNoteEvent->FragmentPos() <= Skip) ++itNoteEvent; |
751 |
} |
} |
752 |
|
|
753 |
|
uint killPos; |
754 |
|
if (itKillEvent) killPos = RTMath::Min(itKillEvent->FragmentPos(), pEngine->MaxFadeOutPos); |
755 |
|
|
756 |
uint i = Skip; |
uint i = Skip; |
757 |
while (i < Samples) { |
while (i < Samples) { |
758 |
int iSubFragmentEnd = RTMath::Min(i + CONFIG_DEFAULT_SUBFRAGMENT_SIZE, Samples); |
int iSubFragmentEnd = RTMath::Min(i + CONFIG_DEFAULT_SUBFRAGMENT_SIZE, Samples); |
773 |
// process transition events (note on, note off & sustain pedal) |
// process transition events (note on, note off & sustain pedal) |
774 |
processTransitionEvents(itNoteEvent, iSubFragmentEnd); |
processTransitionEvents(itNoteEvent, iSubFragmentEnd); |
775 |
|
|
776 |
|
// if the voice was killed in this subfragment switch EG1 to fade out stage |
777 |
|
if (itKillEvent && killPos <= iSubFragmentEnd) { |
778 |
|
EG1.enterFadeOutStage(); |
779 |
|
itKillEvent = Pool<Event>::Iterator(); |
780 |
|
} |
781 |
|
|
782 |
// process envelope generators |
// process envelope generators |
783 |
switch (EG1.getSegmentType()) { |
switch (EG1.getSegmentType()) { |
784 |
case EGADSR::segment_lin: |
case EGADSR::segment_lin: |
811 |
|
|
812 |
// if filter enabled then update filter coefficients |
// if filter enabled then update filter coefficients |
813 |
if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode)) { |
if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode)) { |
814 |
finalSynthesisParameters.filterLeft.SetParameters(fFinalCutoff, fFinalResonance, pEngine->SampleRate); |
finalSynthesisParameters.filterLeft.SetParameters(fFinalCutoff + 1.0, fFinalResonance, pEngine->SampleRate); |
815 |
finalSynthesisParameters.filterRight.SetParameters(fFinalCutoff, fFinalResonance, pEngine->SampleRate); |
finalSynthesisParameters.filterRight.SetParameters(fFinalCutoff + 1.0, fFinalResonance, pEngine->SampleRate); |
816 |
} |
} |
817 |
|
|
818 |
// do we need resampling? |
// do we need resampling? |
830 |
// render audio for one subfragment |
// render audio for one subfragment |
831 |
RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop); |
RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop); |
832 |
|
|
833 |
|
const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch; |
834 |
|
|
835 |
// increment envelopes' positions |
// increment envelopes' positions |
836 |
if (EG1.active()) { |
if (EG1.active()) { |
837 |
|
|
838 |
|
// 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 |
839 |
|
if (pSample->Loops && Pos <= pSample->LoopStart && pSample->LoopStart < newPos) { |
840 |
|
EG1.update(EGADSR::event_hold_end, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
841 |
|
} |
842 |
|
|
843 |
EG1.increment(1); |
EG1.increment(1); |
844 |
if (!EG1.toStageEndLeft()) EG1.update(EGADSR::event_stage_end, finalSynthesisParameters.dPos, finalSynthesisParameters.fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
if (!EG1.toStageEndLeft()) EG1.update(EGADSR::event_stage_end, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
845 |
} |
} |
846 |
if (EG2.active()) { |
if (EG2.active()) { |
847 |
EG2.increment(1); |
EG2.increment(1); |
848 |
if (!EG2.toStageEndLeft()) EG2.update(EGADSR::event_stage_end, finalSynthesisParameters.dPos, finalSynthesisParameters.fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
if (!EG2.toStageEndLeft()) EG2.update(EGADSR::event_stage_end, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
849 |
} |
} |
850 |
EG3.increment(1); |
EG3.increment(1); |
851 |
if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached |
if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached |
852 |
|
|
853 |
|
Pos = newPos; |
854 |
i = iSubFragmentEnd; |
i = iSubFragmentEnd; |
855 |
} |
} |
856 |
} |
} |