/[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 244 - (show annotations) (download)
Fri Sep 17 01:01:11 2004 UTC (19 years, 6 months ago) by schoenebeck
File size: 52393 byte(s)
* added support for scale tuning via MIDI GS system exclusive message

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 pNoteOnEvent - 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(Event* pNoteOnEvent, 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 = pNoteOnEvent->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 = pNoteOnEvent->FragmentPos();
125 pTriggerEvent = pNoteOnEvent;
126 pKillEvent = NULL;
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(pNoteOnEvent, iNewLayer, ReleaseTriggerVoice);
150 break;
151 case ::gig::dimension_velocity:
152 DimValues[i] = pNoteOnEvent->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) pNoteOnEvent->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(pNoteOnEvent->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 pSample = pDimRgn->pSample; // sample won't change until the voice is finished
259
260 Pos = pDimRgn->SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)
261
262 // Check if the sample needs disk streaming or is too short for that
263 long cachedsamples = pSample->GetCache().Size / pSample->FrameSize;
264 DiskVoice = cachedsamples < pSample->SamplesTotal;
265
266 if (DiskVoice) { // voice to be streamed from disk
267 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)
268
269 // check if there's a loop defined which completely fits into the cached (RAM) part of the sample
270 if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) {
271 RAMLoop = true;
272 LoopCyclesLeft = pSample->LoopPlayCount;
273 }
274 else RAMLoop = false;
275
276 if (pDiskThread->OrderNewStream(&DiskStreamRef, pSample, MaxRAMPos, !RAMLoop) < 0) {
277 dmsg(1,("Disk stream order failed!\n"));
278 KillImmediately();
279 return -1;
280 }
281 dmsg(4,("Disk voice launched (cached samples: %d, total Samples: %d, MaxRAMPos: %d, RAMLooping: %s)\n", cachedsamples, pSample->SamplesTotal, MaxRAMPos, (RAMLoop) ? "yes" : "no"));
282 }
283 else { // RAM only voice
284 MaxRAMPos = cachedsamples;
285 if (pSample->Loops) {
286 RAMLoop = true;
287 LoopCyclesLeft = pSample->LoopPlayCount;
288 }
289 else RAMLoop = false;
290 dmsg(4,("RAM only voice launched (Looping: %s)\n", (RAMLoop) ? "yes" : "no"));
291 }
292
293
294 // calculate initial pitch value
295 {
296 double pitchbasecents = pDimRgn->FineTune * 10 + (int) pEngine->ScaleTuning[MIDIKey % 12];
297 if (pDimRgn->PitchTrack) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;
298 this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents) * (double(pSample->SamplesPerSecond) / double(pEngine->pAudioOutputDevice->SampleRate()));
299 this->PitchBend = RTMath::CentsToFreqRatio(((double) PitchBend / 8192.0) * 200.0); // pitchbend wheel +-2 semitones = 200 cents
300 }
301
302
303 Volume = pDimRgn->GetVelocityAttenuation(pNoteOnEvent->Velocity) / 32768.0f; // we downscale by 32768 to convert from int16 value range to DSP value range (which is -1.0..1.0)
304
305
306 // setup EG 1 (VCA EG)
307 {
308 // get current value of EG1 controller
309 double eg1controllervalue;
310 switch (pDimRgn->EG1Controller.type) {
311 case ::gig::eg1_ctrl_t::type_none: // no controller defined
312 eg1controllervalue = 0;
313 break;
314 case ::gig::eg1_ctrl_t::type_channelaftertouch:
315 eg1controllervalue = 0; // TODO: aftertouch not yet supported
316 break;
317 case ::gig::eg1_ctrl_t::type_velocity:
318 eg1controllervalue = pNoteOnEvent->Velocity;
319 break;
320 case ::gig::eg1_ctrl_t::type_controlchange: // MIDI control change controller
321 eg1controllervalue = pEngine->ControllerTable[pDimRgn->EG1Controller.controller_number];
322 break;
323 }
324 if (pDimRgn->EG1ControllerInvert) eg1controllervalue = 127 - eg1controllervalue;
325
326 // calculate influence of EG1 controller on EG1's parameters (TODO: needs to be fine tuned)
327 double eg1attack = (pDimRgn->EG1ControllerAttackInfluence) ? 0.0001 * (double) (1 << pDimRgn->EG1ControllerAttackInfluence) * eg1controllervalue : 0.0;
328 double eg1decay = (pDimRgn->EG1ControllerDecayInfluence) ? 0.0001 * (double) (1 << pDimRgn->EG1ControllerDecayInfluence) * eg1controllervalue : 0.0;
329 double eg1release = (pDimRgn->EG1ControllerReleaseInfluence) ? 0.0001 * (double) (1 << pDimRgn->EG1ControllerReleaseInfluence) * eg1controllervalue : 0.0;
330
331 pEG1->Trigger(pDimRgn->EG1PreAttack,
332 pDimRgn->EG1Attack + eg1attack,
333 pDimRgn->EG1Hold,
334 pSample->LoopStart,
335 pDimRgn->EG1Decay1 + eg1decay,
336 pDimRgn->EG1Decay2 + eg1decay,
337 pDimRgn->EG1InfiniteSustain,
338 pDimRgn->EG1Sustain,
339 pDimRgn->EG1Release + eg1release,
340 Delay);
341 }
342
343
344 #if ENABLE_FILTER
345 // setup EG 2 (VCF Cutoff EG)
346 {
347 // get current value of EG2 controller
348 double eg2controllervalue;
349 switch (pDimRgn->EG2Controller.type) {
350 case ::gig::eg2_ctrl_t::type_none: // no controller defined
351 eg2controllervalue = 0;
352 break;
353 case ::gig::eg2_ctrl_t::type_channelaftertouch:
354 eg2controllervalue = 0; // TODO: aftertouch not yet supported
355 break;
356 case ::gig::eg2_ctrl_t::type_velocity:
357 eg2controllervalue = pNoteOnEvent->Velocity;
358 break;
359 case ::gig::eg2_ctrl_t::type_controlchange: // MIDI control change controller
360 eg2controllervalue = pEngine->ControllerTable[pDimRgn->EG2Controller.controller_number];
361 break;
362 }
363 if (pDimRgn->EG2ControllerInvert) eg2controllervalue = 127 - eg2controllervalue;
364
365 // calculate influence of EG2 controller on EG2's parameters (TODO: needs to be fine tuned)
366 double eg2attack = (pDimRgn->EG2ControllerAttackInfluence) ? 0.0001 * (double) (1 << pDimRgn->EG2ControllerAttackInfluence) * eg2controllervalue : 0.0;
367 double eg2decay = (pDimRgn->EG2ControllerDecayInfluence) ? 0.0001 * (double) (1 << pDimRgn->EG2ControllerDecayInfluence) * eg2controllervalue : 0.0;
368 double eg2release = (pDimRgn->EG2ControllerReleaseInfluence) ? 0.0001 * (double) (1 << pDimRgn->EG2ControllerReleaseInfluence) * eg2controllervalue : 0.0;
369
370 pEG2->Trigger(pDimRgn->EG2PreAttack,
371 pDimRgn->EG2Attack + eg2attack,
372 false,
373 pSample->LoopStart,
374 pDimRgn->EG2Decay1 + eg2decay,
375 pDimRgn->EG2Decay2 + eg2decay,
376 pDimRgn->EG2InfiniteSustain,
377 pDimRgn->EG2Sustain,
378 pDimRgn->EG2Release + eg2release,
379 Delay);
380 }
381 #endif // ENABLE_FILTER
382
383
384 // setup EG 3 (VCO EG)
385 {
386 double eg3depth = RTMath::CentsToFreqRatio(pDimRgn->EG3Depth);
387 pEG3->Trigger(eg3depth, pDimRgn->EG3Attack, Delay);
388 }
389
390
391 // setup LFO 1 (VCA LFO)
392 {
393 uint16_t lfo1_internal_depth;
394 switch (pDimRgn->LFO1Controller) {
395 case ::gig::lfo1_ctrl_internal:
396 lfo1_internal_depth = pDimRgn->LFO1InternalDepth;
397 pLFO1->ExtController = 0; // no external controller
398 break;
399 case ::gig::lfo1_ctrl_modwheel:
400 lfo1_internal_depth = 0;
401 pLFO1->ExtController = 1; // MIDI controller 1
402 break;
403 case ::gig::lfo1_ctrl_breath:
404 lfo1_internal_depth = 0;
405 pLFO1->ExtController = 2; // MIDI controller 2
406 break;
407 case ::gig::lfo1_ctrl_internal_modwheel:
408 lfo1_internal_depth = pDimRgn->LFO1InternalDepth;
409 pLFO1->ExtController = 1; // MIDI controller 1
410 break;
411 case ::gig::lfo1_ctrl_internal_breath:
412 lfo1_internal_depth = pDimRgn->LFO1InternalDepth;
413 pLFO1->ExtController = 2; // MIDI controller 2
414 break;
415 default:
416 lfo1_internal_depth = 0;
417 pLFO1->ExtController = 0; // no external controller
418 }
419 pLFO1->Trigger(pDimRgn->LFO1Frequency,
420 lfo1_internal_depth,
421 pDimRgn->LFO1ControlDepth,
422 pEngine->ControllerTable[pLFO1->ExtController],
423 pDimRgn->LFO1FlipPhase,
424 pEngine->SampleRate,
425 Delay);
426 }
427
428 #if ENABLE_FILTER
429 // setup LFO 2 (VCF Cutoff LFO)
430 {
431 uint16_t lfo2_internal_depth;
432 switch (pDimRgn->LFO2Controller) {
433 case ::gig::lfo2_ctrl_internal:
434 lfo2_internal_depth = pDimRgn->LFO2InternalDepth;
435 pLFO2->ExtController = 0; // no external controller
436 break;
437 case ::gig::lfo2_ctrl_modwheel:
438 lfo2_internal_depth = 0;
439 pLFO2->ExtController = 1; // MIDI controller 1
440 break;
441 case ::gig::lfo2_ctrl_foot:
442 lfo2_internal_depth = 0;
443 pLFO2->ExtController = 4; // MIDI controller 4
444 break;
445 case ::gig::lfo2_ctrl_internal_modwheel:
446 lfo2_internal_depth = pDimRgn->LFO2InternalDepth;
447 pLFO2->ExtController = 1; // MIDI controller 1
448 break;
449 case ::gig::lfo2_ctrl_internal_foot:
450 lfo2_internal_depth = pDimRgn->LFO2InternalDepth;
451 pLFO2->ExtController = 4; // MIDI controller 4
452 break;
453 default:
454 lfo2_internal_depth = 0;
455 pLFO2->ExtController = 0; // no external controller
456 }
457 pLFO2->Trigger(pDimRgn->LFO2Frequency,
458 lfo2_internal_depth,
459 pDimRgn->LFO2ControlDepth,
460 pEngine->ControllerTable[pLFO2->ExtController],
461 pDimRgn->LFO2FlipPhase,
462 pEngine->SampleRate,
463 Delay);
464 }
465 #endif // ENABLE_FILTER
466
467 // setup LFO 3 (VCO LFO)
468 {
469 uint16_t lfo3_internal_depth;
470 switch (pDimRgn->LFO3Controller) {
471 case ::gig::lfo3_ctrl_internal:
472 lfo3_internal_depth = pDimRgn->LFO3InternalDepth;
473 pLFO3->ExtController = 0; // no external controller
474 break;
475 case ::gig::lfo3_ctrl_modwheel:
476 lfo3_internal_depth = 0;
477 pLFO3->ExtController = 1; // MIDI controller 1
478 break;
479 case ::gig::lfo3_ctrl_aftertouch:
480 lfo3_internal_depth = 0;
481 pLFO3->ExtController = 0; // TODO: aftertouch not implemented yet
482 break;
483 case ::gig::lfo3_ctrl_internal_modwheel:
484 lfo3_internal_depth = pDimRgn->LFO3InternalDepth;
485 pLFO3->ExtController = 1; // MIDI controller 1
486 break;
487 case ::gig::lfo3_ctrl_internal_aftertouch:
488 lfo3_internal_depth = pDimRgn->LFO3InternalDepth;
489 pLFO1->ExtController = 0; // TODO: aftertouch not implemented yet
490 break;
491 default:
492 lfo3_internal_depth = 0;
493 pLFO3->ExtController = 0; // no external controller
494 }
495 pLFO3->Trigger(pDimRgn->LFO3Frequency,
496 lfo3_internal_depth,
497 pDimRgn->LFO3ControlDepth,
498 pEngine->ControllerTable[pLFO3->ExtController],
499 false,
500 pEngine->SampleRate,
501 Delay);
502 }
503
504 #if ENABLE_FILTER
505 #if FORCE_FILTER_USAGE
506 FilterLeft.Enabled = FilterRight.Enabled = true;
507 #else // use filter only if instrument file told so
508 FilterLeft.Enabled = FilterRight.Enabled = pDimRgn->VCFEnabled;
509 #endif // FORCE_FILTER_USAGE
510 if (pDimRgn->VCFEnabled) {
511 #ifdef OVERRIDE_FILTER_CUTOFF_CTRL
512 VCFCutoffCtrl.controller = OVERRIDE_FILTER_CUTOFF_CTRL;
513 #else // use the one defined in the instrument file
514 switch (pDimRgn->VCFCutoffController) {
515 case ::gig::vcf_cutoff_ctrl_modwheel:
516 VCFCutoffCtrl.controller = 1;
517 break;
518 case ::gig::vcf_cutoff_ctrl_effect1:
519 VCFCutoffCtrl.controller = 12;
520 break;
521 case ::gig::vcf_cutoff_ctrl_effect2:
522 VCFCutoffCtrl.controller = 13;
523 break;
524 case ::gig::vcf_cutoff_ctrl_breath:
525 VCFCutoffCtrl.controller = 2;
526 break;
527 case ::gig::vcf_cutoff_ctrl_foot:
528 VCFCutoffCtrl.controller = 4;
529 break;
530 case ::gig::vcf_cutoff_ctrl_sustainpedal:
531 VCFCutoffCtrl.controller = 64;
532 break;
533 case ::gig::vcf_cutoff_ctrl_softpedal:
534 VCFCutoffCtrl.controller = 67;
535 break;
536 case ::gig::vcf_cutoff_ctrl_genpurpose7:
537 VCFCutoffCtrl.controller = 82;
538 break;
539 case ::gig::vcf_cutoff_ctrl_genpurpose8:
540 VCFCutoffCtrl.controller = 83;
541 break;
542 case ::gig::vcf_cutoff_ctrl_aftertouch: //TODO: not implemented yet
543 case ::gig::vcf_cutoff_ctrl_none:
544 default:
545 VCFCutoffCtrl.controller = 0;
546 break;
547 }
548 #endif // OVERRIDE_FILTER_CUTOFF_CTRL
549
550 #ifdef OVERRIDE_FILTER_RES_CTRL
551 VCFResonanceCtrl.controller = OVERRIDE_FILTER_RES_CTRL;
552 #else // use the one defined in the instrument file
553 switch (pDimRgn->VCFResonanceController) {
554 case ::gig::vcf_res_ctrl_genpurpose3:
555 VCFResonanceCtrl.controller = 18;
556 break;
557 case ::gig::vcf_res_ctrl_genpurpose4:
558 VCFResonanceCtrl.controller = 19;
559 break;
560 case ::gig::vcf_res_ctrl_genpurpose5:
561 VCFResonanceCtrl.controller = 80;
562 break;
563 case ::gig::vcf_res_ctrl_genpurpose6:
564 VCFResonanceCtrl.controller = 81;
565 break;
566 case ::gig::vcf_res_ctrl_none:
567 default:
568 VCFResonanceCtrl.controller = 0;
569 }
570 #endif // OVERRIDE_FILTER_RES_CTRL
571
572 #ifndef OVERRIDE_FILTER_TYPE
573 FilterLeft.SetType(pDimRgn->VCFType);
574 FilterRight.SetType(pDimRgn->VCFType);
575 #else // override filter type
576 FilterLeft.SetType(OVERRIDE_FILTER_TYPE);
577 FilterRight.SetType(OVERRIDE_FILTER_TYPE);
578 #endif // OVERRIDE_FILTER_TYPE
579
580 VCFCutoffCtrl.value = pEngine->ControllerTable[VCFCutoffCtrl.controller];
581 VCFResonanceCtrl.value = pEngine->ControllerTable[VCFResonanceCtrl.controller];
582
583 // calculate cutoff frequency
584 float cutoff = (!VCFCutoffCtrl.controller)
585 ? exp((float) (127 - pNoteOnEvent->Velocity) * (float) pDimRgn->VCFVelocityScale * 6.2E-5f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX
586 : exp((float) VCFCutoffCtrl.value * 0.00787402f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX;
587
588 // calculate resonance
589 float resonance = (float) VCFResonanceCtrl.value * 0.00787f; // 0.0..1.0
590 if (pDimRgn->VCFKeyboardTracking) {
591 resonance += (float) (pNoteOnEvent->Key - pDimRgn->VCFKeyboardTrackingBreakpoint) * 0.00787f;
592 }
593 Constrain(resonance, 0.0, 1.0); // correct resonance if outside allowed value range (0.0..1.0)
594
595 VCFCutoffCtrl.fvalue = cutoff - FILTER_CUTOFF_MIN;
596 VCFResonanceCtrl.fvalue = resonance;
597
598 FilterLeft.SetParameters(cutoff, resonance, pEngine->SampleRate);
599 FilterRight.SetParameters(cutoff, resonance, pEngine->SampleRate);
600
601 FilterUpdateCounter = -1;
602 }
603 else {
604 VCFCutoffCtrl.controller = 0;
605 VCFResonanceCtrl.controller = 0;
606 }
607 #endif // ENABLE_FILTER
608
609 return 0; // success
610 }
611
612 /**
613 * Renders the audio data for this voice for the current audio fragment.
614 * The sample input data can either come from RAM (cached sample or sample
615 * part) or directly from disk. The output signal will be rendered by
616 * resampling / interpolation. If this voice is a disk streaming voice and
617 * the voice completely played back the cached RAM part of the sample, it
618 * will automatically switch to disk playback for the next RenderAudio()
619 * call.
620 *
621 * @param Samples - number of samples to be rendered in this audio fragment cycle
622 */
623 void Voice::Render(uint Samples) {
624
625 // Reset the synthesis parameter matrix
626 pEngine->ResetSynthesisParameters(Event::destination_vca, this->Volume * this->CrossfadeVolume * pEngine->GlobalVolume);
627 pEngine->ResetSynthesisParameters(Event::destination_vco, this->PitchBase);
628 #if ENABLE_FILTER
629 pEngine->ResetSynthesisParameters(Event::destination_vcfc, VCFCutoffCtrl.fvalue);
630 pEngine->ResetSynthesisParameters(Event::destination_vcfr, VCFResonanceCtrl.fvalue);
631 #endif // ENABLE_FILTER
632
633
634 // Apply events to the synthesis parameter matrix
635 ProcessEvents(Samples);
636
637
638 // Let all modulators write their parameter changes to the synthesis parameter matrix for the current audio fragment
639 pEG1->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, pTriggerEvent, this->Pos, this->PitchBase * this->PitchBend, pKillEvent);
640 #if ENABLE_FILTER
641 pEG2->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, pTriggerEvent, this->Pos, this->PitchBase * this->PitchBend);
642 #endif // ENABLE_FILTER
643 pEG3->Process(Samples);
644 pLFO1->Process(Samples);
645 #if ENABLE_FILTER
646 pLFO2->Process(Samples);
647 #endif // ENABLE_FILTER
648 pLFO3->Process(Samples);
649
650
651 #if ENABLE_FILTER
652 CalculateBiquadParameters(Samples); // calculate the final biquad filter parameters
653 #endif // ENABLE_FILTER
654
655
656 switch (this->PlaybackState) {
657
658 case playback_state_ram: {
659 if (RAMLoop) InterpolateAndLoop(Samples, (sample_t*) pSample->GetCache().pStart, Delay);
660 else Interpolate(Samples, (sample_t*) pSample->GetCache().pStart, Delay);
661 if (DiskVoice) {
662 // check if we reached the allowed limit of the sample RAM cache
663 if (Pos > MaxRAMPos) {
664 dmsg(5,("Voice: switching to disk playback (Pos=%f)\n", Pos));
665 this->PlaybackState = playback_state_disk;
666 }
667 }
668 else if (Pos >= pSample->GetCache().Size / pSample->FrameSize) {
669 this->PlaybackState = playback_state_end;
670 }
671 }
672 break;
673
674 case playback_state_disk: {
675 if (!DiskStreamRef.pStream) {
676 // check if the disk thread created our ordered disk stream in the meantime
677 DiskStreamRef.pStream = pDiskThread->AskForCreatedStream(DiskStreamRef.OrderID);
678 if (!DiskStreamRef.pStream) {
679 std::cout << stderr << "Disk stream not available in time!" << std::endl << std::flush;
680 KillImmediately();
681 return;
682 }
683 DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (RTMath::DoubleToInt(Pos) - MaxRAMPos));
684 Pos -= RTMath::DoubleToInt(Pos);
685 }
686
687 // add silence sample at the end if we reached the end of the stream (for the interpolator)
688 if (DiskStreamRef.State == Stream::state_end && DiskStreamRef.pStream->GetReadSpace() < (pEngine->MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels) {
689 DiskStreamRef.pStream->WriteSilence((pEngine->MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels);
690 this->PlaybackState = playback_state_end;
691 }
692
693 sample_t* ptr = DiskStreamRef.pStream->GetReadPtr(); // get the current read_ptr within the ringbuffer where we read the samples from
694 Interpolate(Samples, ptr, Delay);
695 DiskStreamRef.pStream->IncrementReadPos(RTMath::DoubleToInt(Pos) * pSample->Channels);
696 Pos -= RTMath::DoubleToInt(Pos);
697 }
698 break;
699
700 case playback_state_end:
701 KillImmediately(); // free voice
702 break;
703 }
704
705
706 // Reset synthesis event lists (except VCO, as VCO events apply channel wide currently)
707 pEngine->pSynthesisEvents[Event::destination_vca]->clear();
708 #if ENABLE_FILTER
709 pEngine->pSynthesisEvents[Event::destination_vcfc]->clear();
710 pEngine->pSynthesisEvents[Event::destination_vcfr]->clear();
711 #endif // ENABLE_FILTER
712
713 // Reset delay
714 Delay = 0;
715
716 pTriggerEvent = NULL;
717
718 // If release stage finished, let the voice be killed
719 if (pEG1->GetStage() == EGADSR::stage_end) this->PlaybackState = playback_state_end;
720 }
721
722 /**
723 * Resets voice variables. Should only be called if rendering process is
724 * suspended / not running.
725 */
726 void Voice::Reset() {
727 pLFO1->Reset();
728 pLFO2->Reset();
729 pLFO3->Reset();
730 DiskStreamRef.pStream = NULL;
731 DiskStreamRef.hStream = 0;
732 DiskStreamRef.State = Stream::state_unused;
733 DiskStreamRef.OrderID = 0;
734 Active = false;
735 }
736
737 /**
738 * Process the control change event lists of the engine for the current
739 * audio fragment. Event values will be applied to the synthesis parameter
740 * matrix.
741 *
742 * @param Samples - number of samples to be rendered in this audio fragment cycle
743 */
744 void Voice::ProcessEvents(uint Samples) {
745
746 // dispatch control change events
747 Event* pCCEvent = pEngine->pCCEvents->first();
748 if (Delay) { // skip events that happened before this voice was triggered
749 while (pCCEvent && pCCEvent->FragmentPos() <= Delay) pCCEvent = pEngine->pCCEvents->next();
750 }
751 while (pCCEvent) {
752 if (pCCEvent->Controller) { // if valid MIDI controller
753 #if ENABLE_FILTER
754 if (pCCEvent->Controller == VCFCutoffCtrl.controller) {
755 pEngine->pSynthesisEvents[Event::destination_vcfc]->alloc_assign(*pCCEvent);
756 }
757 if (pCCEvent->Controller == VCFResonanceCtrl.controller) {
758 pEngine->pSynthesisEvents[Event::destination_vcfr]->alloc_assign(*pCCEvent);
759 }
760 #endif // ENABLE_FILTER
761 if (pCCEvent->Controller == pLFO1->ExtController) {
762 pLFO1->SendEvent(pCCEvent);
763 }
764 #if ENABLE_FILTER
765 if (pCCEvent->Controller == pLFO2->ExtController) {
766 pLFO2->SendEvent(pCCEvent);
767 }
768 #endif // ENABLE_FILTER
769 if (pCCEvent->Controller == pLFO3->ExtController) {
770 pLFO3->SendEvent(pCCEvent);
771 }
772 if (pDimRgn->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange &&
773 pCCEvent->Controller == pDimRgn->AttenuationController.controller_number) { // if crossfade event
774 pEngine->pSynthesisEvents[Event::destination_vca]->alloc_assign(*pCCEvent);
775 }
776 }
777
778 pCCEvent = pEngine->pCCEvents->next();
779 }
780
781
782 // process pitch events
783 {
784 RTEList<Event>* pVCOEventList = pEngine->pSynthesisEvents[Event::destination_vco];
785 Event* pVCOEvent = pVCOEventList->first();
786 if (Delay) { // skip events that happened before this voice was triggered
787 while (pVCOEvent && pVCOEvent->FragmentPos() <= Delay) pVCOEvent = pVCOEventList->next();
788 }
789 // apply old pitchbend value until first pitch event occurs
790 if (this->PitchBend != 1.0) {
791 uint end = (pVCOEvent) ? pVCOEvent->FragmentPos() : Samples;
792 for (uint i = Delay; i < end; i++) {
793 pEngine->pSynthesisParameters[Event::destination_vco][i] *= this->PitchBend;
794 }
795 }
796 float pitch;
797 while (pVCOEvent) {
798 Event* pNextVCOEvent = pVCOEventList->next();
799
800 // calculate the influence length of this event (in sample points)
801 uint end = (pNextVCOEvent) ? pNextVCOEvent->FragmentPos() : Samples;
802
803 pitch = RTMath::CentsToFreqRatio(((double) pVCOEvent->Pitch / 8192.0) * 200.0); // +-two semitones = +-200 cents
804
805 // apply pitch value to the pitch parameter sequence
806 for (uint i = pVCOEvent->FragmentPos(); i < end; i++) {
807 pEngine->pSynthesisParameters[Event::destination_vco][i] *= pitch;
808 }
809
810 pVCOEvent = pNextVCOEvent;
811 }
812 if (pVCOEventList->last()) this->PitchBend = pitch;
813 }
814
815 // process volume / attenuation events (TODO: we only handle and _expect_ crossfade events here ATM !)
816 {
817 RTEList<Event>* pVCAEventList = pEngine->pSynthesisEvents[Event::destination_vca];
818 Event* pVCAEvent = pVCAEventList->first();
819 if (Delay) { // skip events that happened before this voice was triggered
820 while (pVCAEvent && pVCAEvent->FragmentPos() <= Delay) pVCAEvent = pVCAEventList->next();
821 }
822 float crossfadevolume;
823 while (pVCAEvent) {
824 Event* pNextVCAEvent = pVCAEventList->next();
825
826 // calculate the influence length of this event (in sample points)
827 uint end = (pNextVCAEvent) ? pNextVCAEvent->FragmentPos() : Samples;
828
829 crossfadevolume = CrossfadeAttenuation(pVCAEvent->Value);
830
831 float effective_volume = crossfadevolume * this->Volume * pEngine->GlobalVolume;
832
833 // apply volume value to the volume parameter sequence
834 for (uint i = pVCAEvent->FragmentPos(); i < end; i++) {
835 pEngine->pSynthesisParameters[Event::destination_vca][i] = effective_volume;
836 }
837
838 pVCAEvent = pNextVCAEvent;
839 }
840 if (pVCAEventList->last()) this->CrossfadeVolume = crossfadevolume;
841 }
842
843 #if ENABLE_FILTER
844 // process filter cutoff events
845 {
846 RTEList<Event>* pCutoffEventList = pEngine->pSynthesisEvents[Event::destination_vcfc];
847 Event* pCutoffEvent = pCutoffEventList->first();
848 if (Delay) { // skip events that happened before this voice was triggered
849 while (pCutoffEvent && pCutoffEvent->FragmentPos() <= Delay) pCutoffEvent = pCutoffEventList->next();
850 }
851 float cutoff;
852 while (pCutoffEvent) {
853 Event* pNextCutoffEvent = pCutoffEventList->next();
854
855 // calculate the influence length of this event (in sample points)
856 uint end = (pNextCutoffEvent) ? pNextCutoffEvent->FragmentPos() : Samples;
857
858 cutoff = exp((float) pCutoffEvent->Value * 0.00787402f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX - FILTER_CUTOFF_MIN;
859
860 // apply cutoff frequency to the cutoff parameter sequence
861 for (uint i = pCutoffEvent->FragmentPos(); i < end; i++) {
862 pEngine->pSynthesisParameters[Event::destination_vcfc][i] = cutoff;
863 }
864
865 pCutoffEvent = pNextCutoffEvent;
866 }
867 if (pCutoffEventList->last()) VCFCutoffCtrl.fvalue = cutoff; // needed for initialization of parameter matrix next time
868 }
869
870 // process filter resonance events
871 {
872 RTEList<Event>* pResonanceEventList = pEngine->pSynthesisEvents[Event::destination_vcfr];
873 Event* pResonanceEvent = pResonanceEventList->first();
874 if (Delay) { // skip events that happened before this voice was triggered
875 while (pResonanceEvent && pResonanceEvent->FragmentPos() <= Delay) pResonanceEvent = pResonanceEventList->next();
876 }
877 while (pResonanceEvent) {
878 Event* pNextResonanceEvent = pResonanceEventList->next();
879
880 // calculate the influence length of this event (in sample points)
881 uint end = (pNextResonanceEvent) ? pNextResonanceEvent->FragmentPos() : Samples;
882
883 // convert absolute controller value to differential
884 int ctrldelta = pResonanceEvent->Value - VCFResonanceCtrl.value;
885 VCFResonanceCtrl.value = pResonanceEvent->Value;
886
887 float resonancedelta = (float) ctrldelta * 0.00787f; // 0.0..1.0
888
889 // apply cutoff frequency to the cutoff parameter sequence
890 for (uint i = pResonanceEvent->FragmentPos(); i < end; i++) {
891 pEngine->pSynthesisParameters[Event::destination_vcfr][i] += resonancedelta;
892 }
893
894 pResonanceEvent = pNextResonanceEvent;
895 }
896 if (pResonanceEventList->last()) VCFResonanceCtrl.fvalue = pResonanceEventList->last()->Value * 0.00787f; // needed for initialization of parameter matrix next time
897 }
898 #endif // ENABLE_FILTER
899 }
900
901 #if ENABLE_FILTER
902 /**
903 * Calculate all necessary, final biquad filter parameters.
904 *
905 * @param Samples - number of samples to be rendered in this audio fragment cycle
906 */
907 void Voice::CalculateBiquadParameters(uint Samples) {
908 if (!FilterLeft.Enabled) return;
909
910 biquad_param_t bqbase;
911 biquad_param_t bqmain;
912 float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0];
913 float prev_res = pEngine->pSynthesisParameters[Event::destination_vcfr][0];
914 FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);
915 pEngine->pBasicFilterParameters[0] = bqbase;
916 pEngine->pMainFilterParameters[0] = bqmain;
917
918 float* bq;
919 for (int i = 1; i < Samples; i++) {
920 // recalculate biquad parameters if cutoff or resonance differ from previous sample point
921 if (!(i & FILTER_UPDATE_MASK)) if (pEngine->pSynthesisParameters[Event::destination_vcfr][i] != prev_res ||
922 pEngine->pSynthesisParameters[Event::destination_vcfc][i] != prev_cutoff) {
923 prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][i];
924 prev_res = pEngine->pSynthesisParameters[Event::destination_vcfr][i];
925 FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);
926 }
927
928 //same as 'pEngine->pBasicFilterParameters[i] = bqbase;'
929 bq = (float*) &pEngine->pBasicFilterParameters[i];
930 bq[0] = bqbase.a1;
931 bq[1] = bqbase.a2;
932 bq[2] = bqbase.b0;
933 bq[3] = bqbase.b1;
934 bq[4] = bqbase.b2;
935
936 // same as 'pEngine->pMainFilterParameters[i] = bqmain;'
937 bq = (float*) &pEngine->pMainFilterParameters[i];
938 bq[0] = bqmain.a1;
939 bq[1] = bqmain.a2;
940 bq[2] = bqmain.b0;
941 bq[3] = bqmain.b1;
942 bq[4] = bqmain.b2;
943 }
944 }
945 #endif // ENABLE_FILTER
946
947 /**
948 * Interpolates the input audio data (no loop).
949 *
950 * @param Samples - number of sample points to be rendered in this audio
951 * fragment cycle
952 * @param pSrc - pointer to input sample data
953 * @param Skip - number of sample points to skip in output buffer
954 */
955 void Voice::Interpolate(uint Samples, sample_t* pSrc, uint Skip) {
956 int i = Skip;
957
958 // FIXME: assuming either mono or stereo
959 if (this->pSample->Channels == 2) { // Stereo Sample
960 while (i < Samples) {
961 InterpolateOneStep_Stereo(pSrc, i,
962 pEngine->pSynthesisParameters[Event::destination_vca][i],
963 pEngine->pSynthesisParameters[Event::destination_vco][i],
964 pEngine->pBasicFilterParameters[i],
965 pEngine->pMainFilterParameters[i]);
966 }
967 }
968 else { // Mono Sample
969 while (i < Samples) {
970 InterpolateOneStep_Mono(pSrc, i,
971 pEngine->pSynthesisParameters[Event::destination_vca][i],
972 pEngine->pSynthesisParameters[Event::destination_vco][i],
973 pEngine->pBasicFilterParameters[i],
974 pEngine->pMainFilterParameters[i]);
975 }
976 }
977 }
978
979 /**
980 * Interpolates the input audio data, this method honors looping.
981 *
982 * @param Samples - number of sample points to be rendered in this audio
983 * fragment cycle
984 * @param pSrc - pointer to input sample data
985 * @param Skip - number of sample points to skip in output buffer
986 */
987 void Voice::InterpolateAndLoop(uint Samples, sample_t* pSrc, uint Skip) {
988 int i = Skip;
989
990 // FIXME: assuming either mono or stereo
991 if (pSample->Channels == 2) { // Stereo Sample
992 if (pSample->LoopPlayCount) {
993 // render loop (loop count limited)
994 while (i < Samples && LoopCyclesLeft) {
995 InterpolateOneStep_Stereo(pSrc, i,
996 pEngine->pSynthesisParameters[Event::destination_vca][i],
997 pEngine->pSynthesisParameters[Event::destination_vco][i],
998 pEngine->pBasicFilterParameters[i],
999 pEngine->pMainFilterParameters[i]);
1000 if (Pos > pSample->LoopEnd) {
1001 Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;
1002 LoopCyclesLeft--;
1003 }
1004 }
1005 // render on without loop
1006 while (i < Samples) {
1007 InterpolateOneStep_Stereo(pSrc, i,
1008 pEngine->pSynthesisParameters[Event::destination_vca][i],
1009 pEngine->pSynthesisParameters[Event::destination_vco][i],
1010 pEngine->pBasicFilterParameters[i],
1011 pEngine->pMainFilterParameters[i]);
1012 }
1013 }
1014 else { // render loop (endless loop)
1015 while (i < Samples) {
1016 InterpolateOneStep_Stereo(pSrc, i,
1017 pEngine->pSynthesisParameters[Event::destination_vca][i],
1018 pEngine->pSynthesisParameters[Event::destination_vco][i],
1019 pEngine->pBasicFilterParameters[i],
1020 pEngine->pMainFilterParameters[i]);
1021 if (Pos > pSample->LoopEnd) {
1022 Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);
1023 }
1024 }
1025 }
1026 }
1027 else { // Mono Sample
1028 if (pSample->LoopPlayCount) {
1029 // render loop (loop count limited)
1030 while (i < Samples && LoopCyclesLeft) {
1031 InterpolateOneStep_Mono(pSrc, i,
1032 pEngine->pSynthesisParameters[Event::destination_vca][i],
1033 pEngine->pSynthesisParameters[Event::destination_vco][i],
1034 pEngine->pBasicFilterParameters[i],
1035 pEngine->pMainFilterParameters[i]);
1036 if (Pos > pSample->LoopEnd) {
1037 Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;
1038 LoopCyclesLeft--;
1039 }
1040 }
1041 // render on without loop
1042 while (i < Samples) {
1043 InterpolateOneStep_Mono(pSrc, i,
1044 pEngine->pSynthesisParameters[Event::destination_vca][i],
1045 pEngine->pSynthesisParameters[Event::destination_vco][i],
1046 pEngine->pBasicFilterParameters[i],
1047 pEngine->pMainFilterParameters[i]);
1048 }
1049 }
1050 else { // render loop (endless loop)
1051 while (i < Samples) {
1052 InterpolateOneStep_Mono(pSrc, i,
1053 pEngine->pSynthesisParameters[Event::destination_vca][i],
1054 pEngine->pSynthesisParameters[Event::destination_vco][i],
1055 pEngine->pBasicFilterParameters[i],
1056 pEngine->pMainFilterParameters[i]);
1057 if (Pos > pSample->LoopEnd) {
1058 Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;
1059 }
1060 }
1061 }
1062 }
1063 }
1064
1065 /**
1066 * Immediately kill the voice. This method should not be used to kill
1067 * a normal, active voice, because it doesn't take care of things like
1068 * fading down the volume level to avoid clicks and regular processing
1069 * until the kill event actually occured!
1070 *
1071 * @see Kill()
1072 */
1073 void Voice::KillImmediately() {
1074 if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {
1075 pDiskThread->OrderDeletionOfStream(&DiskStreamRef);
1076 }
1077 Reset();
1078 }
1079
1080 /**
1081 * Kill the voice in regular sense. Let the voice render audio until
1082 * the kill event actually occured and then fade down the volume level
1083 * very quickly and let the voice die finally. Unlike a normal release
1084 * of a voice, a kill process cannot be cancalled and is therefore
1085 * usually used for voice stealing and key group conflicts.
1086 *
1087 * @param pKillEvent - event which caused the voice to be killed
1088 */
1089 void Voice::Kill(Event* pKillEvent) {
1090 if (pTriggerEvent && pKillEvent->FragmentPos() <= pTriggerEvent->FragmentPos()) return;
1091 this->pKillEvent = pKillEvent;
1092 }
1093
1094 }} // namespace LinuxSampler::gig

  ViewVC Help
Powered by ViewVC