/[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 323 - (show annotations) (download)
Tue Dec 14 00:32:21 2004 UTC (14 years, 10 months ago) by schoenebeck
File size: 49882 byte(s)
* fixed bug which caused samples not to be played back to their actual end
  (patch by Andreas Persson, added a small extra fix)

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