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-2008 Christian Schoenebeck * |
* Copyright (C) 2005-2008 Christian Schoenebeck * |
7 |
* Copyright (C) 2009-2010 Christian Schoenebeck and Grigor Iliev * |
* Copyright (C) 2009-2011 Christian Schoenebeck and Grigor Iliev * |
8 |
* * |
* * |
9 |
* This program is free software; you can redistribute it and/or modify * |
* This program is free software; you can redistribute it and/or modify * |
10 |
* 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 * |
28 |
|
|
29 |
AbstractVoice::AbstractVoice() { |
AbstractVoice::AbstractVoice() { |
30 |
pEngineChannel = NULL; |
pEngineChannel = NULL; |
31 |
pLFO1 = new LFOUnsigned(1.0f); // amplitude EG (0..1 range) |
pLFO1 = new LFOUnsigned(1.0f); // amplitude LFO (0..1 range) |
32 |
pLFO2 = new LFOUnsigned(1.0f); // filter EG (0..1 range) |
pLFO2 = new LFOUnsigned(1.0f); // filter LFO (0..1 range) |
33 |
pLFO3 = new LFOSigned(1200.0f); // pitch EG (-1200..+1200 range) |
pLFO3 = new LFOSigned(1200.0f); // pitch LFO (-1200..+1200 range) |
34 |
PlaybackState = playback_state_end; |
PlaybackState = playback_state_end; |
35 |
SynthesisMode = 0; // set all mode bits to 0 first |
SynthesisMode = 0; // set all mode bits to 0 first |
36 |
// select synthesis implementation (asm core is not supported ATM) |
// select synthesis implementation (asm core is not supported ATM) |
103 |
Delay = itNoteOnEvent->FragmentPos(); |
Delay = itNoteOnEvent->FragmentPos(); |
104 |
itTriggerEvent = itNoteOnEvent; |
itTriggerEvent = itNoteOnEvent; |
105 |
itKillEvent = Pool<Event>::Iterator(); |
itKillEvent = Pool<Event>::Iterator(); |
106 |
|
MidiKeyBase* pKeyInfo = GetMidiKeyInfo(MIDIKey); |
107 |
|
|
108 |
pGroupEvents = iKeyGroup ? pEngineChannel->ActiveKeyGroups[iKeyGroup] : 0; |
pGroupEvents = iKeyGroup ? pEngineChannel->ActiveKeyGroups[iKeyGroup] : 0; |
109 |
|
|
113 |
|
|
114 |
// calculate volume |
// calculate volume |
115 |
const double velocityAttenuation = GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity); |
const double velocityAttenuation = GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity); |
116 |
float volume = CalculateVolume(velocityAttenuation); |
float volume = CalculateVolume(velocityAttenuation) * pKeyInfo->Volume; |
117 |
if (volume <= 0) return -1; |
if (volume <= 0) return -1; |
118 |
|
|
119 |
// select channel mode (mono or stereo) |
// select channel mode (mono or stereo) |
124 |
// get starting crossfade volume level |
// get starting crossfade volume level |
125 |
float crossfadeVolume = CalculateCrossfadeVolume(itNoteOnEvent->Param.Note.Velocity); |
float crossfadeVolume = CalculateCrossfadeVolume(itNoteOnEvent->Param.Note.Velocity); |
126 |
|
|
127 |
VolumeLeft = volume * AbstractEngine::PanCurve[64 - RgnInfo.Pan]; |
VolumeLeft = volume * pKeyInfo->PanLeft * AbstractEngine::PanCurve[64 - RgnInfo.Pan]; |
128 |
VolumeRight = volume * AbstractEngine::PanCurve[64 + RgnInfo.Pan]; |
VolumeRight = volume * pKeyInfo->PanRight * AbstractEngine::PanCurve[64 + RgnInfo.Pan]; |
129 |
|
|
130 |
float subfragmentRate = GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE; |
float subfragmentRate = GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE; |
131 |
CrossfadeSmoother.trigger(crossfadeVolume, subfragmentRate); |
CrossfadeSmoother.trigger(crossfadeVolume, subfragmentRate); |
213 |
// calculate influence of EG2 controller on EG2's parameters |
// calculate influence of EG2 controller on EG2's parameters |
214 |
EGInfo egInfo = CalculateEG2ControllerInfluence(eg2controllervalue); |
EGInfo egInfo = CalculateEG2ControllerInfluence(eg2controllervalue); |
215 |
|
|
216 |
EG2.trigger ( |
TriggerEG2(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity); |
|
uint(RgnInfo.EG2PreAttack), |
|
|
RgnInfo.EG2Attack * egInfo.Attack, |
|
|
false, |
|
|
RgnInfo.EG2Decay1 * egInfo.Decay * velrelease, |
|
|
RgnInfo.EG2Decay2 * egInfo.Decay * velrelease, |
|
|
RgnInfo.EG2InfiniteSustain, |
|
|
uint(RgnInfo.EG2Sustain), |
|
|
RgnInfo.EG2Release * egInfo.Release * velrelease, |
|
|
velocityAttenuation, |
|
|
GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE |
|
|
); |
|
217 |
} |
} |
218 |
|
|
219 |
|
|
296 |
*/ |
*/ |
297 |
void AbstractVoice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) { |
void AbstractVoice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) { |
298 |
AbstractEngineChannel* pChannel = pEngineChannel; |
AbstractEngineChannel* pChannel = pEngineChannel; |
299 |
finalSynthesisParameters.pOutLeft = &pChannel->pChannelLeft->Buffer()[Skip]; |
MidiKeyBase* pMidiKeyInfo = GetMidiKeyInfo(MIDIKey); |
300 |
finalSynthesisParameters.pOutRight = &pChannel->pChannelRight->Buffer()[Skip]; |
|
301 |
finalSynthesisParameters.pSrc = pSrc; |
const bool bVoiceRequiresDedicatedRouting = |
302 |
|
pEngineChannel->GetFxSendCount() > 0 && |
303 |
|
(pMidiKeyInfo->ReverbSend || pMidiKeyInfo->ChorusSend); |
304 |
|
|
305 |
|
if (bVoiceRequiresDedicatedRouting) { |
306 |
|
finalSynthesisParameters.pOutLeft = &GetEngine()->pDedicatedVoiceChannelLeft->Buffer()[Skip]; |
307 |
|
finalSynthesisParameters.pOutRight = &GetEngine()->pDedicatedVoiceChannelRight->Buffer()[Skip]; |
308 |
|
} else { |
309 |
|
finalSynthesisParameters.pOutLeft = &pChannel->pChannelLeft->Buffer()[Skip]; |
310 |
|
finalSynthesisParameters.pOutRight = &pChannel->pChannelRight->Buffer()[Skip]; |
311 |
|
} |
312 |
|
finalSynthesisParameters.pSrc = pSrc; |
313 |
|
|
314 |
RTList<Event>::Iterator itCCEvent = pChannel->pEvents->first(); |
RTList<Event>::Iterator itCCEvent = pChannel->pEvents->first(); |
315 |
RTList<Event>::Iterator itNoteEvent; |
RTList<Event>::Iterator itNoteEvent; |
374 |
// filter EG is finished, switch EG1 to fade out stage |
// filter EG is finished, switch EG1 to fade out stage |
375 |
if ((itKillEvent && killPos <= iSubFragmentEnd) || |
if ((itKillEvent && killPos <= iSubFragmentEnd) || |
376 |
(SYNTHESIS_MODE_GET_FILTER(SynthesisMode) && |
(SYNTHESIS_MODE_GET_FILTER(SynthesisMode) && |
377 |
EG2.getSegmentType() == gig::EGADSR::segment_end)) { |
pEG2->getSegmentType() == EG::segment_end)) { |
378 |
pEG1->enterFadeOutStage(); |
pEG1->enterFadeOutStage(); |
379 |
itKillEvent = Pool<Event>::Iterator(); |
itKillEvent = Pool<Event>::Iterator(); |
380 |
} |
} |
394 |
fFinalVolume *= pEG1->processPow(); |
fFinalVolume *= pEG1->processPow(); |
395 |
break; |
break; |
396 |
} |
} |
397 |
switch (EG2.getSegmentType()) { |
switch (pEG2->getSegmentType()) { |
398 |
case gig::EGADSR::segment_lin: |
case EG::segment_lin: |
399 |
fFinalCutoff *= EG2.processLin(); |
fFinalCutoff *= pEG2->processLin(); |
400 |
break; |
break; |
401 |
case gig::EGADSR::segment_exp: |
case EG::segment_exp: |
402 |
fFinalCutoff *= EG2.processExp(); |
fFinalCutoff *= pEG2->processExp(); |
403 |
break; |
break; |
404 |
case gig::EGADSR::segment_end: |
case EG::segment_end: |
405 |
fFinalCutoff *= EG2.getLevel(); |
fFinalCutoff *= pEG2->getLevel(); |
406 |
break; // noop |
break; // noop |
407 |
|
case EG::segment_pow: |
408 |
|
fFinalCutoff *= pEG2->processPow(); |
409 |
|
break; |
410 |
} |
} |
411 |
if (EG3.active()) finalSynthesisParameters.fFinalPitch *= EG3.render(); |
if (EG3.active()) finalSynthesisParameters.fFinalPitch *= EG3.render(); |
412 |
|
|
465 |
pEG1->increment(1); |
pEG1->increment(1); |
466 |
if (!pEG1->toStageEndLeft()) pEG1->update(EG::event_stage_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
if (!pEG1->toStageEndLeft()) pEG1->update(EG::event_stage_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
467 |
} |
} |
468 |
if (EG2.active()) { |
if (pEG2->active()) { |
469 |
EG2.increment(1); |
pEG2->increment(1); |
470 |
if (!EG2.toStageEndLeft()) EG2.update(gig::EGADSR::event_stage_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
if (!pEG2->toStageEndLeft()) pEG2->update(EG::event_stage_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
471 |
} |
} |
472 |
EG3.increment(1); |
EG3.increment(1); |
473 |
if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached |
if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached |
475 |
Pos = newPos; |
Pos = newPos; |
476 |
i = iSubFragmentEnd; |
i = iSubFragmentEnd; |
477 |
} |
} |
478 |
|
|
479 |
|
if (bVoiceRequiresDedicatedRouting) { |
480 |
|
optional<float> effectSendLevels[2] = { |
481 |
|
pMidiKeyInfo->ReverbSend, |
482 |
|
pMidiKeyInfo->ChorusSend |
483 |
|
}; |
484 |
|
GetEngine()->RouteDedicatedVoiceChannels(pEngineChannel, effectSendLevels, Samples); |
485 |
|
} |
486 |
} |
} |
487 |
|
|
488 |
/** |
/** |
547 |
*/ |
*/ |
548 |
void AbstractVoice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) { |
void AbstractVoice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) { |
549 |
for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) { |
for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) { |
550 |
if (Type != Voice::type_release_trigger) { |
// some voice types ignore note off |
551 |
|
if (!(Type & (Voice::type_one_shot | Voice::type_release_trigger | Voice::type_controller_triggered))) { |
552 |
if (itEvent->Type == Event::type_release) { |
if (itEvent->Type == Event::type_release) { |
553 |
EnterReleaseStage(); |
EnterReleaseStage(); |
554 |
} else if (itEvent->Type == Event::type_cancel_release) { |
} else if (itEvent->Type == Event::type_cancel_release) { |
555 |
pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
556 |
EG2.update(gig::EGADSR::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
pEG2->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
557 |
} |
} |
558 |
} |
} |
559 |
} |
} |
628 |
volume *= GetSampleAttenuation() * pEngineChannel->GlobalVolume * GLOBAL_VOLUME; |
volume *= GetSampleAttenuation() * pEngineChannel->GlobalVolume * GLOBAL_VOLUME; |
629 |
|
|
630 |
// the volume of release triggered samples depends on note length |
// the volume of release triggered samples depends on note length |
631 |
if (Type == Voice::type_release_trigger) { |
if (Type & Voice::type_release_trigger) { |
632 |
float noteLength = float(GetEngine()->FrameTime + Delay - |
float noteLength = float(GetEngine()->FrameTime + Delay - |
633 |
GetNoteOnTime(MIDIKey) ) / GetEngine()->SampleRate; |
GetNoteOnTime(MIDIKey) ) / GetEngine()->SampleRate; |
634 |
|
|
644 |
|
|
645 |
void AbstractVoice::EnterReleaseStage() { |
void AbstractVoice::EnterReleaseStage() { |
646 |
pEG1->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
pEG1->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
647 |
EG2.update(gig::EGADSR::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
pEG2->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
648 |
} |
} |
649 |
|
|
650 |
} // namespace LinuxSampler |
} // namespace LinuxSampler |