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); |
117 |
* Initializes and triggers the voice, a disk stream will be launched if |
* Initializes and triggers the voice, a disk stream will be launched if |
118 |
* needed. |
* needed. |
119 |
* |
* |
120 |
* @param pEngineChannel - engine channel on which this voice was ordered |
* @param pEngineChannel - engine channel on which this voice was ordered |
121 |
* @param itNoteOnEvent - event that caused triggering of this voice |
* @param itNoteOnEvent - event that caused triggering of this voice |
122 |
* @param PitchBend - MIDI detune factor (-8192 ... +8191) |
* @param PitchBend - MIDI detune factor (-8192 ... +8191) |
123 |
* @param pInstrument - points to the loaded instrument which provides sample wave(s) and articulation data |
* @param pDimRgn - points to the dimension region which provides sample wave(s) and articulation data |
124 |
* @param iLayer - layer number this voice refers to (only if this is a layered sound of course) |
* @param VoiceType - type of this voice |
125 |
* @param ReleaseTriggerVoice - if this new voice is a release trigger voice (optional, default = false) |
* @param iKeyGroup - a value > 0 defines a key group in which this voice is member of |
|
* @param VoiceStealingAllowed - wether the voice is allowed to steal voices for further subvoices |
|
126 |
* @returns 0 on success, a value < 0 if the voice wasn't triggered |
* @returns 0 on success, a value < 0 if the voice wasn't triggered |
127 |
* (either due to an error or e.g. because no region is |
* (either due to an error or e.g. because no region is |
128 |
* defined for the given key) |
* defined for the given key) |
129 |
*/ |
*/ |
130 |
int Voice::Trigger(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent, int PitchBend, ::gig::Instrument* pInstrument, int iLayer, bool ReleaseTriggerVoice, bool VoiceStealingAllowed) { |
int Voice::Trigger(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent, int PitchBend, ::gig::DimensionRegion* pDimRgn, type_t VoiceType, int iKeyGroup) { |
131 |
this->pEngineChannel = pEngineChannel; |
this->pEngineChannel = pEngineChannel; |
132 |
if (!pInstrument) { |
this->pDimRgn = pDimRgn; |
133 |
dmsg(1,("voice::trigger: !pInstrument\n")); |
|
134 |
exit(EXIT_FAILURE); |
#if CONFIG_DEVMODE |
135 |
} |
if (itNoteOnEvent->FragmentPos() > pEngine->MaxSamplesPerCycle) { // just a sanity check for debugging |
|
if (itNoteOnEvent->FragmentPos() > pEngine->MaxSamplesPerCycle) { // FIXME: should be removed before the final release (purpose: just a sanity check for debugging) |
|
136 |
dmsg(1,("Voice::Trigger(): ERROR, TriggerDelay > Totalsamples\n")); |
dmsg(1,("Voice::Trigger(): ERROR, TriggerDelay > Totalsamples\n")); |
137 |
} |
} |
138 |
|
#endif // CONFIG_DEVMODE |
139 |
|
|
140 |
Type = type_normal; |
Type = VoiceType; |
141 |
MIDIKey = itNoteOnEvent->Param.Note.Key; |
MIDIKey = itNoteOnEvent->Param.Note.Key; |
142 |
pRegion = pInstrument->GetRegion(MIDIKey); |
PlaybackState = playback_state_init; // mark voice as triggered, but no audio rendered yet |
|
PlaybackState = playback_state_ram; // we always start playback from RAM cache and switch then to disk if needed |
|
143 |
Delay = itNoteOnEvent->FragmentPos(); |
Delay = itNoteOnEvent->FragmentPos(); |
144 |
itTriggerEvent = itNoteOnEvent; |
itTriggerEvent = itNoteOnEvent; |
145 |
itKillEvent = Pool<Event>::Iterator(); |
itKillEvent = Pool<Event>::Iterator(); |
146 |
|
KeyGroup = iKeyGroup; |
147 |
|
pSample = pDimRgn->pSample; // sample won't change until the voice is finished |
148 |
|
|
149 |
if (!pRegion) { |
// calculate volume |
150 |
dmsg(4, ("gig::Voice: No Region defined for MIDI key %d\n", MIDIKey)); |
const double velocityAttenuation = pDimRgn->GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity); |
|
return -1; |
|
|
} |
|
151 |
|
|
152 |
// only mark the first voice of a layered voice (group) to be in a |
Volume = velocityAttenuation / 32768.0f; // we downscale by 32768 to convert from int16 value range to DSP value range (which is -1.0..1.0) |
|
// key group, so the layered voices won't kill each other |
|
|
KeyGroup = (iLayer == 0 && !ReleaseTriggerVoice) ? pRegion->KeyGroup : 0; |
|
153 |
|
|
154 |
// get current dimension values to select the right dimension region |
Volume *= pDimRgn->SampleAttenuation; |
|
//FIXME: controller values for selecting the dimension region here are currently not sample accurate |
|
|
uint DimValues[8] = { 0 }; |
|
|
for (int i = pRegion->Dimensions - 1; i >= 0; i--) { |
|
|
switch (pRegion->pDimensionDefinitions[i].dimension) { |
|
|
case ::gig::dimension_samplechannel: |
|
|
DimValues[i] = 0; //TODO: we currently ignore this dimension |
|
|
break; |
|
|
case ::gig::dimension_layer: |
|
|
DimValues[i] = iLayer; |
|
|
break; |
|
|
case ::gig::dimension_velocity: |
|
|
DimValues[i] = itNoteOnEvent->Param.Note.Velocity; |
|
|
break; |
|
|
case ::gig::dimension_channelaftertouch: |
|
|
DimValues[i] = 0; //TODO: we currently ignore this dimension |
|
|
break; |
|
|
case ::gig::dimension_releasetrigger: |
|
|
Type = (ReleaseTriggerVoice) ? type_release_trigger : (!iLayer) ? type_release_trigger_required : type_normal; |
|
|
DimValues[i] = (uint) ReleaseTriggerVoice; |
|
|
break; |
|
|
case ::gig::dimension_keyboard: |
|
|
DimValues[i] = (uint) pEngineChannel->CurrentKeyDimension; |
|
|
break; |
|
|
case ::gig::dimension_roundrobin: |
|
|
DimValues[i] = (uint) pEngineChannel->pMIDIKeyInfo[MIDIKey].RoundRobinIndex; // incremented for each note on |
|
|
break; |
|
|
case ::gig::dimension_random: |
|
|
pEngine->RandomSeed = pEngine->RandomSeed * 1103515245 + 12345; // classic pseudo random number generator |
|
|
DimValues[i] = (uint) pEngine->RandomSeed >> (32 - pRegion->pDimensionDefinitions[i].bits); // highest bits are most random |
|
|
break; |
|
|
case ::gig::dimension_modwheel: |
|
|
DimValues[i] = pEngineChannel->ControllerTable[1]; |
|
|
break; |
|
|
case ::gig::dimension_breath: |
|
|
DimValues[i] = pEngineChannel->ControllerTable[2]; |
|
|
break; |
|
|
case ::gig::dimension_foot: |
|
|
DimValues[i] = pEngineChannel->ControllerTable[4]; |
|
|
break; |
|
|
case ::gig::dimension_portamentotime: |
|
|
DimValues[i] = pEngineChannel->ControllerTable[5]; |
|
|
break; |
|
|
case ::gig::dimension_effect1: |
|
|
DimValues[i] = pEngineChannel->ControllerTable[12]; |
|
|
break; |
|
|
case ::gig::dimension_effect2: |
|
|
DimValues[i] = pEngineChannel->ControllerTable[13]; |
|
|
break; |
|
|
case ::gig::dimension_genpurpose1: |
|
|
DimValues[i] = pEngineChannel->ControllerTable[16]; |
|
|
break; |
|
|
case ::gig::dimension_genpurpose2: |
|
|
DimValues[i] = pEngineChannel->ControllerTable[17]; |
|
|
break; |
|
|
case ::gig::dimension_genpurpose3: |
|
|
DimValues[i] = pEngineChannel->ControllerTable[18]; |
|
|
break; |
|
|
case ::gig::dimension_genpurpose4: |
|
|
DimValues[i] = pEngineChannel->ControllerTable[19]; |
|
|
break; |
|
|
case ::gig::dimension_sustainpedal: |
|
|
DimValues[i] = pEngineChannel->ControllerTable[64]; |
|
|
break; |
|
|
case ::gig::dimension_portamento: |
|
|
DimValues[i] = pEngineChannel->ControllerTable[65]; |
|
|
break; |
|
|
case ::gig::dimension_sostenutopedal: |
|
|
DimValues[i] = pEngineChannel->ControllerTable[66]; |
|
|
break; |
|
|
case ::gig::dimension_softpedal: |
|
|
DimValues[i] = pEngineChannel->ControllerTable[67]; |
|
|
break; |
|
|
case ::gig::dimension_genpurpose5: |
|
|
DimValues[i] = pEngineChannel->ControllerTable[80]; |
|
|
break; |
|
|
case ::gig::dimension_genpurpose6: |
|
|
DimValues[i] = pEngineChannel->ControllerTable[81]; |
|
|
break; |
|
|
case ::gig::dimension_genpurpose7: |
|
|
DimValues[i] = pEngineChannel->ControllerTable[82]; |
|
|
break; |
|
|
case ::gig::dimension_genpurpose8: |
|
|
DimValues[i] = pEngineChannel->ControllerTable[83]; |
|
|
break; |
|
|
case ::gig::dimension_effect1depth: |
|
|
DimValues[i] = pEngineChannel->ControllerTable[91]; |
|
|
break; |
|
|
case ::gig::dimension_effect2depth: |
|
|
DimValues[i] = pEngineChannel->ControllerTable[92]; |
|
|
break; |
|
|
case ::gig::dimension_effect3depth: |
|
|
DimValues[i] = pEngineChannel->ControllerTable[93]; |
|
|
break; |
|
|
case ::gig::dimension_effect4depth: |
|
|
DimValues[i] = pEngineChannel->ControllerTable[94]; |
|
|
break; |
|
|
case ::gig::dimension_effect5depth: |
|
|
DimValues[i] = pEngineChannel->ControllerTable[95]; |
|
|
break; |
|
|
case ::gig::dimension_none: |
|
|
std::cerr << "gig::Voice::Trigger() Error: dimension=none\n" << std::flush; |
|
|
break; |
|
|
default: |
|
|
std::cerr << "gig::Voice::Trigger() Error: Unknown dimension\n" << std::flush; |
|
|
} |
|
|
} |
|
|
pDimRgn = pRegion->GetDimensionRegionByValue(DimValues); |
|
155 |
|
|
156 |
pSample = pDimRgn->pSample; // sample won't change until the voice is finished |
// the volume of release triggered samples depends on note length |
157 |
if (!pSample || !pSample->SamplesTotal) return -1; // no need to continue if sample is silent |
if (Type == type_release_trigger) { |
158 |
|
float noteLength = float(pEngine->FrameTime + Delay - |
159 |
|
pEngineChannel->pMIDIKeyInfo[MIDIKey].NoteOnTime) / pEngine->SampleRate; |
160 |
|
float attenuation = 1 - 0.01053 * (256 >> pDimRgn->ReleaseTriggerDecay) * noteLength; |
161 |
|
if (attenuation <= 0) return -1; |
162 |
|
Volume *= attenuation; |
163 |
|
} |
164 |
|
|
165 |
// select channel mode (mono or stereo) |
// select channel mode (mono or stereo) |
166 |
SYNTHESIS_MODE_SET_CHANNELS(SynthesisMode, pSample->Channels == 2); |
SYNTHESIS_MODE_SET_CHANNELS(SynthesisMode, pSample->Channels == 2); |
191 |
DiskVoice = cachedsamples < pSample->SamplesTotal; |
DiskVoice = cachedsamples < pSample->SamplesTotal; |
192 |
|
|
193 |
if (DiskVoice) { // voice to be streamed from disk |
if (DiskVoice) { // voice to be streamed from disk |
194 |
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) |
195 |
|
|
196 |
// 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 |
197 |
if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) { |
if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) { |
226 |
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 |
227 |
} |
} |
228 |
|
|
229 |
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 |
230 |
|
const double velrelease = 1 / pDimRgn->GetVelocityRelease(itNoteOnEvent->Param.Note.Velocity); |
|
Volume *= pDimRgn->SampleAttenuation; |
|
231 |
|
|
232 |
// setup EG 1 (VCA EG) |
// setup EG 1 (VCA EG) |
233 |
{ |
{ |
249 |
} |
} |
250 |
if (pDimRgn->EG1ControllerInvert) eg1controllervalue = 127 - eg1controllervalue; |
if (pDimRgn->EG1ControllerInvert) eg1controllervalue = 127 - eg1controllervalue; |
251 |
|
|
252 |
// calculate influence of EG1 controller on EG1's parameters (TODO: needs to be fine tuned) |
// calculate influence of EG1 controller on EG1's parameters |
253 |
double eg1attack = (pDimRgn->EG1ControllerAttackInfluence) ? 0.0001 * (double) (1 << pDimRgn->EG1ControllerAttackInfluence) * eg1controllervalue : 0.0; |
// (eg1attack is different from the others) |
254 |
double eg1decay = (pDimRgn->EG1ControllerDecayInfluence) ? 0.0001 * (double) (1 << pDimRgn->EG1ControllerDecayInfluence) * eg1controllervalue : 0.0; |
double eg1attack = (pDimRgn->EG1ControllerAttackInfluence) ? |
255 |
double eg1release = (pDimRgn->EG1ControllerReleaseInfluence) ? 0.0001 * (double) (1 << pDimRgn->EG1ControllerReleaseInfluence) * eg1controllervalue : 0.0; |
1 + 0.031 * (double) (pDimRgn->EG1ControllerAttackInfluence == 1 ? |
256 |
|
1 : 1 << pDimRgn->EG1ControllerAttackInfluence) * eg1controllervalue : 1.0; |
257 |
|
double eg1decay = (pDimRgn->EG1ControllerDecayInfluence) ? 1 + 0.00775 * (double) (1 << pDimRgn->EG1ControllerDecayInfluence) * eg1controllervalue : 1.0; |
258 |
|
double eg1release = (pDimRgn->EG1ControllerReleaseInfluence) ? 1 + 0.00775 * (double) (1 << pDimRgn->EG1ControllerReleaseInfluence) * eg1controllervalue : 1.0; |
259 |
|
|
260 |
pEG1->Trigger(pDimRgn->EG1PreAttack, |
pEG1->Trigger(pDimRgn->EG1PreAttack, |
261 |
pDimRgn->EG1Attack + eg1attack, |
pDimRgn->EG1Attack * eg1attack, |
262 |
pDimRgn->EG1Hold, |
pDimRgn->EG1Hold, |
263 |
pSample->LoopStart, |
pSample->LoopStart, |
264 |
pDimRgn->EG1Decay1 + eg1decay, |
pDimRgn->EG1Decay1 * eg1decay * velrelease, |
265 |
pDimRgn->EG1Decay2 + eg1decay, |
pDimRgn->EG1Decay2 * eg1decay * velrelease, |
266 |
pDimRgn->EG1InfiniteSustain, |
pDimRgn->EG1InfiniteSustain, |
267 |
pDimRgn->EG1Sustain, |
pDimRgn->EG1Sustain, |
268 |
pDimRgn->EG1Release + eg1release, |
pDimRgn->EG1Release * eg1release * velrelease, |
269 |
// the SSE synthesis implementation requires |
// the SSE synthesis implementation requires |
270 |
// the vca start to be 16 byte aligned |
// the vca start to be 16 byte aligned |
271 |
SYNTHESIS_MODE_GET_IMPLEMENTATION(SynthesisMode) ? |
SYNTHESIS_MODE_GET_IMPLEMENTATION(SynthesisMode) ? |
272 |
Delay & 0xfffffffc : Delay); |
Delay & 0xfffffffc : Delay, |
273 |
|
velocityAttenuation); |
274 |
} |
} |
275 |
|
|
276 |
|
|
294 |
} |
} |
295 |
if (pDimRgn->EG2ControllerInvert) eg2controllervalue = 127 - eg2controllervalue; |
if (pDimRgn->EG2ControllerInvert) eg2controllervalue = 127 - eg2controllervalue; |
296 |
|
|
297 |
// calculate influence of EG2 controller on EG2's parameters (TODO: needs to be fine tuned) |
// calculate influence of EG2 controller on EG2's parameters |
298 |
double eg2attack = (pDimRgn->EG2ControllerAttackInfluence) ? 0.0001 * (double) (1 << pDimRgn->EG2ControllerAttackInfluence) * eg2controllervalue : 0.0; |
double eg2attack = (pDimRgn->EG2ControllerAttackInfluence) ? 1 + 0.00775 * (double) (1 << pDimRgn->EG2ControllerAttackInfluence) * eg2controllervalue : 1.0; |
299 |
double eg2decay = (pDimRgn->EG2ControllerDecayInfluence) ? 0.0001 * (double) (1 << pDimRgn->EG2ControllerDecayInfluence) * eg2controllervalue : 0.0; |
double eg2decay = (pDimRgn->EG2ControllerDecayInfluence) ? 1 + 0.00775 * (double) (1 << pDimRgn->EG2ControllerDecayInfluence) * eg2controllervalue : 1.0; |
300 |
double eg2release = (pDimRgn->EG2ControllerReleaseInfluence) ? 0.0001 * (double) (1 << pDimRgn->EG2ControllerReleaseInfluence) * eg2controllervalue : 0.0; |
double eg2release = (pDimRgn->EG2ControllerReleaseInfluence) ? 1 + 0.00775 * (double) (1 << pDimRgn->EG2ControllerReleaseInfluence) * eg2controllervalue : 1.0; |
301 |
|
|
302 |
pEG2->Trigger(pDimRgn->EG2PreAttack, |
pEG2->Trigger(pDimRgn->EG2PreAttack, |
303 |
pDimRgn->EG2Attack + eg2attack, |
pDimRgn->EG2Attack * eg2attack, |
304 |
false, |
false, |
305 |
pSample->LoopStart, |
pSample->LoopStart, |
306 |
pDimRgn->EG2Decay1 + eg2decay, |
pDimRgn->EG2Decay1 * eg2decay * velrelease, |
307 |
pDimRgn->EG2Decay2 + eg2decay, |
pDimRgn->EG2Decay2 * eg2decay * velrelease, |
308 |
pDimRgn->EG2InfiniteSustain, |
pDimRgn->EG2InfiniteSustain, |
309 |
pDimRgn->EG2Sustain, |
pDimRgn->EG2Sustain, |
310 |
pDimRgn->EG2Release + eg2release, |
pDimRgn->EG2Release * eg2release * velrelease, |
311 |
Delay); |
Delay, |
312 |
|
velocityAttenuation); |
313 |
} |
} |
314 |
|
|
315 |
|
|
327 |
case ::gig::lfo1_ctrl_internal: |
case ::gig::lfo1_ctrl_internal: |
328 |
lfo1_internal_depth = pDimRgn->LFO1InternalDepth; |
lfo1_internal_depth = pDimRgn->LFO1InternalDepth; |
329 |
pLFO1->ExtController = 0; // no external controller |
pLFO1->ExtController = 0; // no external controller |
330 |
|
bLFO1Enabled = (lfo1_internal_depth > 0); |
331 |
break; |
break; |
332 |
case ::gig::lfo1_ctrl_modwheel: |
case ::gig::lfo1_ctrl_modwheel: |
333 |
lfo1_internal_depth = 0; |
lfo1_internal_depth = 0; |
334 |
pLFO1->ExtController = 1; // MIDI controller 1 |
pLFO1->ExtController = 1; // MIDI controller 1 |
335 |
|
bLFO1Enabled = (pDimRgn->LFO1ControlDepth > 0); |
336 |
break; |
break; |
337 |
case ::gig::lfo1_ctrl_breath: |
case ::gig::lfo1_ctrl_breath: |
338 |
lfo1_internal_depth = 0; |
lfo1_internal_depth = 0; |
339 |
pLFO1->ExtController = 2; // MIDI controller 2 |
pLFO1->ExtController = 2; // MIDI controller 2 |
340 |
|
bLFO1Enabled = (pDimRgn->LFO1ControlDepth > 0); |
341 |
break; |
break; |
342 |
case ::gig::lfo1_ctrl_internal_modwheel: |
case ::gig::lfo1_ctrl_internal_modwheel: |
343 |
lfo1_internal_depth = pDimRgn->LFO1InternalDepth; |
lfo1_internal_depth = pDimRgn->LFO1InternalDepth; |
344 |
pLFO1->ExtController = 1; // MIDI controller 1 |
pLFO1->ExtController = 1; // MIDI controller 1 |
345 |
|
bLFO1Enabled = (lfo1_internal_depth > 0 || pDimRgn->LFO1ControlDepth > 0); |
346 |
break; |
break; |
347 |
case ::gig::lfo1_ctrl_internal_breath: |
case ::gig::lfo1_ctrl_internal_breath: |
348 |
lfo1_internal_depth = pDimRgn->LFO1InternalDepth; |
lfo1_internal_depth = pDimRgn->LFO1InternalDepth; |
349 |
pLFO1->ExtController = 2; // MIDI controller 2 |
pLFO1->ExtController = 2; // MIDI controller 2 |
350 |
|
bLFO1Enabled = (lfo1_internal_depth > 0 || pDimRgn->LFO1ControlDepth > 0); |
351 |
break; |
break; |
352 |
default: |
default: |
353 |
lfo1_internal_depth = 0; |
lfo1_internal_depth = 0; |
354 |
pLFO1->ExtController = 0; // no external controller |
pLFO1->ExtController = 0; // no external controller |
355 |
|
bLFO1Enabled = false; |
356 |
} |
} |
357 |
pLFO1->Trigger(pDimRgn->LFO1Frequency, |
if (bLFO1Enabled) pLFO1->Trigger(pDimRgn->LFO1Frequency, |
358 |
lfo1_internal_depth, |
lfo1_internal_depth, |
359 |
pDimRgn->LFO1ControlDepth, |
pDimRgn->LFO1ControlDepth, |
360 |
pEngineChannel->ControllerTable[pLFO1->ExtController], |
pEngineChannel->ControllerTable[pLFO1->ExtController], |
361 |
pDimRgn->LFO1FlipPhase, |
pDimRgn->LFO1FlipPhase, |
362 |
pEngine->SampleRate, |
pEngine->SampleRate, |
363 |
Delay); |
Delay); |
364 |
} |
} |
365 |
|
|
366 |
|
|
371 |
case ::gig::lfo2_ctrl_internal: |
case ::gig::lfo2_ctrl_internal: |
372 |
lfo2_internal_depth = pDimRgn->LFO2InternalDepth; |
lfo2_internal_depth = pDimRgn->LFO2InternalDepth; |
373 |
pLFO2->ExtController = 0; // no external controller |
pLFO2->ExtController = 0; // no external controller |
374 |
|
bLFO2Enabled = (lfo2_internal_depth > 0); |
375 |
break; |
break; |
376 |
case ::gig::lfo2_ctrl_modwheel: |
case ::gig::lfo2_ctrl_modwheel: |
377 |
lfo2_internal_depth = 0; |
lfo2_internal_depth = 0; |
378 |
pLFO2->ExtController = 1; // MIDI controller 1 |
pLFO2->ExtController = 1; // MIDI controller 1 |
379 |
|
bLFO2Enabled = (pDimRgn->LFO2ControlDepth > 0); |
380 |
break; |
break; |
381 |
case ::gig::lfo2_ctrl_foot: |
case ::gig::lfo2_ctrl_foot: |
382 |
lfo2_internal_depth = 0; |
lfo2_internal_depth = 0; |
383 |
pLFO2->ExtController = 4; // MIDI controller 4 |
pLFO2->ExtController = 4; // MIDI controller 4 |
384 |
|
bLFO2Enabled = (pDimRgn->LFO2ControlDepth > 0); |
385 |
break; |
break; |
386 |
case ::gig::lfo2_ctrl_internal_modwheel: |
case ::gig::lfo2_ctrl_internal_modwheel: |
387 |
lfo2_internal_depth = pDimRgn->LFO2InternalDepth; |
lfo2_internal_depth = pDimRgn->LFO2InternalDepth; |
388 |
pLFO2->ExtController = 1; // MIDI controller 1 |
pLFO2->ExtController = 1; // MIDI controller 1 |
389 |
|
bLFO2Enabled = (lfo2_internal_depth > 0 || pDimRgn->LFO2ControlDepth > 0); |
390 |
break; |
break; |
391 |
case ::gig::lfo2_ctrl_internal_foot: |
case ::gig::lfo2_ctrl_internal_foot: |
392 |
lfo2_internal_depth = pDimRgn->LFO2InternalDepth; |
lfo2_internal_depth = pDimRgn->LFO2InternalDepth; |
393 |
pLFO2->ExtController = 4; // MIDI controller 4 |
pLFO2->ExtController = 4; // MIDI controller 4 |
394 |
|
bLFO2Enabled = (lfo2_internal_depth > 0 || pDimRgn->LFO2ControlDepth > 0); |
395 |
break; |
break; |
396 |
default: |
default: |
397 |
lfo2_internal_depth = 0; |
lfo2_internal_depth = 0; |
398 |
pLFO2->ExtController = 0; // no external controller |
pLFO2->ExtController = 0; // no external controller |
399 |
|
bLFO2Enabled = false; |
400 |
} |
} |
401 |
pLFO2->Trigger(pDimRgn->LFO2Frequency, |
if (bLFO2Enabled) pLFO2->Trigger(pDimRgn->LFO2Frequency, |
402 |
lfo2_internal_depth, |
lfo2_internal_depth, |
403 |
pDimRgn->LFO2ControlDepth, |
pDimRgn->LFO2ControlDepth, |
404 |
pEngineChannel->ControllerTable[pLFO2->ExtController], |
pEngineChannel->ControllerTable[pLFO2->ExtController], |
405 |
pDimRgn->LFO2FlipPhase, |
pDimRgn->LFO2FlipPhase, |
406 |
pEngine->SampleRate, |
pEngine->SampleRate, |
407 |
Delay); |
Delay); |
408 |
} |
} |
409 |
|
|
410 |
|
|
415 |
case ::gig::lfo3_ctrl_internal: |
case ::gig::lfo3_ctrl_internal: |
416 |
lfo3_internal_depth = pDimRgn->LFO3InternalDepth; |
lfo3_internal_depth = pDimRgn->LFO3InternalDepth; |
417 |
pLFO3->ExtController = 0; // no external controller |
pLFO3->ExtController = 0; // no external controller |
418 |
|
bLFO3Enabled = (lfo3_internal_depth > 0); |
419 |
break; |
break; |
420 |
case ::gig::lfo3_ctrl_modwheel: |
case ::gig::lfo3_ctrl_modwheel: |
421 |
lfo3_internal_depth = 0; |
lfo3_internal_depth = 0; |
422 |
pLFO3->ExtController = 1; // MIDI controller 1 |
pLFO3->ExtController = 1; // MIDI controller 1 |
423 |
|
bLFO3Enabled = (pDimRgn->LFO3ControlDepth > 0); |
424 |
break; |
break; |
425 |
case ::gig::lfo3_ctrl_aftertouch: |
case ::gig::lfo3_ctrl_aftertouch: |
426 |
lfo3_internal_depth = 0; |
lfo3_internal_depth = 0; |
427 |
pLFO3->ExtController = 0; // TODO: aftertouch not implemented yet |
pLFO3->ExtController = 0; // TODO: aftertouch not implemented yet |
428 |
|
bLFO3Enabled = false; // see TODO comment in line above |
429 |
break; |
break; |
430 |
case ::gig::lfo3_ctrl_internal_modwheel: |
case ::gig::lfo3_ctrl_internal_modwheel: |
431 |
lfo3_internal_depth = pDimRgn->LFO3InternalDepth; |
lfo3_internal_depth = pDimRgn->LFO3InternalDepth; |
432 |
pLFO3->ExtController = 1; // MIDI controller 1 |
pLFO3->ExtController = 1; // MIDI controller 1 |
433 |
|
bLFO3Enabled = (lfo3_internal_depth > 0 || pDimRgn->LFO3ControlDepth > 0); |
434 |
break; |
break; |
435 |
case ::gig::lfo3_ctrl_internal_aftertouch: |
case ::gig::lfo3_ctrl_internal_aftertouch: |
436 |
lfo3_internal_depth = pDimRgn->LFO3InternalDepth; |
lfo3_internal_depth = pDimRgn->LFO3InternalDepth; |
437 |
pLFO1->ExtController = 0; // TODO: aftertouch not implemented yet |
pLFO1->ExtController = 0; // TODO: aftertouch not implemented yet |
438 |
|
bLFO3Enabled = (lfo3_internal_depth > 0 /*|| pDimRgn->LFO3ControlDepth > 0*/); // see TODO comment in line above |
439 |
break; |
break; |
440 |
default: |
default: |
441 |
lfo3_internal_depth = 0; |
lfo3_internal_depth = 0; |
442 |
pLFO3->ExtController = 0; // no external controller |
pLFO3->ExtController = 0; // no external controller |
443 |
|
bLFO3Enabled = false; |
444 |
} |
} |
445 |
pLFO3->Trigger(pDimRgn->LFO3Frequency, |
if (bLFO3Enabled) pLFO3->Trigger(pDimRgn->LFO3Frequency, |
446 |
lfo3_internal_depth, |
lfo3_internal_depth, |
447 |
pDimRgn->LFO3ControlDepth, |
pDimRgn->LFO3ControlDepth, |
448 |
pEngineChannel->ControllerTable[pLFO3->ExtController], |
pEngineChannel->ControllerTable[pLFO3->ExtController], |
449 |
false, |
false, |
450 |
pEngine->SampleRate, |
pEngine->SampleRate, |
451 |
Delay); |
Delay); |
452 |
} |
} |
453 |
|
|
454 |
|
|
455 |
#if FORCE_FILTER_USAGE |
#if CONFIG_FORCE_FILTER |
456 |
const bool bUseFilter = true; |
const bool bUseFilter = true; |
457 |
#else // use filter only if instrument file told so |
#else // use filter only if instrument file told so |
458 |
const bool bUseFilter = pDimRgn->VCFEnabled; |
const bool bUseFilter = pDimRgn->VCFEnabled; |
459 |
#endif // FORCE_FILTER_USAGE |
#endif // CONFIG_FORCE_FILTER |
460 |
SYNTHESIS_MODE_SET_FILTER(SynthesisMode, bUseFilter); |
SYNTHESIS_MODE_SET_FILTER(SynthesisMode, bUseFilter); |
461 |
if (bUseFilter) { |
if (bUseFilter) { |
462 |
#ifdef OVERRIDE_FILTER_CUTOFF_CTRL |
#ifdef CONFIG_OVERRIDE_CUTOFF_CTRL |
463 |
VCFCutoffCtrl.controller = OVERRIDE_FILTER_CUTOFF_CTRL; |
VCFCutoffCtrl.controller = CONFIG_OVERRIDE_CUTOFF_CTRL; |
464 |
#else // use the one defined in the instrument file |
#else // use the one defined in the instrument file |
465 |
switch (pDimRgn->VCFCutoffController) { |
switch (pDimRgn->VCFCutoffController) { |
466 |
case ::gig::vcf_cutoff_ctrl_modwheel: |
case ::gig::vcf_cutoff_ctrl_modwheel: |
496 |
VCFCutoffCtrl.controller = 0; |
VCFCutoffCtrl.controller = 0; |
497 |
break; |
break; |
498 |
} |
} |
499 |
#endif // OVERRIDE_FILTER_CUTOFF_CTRL |
#endif // CONFIG_OVERRIDE_CUTOFF_CTRL |
500 |
|
|
501 |
#ifdef OVERRIDE_FILTER_RES_CTRL |
#ifdef CONFIG_OVERRIDE_RESONANCE_CTRL |
502 |
VCFResonanceCtrl.controller = OVERRIDE_FILTER_RES_CTRL; |
VCFResonanceCtrl.controller = CONFIG_OVERRIDE_RESONANCE_CTRL; |
503 |
#else // use the one defined in the instrument file |
#else // use the one defined in the instrument file |
504 |
switch (pDimRgn->VCFResonanceController) { |
switch (pDimRgn->VCFResonanceController) { |
505 |
case ::gig::vcf_res_ctrl_genpurpose3: |
case ::gig::vcf_res_ctrl_genpurpose3: |
518 |
default: |
default: |
519 |
VCFResonanceCtrl.controller = 0; |
VCFResonanceCtrl.controller = 0; |
520 |
} |
} |
521 |
#endif // OVERRIDE_FILTER_RES_CTRL |
#endif // CONFIG_OVERRIDE_RESONANCE_CTRL |
522 |
|
|
523 |
#ifndef OVERRIDE_FILTER_TYPE |
#ifndef CONFIG_OVERRIDE_FILTER_TYPE |
524 |
FilterLeft.SetType(pDimRgn->VCFType); |
FilterLeft.SetType(pDimRgn->VCFType); |
525 |
FilterRight.SetType(pDimRgn->VCFType); |
FilterRight.SetType(pDimRgn->VCFType); |
526 |
#else // override filter type |
#else // override filter type |
527 |
FilterLeft.SetType(OVERRIDE_FILTER_TYPE); |
FilterLeft.SetType(CONFIG_OVERRIDE_FILTER_TYPE); |
528 |
FilterRight.SetType(OVERRIDE_FILTER_TYPE); |
FilterRight.SetType(CONFIG_OVERRIDE_FILTER_TYPE); |
529 |
#endif // OVERRIDE_FILTER_TYPE |
#endif // CONFIG_OVERRIDE_FILTER_TYPE |
530 |
|
|
531 |
VCFCutoffCtrl.value = pEngineChannel->ControllerTable[VCFCutoffCtrl.controller]; |
VCFCutoffCtrl.value = pEngineChannel->ControllerTable[VCFCutoffCtrl.controller]; |
532 |
VCFResonanceCtrl.value = pEngineChannel->ControllerTable[VCFResonanceCtrl.controller]; |
VCFResonanceCtrl.value = pEngineChannel->ControllerTable[VCFResonanceCtrl.controller]; |
533 |
|
|
534 |
// calculate cutoff frequency |
// calculate cutoff frequency |
535 |
float cutoff = (!VCFCutoffCtrl.controller) |
float cutoff = (!VCFCutoffCtrl.controller) |
536 |
? 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 |
537 |
: 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; |
538 |
|
|
539 |
// calculate resonance |
// calculate resonance |
540 |
float resonance = (float) VCFResonanceCtrl.value * 0.00787f; // 0.0..1.0 |
float resonance = (float) VCFResonanceCtrl.value * 0.00787f; // 0.0..1.0 |
543 |
} |
} |
544 |
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) |
545 |
|
|
546 |
VCFCutoffCtrl.fvalue = cutoff - FILTER_CUTOFF_MIN; |
VCFCutoffCtrl.fvalue = cutoff - CONFIG_FILTER_CUTOFF_MIN; |
547 |
VCFResonanceCtrl.fvalue = resonance; |
VCFResonanceCtrl.fvalue = resonance; |
548 |
|
|
549 |
FilterUpdateCounter = -1; |
FilterUpdateCounter = -1; |
576 |
|
|
577 |
// Reset the synthesis parameter matrix |
// Reset the synthesis parameter matrix |
578 |
|
|
579 |
|
#if CONFIG_PROCESS_MUTED_CHANNELS |
580 |
|
pEngine->ResetSynthesisParameters(Event::destination_vca, this->Volume * this->CrossfadeVolume * (pEngineChannel->GetMute() ? 0 : pEngineChannel->GlobalVolume)); |
581 |
|
#else |
582 |
pEngine->ResetSynthesisParameters(Event::destination_vca, this->Volume * this->CrossfadeVolume * pEngineChannel->GlobalVolume); |
pEngine->ResetSynthesisParameters(Event::destination_vca, this->Volume * this->CrossfadeVolume * pEngineChannel->GlobalVolume); |
583 |
|
#endif |
584 |
pEngine->ResetSynthesisParameters(Event::destination_vco, this->PitchBase); |
pEngine->ResetSynthesisParameters(Event::destination_vco, this->PitchBase); |
585 |
pEngine->ResetSynthesisParameters(Event::destination_vcfc, VCFCutoffCtrl.fvalue); |
pEngine->ResetSynthesisParameters(Event::destination_vcfc, VCFCutoffCtrl.fvalue); |
586 |
pEngine->ResetSynthesisParameters(Event::destination_vcfr, VCFResonanceCtrl.fvalue); |
pEngine->ResetSynthesisParameters(Event::destination_vcfr, VCFResonanceCtrl.fvalue); |
595 |
SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, true); |
SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, true); |
596 |
SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, false); |
SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, false); |
597 |
} |
} |
598 |
pLFO1->Process(Samples); |
if (bLFO1Enabled) pLFO1->Process(Samples); |
599 |
pLFO2->Process(Samples); |
if (bLFO2Enabled) pLFO2->Process(Samples); |
600 |
if (pLFO3->Process(Samples)) { // if pitch LFO modulation is active |
if (bLFO3Enabled) { |
601 |
SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, true); |
if (pLFO3->Process(Samples)) { // if pitch LFO modulation is active |
602 |
SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, false); |
SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, true); |
603 |
|
SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, false); |
604 |
|
} |
605 |
} |
} |
606 |
|
|
607 |
if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode)) |
if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode)) |
609 |
|
|
610 |
switch (this->PlaybackState) { |
switch (this->PlaybackState) { |
611 |
|
|
612 |
|
case playback_state_init: |
613 |
|
this->PlaybackState = playback_state_ram; // we always start playback from RAM cache and switch then to disk if needed |
614 |
|
// no break - continue with playback_state_ram |
615 |
|
|
616 |
case playback_state_ram: { |
case playback_state_ram: { |
617 |
if (RAMLoop) SYNTHESIS_MODE_SET_LOOP(SynthesisMode, true); // enable looping |
if (RAMLoop) SYNTHESIS_MODE_SET_LOOP(SynthesisMode, true); // enable looping |
618 |
|
|
650 |
|
|
651 |
// 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) |
652 |
if (DiskStreamRef.State == Stream::state_end) { |
if (DiskStreamRef.State == Stream::state_end) { |
653 |
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 |
654 |
if (sampleWordsLeftToRead <= maxSampleWordsPerCycle) { |
if (sampleWordsLeftToRead <= maxSampleWordsPerCycle) { |
655 |
// 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 |
656 |
if (RealSampleWordsLeftToRead < 0) RealSampleWordsLeftToRead = sampleWordsLeftToRead; |
if (RealSampleWordsLeftToRead < 0) RealSampleWordsLeftToRead = sampleWordsLeftToRead; |
810 |
|
|
811 |
crossfadevolume = CrossfadeAttenuation(itVCAEvent->Param.CC.Value); |
crossfadevolume = CrossfadeAttenuation(itVCAEvent->Param.CC.Value); |
812 |
|
|
813 |
|
#if CONFIG_PROCESS_MUTED_CHANNELS |
814 |
|
float effective_volume = crossfadevolume * this->Volume * (pEngineChannel->GetMute() ? 0 : pEngineChannel->GlobalVolume); |
815 |
|
#else |
816 |
float effective_volume = crossfadevolume * this->Volume * pEngineChannel->GlobalVolume; |
float effective_volume = crossfadevolume * this->Volume * pEngineChannel->GlobalVolume; |
817 |
|
#endif |
818 |
|
|
819 |
// apply volume value to the volume parameter sequence |
// apply volume value to the volume parameter sequence |
820 |
for (uint i = itVCAEvent->FragmentPos(); i < end; i++) { |
for (uint i = itVCAEvent->FragmentPos(); i < end; i++) { |
841 |
// calculate the influence length of this event (in sample points) |
// calculate the influence length of this event (in sample points) |
842 |
uint end = (itNextCutoffEvent) ? itNextCutoffEvent->FragmentPos() : Samples; |
uint end = (itNextCutoffEvent) ? itNextCutoffEvent->FragmentPos() : Samples; |
843 |
|
|
844 |
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; |
845 |
|
|
846 |
// apply cutoff frequency to the cutoff parameter sequence |
// apply cutoff frequency to the cutoff parameter sequence |
847 |
for (uint i = itCutoffEvent->FragmentPos(); i < end; i++) { |
for (uint i = itCutoffEvent->FragmentPos(); i < end; i++) { |
894 |
biquad_param_t bqmain; |
biquad_param_t bqmain; |
895 |
float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0]; |
float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0]; |
896 |
float prev_res = pEngine->pSynthesisParameters[Event::destination_vcfr][0]; |
float prev_res = pEngine->pSynthesisParameters[Event::destination_vcfr][0]; |
897 |
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); |
898 |
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); |
899 |
pEngine->pBasicFilterParameters[0] = bqbase; |
pEngine->pBasicFilterParameters[0] = bqbase; |
900 |
pEngine->pMainFilterParameters[0] = bqmain; |
pEngine->pMainFilterParameters[0] = bqmain; |
901 |
|
|
908 |
{ |
{ |
909 |
prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][i]; |
prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][i]; |
910 |
prev_res = pEngine->pSynthesisParameters[Event::destination_vcfr][i]; |
prev_res = pEngine->pSynthesisParameters[Event::destination_vcfr][i]; |
911 |
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); |
912 |
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); |
913 |
} |
} |
914 |
} |
} |
915 |
|
|
968 |
* @param itKillEvent - event which caused the voice to be killed |
* @param itKillEvent - event which caused the voice to be killed |
969 |
*/ |
*/ |
970 |
void Voice::Kill(Pool<Event>::Iterator& itKillEvent) { |
void Voice::Kill(Pool<Event>::Iterator& itKillEvent) { |
971 |
//FIXME: just two sanity checks for debugging, can be removed |
#if CONFIG_DEVMODE |
972 |
if (!itKillEvent) dmsg(1,("gig::Voice::Kill(): ERROR, !itKillEvent !!!\n")); |
if (!itKillEvent) dmsg(1,("gig::Voice::Kill(): ERROR, !itKillEvent !!!\n")); |
973 |
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")); |
974 |
|
#endif // CONFIG_DEVMODE |
975 |
|
|
976 |
if (itTriggerEvent && itKillEvent->FragmentPos() <= itTriggerEvent->FragmentPos()) return; |
if (itTriggerEvent && itKillEvent->FragmentPos() <= itTriggerEvent->FragmentPos()) return; |
977 |
this->itKillEvent = itKillEvent; |
this->itKillEvent = itKillEvent; |