/[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 271 - (show annotations) (download)
Fri Oct 8 20:51:39 2004 UTC (19 years, 5 months ago) by schoenebeck
File size: 49959 byte(s)
* libgig: fixed panorama value in DimensionRegion (invalid conversion
  from signed 7 bit to signed 8 bit)
* src/linuxsampler.cpp: stacktrace is now automatically shown on fatal
  errors (that is  segmentation faults, etc.), gdb should be installed for
  this to work
* gig::Voice: tiny accuracy fix of pan calculation
* replaced old pool classes by completely new ones which now offer
  Iterator abstraction

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 Active = false;
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 Active = true;
121 MIDIKey = itNoteOnEvent->Param.Note.Key;
122 pRegion = pInstrument->GetRegion(MIDIKey);
123 PlaybackState = playback_state_ram; // we always start playback from RAM cache and switch then to disk if needed
124 Delay = itNoteOnEvent->FragmentPos();
125 itTriggerEvent = itNoteOnEvent;
126 itKillEvent = Pool<Event>::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 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 KillImmediately(); // free voice
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 release stage finished, let the voice be killed
722 if (pEG1->GetStage() == EGADSR::stage_end) this->PlaybackState = playback_state_end;
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 Active = false;
738 }
739
740 /**
741 * Process the control change event lists of the engine for the current
742 * audio fragment. Event values will be applied to the synthesis parameter
743 * matrix.
744 *
745 * @param Samples - number of samples to be rendered in this audio fragment cycle
746 */
747 void Voice::ProcessEvents(uint Samples) {
748
749 // dispatch control change events
750 RTList<Event>::Iterator itCCEvent = pEngine->pCCEvents->first();
751 if (Delay) { // skip events that happened before this voice was triggered
752 while (itCCEvent && itCCEvent->FragmentPos() <= Delay) ++itCCEvent;
753 }
754 while (itCCEvent) {
755 if (itCCEvent->Param.CC.Controller) { // if valid MIDI controller
756 #if ENABLE_FILTER
757 if (itCCEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {
758 *pEngine->pSynthesisEvents[Event::destination_vcfc]->allocAppend() = *itCCEvent;
759 }
760 if (itCCEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {
761 *pEngine->pSynthesisEvents[Event::destination_vcfr]->allocAppend() = *itCCEvent;
762 }
763 #endif // ENABLE_FILTER
764 if (itCCEvent->Param.CC.Controller == pLFO1->ExtController) {
765 pLFO1->SendEvent(itCCEvent);
766 }
767 #if ENABLE_FILTER
768 if (itCCEvent->Param.CC.Controller == pLFO2->ExtController) {
769 pLFO2->SendEvent(itCCEvent);
770 }
771 #endif // ENABLE_FILTER
772 if (itCCEvent->Param.CC.Controller == pLFO3->ExtController) {
773 pLFO3->SendEvent(itCCEvent);
774 }
775 if (pDimRgn->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange &&
776 itCCEvent->Param.CC.Controller == pDimRgn->AttenuationController.controller_number) { // if crossfade event
777 *pEngine->pSynthesisEvents[Event::destination_vca]->allocAppend() = *itCCEvent;
778 }
779 }
780
781 ++itCCEvent;
782 }
783
784
785 // process pitch events
786 {
787 RTList<Event>* pVCOEventList = pEngine->pSynthesisEvents[Event::destination_vco];
788 RTList<Event>::Iterator itVCOEvent = pVCOEventList->first();
789 if (Delay) { // skip events that happened before this voice was triggered
790 while (itVCOEvent && itVCOEvent->FragmentPos() <= Delay) ++itVCOEvent;
791 }
792 // apply old pitchbend value until first pitch event occurs
793 if (this->PitchBend != 1.0) {
794 uint end = (itVCOEvent) ? itVCOEvent->FragmentPos() : Samples;
795 for (uint i = Delay; i < end; i++) {
796 pEngine->pSynthesisParameters[Event::destination_vco][i] *= this->PitchBend;
797 }
798 }
799 float pitch;
800 while (itVCOEvent) {
801 RTList<Event>::Iterator itNextVCOEvent = itVCOEvent;
802 ++itNextVCOEvent;
803
804 // calculate the influence length of this event (in sample points)
805 uint end = (itNextVCOEvent) ? itNextVCOEvent->FragmentPos() : Samples;
806
807 pitch = RTMath::CentsToFreqRatio(((double) itVCOEvent->Param.Pitch.Pitch / 8192.0) * 200.0); // +-two semitones = +-200 cents
808
809 // apply pitch value to the pitch parameter sequence
810 for (uint i = itVCOEvent->FragmentPos(); i < end; i++) {
811 pEngine->pSynthesisParameters[Event::destination_vco][i] *= pitch;
812 }
813
814 itVCOEvent = itNextVCOEvent;
815 }
816 if (!pVCOEventList->isEmpty()) this->PitchBend = pitch;
817 }
818
819 // process volume / attenuation events (TODO: we only handle and _expect_ crossfade events here ATM !)
820 {
821 RTList<Event>* pVCAEventList = pEngine->pSynthesisEvents[Event::destination_vca];
822 RTList<Event>::Iterator itVCAEvent = pVCAEventList->first();
823 if (Delay) { // skip events that happened before this voice was triggered
824 while (itVCAEvent && itVCAEvent->FragmentPos() <= Delay) ++itVCAEvent;
825 }
826 float crossfadevolume;
827 while (itVCAEvent) {
828 RTList<Event>::Iterator itNextVCAEvent = itVCAEvent;
829 ++itNextVCAEvent;
830
831 // calculate the influence length of this event (in sample points)
832 uint end = (itNextVCAEvent) ? itNextVCAEvent->FragmentPos() : Samples;
833
834 crossfadevolume = CrossfadeAttenuation(itVCAEvent->Param.CC.Value);
835
836 float effective_volume = crossfadevolume * this->Volume * pEngine->GlobalVolume;
837
838 // apply volume value to the volume parameter sequence
839 for (uint i = itVCAEvent->FragmentPos(); i < end; i++) {
840 pEngine->pSynthesisParameters[Event::destination_vca][i] = effective_volume;
841 }
842
843 itVCAEvent = itNextVCAEvent;
844 }
845 if (!pVCAEventList->isEmpty()) this->CrossfadeVolume = crossfadevolume;
846 }
847
848 #if ENABLE_FILTER
849 // process filter cutoff events
850 {
851 RTList<Event>* pCutoffEventList = pEngine->pSynthesisEvents[Event::destination_vcfc];
852 RTList<Event>::Iterator itCutoffEvent = pCutoffEventList->first();
853 if (Delay) { // skip events that happened before this voice was triggered
854 while (itCutoffEvent && itCutoffEvent->FragmentPos() <= Delay) ++itCutoffEvent;
855 }
856 float cutoff;
857 while (itCutoffEvent) {
858 RTList<Event>::Iterator itNextCutoffEvent = itCutoffEvent;
859 ++itNextCutoffEvent;
860
861 // calculate the influence length of this event (in sample points)
862 uint end = (itNextCutoffEvent) ? itNextCutoffEvent->FragmentPos() : Samples;
863
864 cutoff = exp((float) itCutoffEvent->Param.CC.Value * 0.00787402f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX - FILTER_CUTOFF_MIN;
865
866 // apply cutoff frequency to the cutoff parameter sequence
867 for (uint i = itCutoffEvent->FragmentPos(); i < end; i++) {
868 pEngine->pSynthesisParameters[Event::destination_vcfc][i] = cutoff;
869 }
870
871 itCutoffEvent = itNextCutoffEvent;
872 }
873 if (!pCutoffEventList->isEmpty()) VCFCutoffCtrl.fvalue = cutoff; // needed for initialization of parameter matrix next time
874 }
875
876 // process filter resonance events
877 {
878 RTList<Event>* pResonanceEventList = pEngine->pSynthesisEvents[Event::destination_vcfr];
879 RTList<Event>::Iterator itResonanceEvent = pResonanceEventList->first();
880 if (Delay) { // skip events that happened before this voice was triggered
881 while (itResonanceEvent && itResonanceEvent->FragmentPos() <= Delay) ++itResonanceEvent;
882 }
883 while (itResonanceEvent) {
884 RTList<Event>::Iterator itNextResonanceEvent = itResonanceEvent;
885 ++itNextResonanceEvent;
886
887 // calculate the influence length of this event (in sample points)
888 uint end = (itNextResonanceEvent) ? itNextResonanceEvent->FragmentPos() : Samples;
889
890 // convert absolute controller value to differential
891 int ctrldelta = itResonanceEvent->Param.CC.Value - VCFResonanceCtrl.value;
892 VCFResonanceCtrl.value = itResonanceEvent->Param.CC.Value;
893
894 float resonancedelta = (float) ctrldelta * 0.00787f; // 0.0..1.0
895
896 // apply cutoff frequency to the cutoff parameter sequence
897 for (uint i = itResonanceEvent->FragmentPos(); i < end; i++) {
898 pEngine->pSynthesisParameters[Event::destination_vcfr][i] += resonancedelta;
899 }
900
901 itResonanceEvent = itNextResonanceEvent;
902 }
903 if (!pResonanceEventList->isEmpty()) VCFResonanceCtrl.fvalue = pResonanceEventList->last()->Param.CC.Value * 0.00787f; // needed for initialization of parameter matrix next time
904 }
905 #endif // ENABLE_FILTER
906 }
907
908 #if ENABLE_FILTER
909 /**
910 * Calculate all necessary, final biquad filter parameters.
911 *
912 * @param Samples - number of samples to be rendered in this audio fragment cycle
913 */
914 void Voice::CalculateBiquadParameters(uint Samples) {
915 if (!FilterLeft.Enabled) return;
916
917 biquad_param_t bqbase;
918 biquad_param_t bqmain;
919 float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0];
920 float prev_res = pEngine->pSynthesisParameters[Event::destination_vcfr][0];
921 FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);
922 pEngine->pBasicFilterParameters[0] = bqbase;
923 pEngine->pMainFilterParameters[0] = bqmain;
924
925 float* bq;
926 for (int i = 1; i < Samples; i++) {
927 // recalculate biquad parameters if cutoff or resonance differ from previous sample point
928 if (!(i & FILTER_UPDATE_MASK)) if (pEngine->pSynthesisParameters[Event::destination_vcfr][i] != prev_res ||
929 pEngine->pSynthesisParameters[Event::destination_vcfc][i] != prev_cutoff) {
930 prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][i];
931 prev_res = pEngine->pSynthesisParameters[Event::destination_vcfr][i];
932 FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);
933 }
934
935 //same as 'pEngine->pBasicFilterParameters[i] = bqbase;'
936 bq = (float*) &pEngine->pBasicFilterParameters[i];
937 bq[0] = bqbase.a1;
938 bq[1] = bqbase.a2;
939 bq[2] = bqbase.b0;
940 bq[3] = bqbase.b1;
941 bq[4] = bqbase.b2;
942
943 // same as 'pEngine->pMainFilterParameters[i] = bqmain;'
944 bq = (float*) &pEngine->pMainFilterParameters[i];
945 bq[0] = bqmain.a1;
946 bq[1] = bqmain.a2;
947 bq[2] = bqmain.b0;
948 bq[3] = bqmain.b1;
949 bq[4] = bqmain.b2;
950 }
951 }
952 #endif // ENABLE_FILTER
953
954 /**
955 * Interpolates the input audio data (without looping).
956 *
957 * @param Samples - number of sample points to be rendered in this audio
958 * fragment cycle
959 * @param pSrc - pointer to input sample data
960 * @param Skip - number of sample points to skip in output buffer
961 */
962 void Voice::InterpolateNoLoop(uint Samples, sample_t* pSrc, uint Skip) {
963 int i = Skip;
964
965 // FIXME: assuming either mono or stereo
966 if (this->pSample->Channels == 2) { // Stereo Sample
967 while (i < Samples) InterpolateStereo(pSrc, i);
968 }
969 else { // Mono Sample
970 while (i < Samples) InterpolateMono(pSrc, i);
971 }
972 }
973
974 /**
975 * Interpolates the input audio data, this method honors looping.
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::InterpolateAndLoop(uint Samples, sample_t* pSrc, uint Skip) {
983 int i = Skip;
984
985 // FIXME: assuming either mono or stereo
986 if (pSample->Channels == 2) { // Stereo Sample
987 if (pSample->LoopPlayCount) {
988 // render loop (loop count limited)
989 while (i < Samples && LoopCyclesLeft) {
990 InterpolateStereo(pSrc, i);
991 if (Pos > pSample->LoopEnd) {
992 Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;
993 LoopCyclesLeft--;
994 }
995 }
996 // render on without loop
997 while (i < Samples) InterpolateStereo(pSrc, i);
998 }
999 else { // render loop (endless loop)
1000 while (i < Samples) {
1001 InterpolateStereo(pSrc, i);
1002 if (Pos > pSample->LoopEnd) {
1003 Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);
1004 }
1005 }
1006 }
1007 }
1008 else { // Mono Sample
1009 if (pSample->LoopPlayCount) {
1010 // render loop (loop count limited)
1011 while (i < Samples && LoopCyclesLeft) {
1012 InterpolateMono(pSrc, i);
1013 if (Pos > pSample->LoopEnd) {
1014 Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;
1015 LoopCyclesLeft--;
1016 }
1017 }
1018 // render on without loop
1019 while (i < Samples) InterpolateMono(pSrc, i);
1020 }
1021 else { // render loop (endless loop)
1022 while (i < Samples) {
1023 InterpolateMono(pSrc, i);
1024 if (Pos > pSample->LoopEnd) {
1025 Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;
1026 }
1027 }
1028 }
1029 }
1030 }
1031
1032 /**
1033 * Immediately kill the voice. This method should not be used to kill
1034 * a normal, active voice, because it doesn't take care of things like
1035 * fading down the volume level to avoid clicks and regular processing
1036 * until the kill event actually occured!
1037 *
1038 * @see Kill()
1039 */
1040 void Voice::KillImmediately() {
1041 if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {
1042 pDiskThread->OrderDeletionOfStream(&DiskStreamRef);
1043 }
1044 Reset();
1045 }
1046
1047 /**
1048 * Kill the voice in regular sense. Let the voice render audio until
1049 * the kill event actually occured and then fade down the volume level
1050 * very quickly and let the voice die finally. Unlike a normal release
1051 * of a voice, a kill process cannot be cancalled and is therefore
1052 * usually used for voice stealing and key group conflicts.
1053 *
1054 * @param itKillEvent - event which caused the voice to be killed
1055 */
1056 void Voice::Kill(Pool<Event>::Iterator& itKillEvent) {
1057 if (itTriggerEvent && itKillEvent->FragmentPos() <= itTriggerEvent->FragmentPos()) return;
1058 this->itKillEvent = itKillEvent;
1059 }
1060
1061 }} // namespace LinuxSampler::gig

  ViewVC Help
Powered by ViewVC