/[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 236 - (show annotations) (download)
Thu Sep 9 18:44:18 2004 UTC (19 years, 6 months ago) by schoenebeck
File size: 51184 byte(s)
* added support for crossfades
* support sample playback start offset

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

  ViewVC Help
Powered by ViewVC