35 |
const int Voice::FILTER_UPDATE_MASK(CalculateFilterUpdateMask()); |
const int Voice::FILTER_UPDATE_MASK(CalculateFilterUpdateMask()); |
36 |
|
|
37 |
float Voice::CalculateFilterCutoffCoeff() { |
float Voice::CalculateFilterCutoffCoeff() { |
38 |
return log(FILTER_CUTOFF_MIN / FILTER_CUTOFF_MAX); |
return log(CONFIG_FILTER_CUTOFF_MIN / CONFIG_FILTER_CUTOFF_MAX); |
39 |
} |
} |
40 |
|
|
41 |
int Voice::CalculateFilterUpdateMask() { |
int Voice::CalculateFilterUpdateMask() { |
42 |
if (FILTER_UPDATE_PERIOD <= 0) return 0; |
if (CONFIG_FILTER_UPDATE_STEPS <= 0) return 0; |
43 |
int power_of_two; |
int power_of_two; |
44 |
for (power_of_two = 0; 1<<power_of_two < FILTER_UPDATE_PERIOD; power_of_two++); |
for (power_of_two = 0; 1<<power_of_two < CONFIG_FILTER_UPDATE_STEPS; power_of_two++); |
45 |
return (1 << power_of_two) - 1; |
return (1 << power_of_two) - 1; |
46 |
} |
} |
47 |
|
|
61 |
KeyGroup = 0; |
KeyGroup = 0; |
62 |
SynthesisMode = 0; // set all mode bits to 0 first |
SynthesisMode = 0; // set all mode bits to 0 first |
63 |
// select synthesis implementation (currently either pure C++ or MMX+SSE(1)) |
// select synthesis implementation (currently either pure C++ or MMX+SSE(1)) |
64 |
#if ARCH_X86 |
#if CONFIG_ASM && ARCH_X86 |
65 |
SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, Features::supportsMMX() && Features::supportsSSE()); |
SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, Features::supportsMMX() && Features::supportsSSE()); |
66 |
#else |
#else |
67 |
SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, false); |
SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, false); |
134 |
dmsg(1,("voice::trigger: !pInstrument\n")); |
dmsg(1,("voice::trigger: !pInstrument\n")); |
135 |
exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
136 |
} |
} |
137 |
if (itNoteOnEvent->FragmentPos() > pEngine->MaxSamplesPerCycle) { // FIXME: should be removed before the final release (purpose: just a sanity check for debugging) |
#if CONFIG_DEVMODE |
138 |
|
if (itNoteOnEvent->FragmentPos() > pEngine->MaxSamplesPerCycle) { // just a sanity check for debugging |
139 |
dmsg(1,("Voice::Trigger(): ERROR, TriggerDelay > Totalsamples\n")); |
dmsg(1,("Voice::Trigger(): ERROR, TriggerDelay > Totalsamples\n")); |
140 |
} |
} |
141 |
|
#endif // CONFIG_DEVMODE |
142 |
|
|
143 |
Type = type_normal; |
Type = type_normal; |
144 |
MIDIKey = itNoteOnEvent->Param.Note.Key; |
MIDIKey = itNoteOnEvent->Param.Note.Key; |
145 |
pRegion = pInstrument->GetRegion(MIDIKey); |
pRegion = pInstrument->GetRegion(MIDIKey); |
146 |
PlaybackState = playback_state_ram; // we always start playback from RAM cache and switch then to disk if needed |
PlaybackState = playback_state_init; // mark voice as triggered, but no audio rendered yet |
147 |
Delay = itNoteOnEvent->FragmentPos(); |
Delay = itNoteOnEvent->FragmentPos(); |
148 |
itTriggerEvent = itNoteOnEvent; |
itTriggerEvent = itNoteOnEvent; |
149 |
itKillEvent = Pool<Event>::Iterator(); |
itKillEvent = Pool<Event>::Iterator(); |
269 |
pSample = pDimRgn->pSample; // sample won't change until the voice is finished |
pSample = pDimRgn->pSample; // sample won't change until the voice is finished |
270 |
if (!pSample || !pSample->SamplesTotal) return -1; // no need to continue if sample is silent |
if (!pSample || !pSample->SamplesTotal) return -1; // no need to continue if sample is silent |
271 |
|
|
272 |
|
// calculate volume |
273 |
|
const double velocityAttenuation = pDimRgn->GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity); |
274 |
|
|
275 |
|
Volume = velocityAttenuation / 32768.0f; // we downscale by 32768 to convert from int16 value range to DSP value range (which is -1.0..1.0) |
276 |
|
|
277 |
|
Volume *= pDimRgn->SampleAttenuation; |
278 |
|
|
279 |
|
// the volume of release triggered samples depends on note length |
280 |
|
if (ReleaseTriggerVoice) { |
281 |
|
float noteLength = float(pEngine->FrameTime + Delay - |
282 |
|
pEngineChannel->pMIDIKeyInfo[MIDIKey].NoteOnTime) / pEngine->SampleRate; |
283 |
|
float attenuation = 1 - 0.01053 * (256 >> pDimRgn->ReleaseTriggerDecay) * noteLength; |
284 |
|
if (attenuation <= 0) return -1; |
285 |
|
Volume *= attenuation; |
286 |
|
} |
287 |
|
|
288 |
// select channel mode (mono or stereo) |
// select channel mode (mono or stereo) |
289 |
SYNTHESIS_MODE_SET_CHANNELS(SynthesisMode, pSample->Channels == 2); |
SYNTHESIS_MODE_SET_CHANNELS(SynthesisMode, pSample->Channels == 2); |
290 |
|
|
314 |
DiskVoice = cachedsamples < pSample->SamplesTotal; |
DiskVoice = cachedsamples < pSample->SamplesTotal; |
315 |
|
|
316 |
if (DiskVoice) { // voice to be streamed from disk |
if (DiskVoice) { // voice to be streamed from disk |
317 |
MaxRAMPos = cachedsamples - (pEngine->MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels; //TODO: this calculation is too pessimistic and may better be moved to Render() method, so it calculates MaxRAMPos dependent to the current demand of sample points to be rendered (e.g. in case of JACK) |
MaxRAMPos = cachedsamples - (pEngine->MaxSamplesPerCycle << CONFIG_MAX_PITCH) / pSample->Channels; //TODO: this calculation is too pessimistic and may better be moved to Render() method, so it calculates MaxRAMPos dependent to the current demand of sample points to be rendered (e.g. in case of JACK) |
318 |
|
|
319 |
// check if there's a loop defined which completely fits into the cached (RAM) part of the sample |
// check if there's a loop defined which completely fits into the cached (RAM) part of the sample |
320 |
if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) { |
if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) { |
349 |
this->PitchBend = RTMath::CentsToFreqRatio(((double) PitchBend / 8192.0) * 200.0); // pitchbend wheel +-2 semitones = 200 cents |
this->PitchBend = RTMath::CentsToFreqRatio(((double) PitchBend / 8192.0) * 200.0); // pitchbend wheel +-2 semitones = 200 cents |
350 |
} |
} |
351 |
|
|
352 |
Volume = pDimRgn->GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity) / 32768.0f; // we downscale by 32768 to convert from int16 value range to DSP value range (which is -1.0..1.0) |
// the length of the decay and release curves are dependent on the velocity |
353 |
|
const double velrelease = 1 / pDimRgn->GetVelocityRelease(itNoteOnEvent->Param.Note.Velocity); |
|
Volume *= pDimRgn->SampleAttenuation; |
|
354 |
|
|
355 |
// setup EG 1 (VCA EG) |
// setup EG 1 (VCA EG) |
356 |
{ |
{ |
381 |
pDimRgn->EG1Attack + eg1attack, |
pDimRgn->EG1Attack + eg1attack, |
382 |
pDimRgn->EG1Hold, |
pDimRgn->EG1Hold, |
383 |
pSample->LoopStart, |
pSample->LoopStart, |
384 |
pDimRgn->EG1Decay1 + eg1decay, |
(pDimRgn->EG1Decay1 + eg1decay) * velrelease, |
385 |
pDimRgn->EG1Decay2 + eg1decay, |
(pDimRgn->EG1Decay2 + eg1decay) * velrelease, |
386 |
pDimRgn->EG1InfiniteSustain, |
pDimRgn->EG1InfiniteSustain, |
387 |
pDimRgn->EG1Sustain, |
pDimRgn->EG1Sustain, |
388 |
pDimRgn->EG1Release + eg1release, |
(pDimRgn->EG1Release + eg1release) * velrelease, |
389 |
// the SSE synthesis implementation requires |
// the SSE synthesis implementation requires |
390 |
// the vca start to be 16 byte aligned |
// the vca start to be 16 byte aligned |
391 |
SYNTHESIS_MODE_GET_IMPLEMENTATION(SynthesisMode) ? |
SYNTHESIS_MODE_GET_IMPLEMENTATION(SynthesisMode) ? |
392 |
Delay & 0xfffffffc : Delay); |
Delay & 0xfffffffc : Delay, |
393 |
|
velocityAttenuation); |
394 |
} |
} |
395 |
|
|
396 |
|
|
423 |
pDimRgn->EG2Attack + eg2attack, |
pDimRgn->EG2Attack + eg2attack, |
424 |
false, |
false, |
425 |
pSample->LoopStart, |
pSample->LoopStart, |
426 |
pDimRgn->EG2Decay1 + eg2decay, |
(pDimRgn->EG2Decay1 + eg2decay) * velrelease, |
427 |
pDimRgn->EG2Decay2 + eg2decay, |
(pDimRgn->EG2Decay2 + eg2decay) * velrelease, |
428 |
pDimRgn->EG2InfiniteSustain, |
pDimRgn->EG2InfiniteSustain, |
429 |
pDimRgn->EG2Sustain, |
pDimRgn->EG2Sustain, |
430 |
pDimRgn->EG2Release + eg2release, |
(pDimRgn->EG2Release + eg2release) * velrelease, |
431 |
Delay); |
Delay, |
432 |
|
velocityAttenuation); |
433 |
} |
} |
434 |
|
|
435 |
|
|
554 |
} |
} |
555 |
|
|
556 |
|
|
557 |
#if FORCE_FILTER_USAGE |
#if CONFIG_FORCE_FILTER |
558 |
const bool bUseFilter = true; |
const bool bUseFilter = true; |
559 |
#else // use filter only if instrument file told so |
#else // use filter only if instrument file told so |
560 |
const bool bUseFilter = pDimRgn->VCFEnabled; |
const bool bUseFilter = pDimRgn->VCFEnabled; |
561 |
#endif // FORCE_FILTER_USAGE |
#endif // CONFIG_FORCE_FILTER |
562 |
SYNTHESIS_MODE_SET_FILTER(SynthesisMode, bUseFilter); |
SYNTHESIS_MODE_SET_FILTER(SynthesisMode, bUseFilter); |
563 |
if (bUseFilter) { |
if (bUseFilter) { |
564 |
#ifdef OVERRIDE_FILTER_CUTOFF_CTRL |
#ifdef CONFIG_OVERRIDE_CUTOFF_CTRL |
565 |
VCFCutoffCtrl.controller = OVERRIDE_FILTER_CUTOFF_CTRL; |
VCFCutoffCtrl.controller = CONFIG_OVERRIDE_CUTOFF_CTRL; |
566 |
#else // use the one defined in the instrument file |
#else // use the one defined in the instrument file |
567 |
switch (pDimRgn->VCFCutoffController) { |
switch (pDimRgn->VCFCutoffController) { |
568 |
case ::gig::vcf_cutoff_ctrl_modwheel: |
case ::gig::vcf_cutoff_ctrl_modwheel: |
598 |
VCFCutoffCtrl.controller = 0; |
VCFCutoffCtrl.controller = 0; |
599 |
break; |
break; |
600 |
} |
} |
601 |
#endif // OVERRIDE_FILTER_CUTOFF_CTRL |
#endif // CONFIG_OVERRIDE_CUTOFF_CTRL |
602 |
|
|
603 |
#ifdef OVERRIDE_FILTER_RES_CTRL |
#ifdef CONFIG_OVERRIDE_RESONANCE_CTRL |
604 |
VCFResonanceCtrl.controller = OVERRIDE_FILTER_RES_CTRL; |
VCFResonanceCtrl.controller = CONFIG_OVERRIDE_RESONANCE_CTRL; |
605 |
#else // use the one defined in the instrument file |
#else // use the one defined in the instrument file |
606 |
switch (pDimRgn->VCFResonanceController) { |
switch (pDimRgn->VCFResonanceController) { |
607 |
case ::gig::vcf_res_ctrl_genpurpose3: |
case ::gig::vcf_res_ctrl_genpurpose3: |
620 |
default: |
default: |
621 |
VCFResonanceCtrl.controller = 0; |
VCFResonanceCtrl.controller = 0; |
622 |
} |
} |
623 |
#endif // OVERRIDE_FILTER_RES_CTRL |
#endif // CONFIG_OVERRIDE_RESONANCE_CTRL |
624 |
|
|
625 |
#ifndef OVERRIDE_FILTER_TYPE |
#ifndef CONFIG_OVERRIDE_FILTER_TYPE |
626 |
FilterLeft.SetType(pDimRgn->VCFType); |
FilterLeft.SetType(pDimRgn->VCFType); |
627 |
FilterRight.SetType(pDimRgn->VCFType); |
FilterRight.SetType(pDimRgn->VCFType); |
628 |
#else // override filter type |
#else // override filter type |
629 |
FilterLeft.SetType(OVERRIDE_FILTER_TYPE); |
FilterLeft.SetType(CONFIG_OVERRIDE_FILTER_TYPE); |
630 |
FilterRight.SetType(OVERRIDE_FILTER_TYPE); |
FilterRight.SetType(CONFIG_OVERRIDE_FILTER_TYPE); |
631 |
#endif // OVERRIDE_FILTER_TYPE |
#endif // CONFIG_OVERRIDE_FILTER_TYPE |
632 |
|
|
633 |
VCFCutoffCtrl.value = pEngineChannel->ControllerTable[VCFCutoffCtrl.controller]; |
VCFCutoffCtrl.value = pEngineChannel->ControllerTable[VCFCutoffCtrl.controller]; |
634 |
VCFResonanceCtrl.value = pEngineChannel->ControllerTable[VCFResonanceCtrl.controller]; |
VCFResonanceCtrl.value = pEngineChannel->ControllerTable[VCFResonanceCtrl.controller]; |
635 |
|
|
636 |
// calculate cutoff frequency |
// calculate cutoff frequency |
637 |
float cutoff = (!VCFCutoffCtrl.controller) |
float cutoff = (!VCFCutoffCtrl.controller) |
638 |
? exp((float) (127 - itNoteOnEvent->Param.Note.Velocity) * (float) pDimRgn->VCFVelocityScale * 6.2E-5f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX |
? exp((float) (127 - itNoteOnEvent->Param.Note.Velocity) * (float) pDimRgn->VCFVelocityScale * 6.2E-5f * FILTER_CUTOFF_COEFF) * CONFIG_FILTER_CUTOFF_MAX |
639 |
: exp((float) VCFCutoffCtrl.value * 0.00787402f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX; |
: exp((float) VCFCutoffCtrl.value * 0.00787402f * FILTER_CUTOFF_COEFF) * CONFIG_FILTER_CUTOFF_MAX; |
640 |
|
|
641 |
// calculate resonance |
// calculate resonance |
642 |
float resonance = (float) VCFResonanceCtrl.value * 0.00787f; // 0.0..1.0 |
float resonance = (float) VCFResonanceCtrl.value * 0.00787f; // 0.0..1.0 |
645 |
} |
} |
646 |
Constrain(resonance, 0.0, 1.0); // correct resonance if outside allowed value range (0.0..1.0) |
Constrain(resonance, 0.0, 1.0); // correct resonance if outside allowed value range (0.0..1.0) |
647 |
|
|
648 |
VCFCutoffCtrl.fvalue = cutoff - FILTER_CUTOFF_MIN; |
VCFCutoffCtrl.fvalue = cutoff - CONFIG_FILTER_CUTOFF_MIN; |
649 |
VCFResonanceCtrl.fvalue = resonance; |
VCFResonanceCtrl.fvalue = resonance; |
650 |
|
|
651 |
FilterUpdateCounter = -1; |
FilterUpdateCounter = -1; |
705 |
|
|
706 |
switch (this->PlaybackState) { |
switch (this->PlaybackState) { |
707 |
|
|
708 |
|
case playback_state_init: |
709 |
|
this->PlaybackState = playback_state_ram; // we always start playback from RAM cache and switch then to disk if needed |
710 |
|
// no break - continue with playback_state_ram |
711 |
|
|
712 |
case playback_state_ram: { |
case playback_state_ram: { |
713 |
if (RAMLoop) SYNTHESIS_MODE_SET_LOOP(SynthesisMode, true); // enable looping |
if (RAMLoop) SYNTHESIS_MODE_SET_LOOP(SynthesisMode, true); // enable looping |
714 |
|
|
746 |
|
|
747 |
// add silence sample at the end if we reached the end of the stream (for the interpolator) |
// add silence sample at the end if we reached the end of the stream (for the interpolator) |
748 |
if (DiskStreamRef.State == Stream::state_end) { |
if (DiskStreamRef.State == Stream::state_end) { |
749 |
const int maxSampleWordsPerCycle = (pEngine->MaxSamplesPerCycle << MAX_PITCH) * pSample->Channels + 6; // +6 for the interpolator algorithm |
const int maxSampleWordsPerCycle = (pEngine->MaxSamplesPerCycle << CONFIG_MAX_PITCH) * pSample->Channels + 6; // +6 for the interpolator algorithm |
750 |
if (sampleWordsLeftToRead <= maxSampleWordsPerCycle) { |
if (sampleWordsLeftToRead <= maxSampleWordsPerCycle) { |
751 |
// remember how many sample words there are before any silence has been added |
// remember how many sample words there are before any silence has been added |
752 |
if (RealSampleWordsLeftToRead < 0) RealSampleWordsLeftToRead = sampleWordsLeftToRead; |
if (RealSampleWordsLeftToRead < 0) RealSampleWordsLeftToRead = sampleWordsLeftToRead; |
933 |
// calculate the influence length of this event (in sample points) |
// calculate the influence length of this event (in sample points) |
934 |
uint end = (itNextCutoffEvent) ? itNextCutoffEvent->FragmentPos() : Samples; |
uint end = (itNextCutoffEvent) ? itNextCutoffEvent->FragmentPos() : Samples; |
935 |
|
|
936 |
cutoff = exp((float) itCutoffEvent->Param.CC.Value * 0.00787402f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX - FILTER_CUTOFF_MIN; |
cutoff = exp((float) itCutoffEvent->Param.CC.Value * 0.00787402f * FILTER_CUTOFF_COEFF) * CONFIG_FILTER_CUTOFF_MAX - CONFIG_FILTER_CUTOFF_MIN; |
937 |
|
|
938 |
// apply cutoff frequency to the cutoff parameter sequence |
// apply cutoff frequency to the cutoff parameter sequence |
939 |
for (uint i = itCutoffEvent->FragmentPos(); i < end; i++) { |
for (uint i = itCutoffEvent->FragmentPos(); i < end; i++) { |
986 |
biquad_param_t bqmain; |
biquad_param_t bqmain; |
987 |
float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0]; |
float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0]; |
988 |
float prev_res = pEngine->pSynthesisParameters[Event::destination_vcfr][0]; |
float prev_res = pEngine->pSynthesisParameters[Event::destination_vcfr][0]; |
989 |
FilterLeft.SetParameters( &bqbase, &bqmain, prev_cutoff + FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate); |
FilterLeft.SetParameters( &bqbase, &bqmain, prev_cutoff + CONFIG_FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate); |
990 |
FilterRight.SetParameters(&bqbase, &bqmain, prev_cutoff + FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate); |
FilterRight.SetParameters(&bqbase, &bqmain, prev_cutoff + CONFIG_FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate); |
991 |
pEngine->pBasicFilterParameters[0] = bqbase; |
pEngine->pBasicFilterParameters[0] = bqbase; |
992 |
pEngine->pMainFilterParameters[0] = bqmain; |
pEngine->pMainFilterParameters[0] = bqmain; |
993 |
|
|
1000 |
{ |
{ |
1001 |
prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][i]; |
prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][i]; |
1002 |
prev_res = pEngine->pSynthesisParameters[Event::destination_vcfr][i]; |
prev_res = pEngine->pSynthesisParameters[Event::destination_vcfr][i]; |
1003 |
FilterLeft.SetParameters( &bqbase, &bqmain, prev_cutoff + FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate); |
FilterLeft.SetParameters( &bqbase, &bqmain, prev_cutoff + CONFIG_FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate); |
1004 |
FilterRight.SetParameters(&bqbase, &bqmain, prev_cutoff + FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate); |
FilterRight.SetParameters(&bqbase, &bqmain, prev_cutoff + CONFIG_FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate); |
1005 |
} |
} |
1006 |
} |
} |
1007 |
|
|
1060 |
* @param itKillEvent - event which caused the voice to be killed |
* @param itKillEvent - event which caused the voice to be killed |
1061 |
*/ |
*/ |
1062 |
void Voice::Kill(Pool<Event>::Iterator& itKillEvent) { |
void Voice::Kill(Pool<Event>::Iterator& itKillEvent) { |
1063 |
//FIXME: just two sanity checks for debugging, can be removed |
#if CONFIG_DEVMODE |
1064 |
if (!itKillEvent) dmsg(1,("gig::Voice::Kill(): ERROR, !itKillEvent !!!\n")); |
if (!itKillEvent) dmsg(1,("gig::Voice::Kill(): ERROR, !itKillEvent !!!\n")); |
1065 |
if (itKillEvent && !itKillEvent.isValid()) dmsg(1,("gig::Voice::Kill(): ERROR, itKillEvent invalid !!!\n")); |
if (itKillEvent && !itKillEvent.isValid()) dmsg(1,("gig::Voice::Kill(): ERROR, itKillEvent invalid !!!\n")); |
1066 |
|
#endif // CONFIG_DEVMODE |
1067 |
|
|
1068 |
if (itTriggerEvent && itKillEvent->FragmentPos() <= itTriggerEvent->FragmentPos()) return; |
if (itTriggerEvent && itKillEvent->FragmentPos() <= itTriggerEvent->FragmentPos()) return; |
1069 |
this->itKillEvent = itKillEvent; |
this->itKillEvent = itKillEvent; |