32 |
pLFO2 = new LFOUnsigned(1.0f); // filter EG (0..1 range) |
pLFO2 = new LFOUnsigned(1.0f); // filter EG (0..1 range) |
33 |
pLFO3 = new LFOSigned(1200.0f); // pitch EG (-1200..+1200 range) |
pLFO3 = new LFOSigned(1200.0f); // pitch EG (-1200..+1200 range) |
34 |
PlaybackState = playback_state_end; |
PlaybackState = playback_state_end; |
|
KeyGroup = 0; |
|
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) |
37 |
#if 0 // CONFIG_ASM && ARCH_X86 |
#if 0 // CONFIG_ASM && ARCH_X86 |
103 |
Delay = itNoteOnEvent->FragmentPos(); |
Delay = itNoteOnEvent->FragmentPos(); |
104 |
itTriggerEvent = itNoteOnEvent; |
itTriggerEvent = itNoteOnEvent; |
105 |
itKillEvent = Pool<Event>::Iterator(); |
itKillEvent = Pool<Event>::Iterator(); |
106 |
KeyGroup = iKeyGroup; |
MidiKeyBase* pKeyInfo = GetMidiKeyInfo(MIDIKey); |
107 |
|
|
108 |
|
pGroupEvents = iKeyGroup ? pEngineChannel->ActiveKeyGroups[iKeyGroup] : 0; |
109 |
|
|
110 |
SmplInfo = GetSampleInfo(); |
SmplInfo = GetSampleInfo(); |
111 |
RgnInfo = GetRegionInfo(); |
RgnInfo = GetRegionInfo(); |
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); |
307 |
*/ |
*/ |
308 |
void AbstractVoice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) { |
void AbstractVoice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) { |
309 |
AbstractEngineChannel* pChannel = pEngineChannel; |
AbstractEngineChannel* pChannel = pEngineChannel; |
310 |
finalSynthesisParameters.pOutLeft = &pChannel->pChannelLeft->Buffer()[Skip]; |
MidiKeyBase* pMidiKeyInfo = GetMidiKeyInfo(MIDIKey); |
311 |
finalSynthesisParameters.pOutRight = &pChannel->pChannelRight->Buffer()[Skip]; |
|
312 |
finalSynthesisParameters.pSrc = pSrc; |
const bool bVoiceRequiresDedicatedRouting = |
313 |
|
pEngineChannel->GetFxSendCount() > 0 && |
314 |
|
(pMidiKeyInfo->ReverbSend || pMidiKeyInfo->ChorusSend); |
315 |
|
|
316 |
|
if (bVoiceRequiresDedicatedRouting) { |
317 |
|
finalSynthesisParameters.pOutLeft = &GetEngine()->pDedicatedVoiceChannelLeft->Buffer()[Skip]; |
318 |
|
finalSynthesisParameters.pOutRight = &GetEngine()->pDedicatedVoiceChannelRight->Buffer()[Skip]; |
319 |
|
} else { |
320 |
|
finalSynthesisParameters.pOutLeft = &pChannel->pChannelLeft->Buffer()[Skip]; |
321 |
|
finalSynthesisParameters.pOutRight = &pChannel->pChannelRight->Buffer()[Skip]; |
322 |
|
} |
323 |
|
finalSynthesisParameters.pSrc = pSrc; |
324 |
|
|
325 |
RTList<Event>::Iterator itCCEvent = pChannel->pEvents->first(); |
RTList<Event>::Iterator itCCEvent = pChannel->pEvents->first(); |
326 |
RTList<Event>::Iterator itNoteEvent; |
RTList<Event>::Iterator itNoteEvent; |
327 |
GetFirstEventOnKey(MIDIKey, itNoteEvent); |
GetFirstEventOnKey(MIDIKey, itNoteEvent); |
328 |
|
|
329 |
|
RTList<Event>::Iterator itGroupEvent; |
330 |
|
if (pGroupEvents) itGroupEvent = pGroupEvents->first(); |
331 |
|
|
332 |
if (itTriggerEvent) { // skip events that happened before this voice was triggered |
if (itTriggerEvent) { // skip events that happened before this voice was triggered |
333 |
while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent; |
while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent; |
334 |
|
while (itGroupEvent && itGroupEvent->FragmentPos() <= Skip) ++itGroupEvent; |
335 |
|
|
336 |
// we can't simply compare the timestamp here, because note events |
// we can't simply compare the timestamp here, because note events |
337 |
// might happen on the same time stamp, so we have to deal on the |
// might happen on the same time stamp, so we have to deal on the |
338 |
// actual sequence the note events arrived instead (see bug #112) |
// actual sequence the note events arrived instead (see bug #112) |
379 |
|
|
380 |
// process transition events (note on, note off & sustain pedal) |
// process transition events (note on, note off & sustain pedal) |
381 |
processTransitionEvents(itNoteEvent, iSubFragmentEnd); |
processTransitionEvents(itNoteEvent, iSubFragmentEnd); |
382 |
|
processGroupEvents(itGroupEvent, iSubFragmentEnd); |
383 |
|
|
384 |
// if the voice was killed in this subfragment, or if the |
// if the voice was killed in this subfragment, or if the |
385 |
// filter EG is finished, switch EG1 to fade out stage |
// filter EG is finished, switch EG1 to fade out stage |
483 |
Pos = newPos; |
Pos = newPos; |
484 |
i = iSubFragmentEnd; |
i = iSubFragmentEnd; |
485 |
} |
} |
486 |
|
|
487 |
|
if (bVoiceRequiresDedicatedRouting) { |
488 |
|
optional<float> effectSendLevels[2] = { |
489 |
|
pMidiKeyInfo->ReverbSend, |
490 |
|
pMidiKeyInfo->ChorusSend |
491 |
|
}; |
492 |
|
GetEngine()->RouteDedicatedVoiceChannels(pEngineChannel, effectSendLevels, Samples); |
493 |
|
} |
494 |
} |
} |
495 |
|
|
496 |
/** |
/** |
555 |
*/ |
*/ |
556 |
void AbstractVoice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) { |
void AbstractVoice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) { |
557 |
for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) { |
for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) { |
558 |
if (itEvent->Type == Event::type_release) { |
// some voice types ignore note off |
559 |
pEG1->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
if (!(Type & (Voice::type_one_shot | Voice::type_release_trigger | Voice::type_controller_triggered))) { |
560 |
EG2.update(gig::EGADSR::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
if (itEvent->Type == Event::type_release) { |
561 |
} else if (itEvent->Type == Event::type_cancel_release) { |
EnterReleaseStage(); |
562 |
pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
} else if (itEvent->Type == Event::type_cancel_release) { |
563 |
EG2.update(gig::EGADSR::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
564 |
|
EG2.update(gig::EGADSR::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
565 |
|
} |
566 |
} |
} |
567 |
} |
} |
568 |
} |
} |
569 |
|
|
570 |
|
/** |
571 |
|
* Process given list of events aimed at all voices in a key group. |
572 |
|
* |
573 |
|
* @param itEvent - iterator pointing to the next event to be processed |
574 |
|
* @param End - youngest time stamp where processing should be stopped |
575 |
|
*/ |
576 |
|
void AbstractVoice::processGroupEvents(RTList<Event>::Iterator& itEvent, uint End) { |
577 |
|
for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) { |
578 |
|
ProcessGroupEvent(itEvent); |
579 |
|
} |
580 |
|
} |
581 |
|
|
582 |
/** @brief Update current portamento position. |
/** @brief Update current portamento position. |
583 |
* |
* |
584 |
* Will be called when portamento mode is enabled to get the final |
* Will be called when portamento mode is enabled to get the final |
636 |
volume *= GetSampleAttenuation() * pEngineChannel->GlobalVolume * GLOBAL_VOLUME; |
volume *= GetSampleAttenuation() * pEngineChannel->GlobalVolume * GLOBAL_VOLUME; |
637 |
|
|
638 |
// the volume of release triggered samples depends on note length |
// the volume of release triggered samples depends on note length |
639 |
if (Type == Voice::type_release_trigger) { |
if (Type & Voice::type_release_trigger) { |
640 |
float noteLength = float(GetEngine()->FrameTime + Delay - |
float noteLength = float(GetEngine()->FrameTime + Delay - |
641 |
GetNoteOnTime(MIDIKey) ) / GetEngine()->SampleRate; |
GetNoteOnTime(MIDIKey) ) / GetEngine()->SampleRate; |
642 |
|
|
649 |
float AbstractVoice::GetReleaseTriggerAttenuation(float noteLength) { |
float AbstractVoice::GetReleaseTriggerAttenuation(float noteLength) { |
650 |
return 1 - RgnInfo.ReleaseTriggerDecay * noteLength; |
return 1 - RgnInfo.ReleaseTriggerDecay * noteLength; |
651 |
} |
} |
652 |
|
|
653 |
|
void AbstractVoice::EnterReleaseStage() { |
654 |
|
pEG1->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
655 |
|
EG2.update(gig::EGADSR::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
656 |
|
} |
657 |
|
|
658 |
} // namespace LinuxSampler |
} // namespace LinuxSampler |