/[svn]/linuxsampler/trunk/src/engines/gig/Voice.cpp
ViewVC logotype

Contents of /linuxsampler/trunk/src/engines/gig/Voice.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 354 - (show annotations) (download)
Sat Jan 29 15:17:59 2005 UTC (19 years, 2 months ago) by schoenebeck
File size: 50206 byte(s)
* support for keyswitching
* ignore if no sample was defined for region(s) or dimension region(s)
(patch by Andreas Persson)

1 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the Free Software *
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
20 * MA 02111-1307 USA *
21 ***************************************************************************/
22
23 #include "EGADSR.h"
24 #include "Manipulator.h"
25 #include "../../common/Features.h"
26 #include "Synthesizer.h"
27
28 #include "Voice.h"
29
30 namespace LinuxSampler { namespace gig {
31
32 const float Voice::FILTER_CUTOFF_COEFF(CalculateFilterCutoffCoeff());
33
34 const int Voice::FILTER_UPDATE_MASK(CalculateFilterUpdateMask());
35
36 float Voice::CalculateFilterCutoffCoeff() {
37 return log(FILTER_CUTOFF_MIN / FILTER_CUTOFF_MAX);
38 }
39
40 int Voice::CalculateFilterUpdateMask() {
41 if (FILTER_UPDATE_PERIOD <= 0) return 0;
42 int power_of_two;
43 for (power_of_two = 0; 1<<power_of_two < FILTER_UPDATE_PERIOD; power_of_two++);
44 return (1 << power_of_two) - 1;
45 }
46
47 Voice::Voice() {
48 pEngine = NULL;
49 pDiskThread = NULL;
50 PlaybackState = playback_state_end;
51 pEG1 = NULL;
52 pEG2 = NULL;
53 pEG3 = NULL;
54 pVCAManipulator = NULL;
55 pVCFCManipulator = NULL;
56 pVCOManipulator = NULL;
57 pLFO1 = NULL;
58 pLFO2 = NULL;
59 pLFO3 = NULL;
60 KeyGroup = 0;
61 SynthesisMode = 0; //Set all mode bits to 0 first
62
63 // select synthesis implementation (currently either pure C++ or MMX+SSE(1))
64 SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, Features::supportsMMX() && Features::supportsSSE());
65 SYNTHESIS_MODE_SET_PROFILING(SynthesisMode, true);
66 }
67
68 Voice::~Voice() {
69 if (pEG1) delete pEG1;
70 if (pEG2) delete pEG2;
71 if (pEG3) delete pEG3;
72 if (pLFO1) delete pLFO1;
73 if (pLFO2) delete pLFO2;
74 if (pLFO3) delete pLFO3;
75 if (pVCAManipulator) delete pVCAManipulator;
76 if (pVCFCManipulator) delete pVCFCManipulator;
77 if (pVCOManipulator) delete pVCOManipulator;
78 }
79
80 void Voice::SetEngine(Engine* pEngine) {
81 this->pEngine = pEngine;
82
83 // delete old objects
84 if (pEG1) delete pEG1;
85 if (pEG2) delete pEG2;
86 if (pEG3) delete pEG3;
87 if (pVCAManipulator) delete pVCAManipulator;
88 if (pVCFCManipulator) delete pVCFCManipulator;
89 if (pVCOManipulator) delete pVCOManipulator;
90 if (pLFO1) delete pLFO1;
91 if (pLFO2) delete pLFO2;
92 if (pLFO3) delete pLFO3;
93
94 // create new ones
95 pEG1 = new EGADSR(pEngine, Event::destination_vca);
96 pEG2 = new EGADSR(pEngine, Event::destination_vcfc);
97 pEG3 = new EGDecay(pEngine, Event::destination_vco);
98 pVCAManipulator = new VCAManipulator(pEngine);
99 pVCFCManipulator = new VCFCManipulator(pEngine);
100 pVCOManipulator = new VCOManipulator(pEngine);
101 pLFO1 = new LFO<gig::VCAManipulator>(0.0f, 1.0f, LFO<VCAManipulator>::propagation_top_down, pVCAManipulator, pEngine->pEventPool);
102 pLFO2 = new LFO<gig::VCFCManipulator>(0.0f, 1.0f, LFO<VCFCManipulator>::propagation_top_down, pVCFCManipulator, pEngine->pEventPool);
103 pLFO3 = new LFO<gig::VCOManipulator>(-1200.0f, 1200.0f, LFO<VCOManipulator>::propagation_middle_balanced, pVCOManipulator, pEngine->pEventPool); // +-1 octave (+-1200 cents) max.
104
105 this->pDiskThread = pEngine->pDiskThread;
106 dmsg(6,("Voice::SetEngine()\n"));
107 }
108
109 /**
110 * Initializes and triggers the voice, a disk stream will be launched if
111 * needed.
112 *
113 * @param itNoteOnEvent - event that caused triggering of this voice
114 * @param PitchBend - MIDI detune factor (-8192 ... +8191)
115 * @param pInstrument - points to the loaded instrument which provides sample wave(s) and articulation data
116 * @param iLayer - layer number this voice refers to (only if this is a layered sound of course)
117 * @param ReleaseTriggerVoice - if this new voice is a release trigger voice (optional, default = false)
118 * @param VoiceStealing - wether the voice is allowed to steal voices for further subvoices
119 * @returns 0 on success, a value < 0 if the voice wasn't triggered
120 * (either due to an error or e.g. because no region is
121 * defined for the given key)
122 */
123 int Voice::Trigger(Pool<Event>::Iterator& itNoteOnEvent, int PitchBend, ::gig::Instrument* pInstrument, int iLayer, bool ReleaseTriggerVoice, bool VoiceStealing) {
124 if (!pInstrument) {
125 dmsg(1,("voice::trigger: !pInstrument\n"));
126 exit(EXIT_FAILURE);
127 }
128 if (itNoteOnEvent->FragmentPos() > pEngine->MaxSamplesPerCycle) { // FIXME: should be removed before the final release (purpose: just a sanity check for debugging)
129 dmsg(1,("Voice::Trigger(): ERROR, TriggerDelay > Totalsamples\n"));
130 }
131
132 Type = type_normal;
133 MIDIKey = itNoteOnEvent->Param.Note.Key;
134 pRegion = pInstrument->GetRegion(MIDIKey);
135 PlaybackState = playback_state_ram; // we always start playback from RAM cache and switch then to disk if needed
136 Delay = itNoteOnEvent->FragmentPos();
137 itTriggerEvent = itNoteOnEvent;
138 itKillEvent = Pool<Event>::Iterator();
139 itChildVoice = Pool<Voice>::Iterator();
140
141 if (!pRegion) {
142 dmsg(4, ("gig::Voice: No Region defined for MIDI key %d\n", MIDIKey));
143 return -1;
144 }
145
146 KeyGroup = pRegion->KeyGroup;
147
148 // get current dimension values to select the right dimension region
149 //FIXME: controller values for selecting the dimension region here are currently not sample accurate
150 uint DimValues[8] = { 0 };
151 for (int i = pRegion->Dimensions - 1; i >= 0; i--) {
152 switch (pRegion->pDimensionDefinitions[i].dimension) {
153 case ::gig::dimension_samplechannel:
154 DimValues[i] = 0; //TODO: we currently ignore this dimension
155 break;
156 case ::gig::dimension_layer:
157 DimValues[i] = iLayer;
158 // if this is the 1st layer then spawn further voices for all the other layers
159 if (iLayer == 0)
160 for (int iNewLayer = 1; iNewLayer < pRegion->pDimensionDefinitions[i].zones; iNewLayer++)
161 itChildVoice = pEngine->LaunchVoice(itNoteOnEvent, iNewLayer, ReleaseTriggerVoice, VoiceStealing);
162 break;
163 case ::gig::dimension_velocity:
164 DimValues[i] = itNoteOnEvent->Param.Note.Velocity;
165 break;
166 case ::gig::dimension_channelaftertouch:
167 DimValues[i] = 0; //TODO: we currently ignore this dimension
168 break;
169 case ::gig::dimension_releasetrigger:
170 Type = (ReleaseTriggerVoice) ? type_release_trigger : (!iLayer) ? type_release_trigger_required : type_normal;
171 DimValues[i] = (uint) ReleaseTriggerVoice;
172 break;
173 case ::gig::dimension_keyboard:
174 DimValues[i] = (uint) pEngine->CurrentKeyDimension;
175 break;
176 case ::gig::dimension_modwheel:
177 DimValues[i] = pEngine->ControllerTable[1];
178 break;
179 case ::gig::dimension_breath:
180 DimValues[i] = pEngine->ControllerTable[2];
181 break;
182 case ::gig::dimension_foot:
183 DimValues[i] = pEngine->ControllerTable[4];
184 break;
185 case ::gig::dimension_portamentotime:
186 DimValues[i] = pEngine->ControllerTable[5];
187 break;
188 case ::gig::dimension_effect1:
189 DimValues[i] = pEngine->ControllerTable[12];
190 break;
191 case ::gig::dimension_effect2:
192 DimValues[i] = pEngine->ControllerTable[13];
193 break;
194 case ::gig::dimension_genpurpose1:
195 DimValues[i] = pEngine->ControllerTable[16];
196 break;
197 case ::gig::dimension_genpurpose2:
198 DimValues[i] = pEngine->ControllerTable[17];
199 break;
200 case ::gig::dimension_genpurpose3:
201 DimValues[i] = pEngine->ControllerTable[18];
202 break;
203 case ::gig::dimension_genpurpose4:
204 DimValues[i] = pEngine->ControllerTable[19];
205 break;
206 case ::gig::dimension_sustainpedal:
207 DimValues[i] = pEngine->ControllerTable[64];
208 break;
209 case ::gig::dimension_portamento:
210 DimValues[i] = pEngine->ControllerTable[65];
211 break;
212 case ::gig::dimension_sostenutopedal:
213 DimValues[i] = pEngine->ControllerTable[66];
214 break;
215 case ::gig::dimension_softpedal:
216 DimValues[i] = pEngine->ControllerTable[67];
217 break;
218 case ::gig::dimension_genpurpose5:
219 DimValues[i] = pEngine->ControllerTable[80];
220 break;
221 case ::gig::dimension_genpurpose6:
222 DimValues[i] = pEngine->ControllerTable[81];
223 break;
224 case ::gig::dimension_genpurpose7:
225 DimValues[i] = pEngine->ControllerTable[82];
226 break;
227 case ::gig::dimension_genpurpose8:
228 DimValues[i] = pEngine->ControllerTable[83];
229 break;
230 case ::gig::dimension_effect1depth:
231 DimValues[i] = pEngine->ControllerTable[91];
232 break;
233 case ::gig::dimension_effect2depth:
234 DimValues[i] = pEngine->ControllerTable[92];
235 break;
236 case ::gig::dimension_effect3depth:
237 DimValues[i] = pEngine->ControllerTable[93];
238 break;
239 case ::gig::dimension_effect4depth:
240 DimValues[i] = pEngine->ControllerTable[94];
241 break;
242 case ::gig::dimension_effect5depth:
243 DimValues[i] = pEngine->ControllerTable[95];
244 break;
245 case ::gig::dimension_none:
246 std::cerr << "gig::Voice::Trigger() Error: dimension=none\n" << std::flush;
247 break;
248 default:
249 std::cerr << "gig::Voice::Trigger() Error: Unknown dimension\n" << std::flush;
250 }
251 }
252 pDimRgn = pRegion->GetDimensionRegionByValue(DimValues);
253
254 pSample = pDimRgn->pSample; // sample won't change until the voice is finished
255 if (!pSample || !pSample->SamplesTotal) return -1; // no need to continue if sample is silent
256
257 // select channel mode (mono or stereo)
258 SYNTHESIS_MODE_SET_CHANNELS(SynthesisMode, pSample->Channels == 2);
259
260 // get starting crossfade volume level
261 switch (pDimRgn->AttenuationController.type) {
262 case ::gig::attenuation_ctrl_t::type_channelaftertouch:
263 CrossfadeVolume = 1.0f; //TODO: aftertouch not supported yet
264 break;
265 case ::gig::attenuation_ctrl_t::type_velocity:
266 CrossfadeVolume = CrossfadeAttenuation(itNoteOnEvent->Param.Note.Velocity);
267 break;
268 case ::gig::attenuation_ctrl_t::type_controlchange: //FIXME: currently not sample accurate
269 CrossfadeVolume = CrossfadeAttenuation(pEngine->ControllerTable[pDimRgn->AttenuationController.controller_number]);
270 break;
271 case ::gig::attenuation_ctrl_t::type_none: // no crossfade defined
272 default:
273 CrossfadeVolume = 1.0f;
274 }
275
276 PanLeft = 1.0f - float(RTMath::Max(pDimRgn->Pan, 0)) / 63.0f;
277 PanRight = 1.0f - float(RTMath::Min(pDimRgn->Pan, 0)) / -64.0f;
278
279 Pos = pDimRgn->SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)
280
281 // Check if the sample needs disk streaming or is too short for that
282 long cachedsamples = pSample->GetCache().Size / pSample->FrameSize;
283 DiskVoice = cachedsamples < pSample->SamplesTotal;
284
285 if (DiskVoice) { // voice to be streamed from disk
286 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)
287
288 // check if there's a loop defined which completely fits into the cached (RAM) part of the sample
289 if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) {
290 RAMLoop = true;
291 LoopCyclesLeft = pSample->LoopPlayCount;
292 }
293 else RAMLoop = false;
294
295 if (pDiskThread->OrderNewStream(&DiskStreamRef, pSample, MaxRAMPos, !RAMLoop) < 0) {
296 dmsg(1,("Disk stream order failed!\n"));
297 KillImmediately();
298 return -1;
299 }
300 dmsg(4,("Disk voice launched (cached samples: %d, total Samples: %d, MaxRAMPos: %d, RAMLooping: %s)\n", cachedsamples, pSample->SamplesTotal, MaxRAMPos, (RAMLoop) ? "yes" : "no"));
301 }
302 else { // RAM only voice
303 MaxRAMPos = cachedsamples;
304 if (pSample->Loops) {
305 RAMLoop = true;
306 LoopCyclesLeft = pSample->LoopPlayCount;
307 }
308 else RAMLoop = false;
309 dmsg(4,("RAM only voice launched (Looping: %s)\n", (RAMLoop) ? "yes" : "no"));
310 }
311
312
313 // calculate initial pitch value
314 {
315 double pitchbasecents = pDimRgn->FineTune + (int) pEngine->ScaleTuning[MIDIKey % 12];
316 if (pDimRgn->PitchTrack) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;
317 this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents) * (double(pSample->SamplesPerSecond) / double(pEngine->pAudioOutputDevice->SampleRate()));
318 this->PitchBend = RTMath::CentsToFreqRatio(((double) PitchBend / 8192.0) * 200.0); // pitchbend wheel +-2 semitones = 200 cents
319 }
320
321 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)
322
323 // setup EG 1 (VCA EG)
324 {
325 // get current value of EG1 controller
326 double eg1controllervalue;
327 switch (pDimRgn->EG1Controller.type) {
328 case ::gig::eg1_ctrl_t::type_none: // no controller defined
329 eg1controllervalue = 0;
330 break;
331 case ::gig::eg1_ctrl_t::type_channelaftertouch:
332 eg1controllervalue = 0; // TODO: aftertouch not yet supported
333 break;
334 case ::gig::eg1_ctrl_t::type_velocity:
335 eg1controllervalue = itNoteOnEvent->Param.Note.Velocity;
336 break;
337 case ::gig::eg1_ctrl_t::type_controlchange: // MIDI control change controller
338 eg1controllervalue = pEngine->ControllerTable[pDimRgn->EG1Controller.controller_number];
339 break;
340 }
341 if (pDimRgn->EG1ControllerInvert) eg1controllervalue = 127 - eg1controllervalue;
342
343 // calculate influence of EG1 controller on EG1's parameters (TODO: needs to be fine tuned)
344 double eg1attack = (pDimRgn->EG1ControllerAttackInfluence) ? 0.0001 * (double) (1 << pDimRgn->EG1ControllerAttackInfluence) * eg1controllervalue : 0.0;
345 double eg1decay = (pDimRgn->EG1ControllerDecayInfluence) ? 0.0001 * (double) (1 << pDimRgn->EG1ControllerDecayInfluence) * eg1controllervalue : 0.0;
346 double eg1release = (pDimRgn->EG1ControllerReleaseInfluence) ? 0.0001 * (double) (1 << pDimRgn->EG1ControllerReleaseInfluence) * eg1controllervalue : 0.0;
347
348 pEG1->Trigger(pDimRgn->EG1PreAttack,
349 pDimRgn->EG1Attack + eg1attack,
350 pDimRgn->EG1Hold,
351 pSample->LoopStart,
352 pDimRgn->EG1Decay1 + eg1decay,
353 pDimRgn->EG1Decay2 + eg1decay,
354 pDimRgn->EG1InfiniteSustain,
355 pDimRgn->EG1Sustain,
356 pDimRgn->EG1Release + eg1release,
357 Delay);
358 }
359
360
361 // setup EG 2 (VCF Cutoff EG)
362 {
363 // get current value of EG2 controller
364 double eg2controllervalue;
365 switch (pDimRgn->EG2Controller.type) {
366 case ::gig::eg2_ctrl_t::type_none: // no controller defined
367 eg2controllervalue = 0;
368 break;
369 case ::gig::eg2_ctrl_t::type_channelaftertouch:
370 eg2controllervalue = 0; // TODO: aftertouch not yet supported
371 break;
372 case ::gig::eg2_ctrl_t::type_velocity:
373 eg2controllervalue = itNoteOnEvent->Param.Note.Velocity;
374 break;
375 case ::gig::eg2_ctrl_t::type_controlchange: // MIDI control change controller
376 eg2controllervalue = pEngine->ControllerTable[pDimRgn->EG2Controller.controller_number];
377 break;
378 }
379 if (pDimRgn->EG2ControllerInvert) eg2controllervalue = 127 - eg2controllervalue;
380
381 // calculate influence of EG2 controller on EG2's parameters (TODO: needs to be fine tuned)
382 double eg2attack = (pDimRgn->EG2ControllerAttackInfluence) ? 0.0001 * (double) (1 << pDimRgn->EG2ControllerAttackInfluence) * eg2controllervalue : 0.0;
383 double eg2decay = (pDimRgn->EG2ControllerDecayInfluence) ? 0.0001 * (double) (1 << pDimRgn->EG2ControllerDecayInfluence) * eg2controllervalue : 0.0;
384 double eg2release = (pDimRgn->EG2ControllerReleaseInfluence) ? 0.0001 * (double) (1 << pDimRgn->EG2ControllerReleaseInfluence) * eg2controllervalue : 0.0;
385
386 pEG2->Trigger(pDimRgn->EG2PreAttack,
387 pDimRgn->EG2Attack + eg2attack,
388 false,
389 pSample->LoopStart,
390 pDimRgn->EG2Decay1 + eg2decay,
391 pDimRgn->EG2Decay2 + eg2decay,
392 pDimRgn->EG2InfiniteSustain,
393 pDimRgn->EG2Sustain,
394 pDimRgn->EG2Release + eg2release,
395 Delay);
396 }
397
398
399 // setup EG 3 (VCO EG)
400 {
401 double eg3depth = RTMath::CentsToFreqRatio(pDimRgn->EG3Depth);
402 pEG3->Trigger(eg3depth, pDimRgn->EG3Attack, Delay);
403 }
404
405
406 // setup LFO 1 (VCA LFO)
407 {
408 uint16_t lfo1_internal_depth;
409 switch (pDimRgn->LFO1Controller) {
410 case ::gig::lfo1_ctrl_internal:
411 lfo1_internal_depth = pDimRgn->LFO1InternalDepth;
412 pLFO1->ExtController = 0; // no external controller
413 break;
414 case ::gig::lfo1_ctrl_modwheel:
415 lfo1_internal_depth = 0;
416 pLFO1->ExtController = 1; // MIDI controller 1
417 break;
418 case ::gig::lfo1_ctrl_breath:
419 lfo1_internal_depth = 0;
420 pLFO1->ExtController = 2; // MIDI controller 2
421 break;
422 case ::gig::lfo1_ctrl_internal_modwheel:
423 lfo1_internal_depth = pDimRgn->LFO1InternalDepth;
424 pLFO1->ExtController = 1; // MIDI controller 1
425 break;
426 case ::gig::lfo1_ctrl_internal_breath:
427 lfo1_internal_depth = pDimRgn->LFO1InternalDepth;
428 pLFO1->ExtController = 2; // MIDI controller 2
429 break;
430 default:
431 lfo1_internal_depth = 0;
432 pLFO1->ExtController = 0; // no external controller
433 }
434 pLFO1->Trigger(pDimRgn->LFO1Frequency,
435 lfo1_internal_depth,
436 pDimRgn->LFO1ControlDepth,
437 pEngine->ControllerTable[pLFO1->ExtController],
438 pDimRgn->LFO1FlipPhase,
439 pEngine->SampleRate,
440 Delay);
441 }
442
443
444 // setup LFO 2 (VCF Cutoff LFO)
445 {
446 uint16_t lfo2_internal_depth;
447 switch (pDimRgn->LFO2Controller) {
448 case ::gig::lfo2_ctrl_internal:
449 lfo2_internal_depth = pDimRgn->LFO2InternalDepth;
450 pLFO2->ExtController = 0; // no external controller
451 break;
452 case ::gig::lfo2_ctrl_modwheel:
453 lfo2_internal_depth = 0;
454 pLFO2->ExtController = 1; // MIDI controller 1
455 break;
456 case ::gig::lfo2_ctrl_foot:
457 lfo2_internal_depth = 0;
458 pLFO2->ExtController = 4; // MIDI controller 4
459 break;
460 case ::gig::lfo2_ctrl_internal_modwheel:
461 lfo2_internal_depth = pDimRgn->LFO2InternalDepth;
462 pLFO2->ExtController = 1; // MIDI controller 1
463 break;
464 case ::gig::lfo2_ctrl_internal_foot:
465 lfo2_internal_depth = pDimRgn->LFO2InternalDepth;
466 pLFO2->ExtController = 4; // MIDI controller 4
467 break;
468 default:
469 lfo2_internal_depth = 0;
470 pLFO2->ExtController = 0; // no external controller
471 }
472 pLFO2->Trigger(pDimRgn->LFO2Frequency,
473 lfo2_internal_depth,
474 pDimRgn->LFO2ControlDepth,
475 pEngine->ControllerTable[pLFO2->ExtController],
476 pDimRgn->LFO2FlipPhase,
477 pEngine->SampleRate,
478 Delay);
479 }
480
481
482 // setup LFO 3 (VCO LFO)
483 {
484 uint16_t lfo3_internal_depth;
485 switch (pDimRgn->LFO3Controller) {
486 case ::gig::lfo3_ctrl_internal:
487 lfo3_internal_depth = pDimRgn->LFO3InternalDepth;
488 pLFO3->ExtController = 0; // no external controller
489 break;
490 case ::gig::lfo3_ctrl_modwheel:
491 lfo3_internal_depth = 0;
492 pLFO3->ExtController = 1; // MIDI controller 1
493 break;
494 case ::gig::lfo3_ctrl_aftertouch:
495 lfo3_internal_depth = 0;
496 pLFO3->ExtController = 0; // TODO: aftertouch not implemented yet
497 break;
498 case ::gig::lfo3_ctrl_internal_modwheel:
499 lfo3_internal_depth = pDimRgn->LFO3InternalDepth;
500 pLFO3->ExtController = 1; // MIDI controller 1
501 break;
502 case ::gig::lfo3_ctrl_internal_aftertouch:
503 lfo3_internal_depth = pDimRgn->LFO3InternalDepth;
504 pLFO1->ExtController = 0; // TODO: aftertouch not implemented yet
505 break;
506 default:
507 lfo3_internal_depth = 0;
508 pLFO3->ExtController = 0; // no external controller
509 }
510 pLFO3->Trigger(pDimRgn->LFO3Frequency,
511 lfo3_internal_depth,
512 pDimRgn->LFO3ControlDepth,
513 pEngine->ControllerTable[pLFO3->ExtController],
514 false,
515 pEngine->SampleRate,
516 Delay);
517 }
518
519
520 #if FORCE_FILTER_USAGE
521 SYNTHESIS_MODE_SET_FILTER(SynthesisMode, true);
522 #else // use filter only if instrument file told so
523 SYNTHESIS_MODE_SET_FILTER(SynthesisMode, pDimRgn->VCFEnabled);
524 #endif // FORCE_FILTER_USAGE
525 if (pDimRgn->VCFEnabled) {
526 #ifdef OVERRIDE_FILTER_CUTOFF_CTRL
527 VCFCutoffCtrl.controller = OVERRIDE_FILTER_CUTOFF_CTRL;
528 #else // use the one defined in the instrument file
529 switch (pDimRgn->VCFCutoffController) {
530 case ::gig::vcf_cutoff_ctrl_modwheel:
531 VCFCutoffCtrl.controller = 1;
532 break;
533 case ::gig::vcf_cutoff_ctrl_effect1:
534 VCFCutoffCtrl.controller = 12;
535 break;
536 case ::gig::vcf_cutoff_ctrl_effect2:
537 VCFCutoffCtrl.controller = 13;
538 break;
539 case ::gig::vcf_cutoff_ctrl_breath:
540 VCFCutoffCtrl.controller = 2;
541 break;
542 case ::gig::vcf_cutoff_ctrl_foot:
543 VCFCutoffCtrl.controller = 4;
544 break;
545 case ::gig::vcf_cutoff_ctrl_sustainpedal:
546 VCFCutoffCtrl.controller = 64;
547 break;
548 case ::gig::vcf_cutoff_ctrl_softpedal:
549 VCFCutoffCtrl.controller = 67;
550 break;
551 case ::gig::vcf_cutoff_ctrl_genpurpose7:
552 VCFCutoffCtrl.controller = 82;
553 break;
554 case ::gig::vcf_cutoff_ctrl_genpurpose8:
555 VCFCutoffCtrl.controller = 83;
556 break;
557 case ::gig::vcf_cutoff_ctrl_aftertouch: //TODO: not implemented yet
558 case ::gig::vcf_cutoff_ctrl_none:
559 default:
560 VCFCutoffCtrl.controller = 0;
561 break;
562 }
563 #endif // OVERRIDE_FILTER_CUTOFF_CTRL
564
565 #ifdef OVERRIDE_FILTER_RES_CTRL
566 VCFResonanceCtrl.controller = OVERRIDE_FILTER_RES_CTRL;
567 #else // use the one defined in the instrument file
568 switch (pDimRgn->VCFResonanceController) {
569 case ::gig::vcf_res_ctrl_genpurpose3:
570 VCFResonanceCtrl.controller = 18;
571 break;
572 case ::gig::vcf_res_ctrl_genpurpose4:
573 VCFResonanceCtrl.controller = 19;
574 break;
575 case ::gig::vcf_res_ctrl_genpurpose5:
576 VCFResonanceCtrl.controller = 80;
577 break;
578 case ::gig::vcf_res_ctrl_genpurpose6:
579 VCFResonanceCtrl.controller = 81;
580 break;
581 case ::gig::vcf_res_ctrl_none:
582 default:
583 VCFResonanceCtrl.controller = 0;
584 }
585 #endif // OVERRIDE_FILTER_RES_CTRL
586
587 #ifndef OVERRIDE_FILTER_TYPE
588 FilterLeft.SetType(pDimRgn->VCFType);
589 FilterRight.SetType(pDimRgn->VCFType);
590 #else // override filter type
591 FilterLeft.SetType(OVERRIDE_FILTER_TYPE);
592 FilterRight.SetType(OVERRIDE_FILTER_TYPE);
593 #endif // OVERRIDE_FILTER_TYPE
594
595 VCFCutoffCtrl.value = pEngine->ControllerTable[VCFCutoffCtrl.controller];
596 VCFResonanceCtrl.value = pEngine->ControllerTable[VCFResonanceCtrl.controller];
597
598 // calculate cutoff frequency
599 float cutoff = (!VCFCutoffCtrl.controller)
600 ? exp((float) (127 - itNoteOnEvent->Param.Note.Velocity) * (float) pDimRgn->VCFVelocityScale * 6.2E-5f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX
601 : exp((float) VCFCutoffCtrl.value * 0.00787402f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX;
602
603 // calculate resonance
604 float resonance = (float) VCFResonanceCtrl.value * 0.00787f; // 0.0..1.0
605 if (pDimRgn->VCFKeyboardTracking) {
606 resonance += (float) (itNoteOnEvent->Param.Note.Key - pDimRgn->VCFKeyboardTrackingBreakpoint) * 0.00787f;
607 }
608 Constrain(resonance, 0.0, 1.0); // correct resonance if outside allowed value range (0.0..1.0)
609
610 VCFCutoffCtrl.fvalue = cutoff - FILTER_CUTOFF_MIN;
611 VCFResonanceCtrl.fvalue = resonance;
612
613 FilterUpdateCounter = -1;
614 }
615 else {
616 VCFCutoffCtrl.controller = 0;
617 VCFResonanceCtrl.controller = 0;
618 }
619
620 return 0; // success
621 }
622
623 /**
624 * Renders the audio data for this voice for the current audio fragment.
625 * The sample input data can either come from RAM (cached sample or sample
626 * part) or directly from disk. The output signal will be rendered by
627 * resampling / interpolation. If this voice is a disk streaming voice and
628 * the voice completely played back the cached RAM part of the sample, it
629 * will automatically switch to disk playback for the next RenderAudio()
630 * call.
631 *
632 * @param Samples - number of samples to be rendered in this audio fragment cycle
633 */
634 void Voice::Render(uint Samples) {
635
636 // select default values for synthesis mode bits
637 SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, (PitchBase * PitchBend) != 1.0f);
638 SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, true);
639 SYNTHESIS_MODE_SET_LOOP(SynthesisMode, false);
640
641 // Reset the synthesis parameter matrix
642
643 pEngine->ResetSynthesisParameters(Event::destination_vca, this->Volume * this->CrossfadeVolume * pEngine->GlobalVolume);
644 pEngine->ResetSynthesisParameters(Event::destination_vco, this->PitchBase);
645 pEngine->ResetSynthesisParameters(Event::destination_vcfc, VCFCutoffCtrl.fvalue);
646 pEngine->ResetSynthesisParameters(Event::destination_vcfr, VCFResonanceCtrl.fvalue);
647
648 // Apply events to the synthesis parameter matrix
649 ProcessEvents(Samples);
650
651 // Let all modulators write their parameter changes to the synthesis parameter matrix for the current audio fragment
652 pEG1->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, itTriggerEvent, this->Pos, this->PitchBase * this->PitchBend, itKillEvent);
653 pEG2->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, itTriggerEvent, this->Pos, this->PitchBase * this->PitchBend);
654 if (pEG3->Process(Samples)) { // if pitch EG is active
655 SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, true);
656 SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, false);
657 }
658 pLFO1->Process(Samples);
659 pLFO2->Process(Samples);
660 if (pLFO3->Process(Samples)) { // if pitch LFO modulation is active
661 SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, true);
662 SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, false);
663 }
664
665 if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode))
666 CalculateBiquadParameters(Samples); // calculate the final biquad filter parameters
667
668 switch (this->PlaybackState) {
669
670 case playback_state_ram: {
671 if (RAMLoop) SYNTHESIS_MODE_SET_LOOP(SynthesisMode, true); // enable looping
672
673 // render current fragment
674 Synthesize(Samples, (sample_t*) pSample->GetCache().pStart, Delay);
675
676 if (DiskVoice) {
677 // check if we reached the allowed limit of the sample RAM cache
678 if (Pos > MaxRAMPos) {
679 dmsg(5,("Voice: switching to disk playback (Pos=%f)\n", Pos));
680 this->PlaybackState = playback_state_disk;
681 }
682 }
683 else if (Pos >= pSample->GetCache().Size / pSample->FrameSize) {
684 this->PlaybackState = playback_state_end;
685 }
686 }
687 break;
688
689 case playback_state_disk: {
690 if (!DiskStreamRef.pStream) {
691 // check if the disk thread created our ordered disk stream in the meantime
692 DiskStreamRef.pStream = pDiskThread->AskForCreatedStream(DiskStreamRef.OrderID);
693 if (!DiskStreamRef.pStream) {
694 std::cout << stderr << "Disk stream not available in time!" << std::endl << std::flush;
695 KillImmediately();
696 return;
697 }
698 DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (int(Pos) - MaxRAMPos));
699 Pos -= int(Pos);
700 RealSampleWordsLeftToRead = -1; // -1 means no silence has been added yet
701 }
702
703 const int sampleWordsLeftToRead = DiskStreamRef.pStream->GetReadSpace();
704
705 // add silence sample at the end if we reached the end of the stream (for the interpolator)
706 if (DiskStreamRef.State == Stream::state_end) {
707 const int maxSampleWordsPerCycle = (pEngine->MaxSamplesPerCycle << MAX_PITCH) * pSample->Channels + 6; // +6 for the interpolator algorithm
708 if (sampleWordsLeftToRead <= maxSampleWordsPerCycle) {
709 // remember how many sample words there are before any silence has been added
710 if (RealSampleWordsLeftToRead < 0) RealSampleWordsLeftToRead = sampleWordsLeftToRead;
711 DiskStreamRef.pStream->WriteSilence(maxSampleWordsPerCycle - sampleWordsLeftToRead);
712 }
713 }
714
715 sample_t* ptr = DiskStreamRef.pStream->GetReadPtr(); // get the current read_ptr within the ringbuffer where we read the samples from
716
717 // render current audio fragment
718 Synthesize(Samples, ptr, Delay);
719
720 const int iPos = (int) Pos;
721 const int readSampleWords = iPos * pSample->Channels; // amount of sample words actually been read
722 DiskStreamRef.pStream->IncrementReadPos(readSampleWords);
723 Pos -= iPos; // just keep fractional part of Pos
724
725 // change state of voice to 'end' if we really reached the end of the sample data
726 if (RealSampleWordsLeftToRead >= 0) {
727 RealSampleWordsLeftToRead -= readSampleWords;
728 if (RealSampleWordsLeftToRead <= 0) this->PlaybackState = playback_state_end;
729 }
730 }
731 break;
732
733 case playback_state_end:
734 std::cerr << "gig::Voice::Render(): entered with playback_state_end, this is a bug!\n" << std::flush;
735 break;
736 }
737
738 // Reset synthesis event lists (except VCO, as VCO events apply channel wide currently)
739 pEngine->pSynthesisEvents[Event::destination_vca]->clear();
740 pEngine->pSynthesisEvents[Event::destination_vcfc]->clear();
741 pEngine->pSynthesisEvents[Event::destination_vcfr]->clear();
742
743 // Reset delay
744 Delay = 0;
745
746 itTriggerEvent = Pool<Event>::Iterator();
747
748 // If sample stream or release stage finished, kill the voice
749 if (PlaybackState == playback_state_end || pEG1->GetStage() == EGADSR::stage_end) KillImmediately();
750 }
751
752 /**
753 * Resets voice variables. Should only be called if rendering process is
754 * suspended / not running.
755 */
756 void Voice::Reset() {
757 pLFO1->Reset();
758 pLFO2->Reset();
759 pLFO3->Reset();
760 FilterLeft.Reset();
761 FilterRight.Reset();
762 DiskStreamRef.pStream = NULL;
763 DiskStreamRef.hStream = 0;
764 DiskStreamRef.State = Stream::state_unused;
765 DiskStreamRef.OrderID = 0;
766 PlaybackState = playback_state_end;
767 itTriggerEvent = Pool<Event>::Iterator();
768 itKillEvent = Pool<Event>::Iterator();
769 }
770
771 /**
772 * Process the control change event lists of the engine for the current
773 * audio fragment. Event values will be applied to the synthesis parameter
774 * matrix.
775 *
776 * @param Samples - number of samples to be rendered in this audio fragment cycle
777 */
778 void Voice::ProcessEvents(uint Samples) {
779
780 // dispatch control change events
781 RTList<Event>::Iterator itCCEvent = pEngine->pCCEvents->first();
782 if (Delay) { // skip events that happened before this voice was triggered
783 while (itCCEvent && itCCEvent->FragmentPos() <= Delay) ++itCCEvent;
784 }
785 while (itCCEvent) {
786 if (itCCEvent->Param.CC.Controller) { // if valid MIDI controller
787 if (itCCEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {
788 *pEngine->pSynthesisEvents[Event::destination_vcfc]->allocAppend() = *itCCEvent;
789 }
790 if (itCCEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {
791 *pEngine->pSynthesisEvents[Event::destination_vcfr]->allocAppend() = *itCCEvent;
792 }
793 if (itCCEvent->Param.CC.Controller == pLFO1->ExtController) {
794 pLFO1->SendEvent(itCCEvent);
795 }
796 if (itCCEvent->Param.CC.Controller == pLFO2->ExtController) {
797 pLFO2->SendEvent(itCCEvent);
798 }
799 if (itCCEvent->Param.CC.Controller == pLFO3->ExtController) {
800 pLFO3->SendEvent(itCCEvent);
801 }
802 if (pDimRgn->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange &&
803 itCCEvent->Param.CC.Controller == pDimRgn->AttenuationController.controller_number) { // if crossfade event
804 *pEngine->pSynthesisEvents[Event::destination_vca]->allocAppend() = *itCCEvent;
805 }
806 }
807
808 ++itCCEvent;
809 }
810
811
812 // process pitch events
813 {
814 RTList<Event>* pVCOEventList = pEngine->pSynthesisEvents[Event::destination_vco];
815 RTList<Event>::Iterator itVCOEvent = pVCOEventList->first();
816 if (Delay) { // skip events that happened before this voice was triggered
817 while (itVCOEvent && itVCOEvent->FragmentPos() <= Delay) ++itVCOEvent;
818 }
819 // apply old pitchbend value until first pitch event occurs
820 if (this->PitchBend != 1.0) {
821 uint end = (itVCOEvent) ? itVCOEvent->FragmentPos() : Samples;
822 for (uint i = Delay; i < end; i++) {
823 pEngine->pSynthesisParameters[Event::destination_vco][i] *= this->PitchBend;
824 }
825 }
826 float pitch;
827 while (itVCOEvent) {
828 RTList<Event>::Iterator itNextVCOEvent = itVCOEvent;
829 ++itNextVCOEvent;
830
831 // calculate the influence length of this event (in sample points)
832 uint end = (itNextVCOEvent) ? itNextVCOEvent->FragmentPos() : Samples;
833
834 pitch = RTMath::CentsToFreqRatio(((double) itVCOEvent->Param.Pitch.Pitch / 8192.0) * 200.0); // +-two semitones = +-200 cents
835
836 // apply pitch value to the pitch parameter sequence
837 for (uint i = itVCOEvent->FragmentPos(); i < end; i++) {
838 pEngine->pSynthesisParameters[Event::destination_vco][i] *= pitch;
839 }
840
841 itVCOEvent = itNextVCOEvent;
842 }
843 if (!pVCOEventList->isEmpty()) {
844 this->PitchBend = pitch;
845 SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, true);
846 SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, false);
847 }
848 }
849
850 // process volume / attenuation events (TODO: we only handle and _expect_ crossfade events here ATM !)
851 {
852 RTList<Event>* pVCAEventList = pEngine->pSynthesisEvents[Event::destination_vca];
853 RTList<Event>::Iterator itVCAEvent = pVCAEventList->first();
854 if (Delay) { // skip events that happened before this voice was triggered
855 while (itVCAEvent && itVCAEvent->FragmentPos() <= Delay) ++itVCAEvent;
856 }
857 float crossfadevolume;
858 while (itVCAEvent) {
859 RTList<Event>::Iterator itNextVCAEvent = itVCAEvent;
860 ++itNextVCAEvent;
861
862 // calculate the influence length of this event (in sample points)
863 uint end = (itNextVCAEvent) ? itNextVCAEvent->FragmentPos() : Samples;
864
865 crossfadevolume = CrossfadeAttenuation(itVCAEvent->Param.CC.Value);
866
867 float effective_volume = crossfadevolume * this->Volume * pEngine->GlobalVolume;
868
869 // apply volume value to the volume parameter sequence
870 for (uint i = itVCAEvent->FragmentPos(); i < end; i++) {
871 pEngine->pSynthesisParameters[Event::destination_vca][i] = effective_volume;
872 }
873
874 itVCAEvent = itNextVCAEvent;
875 }
876 if (!pVCAEventList->isEmpty()) this->CrossfadeVolume = crossfadevolume;
877 }
878
879 // process filter cutoff events
880 {
881 RTList<Event>* pCutoffEventList = pEngine->pSynthesisEvents[Event::destination_vcfc];
882 RTList<Event>::Iterator itCutoffEvent = pCutoffEventList->first();
883 if (Delay) { // skip events that happened before this voice was triggered
884 while (itCutoffEvent && itCutoffEvent->FragmentPos() <= Delay) ++itCutoffEvent;
885 }
886 float cutoff;
887 while (itCutoffEvent) {
888 RTList<Event>::Iterator itNextCutoffEvent = itCutoffEvent;
889 ++itNextCutoffEvent;
890
891 // calculate the influence length of this event (in sample points)
892 uint end = (itNextCutoffEvent) ? itNextCutoffEvent->FragmentPos() : Samples;
893
894 cutoff = exp((float) itCutoffEvent->Param.CC.Value * 0.00787402f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX - FILTER_CUTOFF_MIN;
895
896 // apply cutoff frequency to the cutoff parameter sequence
897 for (uint i = itCutoffEvent->FragmentPos(); i < end; i++) {
898 pEngine->pSynthesisParameters[Event::destination_vcfc][i] = cutoff;
899 }
900
901 itCutoffEvent = itNextCutoffEvent;
902 }
903 if (!pCutoffEventList->isEmpty()) VCFCutoffCtrl.fvalue = cutoff; // needed for initialization of parameter matrix next time
904 }
905
906 // process filter resonance events
907 {
908 RTList<Event>* pResonanceEventList = pEngine->pSynthesisEvents[Event::destination_vcfr];
909 RTList<Event>::Iterator itResonanceEvent = pResonanceEventList->first();
910 if (Delay) { // skip events that happened before this voice was triggered
911 while (itResonanceEvent && itResonanceEvent->FragmentPos() <= Delay) ++itResonanceEvent;
912 }
913 while (itResonanceEvent) {
914 RTList<Event>::Iterator itNextResonanceEvent = itResonanceEvent;
915 ++itNextResonanceEvent;
916
917 // calculate the influence length of this event (in sample points)
918 uint end = (itNextResonanceEvent) ? itNextResonanceEvent->FragmentPos() : Samples;
919
920 // convert absolute controller value to differential
921 int ctrldelta = itResonanceEvent->Param.CC.Value - VCFResonanceCtrl.value;
922 VCFResonanceCtrl.value = itResonanceEvent->Param.CC.Value;
923
924 float resonancedelta = (float) ctrldelta * 0.00787f; // 0.0..1.0
925
926 // apply cutoff frequency to the cutoff parameter sequence
927 for (uint i = itResonanceEvent->FragmentPos(); i < end; i++) {
928 pEngine->pSynthesisParameters[Event::destination_vcfr][i] += resonancedelta;
929 }
930
931 itResonanceEvent = itNextResonanceEvent;
932 }
933 if (!pResonanceEventList->isEmpty()) VCFResonanceCtrl.fvalue = pResonanceEventList->last()->Param.CC.Value * 0.00787f; // needed for initialization of parameter matrix next time
934 }
935 }
936
937 /**
938 * Calculate all necessary, final biquad filter parameters.
939 *
940 * @param Samples - number of samples to be rendered in this audio fragment cycle
941 */
942 void Voice::CalculateBiquadParameters(uint Samples) {
943 biquad_param_t bqbase;
944 biquad_param_t bqmain;
945 float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0];
946 float prev_res = pEngine->pSynthesisParameters[Event::destination_vcfr][0];
947 FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);
948 FilterRight.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);
949 pEngine->pBasicFilterParameters[0] = bqbase;
950 pEngine->pMainFilterParameters[0] = bqmain;
951
952 float* bq;
953 for (int i = 1; i < Samples; i++) {
954 // recalculate biquad parameters if cutoff or resonance differ from previous sample point
955 if (!(i & FILTER_UPDATE_MASK)) {
956 if (pEngine->pSynthesisParameters[Event::destination_vcfr][i] != prev_res ||
957 pEngine->pSynthesisParameters[Event::destination_vcfc][i] != prev_cutoff)
958 {
959 prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][i];
960 prev_res = pEngine->pSynthesisParameters[Event::destination_vcfr][i];
961 FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);
962 FilterRight.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);
963 }
964 }
965
966 //same as 'pEngine->pBasicFilterParameters[i] = bqbase;'
967 bq = (float*) &pEngine->pBasicFilterParameters[i];
968 bq[0] = bqbase.b0;
969 bq[1] = bqbase.b1;
970 bq[2] = bqbase.b2;
971 bq[3] = bqbase.a1;
972 bq[4] = bqbase.a2;
973
974 // same as 'pEngine->pMainFilterParameters[i] = bqmain;'
975 bq = (float*) &pEngine->pMainFilterParameters[i];
976 bq[0] = bqmain.b0;
977 bq[1] = bqmain.b1;
978 bq[2] = bqmain.b2;
979 bq[3] = bqmain.a1;
980 bq[4] = bqmain.a2;
981 }
982 }
983
984 /**
985 * Synthesizes the current audio fragment for this voice.
986 *
987 * @param Samples - number of sample points to be rendered in this audio
988 * fragment cycle
989 * @param pSrc - pointer to input sample data
990 * @param Skip - number of sample points to skip in output buffer
991 */
992 void Voice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {
993 RunSynthesisFunction(SynthesisMode, *this, Samples, pSrc, Skip);
994 }
995
996 /**
997 * Immediately kill the voice. This method should not be used to kill
998 * a normal, active voice, because it doesn't take care of things like
999 * fading down the volume level to avoid clicks and regular processing
1000 * until the kill event actually occured!
1001 *
1002 * @see Kill()
1003 */
1004 void Voice::KillImmediately() {
1005 if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {
1006 pDiskThread->OrderDeletionOfStream(&DiskStreamRef);
1007 }
1008 Reset();
1009 }
1010
1011 /**
1012 * Kill the voice in regular sense. Let the voice render audio until
1013 * the kill event actually occured and then fade down the volume level
1014 * very quickly and let the voice die finally. Unlike a normal release
1015 * of a voice, a kill process cannot be cancalled and is therefore
1016 * usually used for voice stealing and key group conflicts.
1017 *
1018 * @param itKillEvent - event which caused the voice to be killed
1019 */
1020 void Voice::Kill(Pool<Event>::Iterator& itKillEvent) {
1021 //FIXME: just two sanity checks for debugging, can be removed
1022 if (!itKillEvent) dmsg(1,("gig::Voice::Kill(): ERROR, !itKillEvent !!!\n"));
1023 if (itKillEvent && !itKillEvent.isValid()) dmsg(1,("gig::Voice::Kill(): ERROR, itKillEvent invalid !!!\n"));
1024
1025 if (itTriggerEvent && itKillEvent->FragmentPos() <= itTriggerEvent->FragmentPos()) return;
1026 this->itKillEvent = itKillEvent;
1027 }
1028
1029 }} // namespace LinuxSampler::gig

  ViewVC Help
Powered by ViewVC