3 |
* LinuxSampler - modular, streaming capable sampler * |
* LinuxSampler - modular, streaming capable sampler * |
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-2009 Christian Schoenebeck * |
* Copyright (C) 2005-2008 Christian Schoenebeck * |
7 |
* Copyright (C) 2009 Grigor Iliev * |
* Copyright (C) 2009-2010 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 * |
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 |
50 |
if (pLFO2) delete pLFO2; |
if (pLFO2) delete pLFO2; |
51 |
if (pLFO3) delete pLFO3; |
if (pLFO3) delete pLFO3; |
52 |
} |
} |
53 |
|
|
54 |
/** |
/** |
55 |
* Resets voice variables. Should only be called if rendering process is |
* Resets voice variables. Should only be called if rendering process is |
56 |
* suspended / not running. |
* suspended / not running. |
103 |
Delay = itNoteOnEvent->FragmentPos(); |
Delay = itNoteOnEvent->FragmentPos(); |
104 |
itTriggerEvent = itNoteOnEvent; |
itTriggerEvent = itNoteOnEvent; |
105 |
itKillEvent = Pool<Event>::Iterator(); |
itKillEvent = Pool<Event>::Iterator(); |
106 |
KeyGroup = iKeyGroup; |
|
107 |
|
pGroupEvents = iKeyGroup ? pEngineChannel->ActiveKeyGroups[iKeyGroup] : 0; |
108 |
|
|
109 |
SmplInfo = GetSampleInfo(); |
SmplInfo = GetSampleInfo(); |
110 |
RgnInfo = GetRegionInfo(); |
RgnInfo = GetRegionInfo(); |
183 |
// calculate influence of EG1 controller on EG1's parameters |
// calculate influence of EG1 controller on EG1's parameters |
184 |
EGInfo egInfo = CalculateEG1ControllerInfluence(eg1controllervalue); |
EGInfo egInfo = CalculateEG1ControllerInfluence(eg1controllervalue); |
185 |
|
|
186 |
EG1.trigger ( |
TriggerEG1(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity); |
|
RgnInfo.EG1PreAttack, |
|
|
RgnInfo.EG1Attack * egInfo.Attack, |
|
|
RgnInfo.EG1Hold, |
|
|
RgnInfo.EG1Decay1 * egInfo.Decay * velrelease, |
|
|
RgnInfo.EG1Decay2 * egInfo.Decay * velrelease, |
|
|
RgnInfo.EG1InfiniteSustain, |
|
|
RgnInfo.EG1Sustain, |
|
|
RgnInfo.EG1Release * egInfo.Release * velrelease, |
|
|
velocityAttenuation, |
|
|
GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE |
|
|
); |
|
187 |
} |
} |
188 |
|
|
189 |
#ifdef CONFIG_INTERPOLATE_VOLUME |
#ifdef CONFIG_INTERPOLATE_VOLUME |
196 |
else |
else |
197 |
#else |
#else |
198 |
{ |
{ |
199 |
float finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * EG1.getLevel(); |
float finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pEG1->getLevel(); |
200 |
|
|
201 |
finalSynthesisParameters.fFinalVolumeLeft = finalVolume * VolumeLeft * pEngineChannel->GlobalPanLeft; |
finalSynthesisParameters.fFinalVolumeLeft = finalVolume * VolumeLeft * pEngineChannel->GlobalPanLeft; |
202 |
finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * pEngineChannel->GlobalPanRight; |
finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * pEngineChannel->GlobalPanRight; |
213 |
EGInfo egInfo = CalculateEG2ControllerInfluence(eg2controllervalue); |
EGInfo egInfo = CalculateEG2ControllerInfluence(eg2controllervalue); |
214 |
|
|
215 |
EG2.trigger ( |
EG2.trigger ( |
216 |
RgnInfo.EG2PreAttack, |
uint(RgnInfo.EG2PreAttack), |
217 |
RgnInfo.EG2Attack * egInfo.Attack, |
RgnInfo.EG2Attack * egInfo.Attack, |
218 |
false, |
false, |
219 |
RgnInfo.EG2Decay1 * egInfo.Decay * velrelease, |
RgnInfo.EG2Decay1 * egInfo.Decay * velrelease, |
220 |
RgnInfo.EG2Decay2 * egInfo.Decay * velrelease, |
RgnInfo.EG2Decay2 * egInfo.Decay * velrelease, |
221 |
RgnInfo.EG2InfiniteSustain, |
RgnInfo.EG2InfiniteSustain, |
222 |
RgnInfo.EG2Sustain, |
uint(RgnInfo.EG2Sustain), |
223 |
RgnInfo.EG2Release * egInfo.Release * velrelease, |
RgnInfo.EG2Release * egInfo.Release * velrelease, |
224 |
velocityAttenuation, |
velocityAttenuation, |
225 |
GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE |
GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE |
314 |
RTList<Event>::Iterator itNoteEvent; |
RTList<Event>::Iterator itNoteEvent; |
315 |
GetFirstEventOnKey(MIDIKey, itNoteEvent); |
GetFirstEventOnKey(MIDIKey, itNoteEvent); |
316 |
|
|
317 |
|
RTList<Event>::Iterator itGroupEvent; |
318 |
|
if (pGroupEvents) itGroupEvent = pGroupEvents->first(); |
319 |
|
|
320 |
if (itTriggerEvent) { // skip events that happened before this voice was triggered |
if (itTriggerEvent) { // skip events that happened before this voice was triggered |
321 |
while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent; |
while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent; |
322 |
|
while (itGroupEvent && itGroupEvent->FragmentPos() <= Skip) ++itGroupEvent; |
323 |
|
|
324 |
// we can't simply compare the timestamp here, because note events |
// we can't simply compare the timestamp here, because note events |
325 |
// 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 |
326 |
// actual sequence the note events arrived instead (see bug #112) |
// actual sequence the note events arrived instead (see bug #112) |
341 |
// drivers that use Samples < MaxSamplesPerCycle). |
// drivers that use Samples < MaxSamplesPerCycle). |
342 |
// End the EG1 here, at pos 0, with a shorter max fade |
// End the EG1 here, at pos 0, with a shorter max fade |
343 |
// out time. |
// out time. |
344 |
EG1.enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
pEG1->enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
345 |
itKillEvent = Pool<Event>::Iterator(); |
itKillEvent = Pool<Event>::Iterator(); |
346 |
} else { |
} else { |
347 |
killPos = RTMath::Min(itKillEvent->FragmentPos(), maxFadeOutPos); |
killPos = RTMath::Min(itKillEvent->FragmentPos(), maxFadeOutPos); |
367 |
|
|
368 |
// process transition events (note on, note off & sustain pedal) |
// process transition events (note on, note off & sustain pedal) |
369 |
processTransitionEvents(itNoteEvent, iSubFragmentEnd); |
processTransitionEvents(itNoteEvent, iSubFragmentEnd); |
370 |
|
processGroupEvents(itGroupEvent, iSubFragmentEnd); |
371 |
|
|
372 |
// if the voice was killed in this subfragment, or if the |
// if the voice was killed in this subfragment, or if the |
373 |
// filter EG is finished, switch EG1 to fade out stage |
// filter EG is finished, switch EG1 to fade out stage |
374 |
if ((itKillEvent && killPos <= iSubFragmentEnd) || |
if ((itKillEvent && killPos <= iSubFragmentEnd) || |
375 |
(SYNTHESIS_MODE_GET_FILTER(SynthesisMode) && |
(SYNTHESIS_MODE_GET_FILTER(SynthesisMode) && |
376 |
EG2.getSegmentType() == gig::EGADSR::segment_end)) { |
EG2.getSegmentType() == gig::EGADSR::segment_end)) { |
377 |
EG1.enterFadeOutStage(); |
pEG1->enterFadeOutStage(); |
378 |
itKillEvent = Pool<Event>::Iterator(); |
itKillEvent = Pool<Event>::Iterator(); |
379 |
} |
} |
380 |
|
|
381 |
// process envelope generators |
// process envelope generators |
382 |
switch (EG1.getSegmentType()) { |
switch (pEG1->getSegmentType()) { |
383 |
case gig::EGADSR::segment_lin: |
case EG::segment_lin: |
384 |
fFinalVolume *= EG1.processLin(); |
fFinalVolume *= pEG1->processLin(); |
385 |
break; |
break; |
386 |
case gig::EGADSR::segment_exp: |
case EG::segment_exp: |
387 |
fFinalVolume *= EG1.processExp(); |
fFinalVolume *= pEG1->processExp(); |
388 |
break; |
break; |
389 |
case gig::EGADSR::segment_end: |
case EG::segment_end: |
390 |
fFinalVolume *= EG1.getLevel(); |
fFinalVolume *= pEG1->getLevel(); |
391 |
break; // noop |
break; // noop |
392 |
|
case EG::segment_pow: |
393 |
|
fFinalVolume *= pEG1->processPow(); |
394 |
|
break; |
395 |
} |
} |
396 |
switch (EG2.getSegmentType()) { |
switch (EG2.getSegmentType()) { |
397 |
case gig::EGADSR::segment_lin: |
case gig::EGADSR::segment_lin: |
446 |
RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop); |
RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop); |
447 |
|
|
448 |
// stop the rendering if volume EG is finished |
// stop the rendering if volume EG is finished |
449 |
if (EG1.getSegmentType() == gig::EGADSR::segment_end) break; |
if (pEG1->getSegmentType() == EG::segment_end) break; |
450 |
|
|
451 |
const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch; |
const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch; |
452 |
|
|
453 |
// increment envelopes' positions |
// increment envelopes' positions |
454 |
if (EG1.active()) { |
if (pEG1->active()) { |
455 |
|
|
456 |
// 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 |
// 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 |
457 |
if (SmplInfo.HasLoops && Pos <= SmplInfo.LoopStart && SmplInfo.LoopStart < newPos) { |
if (SmplInfo.HasLoops && Pos <= SmplInfo.LoopStart && SmplInfo.LoopStart < newPos) { |
458 |
EG1.update(gig::EGADSR::event_hold_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
pEG1->update(EG::event_hold_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
459 |
} |
} |
460 |
|
|
461 |
EG1.increment(1); |
pEG1->increment(1); |
462 |
if (!EG1.toStageEndLeft()) EG1.update(gig::EGADSR::event_stage_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
if (!pEG1->toStageEndLeft()) pEG1->update(EG::event_stage_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
463 |
} |
} |
464 |
if (EG2.active()) { |
if (EG2.active()) { |
465 |
EG2.increment(1); |
EG2.increment(1); |
472 |
i = iSubFragmentEnd; |
i = iSubFragmentEnd; |
473 |
} |
} |
474 |
} |
} |
475 |
|
|
476 |
/** |
/** |
477 |
* Process given list of MIDI control change and pitch bend events for |
* Process given list of MIDI control change and pitch bend events for |
478 |
* the given time. |
* the given time. |
535 |
*/ |
*/ |
536 |
void AbstractVoice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) { |
void AbstractVoice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) { |
537 |
for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) { |
for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) { |
538 |
if (itEvent->Type == Event::type_release) { |
// some voice types ignore note off |
539 |
EG1.update(gig::EGADSR::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
if (!(Type & (Voice::type_one_shot | Voice::type_release_trigger | Voice::type_controller_triggered))) { |
540 |
EG2.update(gig::EGADSR::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
if (itEvent->Type == Event::type_release) { |
541 |
} else if (itEvent->Type == Event::type_cancel_release) { |
EnterReleaseStage(); |
542 |
EG1.update(gig::EGADSR::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
} else if (itEvent->Type == Event::type_cancel_release) { |
543 |
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); |
544 |
|
EG2.update(gig::EGADSR::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
545 |
|
} |
546 |
} |
} |
547 |
} |
} |
548 |
} |
} |
549 |
|
|
550 |
|
/** |
551 |
|
* Process given list of events aimed at all voices in a key group. |
552 |
|
* |
553 |
|
* @param itEvent - iterator pointing to the next event to be processed |
554 |
|
* @param End - youngest time stamp where processing should be stopped |
555 |
|
*/ |
556 |
|
void AbstractVoice::processGroupEvents(RTList<Event>::Iterator& itEvent, uint End) { |
557 |
|
for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) { |
558 |
|
ProcessGroupEvent(itEvent); |
559 |
|
} |
560 |
|
} |
561 |
|
|
562 |
/** @brief Update current portamento position. |
/** @brief Update current portamento position. |
563 |
* |
* |
564 |
* Will be called when portamento mode is enabled to get the final |
* Will be called when portamento mode is enabled to get the final |
616 |
volume *= GetSampleAttenuation() * pEngineChannel->GlobalVolume * GLOBAL_VOLUME; |
volume *= GetSampleAttenuation() * pEngineChannel->GlobalVolume * GLOBAL_VOLUME; |
617 |
|
|
618 |
// the volume of release triggered samples depends on note length |
// the volume of release triggered samples depends on note length |
619 |
if (Type == Voice::type_release_trigger) { |
if (Type & Voice::type_release_trigger) { |
620 |
float noteLength = float(GetEngine()->FrameTime + Delay - |
float noteLength = float(GetEngine()->FrameTime + Delay - |
621 |
GetNoteOnTime(MIDIKey) ) / GetEngine()->SampleRate; |
GetNoteOnTime(MIDIKey) ) / GetEngine()->SampleRate; |
622 |
|
|
623 |
float attenuation = 1 - 0.01053 * (256 >> RgnInfo.ReleaseTriggerDecay) * noteLength; |
volume *= GetReleaseTriggerAttenuation(noteLength); |
|
volume *= attenuation; |
|
624 |
} |
} |
625 |
|
|
626 |
return volume; |
return volume; |
627 |
} |
} |
628 |
|
|
629 |
|
float AbstractVoice::GetReleaseTriggerAttenuation(float noteLength) { |
630 |
|
return 1 - RgnInfo.ReleaseTriggerDecay * noteLength; |
631 |
|
} |
632 |
|
|
633 |
|
void AbstractVoice::EnterReleaseStage() { |
634 |
|
pEG1->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
635 |
|
EG2.update(gig::EGADSR::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); |
636 |
|
} |
637 |
|
|
638 |
} // namespace LinuxSampler |
} // namespace LinuxSampler |