693 |
void Voice::processPitchEvent(RTList<Event>::Iterator& itEvent) { |
void Voice::processPitchEvent(RTList<Event>::Iterator& itEvent) { |
694 |
const float pitch = RTMath::CentsToFreqRatio(((double) itEvent->Param.Pitch.Pitch / 8192.0) * 200.0); // +-two semitones = +-200 cents |
const float pitch = RTMath::CentsToFreqRatio(((double) itEvent->Param.Pitch.Pitch / 8192.0) * 200.0); // +-two semitones = +-200 cents |
695 |
fFinalPitch *= pitch; |
fFinalPitch *= pitch; |
696 |
|
PitchBend = pitch; |
697 |
} |
} |
698 |
|
|
699 |
void Voice::processCrossFadeEvent(RTList<Event>::Iterator& itEvent) { |
void Voice::processCrossFadeEvent(RTList<Event>::Iterator& itEvent) { |
740 |
void Voice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) { |
void Voice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) { |
741 |
RTList<Event>::Iterator itCCEvent = pEngineChannel->pEvents->first(); |
RTList<Event>::Iterator itCCEvent = pEngineChannel->pEvents->first(); |
742 |
RTList<Event>::Iterator itNoteEvent = pEngineChannel->pMIDIKeyInfo[MIDIKey].pEvents->first(); |
RTList<Event>::Iterator itNoteEvent = pEngineChannel->pMIDIKeyInfo[MIDIKey].pEvents->first(); |
743 |
|
|
744 |
if (Skip) { // skip events that happened before this voice was triggered |
if (Skip) { // skip events that happened before this voice was triggered |
745 |
while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent; |
while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent; |
746 |
while (itNoteEvent && itNoteEvent->FragmentPos() <= Skip) ++itNoteEvent; |
while (itNoteEvent && itNoteEvent->FragmentPos() <= Skip) ++itNoteEvent; |
747 |
} |
} |
748 |
|
|
749 |
uint i = Skip; |
uint i = Skip; |
750 |
while (i < Samples) { |
while (i < Samples) { |
751 |
int iSubFragmentEnd = RTMath::Min(i + CONFIG_DEFAULT_SUBFRAGMENT_SIZE, Samples); |
int iSubFragmentEnd = RTMath::Min(i + CONFIG_DEFAULT_SUBFRAGMENT_SIZE, Samples); |
752 |
|
|
753 |
// initialize all final synthesis parameters |
// initialize all final synthesis parameters |
754 |
fFinalPitch = PitchBase * PitchBend; |
fFinalPitch = PitchBase * PitchBend; |
755 |
#if CONFIG_PROCESS_MUTED_CHANNELS |
#if CONFIG_PROCESS_MUTED_CHANNELS |
756 |
fFinalVolume = this->Volume * this->CrossfadeVolume * (pEngineChannel->GetMute() ? 0 : pEngineChannel->GlobalVolume)); |
fFinalVolume = this->Volume * this->CrossfadeVolume * (pEngineChannel->GetMute() ? 0 : pEngineChannel->GlobalVolume); |
757 |
#else |
#else |
758 |
fFinalVolume = this->Volume * this->CrossfadeVolume * pEngineChannel->GlobalVolume; |
fFinalVolume = this->Volume * this->CrossfadeVolume * pEngineChannel->GlobalVolume; |
759 |
#endif |
#endif |
760 |
fFinalCutoff = VCFCutoffCtrl.fvalue; |
fFinalCutoff = VCFCutoffCtrl.fvalue; |
761 |
fFinalResonance = VCFResonanceCtrl.fvalue; |
fFinalResonance = VCFResonanceCtrl.fvalue; |
762 |
|
|
763 |
// process MIDI control change and pitchbend events for this subfragment |
// process MIDI control change and pitchbend events for this subfragment |
764 |
processCCEvents(itCCEvent, iSubFragmentEnd); |
processCCEvents(itCCEvent, iSubFragmentEnd); |
765 |
|
|
766 |
// process transition events (note on, note off & sustain pedal) |
// process transition events (note on, note off & sustain pedal) |
767 |
processTransitionEvents(itNoteEvent, iSubFragmentEnd); |
processTransitionEvents(itNoteEvent, iSubFragmentEnd); |
768 |
|
|
769 |
// process envelope generators |
// process envelope generators |
770 |
switch (EG1.getSegmentType()) { |
switch (EG1.getSegmentType()) { |
771 |
case EGADSR::segment_lin: |
case EGADSR::segment_lin: |
790 |
break; // noop |
break; // noop |
791 |
} |
} |
792 |
fFinalPitch *= RTMath::CentsToFreqRatio(EG3.render()); |
fFinalPitch *= RTMath::CentsToFreqRatio(EG3.render()); |
793 |
|
|
794 |
// process low frequency oscillators |
// process low frequency oscillators |
795 |
if (bLFO1Enabled) fFinalVolume *= pLFO1->render(); |
if (bLFO1Enabled) fFinalVolume *= pLFO1->render(); |
796 |
if (bLFO2Enabled) fFinalCutoff *= pLFO2->render(); |
if (bLFO2Enabled) fFinalCutoff *= pLFO2->render(); |
804 |
|
|
805 |
// how many steps do we calculate for this next subfragment |
// how many steps do we calculate for this next subfragment |
806 |
const int steps = iSubFragmentEnd - i; |
const int steps = iSubFragmentEnd - i; |
807 |
|
|
808 |
// select the appropriate synthesis mode |
// select the appropriate synthesis mode |
809 |
SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, fFinalPitch != 1.0f); |
SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, fFinalPitch != 1.0f); |
810 |
|
|
811 |
// render audio for one subfragment |
// render audio for one subfragment |
812 |
RunSynthesisFunction(SynthesisMode, *this, iSubFragmentEnd, pSrc, i); |
RunSynthesisFunction(SynthesisMode, *this, iSubFragmentEnd, pSrc, i); |
813 |
|
|
814 |
// increment envelopes' positions |
// increment envelopes' positions |
815 |
if (EG1.active()) { |
if (EG1.active()) { |
816 |
EG1.increment(steps); |
EG1.increment(1); |
817 |
if (!EG1.toStageEndLeft()) EG1.update(EGADSR::event_stage_end, this->Pos, fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
if (!EG1.toStageEndLeft()) EG1.update(EGADSR::event_stage_end, this->Pos, fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
818 |
} |
} |
819 |
if (EG2.active()) { |
if (EG2.active()) { |
820 |
EG2.increment(steps); |
EG2.increment(1); |
821 |
if (!EG2.toStageEndLeft()) EG2.update(EGADSR::event_stage_end, this->Pos, fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
if (!EG2.toStageEndLeft()) EG2.update(EGADSR::event_stage_end, this->Pos, fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
822 |
} |
} |
823 |
EG3.increment(steps); |
EG3.increment(1); |
824 |
if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached |
if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached |
825 |
|
|
826 |
|
i = iSubFragmentEnd; |
827 |
} |
} |
828 |
} |
} |
829 |
|
|