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, 2006 Christian Schoenebeck * |
* Copyright (C) 2005 - 2007 Christian Schoenebeck * |
7 |
* * |
* * |
8 |
* This program is free software; you can redistribute it and/or modify * |
* This program is free software; you can redistribute it and/or modify * |
9 |
* 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 * |
38 |
pLFO3 = new LFOSigned(1200.0f); // pitch EG (-1200..+1200 range) |
pLFO3 = new LFOSigned(1200.0f); // pitch EG (-1200..+1200 range) |
39 |
KeyGroup = 0; |
KeyGroup = 0; |
40 |
SynthesisMode = 0; // set all mode bits to 0 first |
SynthesisMode = 0; // set all mode bits to 0 first |
41 |
// select synthesis implementation (currently either pure C++ or MMX+SSE(1)) |
// select synthesis implementation (asm core is not supported ATM) |
42 |
#if CONFIG_ASM && ARCH_X86 |
#if 0 // CONFIG_ASM && ARCH_X86 |
43 |
SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, Features::supportsMMX() && Features::supportsSSE()); |
SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, Features::supportsMMX() && Features::supportsSSE()); |
44 |
#else |
#else |
45 |
SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, false); |
SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, false); |
79 |
int Voice::Trigger(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent, int PitchBend, ::gig::DimensionRegion* pDimRgn, type_t VoiceType, int iKeyGroup) { |
int Voice::Trigger(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent, int PitchBend, ::gig::DimensionRegion* pDimRgn, type_t VoiceType, int iKeyGroup) { |
80 |
this->pEngineChannel = pEngineChannel; |
this->pEngineChannel = pEngineChannel; |
81 |
this->pDimRgn = pDimRgn; |
this->pDimRgn = pDimRgn; |
82 |
|
Orphan = false; |
83 |
|
|
84 |
#if CONFIG_DEVMODE |
#if CONFIG_DEVMODE |
85 |
if (itNoteOnEvent->FragmentPos() > pEngine->MaxSamplesPerCycle) { // just a sanity check for debugging |
if (itNoteOnEvent->FragmentPos() > pEngine->MaxSamplesPerCycle) { // just a sanity check for debugging |
99 |
// calculate volume |
// calculate volume |
100 |
const double velocityAttenuation = pDimRgn->GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity); |
const double velocityAttenuation = pDimRgn->GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity); |
101 |
|
|
102 |
float volume = velocityAttenuation / 32768.0f; // we downscale by 32768 to convert from int16 value range to DSP value range (which is -1.0..1.0) |
// For 16 bit samples, we downscale by 32768 to convert from |
103 |
|
// int16 value range to DSP value range (which is |
104 |
|
// -1.0..1.0). For 24 bit, we downscale from int32. |
105 |
|
float volume = velocityAttenuation / (pSample->BitDepth == 16 ? 32768.0f : 32768.0f * 65536.0f); |
106 |
|
|
107 |
volume *= pDimRgn->SampleAttenuation; |
volume *= pDimRgn->SampleAttenuation * pEngineChannel->GlobalVolume * GLOBAL_VOLUME; |
108 |
|
|
109 |
// the volume of release triggered samples depends on note length |
// the volume of release triggered samples depends on note length |
110 |
if (Type == type_release_trigger) { |
if (Type == type_release_trigger) { |
117 |
|
|
118 |
// select channel mode (mono or stereo) |
// select channel mode (mono or stereo) |
119 |
SYNTHESIS_MODE_SET_CHANNELS(SynthesisMode, pSample->Channels == 2); |
SYNTHESIS_MODE_SET_CHANNELS(SynthesisMode, pSample->Channels == 2); |
120 |
|
// select bit depth (16 or 24) |
121 |
|
SYNTHESIS_MODE_SET_BITDEPTH24(SynthesisMode, pSample->BitDepth == 24); |
122 |
|
|
123 |
// get starting crossfade volume level |
// get starting crossfade volume level |
124 |
float crossfadeVolume; |
float crossfadeVolume; |
125 |
switch (pDimRgn->AttenuationController.type) { |
switch (pDimRgn->AttenuationController.type) { |
126 |
case ::gig::attenuation_ctrl_t::type_channelaftertouch: |
case ::gig::attenuation_ctrl_t::type_channelaftertouch: |
127 |
crossfadeVolume = 1.0f; //TODO: aftertouch not supported yet |
crossfadeVolume = Engine::CrossfadeCurve[CrossfadeAttenuation(pEngineChannel->ControllerTable[128])]; |
128 |
break; |
break; |
129 |
case ::gig::attenuation_ctrl_t::type_velocity: |
case ::gig::attenuation_ctrl_t::type_velocity: |
130 |
crossfadeVolume = Engine::CrossfadeCurve[CrossfadeAttenuation(itNoteOnEvent->Param.Note.Velocity)]; |
crossfadeVolume = Engine::CrossfadeCurve[CrossfadeAttenuation(itNoteOnEvent->Param.Note.Velocity)]; |
142 |
|
|
143 |
float subfragmentRate = pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE; |
float subfragmentRate = pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE; |
144 |
CrossfadeSmoother.trigger(crossfadeVolume, subfragmentRate); |
CrossfadeSmoother.trigger(crossfadeVolume, subfragmentRate); |
145 |
VolumeSmoother.trigger(pEngineChannel->GlobalVolume, subfragmentRate); |
VolumeSmoother.trigger(pEngineChannel->MidiVolume, subfragmentRate); |
146 |
PanLeftSmoother.trigger(pEngineChannel->GlobalPanLeft, subfragmentRate); |
PanLeftSmoother.trigger(pEngineChannel->GlobalPanLeft, subfragmentRate); |
147 |
PanRightSmoother.trigger(pEngineChannel->GlobalPanRight, subfragmentRate); |
PanRightSmoother.trigger(pEngineChannel->GlobalPanRight, subfragmentRate); |
148 |
|
|
201 |
eg1controllervalue = 0; |
eg1controllervalue = 0; |
202 |
break; |
break; |
203 |
case ::gig::eg1_ctrl_t::type_channelaftertouch: |
case ::gig::eg1_ctrl_t::type_channelaftertouch: |
204 |
eg1controllervalue = 0; // TODO: aftertouch not yet supported |
eg1controllervalue = pEngineChannel->ControllerTable[128]; |
205 |
break; |
break; |
206 |
case ::gig::eg1_ctrl_t::type_velocity: |
case ::gig::eg1_ctrl_t::type_velocity: |
207 |
eg1controllervalue = itNoteOnEvent->Param.Note.Velocity; |
eg1controllervalue = itNoteOnEvent->Param.Note.Velocity; |
242 |
else |
else |
243 |
#else |
#else |
244 |
{ |
{ |
245 |
float finalVolume = pEngineChannel->GlobalVolume * crossfadeVolume * EG1.getLevel(); |
float finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * EG1.getLevel(); |
246 |
|
|
247 |
finalSynthesisParameters.fFinalVolumeLeft = finalVolume * VolumeLeft * pEngineChannel->GlobalPanLeft; |
finalSynthesisParameters.fFinalVolumeLeft = finalVolume * VolumeLeft * pEngineChannel->GlobalPanLeft; |
248 |
finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * pEngineChannel->GlobalPanRight; |
finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * pEngineChannel->GlobalPanRight; |
259 |
eg2controllervalue = 0; |
eg2controllervalue = 0; |
260 |
break; |
break; |
261 |
case ::gig::eg2_ctrl_t::type_channelaftertouch: |
case ::gig::eg2_ctrl_t::type_channelaftertouch: |
262 |
eg2controllervalue = 0; // TODO: aftertouch not yet supported |
eg2controllervalue = pEngineChannel->ControllerTable[128]; |
263 |
break; |
break; |
264 |
case ::gig::eg2_ctrl_t::type_velocity: |
case ::gig::eg2_ctrl_t::type_velocity: |
265 |
eg2controllervalue = itNoteOnEvent->Param.Note.Velocity; |
eg2controllervalue = itNoteOnEvent->Param.Note.Velocity; |
339 |
} |
} |
340 |
if (bLFO1Enabled) { |
if (bLFO1Enabled) { |
341 |
pLFO1->trigger(pDimRgn->LFO1Frequency, |
pLFO1->trigger(pDimRgn->LFO1Frequency, |
342 |
start_level_max, |
start_level_min, |
343 |
lfo1_internal_depth, |
lfo1_internal_depth, |
344 |
pDimRgn->LFO1ControlDepth, |
pDimRgn->LFO1ControlDepth, |
345 |
pDimRgn->LFO1FlipPhase, |
pDimRgn->LFO1FlipPhase, |
411 |
break; |
break; |
412 |
case ::gig::lfo3_ctrl_aftertouch: |
case ::gig::lfo3_ctrl_aftertouch: |
413 |
lfo3_internal_depth = 0; |
lfo3_internal_depth = 0; |
414 |
pLFO3->ExtController = 0; // TODO: aftertouch not implemented yet |
pLFO3->ExtController = 128; |
415 |
bLFO3Enabled = false; // see TODO comment in line above |
bLFO3Enabled = true; |
416 |
break; |
break; |
417 |
case ::gig::lfo3_ctrl_internal_modwheel: |
case ::gig::lfo3_ctrl_internal_modwheel: |
418 |
lfo3_internal_depth = pDimRgn->LFO3InternalDepth; |
lfo3_internal_depth = pDimRgn->LFO3InternalDepth; |
421 |
break; |
break; |
422 |
case ::gig::lfo3_ctrl_internal_aftertouch: |
case ::gig::lfo3_ctrl_internal_aftertouch: |
423 |
lfo3_internal_depth = pDimRgn->LFO3InternalDepth; |
lfo3_internal_depth = pDimRgn->LFO3InternalDepth; |
424 |
pLFO1->ExtController = 0; // TODO: aftertouch not implemented yet |
pLFO1->ExtController = 128; |
425 |
bLFO3Enabled = (lfo3_internal_depth > 0 /*|| pDimRgn->LFO3ControlDepth > 0*/); // see TODO comment in line above |
bLFO3Enabled = (lfo3_internal_depth > 0 || pDimRgn->LFO3ControlDepth > 0); |
426 |
break; |
break; |
427 |
default: |
default: |
428 |
lfo3_internal_depth = 0; |
lfo3_internal_depth = 0; |
479 |
case ::gig::vcf_cutoff_ctrl_genpurpose8: |
case ::gig::vcf_cutoff_ctrl_genpurpose8: |
480 |
VCFCutoffCtrl.controller = 83; |
VCFCutoffCtrl.controller = 83; |
481 |
break; |
break; |
482 |
case ::gig::vcf_cutoff_ctrl_aftertouch: //TODO: not implemented yet |
case ::gig::vcf_cutoff_ctrl_aftertouch: |
483 |
|
VCFCutoffCtrl.controller = 128; |
484 |
|
break; |
485 |
case ::gig::vcf_cutoff_ctrl_none: |
case ::gig::vcf_cutoff_ctrl_none: |
486 |
default: |
default: |
487 |
VCFCutoffCtrl.controller = 0; |
VCFCutoffCtrl.controller = 0; |
515 |
finalSynthesisParameters.filterLeft.SetType(pDimRgn->VCFType); |
finalSynthesisParameters.filterLeft.SetType(pDimRgn->VCFType); |
516 |
finalSynthesisParameters.filterRight.SetType(pDimRgn->VCFType); |
finalSynthesisParameters.filterRight.SetType(pDimRgn->VCFType); |
517 |
#else // override filter type |
#else // override filter type |
518 |
FilterLeft.SetType(CONFIG_OVERRIDE_FILTER_TYPE); |
finalSynthesisParameters.filterLeft.SetType(CONFIG_OVERRIDE_FILTER_TYPE); |
519 |
FilterRight.SetType(CONFIG_OVERRIDE_FILTER_TYPE); |
finalSynthesisParameters.filterRight.SetType(CONFIG_OVERRIDE_FILTER_TYPE); |
520 |
#endif // CONFIG_OVERRIDE_FILTER_TYPE |
#endif // CONFIG_OVERRIDE_FILTER_TYPE |
521 |
|
|
522 |
VCFCutoffCtrl.value = pEngineChannel->ControllerTable[VCFCutoffCtrl.controller]; |
VCFCutoffCtrl.value = pEngineChannel->ControllerTable[VCFCutoffCtrl.controller]; |
622 |
} |
} |
623 |
} |
} |
624 |
|
|
625 |
sample_t* ptr = DiskStreamRef.pStream->GetReadPtr(); // get the current read_ptr within the ringbuffer where we read the samples from |
sample_t* ptr = (sample_t*)DiskStreamRef.pStream->GetReadPtr(); // get the current read_ptr within the ringbuffer where we read the samples from |
626 |
|
|
627 |
// render current audio fragment |
// render current audio fragment |
628 |
Synthesize(Samples, ptr, Delay); |
Synthesize(Samples, ptr, Delay); |
720 |
CrossfadeSmoother.update(Engine::CrossfadeCurve[CrossfadeAttenuation(itEvent->Param.CC.Value)]); |
CrossfadeSmoother.update(Engine::CrossfadeCurve[CrossfadeAttenuation(itEvent->Param.CC.Value)]); |
721 |
} |
} |
722 |
if (itEvent->Param.CC.Controller == 7) { // volume |
if (itEvent->Param.CC.Controller == 7) { // volume |
723 |
VolumeSmoother.update(Engine::VolumeCurve[itEvent->Param.CC.Value] * CONFIG_GLOBAL_ATTENUATION); |
VolumeSmoother.update(Engine::VolumeCurve[itEvent->Param.CC.Value]); |
724 |
} else if (itEvent->Param.CC.Controller == 10) { // panpot |
} else if (itEvent->Param.CC.Controller == 10) { // panpot |
725 |
PanLeftSmoother.update(Engine::PanCurve[128 - itEvent->Param.CC.Value]); |
PanLeftSmoother.update(Engine::PanCurve[128 - itEvent->Param.CC.Value]); |
726 |
PanRightSmoother.update(Engine::PanCurve[itEvent->Param.CC.Value]); |
PanRightSmoother.update(Engine::PanCurve[itEvent->Param.CC.Value]); |
769 |
* @param Skip - number of sample points to skip in output buffer |
* @param Skip - number of sample points to skip in output buffer |
770 |
*/ |
*/ |
771 |
void Voice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) { |
void Voice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) { |
772 |
finalSynthesisParameters.pOutLeft = &pEngineChannel->pOutputLeft[Skip]; |
finalSynthesisParameters.pOutLeft = &pEngineChannel->pChannelLeft->Buffer()[Skip]; |
773 |
finalSynthesisParameters.pOutRight = &pEngineChannel->pOutputRight[Skip]; |
finalSynthesisParameters.pOutRight = &pEngineChannel->pChannelRight->Buffer()[Skip]; |
774 |
finalSynthesisParameters.pSrc = pSrc; |
finalSynthesisParameters.pSrc = pSrc; |
775 |
|
|
776 |
RTList<Event>::Iterator itCCEvent = pEngineChannel->pEvents->first(); |
RTList<Event>::Iterator itCCEvent = pEngineChannel->pEvents->first(); |
804 |
// process transition events (note on, note off & sustain pedal) |
// process transition events (note on, note off & sustain pedal) |
805 |
processTransitionEvents(itNoteEvent, iSubFragmentEnd); |
processTransitionEvents(itNoteEvent, iSubFragmentEnd); |
806 |
|
|
807 |
// if the voice was killed in this subfragment switch EG1 to fade out stage |
// if the voice was killed in this subfragment, or if the |
808 |
if (itKillEvent && killPos <= iSubFragmentEnd) { |
// filter EG is finished, switch EG1 to fade out stage |
809 |
|
if ((itKillEvent && killPos <= iSubFragmentEnd) || |
810 |
|
(SYNTHESIS_MODE_GET_FILTER(SynthesisMode) && |
811 |
|
EG2.getSegmentType() == EGADSR::segment_end)) { |
812 |
EG1.enterFadeOutStage(); |
EG1.enterFadeOutStage(); |
813 |
itKillEvent = Pool<Event>::Iterator(); |
itKillEvent = Pool<Event>::Iterator(); |
814 |
} |
} |
839 |
if (EG3.active()) finalSynthesisParameters.fFinalPitch *= EG3.render(); |
if (EG3.active()) finalSynthesisParameters.fFinalPitch *= EG3.render(); |
840 |
|
|
841 |
// process low frequency oscillators |
// process low frequency oscillators |
842 |
if (bLFO1Enabled) fFinalVolume *= pLFO1->render(); |
if (bLFO1Enabled) fFinalVolume *= (1.0f - pLFO1->render()); |
843 |
if (bLFO2Enabled) fFinalCutoff *= pLFO2->render(); |
if (bLFO2Enabled) fFinalCutoff *= pLFO2->render(); |
844 |
if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render()); |
if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render()); |
845 |
|
|
921 |
* fading down the volume level to avoid clicks and regular processing |
* fading down the volume level to avoid clicks and regular processing |
922 |
* until the kill event actually occured! |
* until the kill event actually occured! |
923 |
* |
* |
924 |
* @see Kill() |
* If it's necessary to know when the voice's disk stream was actually |
925 |
|
* deleted, then one can set the optional @a bRequestNotification |
926 |
|
* parameter and this method will then return the handle of the disk |
927 |
|
* stream (unique identifier) and one can use this handle to poll the |
928 |
|
* disk thread if this stream has been deleted. In any case this method |
929 |
|
* will return immediately and will not block until the stream actually |
930 |
|
* was deleted. |
931 |
|
* |
932 |
|
* @param bRequestNotification - (optional) whether the disk thread shall |
933 |
|
* provide a notification once it deleted |
934 |
|
* the respective disk stream |
935 |
|
* (default=false) |
936 |
|
* @returns handle to the voice's disk stream or @c Stream::INVALID_HANDLE |
937 |
|
* if the voice did not use a disk stream at all |
938 |
|
* @see Kill() |
939 |
*/ |
*/ |
940 |
void Voice::KillImmediately() { |
Stream::Handle Voice::KillImmediately(bool bRequestNotification) { |
941 |
|
Stream::Handle hStream = Stream::INVALID_HANDLE; |
942 |
if (DiskVoice && DiskStreamRef.State != Stream::state_unused) { |
if (DiskVoice && DiskStreamRef.State != Stream::state_unused) { |
943 |
pDiskThread->OrderDeletionOfStream(&DiskStreamRef); |
pDiskThread->OrderDeletionOfStream(&DiskStreamRef, bRequestNotification); |
944 |
|
hStream = DiskStreamRef.hStream; |
945 |
} |
} |
946 |
Reset(); |
Reset(); |
947 |
|
return hStream; |
948 |
} |
} |
949 |
|
|
950 |
/** |
/** |