/[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 285 - (show annotations) (download)
Thu Oct 14 21:31:26 2004 UTC (19 years, 5 months ago) by schoenebeck
File size: 50226 byte(s)
* bunch of bugfixes (e.g. segfault on voice stealing)

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

  ViewVC Help
Powered by ViewVC