/[svn]/linuxsampler/trunk/src/voice.cpp
ViewVC logotype

Contents of /linuxsampler/trunk/src/voice.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 39 - (show annotations) (download)
Sun Mar 21 16:09:43 2004 UTC (20 years, 1 month ago) by schoenebeck
File size: 35452 byte(s)
* implemented all three low frequency oscillators (LFO1 = volume,
  LFO2 = filter cutoff frequency, LFO3 = pitch) for accurate .gig playback

1 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003 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 "voice.h"
24
25 // FIXME: no support for layers (nor crossfades) yet
26
27 DiskThread* Voice::pDiskThread = NULL;
28 AudioThread* Voice::pEngine = NULL;
29
30 Voice::Voice() {
31 Active = false;
32 pLFO1 = new LFO(ModulationSystem::destination_vca, LFO::manipulation_type_multiply, 0.0f, 1.0f, LFO::propagation_top_down, pEngine->pEventPool);
33 pLFO2 = new LFO(ModulationSystem::destination_vcfc, LFO::manipulation_type_multiply, 0.0f, 1.0f, LFO::propagation_top_down, pEngine->pEventPool);
34 pLFO3 = new LFO(ModulationSystem::destination_vco, LFO::manipulation_type_add, -1.0f, 1.0f, LFO::propagation_middle_balanced, pEngine->pEventPool);
35 }
36
37 Voice::~Voice() {
38 if (pLFO1) delete pLFO1;
39 if (pLFO2) delete pLFO2;
40 if (pLFO3) delete pLFO3;
41 }
42
43 /**
44 * Initializes and triggers the voice, a disk stream will be launched if
45 * needed.
46 *
47 * @param pNoteOnEvent - event that caused triggering of this voice
48 * @param Pitch - MIDI detune factor (-8192 ... +8191)
49 * @param pInstrument - points to the loaded instrument which provides sample wave(s) and articulation data
50 * @returns 0 on success, a value < 0 if something failed
51 */
52 int Voice::Trigger(ModulationSystem::Event* pNoteOnEvent, int Pitch, gig::Instrument* pInstrument) {
53 Active = true;
54 MIDIKey = pNoteOnEvent->Key;
55 pRegion = pInstrument->GetRegion(MIDIKey);
56 PlaybackState = playback_state_ram; // we always start playback from RAM cache and switch then to disk if needed
57 Pos = 0;
58 ReleaseVelocity = 127; // default release velocity value
59 Delay = pNoteOnEvent->FragmentPos();
60 pTriggerEvent = pNoteOnEvent;
61
62 if (!pRegion) {
63 std::cerr << "Audio Thread: No Region defined for MIDI key " << MIDIKey << std::endl << std::flush;
64 Kill();
65 return -1;
66 }
67
68 //TODO: current MIDI controller values are not taken into account yet
69 gig::DimensionRegion* pDimRgn = NULL;
70 for (int i = pRegion->Dimensions - 1; i >= 0; i--) { // Check if instrument has a velocity split
71 if (pRegion->pDimensionDefinitions[i].dimension == gig::dimension_velocity) {
72 uint DimValues[5] = {0,0,0,0,0};
73 DimValues[i] = pNoteOnEvent->Velocity;
74 pDimRgn = pRegion->GetDimensionRegionByValue(DimValues[4],DimValues[3],DimValues[2],DimValues[1],DimValues[0]);
75 break;
76 }
77 }
78 if (!pDimRgn) { // if there was no velocity split
79 pDimRgn = pRegion->GetDimensionRegionByValue(0,0,0,0,0);
80 }
81
82 pSample = pDimRgn->pSample; // sample won't change until the voice is finished
83
84 // Check if the sample needs disk streaming or is too short for that
85 long cachedsamples = pSample->GetCache().Size / pSample->FrameSize;
86 DiskVoice = cachedsamples < pSample->SamplesTotal;
87
88 if (DiskVoice) { // voice to be streamed from disk
89 MaxRAMPos = cachedsamples - (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)
90
91 // check if there's a loop defined which completely fits into the cached (RAM) part of the sample
92 if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) {
93 RAMLoop = true;
94 LoopCyclesLeft = pSample->LoopPlayCount;
95 }
96 else RAMLoop = false;
97
98 if (pDiskThread->OrderNewStream(&DiskStreamRef, pSample, MaxRAMPos, !RAMLoop) < 0) {
99 dmsg(1,("Disk stream order failed!\n"));
100 Kill();
101 return -1;
102 }
103 dmsg(4,("Disk voice launched (cached samples: %d, total Samples: %d, MaxRAMPos: %d, RAMLooping: %s)\n", cachedsamples, pSample->SamplesTotal, MaxRAMPos, (RAMLoop) ? "yes" : "no"));
104 }
105 else { // RAM only voice
106 MaxRAMPos = cachedsamples;
107 if (pSample->Loops) {
108 RAMLoop = true;
109 LoopCyclesLeft = pSample->LoopPlayCount;
110 }
111 else RAMLoop = false;
112 dmsg(4,("RAM only voice launched (Looping: %s)\n", (RAMLoop) ? "yes" : "no"));
113 }
114
115
116 // Pitch according to keyboard position (if 'PitchTrack' is set) and given detune factor
117 this->Pitch = ((double) Pitch / 8192.0) / 12.0 + ((pDimRgn->PitchTrack) ? pow(2, ((double) (MIDIKey - (int) pDimRgn->UnityNote) + (double) pDimRgn->FineTune / 100.0) / 12.0)
118 : pow(2, ((double) pDimRgn->FineTune / 100.0) / 12.0));
119
120 Volume = pDimRgn->GetVelocityAttenuation(pNoteOnEvent->Velocity);
121
122 // get current value of EG1 controller
123 double eg1controllervalue;
124 switch (pDimRgn->EG1Controller.type) {
125 case gig::eg1_ctrl_t::type_none: // no controller defined
126 eg1controllervalue = 0;
127 break;
128 case gig::eg1_ctrl_t::type_channelaftertouch:
129 eg1controllervalue = 0; // TODO: aftertouch not yet supported
130 break;
131 case gig::eg1_ctrl_t::type_velocity:
132 eg1controllervalue = pNoteOnEvent->Velocity;
133 break;
134 case gig::eg1_ctrl_t::type_controlchange: // MIDI control change controller
135 eg1controllervalue = pEngine->ControllerTable[pDimRgn->EG1Controller.controller_number];
136 break;
137 }
138 if (pDimRgn->EG1ControllerInvert) eg1controllervalue = 127 - eg1controllervalue;
139
140 // calculate influence of EG1 controller on EG1's parameters (TODO: needs to be fine tuned)
141 double eg1attack = (pDimRgn->EG1ControllerAttackInfluence) ? 0.0001 * (double) (1 << pDimRgn->EG1ControllerAttackInfluence) * eg1controllervalue : 0.0;
142 double eg1decay = (pDimRgn->EG1ControllerDecayInfluence) ? 0.0001 * (double) (1 << pDimRgn->EG1ControllerDecayInfluence) * eg1controllervalue : 0.0;
143 double eg1release = (pDimRgn->EG1ControllerReleaseInfluence) ? 0.0001 * (double) (1 << pDimRgn->EG1ControllerReleaseInfluence) * eg1controllervalue : 0.0;
144
145 EG1.Trigger(pDimRgn->EG1PreAttack,
146 pDimRgn->EG1Attack + eg1attack,
147 pDimRgn->EG1Hold,
148 pSample->LoopStart,
149 pDimRgn->EG1Decay1 + eg1decay,
150 pDimRgn->EG1Decay2 + eg1decay,
151 pDimRgn->EG1InfiniteSustain,
152 pDimRgn->EG1Sustain,
153 pDimRgn->EG1Release + eg1release,
154 Delay);
155
156 // setup LFO 1 (VCA LFO)
157 {
158 uint16_t lfo1_internal_depth;
159 switch (pDimRgn->LFO1Controller) {
160 case gig::lfo1_ctrl_internal:
161 lfo1_internal_depth = pDimRgn->LFO1InternalDepth;
162 pLFO1->ExtController = 0; // no external controller
163 break;
164 case gig::lfo1_ctrl_modwheel:
165 lfo1_internal_depth = 0;
166 pLFO1->ExtController = 1; // MIDI controller 1
167 break;
168 case gig::lfo1_ctrl_breath:
169 lfo1_internal_depth = 0;
170 pLFO1->ExtController = 2; // MIDI controller 2
171 break;
172 case gig::lfo1_ctrl_internal_modwheel:
173 lfo1_internal_depth = pDimRgn->LFO1InternalDepth;
174 pLFO1->ExtController = 1; // MIDI controller 1
175 break;
176 case gig::lfo1_ctrl_internal_breath:
177 lfo1_internal_depth = pDimRgn->LFO1InternalDepth;
178 pLFO1->ExtController = 2; // MIDI controller 2
179 break;
180 default:
181 lfo1_internal_depth = 0;
182 pLFO1->ExtController = 0; // no external controller
183 }
184 pLFO1->Trigger(pDimRgn->LFO1Frequency,
185 lfo1_internal_depth,
186 pDimRgn->LFO1ControlDepth,
187 pEngine->ControllerTable[pLFO1->ExtController],
188 pDimRgn->LFO1FlipPhase,
189 Delay);
190 }
191
192 #if ENABLE_FILTER
193 // setup LFO 2 (VCF Cutoff LFO)
194 {
195 uint16_t lfo2_internal_depth;
196 switch (pDimRgn->LFO2Controller) {
197 case gig::lfo2_ctrl_internal:
198 lfo2_internal_depth = pDimRgn->LFO2InternalDepth;
199 pLFO2->ExtController = 0; // no external controller
200 break;
201 case gig::lfo2_ctrl_modwheel:
202 lfo2_internal_depth = 0;
203 pLFO2->ExtController = 1; // MIDI controller 1
204 break;
205 case gig::lfo2_ctrl_foot:
206 lfo2_internal_depth = 0;
207 pLFO2->ExtController = 4; // MIDI controller 4
208 break;
209 case gig::lfo2_ctrl_internal_modwheel:
210 lfo2_internal_depth = pDimRgn->LFO2InternalDepth;
211 pLFO2->ExtController = 1; // MIDI controller 1
212 break;
213 case gig::lfo2_ctrl_internal_foot:
214 lfo2_internal_depth = pDimRgn->LFO2InternalDepth;
215 pLFO2->ExtController = 4; // MIDI controller 4
216 break;
217 default:
218 lfo2_internal_depth = 0;
219 pLFO2->ExtController = 0; // no external controller
220 }
221 pLFO2->Trigger(pDimRgn->LFO2Frequency,
222 lfo2_internal_depth,
223 pDimRgn->LFO2ControlDepth,
224 pEngine->ControllerTable[pLFO2->ExtController],
225 pDimRgn->LFO2FlipPhase,
226 Delay);
227 }
228 #endif // ENABLE_FILTER
229
230 // setup LFO 3 (VCO LFO)
231 {
232 uint16_t lfo3_internal_depth;
233 switch (pDimRgn->LFO3Controller) {
234 case gig::lfo3_ctrl_internal:
235 lfo3_internal_depth = pDimRgn->LFO3InternalDepth;
236 pLFO3->ExtController = 0; // no external controller
237 break;
238 case gig::lfo3_ctrl_modwheel:
239 lfo3_internal_depth = 0;
240 pLFO3->ExtController = 1; // MIDI controller 1
241 break;
242 case gig::lfo3_ctrl_aftertouch:
243 lfo3_internal_depth = 0;
244 pLFO3->ExtController = 0; // TODO: aftertouch not implemented yet
245 break;
246 case gig::lfo3_ctrl_internal_modwheel:
247 lfo3_internal_depth = pDimRgn->LFO3InternalDepth;
248 pLFO3->ExtController = 1; // MIDI controller 1
249 break;
250 case gig::lfo3_ctrl_internal_aftertouch:
251 lfo3_internal_depth = pDimRgn->LFO3InternalDepth;
252 pLFO1->ExtController = 0; // TODO: aftertouch not implemented yet
253 break;
254 default:
255 lfo3_internal_depth = 0;
256 pLFO3->ExtController = 0; // no external controller
257 }
258 pLFO3->Trigger(pDimRgn->LFO3Frequency,
259 lfo3_internal_depth,
260 pDimRgn->LFO3ControlDepth,
261 pEngine->ControllerTable[pLFO3->ExtController],
262 false,
263 Delay);
264 }
265
266 #if ENABLE_FILTER
267 #if FORCE_FILTER_USAGE
268 FilterLeft.Enabled = FilterRight.Enabled = true;
269 #else // use filter only if instrument file told so
270 FilterLeft.Enabled = FilterRight.Enabled = pDimRgn->VCFEnabled;
271 #endif // FORCE_FILTER_USAGE
272 if (pDimRgn->VCFEnabled) {
273 #ifdef OVERRIDE_FILTER_CUTOFF_CTRL
274 VCFCutoffCtrl.controller = OVERRIDE_FILTER_CUTOFF_CTRL;
275 #else // use the one defined in the instrument file
276 switch (pDimRgn->VCFCutoffController) {
277 case gig::vcf_cutoff_ctrl_modwheel:
278 VCFCutoffCtrl.controller = 1;
279 break;
280 case gig::vcf_cutoff_ctrl_effect1:
281 VCFCutoffCtrl.controller = 12;
282 break;
283 case gig::vcf_cutoff_ctrl_effect2:
284 VCFCutoffCtrl.controller = 13;
285 break;
286 case gig::vcf_cutoff_ctrl_breath:
287 VCFCutoffCtrl.controller = 2;
288 break;
289 case gig::vcf_cutoff_ctrl_foot:
290 VCFCutoffCtrl.controller = 4;
291 break;
292 case gig::vcf_cutoff_ctrl_sustainpedal:
293 VCFCutoffCtrl.controller = 64;
294 break;
295 case gig::vcf_cutoff_ctrl_softpedal:
296 VCFCutoffCtrl.controller = 67;
297 break;
298 case gig::vcf_cutoff_ctrl_genpurpose7:
299 VCFCutoffCtrl.controller = 82;
300 break;
301 case gig::vcf_cutoff_ctrl_genpurpose8:
302 VCFCutoffCtrl.controller = 83;
303 break;
304 case gig::vcf_cutoff_ctrl_aftertouch: //TODO: not implemented yet
305 case gig::vcf_cutoff_ctrl_none:
306 default:
307 VCFCutoffCtrl.controller = 0;
308 break;
309 }
310 #endif // OVERRIDE_FILTER_CUTOFF_CTRL
311
312 #ifdef OVERRIDE_FILTER_RES_CTRL
313 VCFResonanceCtrl.controller = OVERRIDE_FILTER_RES_CTRL;
314 #else // use the one defined in the instrument file
315 switch (pDimRgn->VCFResonanceController) {
316 case gig::vcf_res_ctrl_genpurpose3:
317 VCFResonanceCtrl.controller = 18;
318 break;
319 case gig::vcf_res_ctrl_genpurpose4:
320 VCFResonanceCtrl.controller = 19;
321 break;
322 case gig::vcf_res_ctrl_genpurpose5:
323 VCFResonanceCtrl.controller = 80;
324 break;
325 case gig::vcf_res_ctrl_genpurpose6:
326 VCFResonanceCtrl.controller = 81;
327 break;
328 case gig::vcf_res_ctrl_none:
329 default:
330 VCFResonanceCtrl.controller = 0;
331 }
332 #endif // OVERRIDE_FILTER_RES_CTRL
333
334 #ifndef OVERRIDE_FILTER_TYPE
335 FilterLeft.SetType(pDimRgn->VCFType);
336 FilterRight.SetType(pDimRgn->VCFType);
337 #else // override filter type
338 FilterLeft.SetType(OVERRIDE_FILTER_TYPE);
339 FilterRight.SetType(OVERRIDE_FILTER_TYPE);
340 #endif // OVERRIDE_FILTER_TYPE
341
342 VCFCutoffCtrl.value = pEngine->ControllerTable[VCFCutoffCtrl.controller];
343 VCFResonanceCtrl.value = pEngine->ControllerTable[VCFResonanceCtrl.controller];
344
345 // calculate cutoff frequency
346 float cutoff = (!VCFCutoffCtrl.controller && pDimRgn->VCFVelocityScale)
347 ? (float) pNoteOnEvent->Velocity * pDimRgn->VCFVelocityScale * 0.31f // up to 5kHz
348 : (float) (127 - VCFCutoffCtrl.value) * 39.4f; // up to 5kHz (inverted)
349
350 // calculate resonance
351 float resonance = (float) VCFResonanceCtrl.value * 0.00787f; // 0.0..1.0
352 if (pDimRgn->VCFKeyboardTracking) {
353 resonance += (float) (pNoteOnEvent->Key - pDimRgn->VCFKeyboardTrackingBreakpoint) * 0.00787f;
354 }
355 Constrain(resonance, 0.0, 1.0); // correct resonance if outside allowed value range (0.0..1.0)
356
357 VCFCutoffCtrl.fvalue = cutoff;
358 VCFResonanceCtrl.fvalue = resonance;
359
360 FilterLeft.SetParameters(cutoff + 20.0f, resonance, ModulationSystem::SampleRate()); // 20Hz min.
361 FilterRight.SetParameters(cutoff + 20.0f, resonance, ModulationSystem::SampleRate()); // 20Hz min.
362 }
363 else {
364 VCFCutoffCtrl.controller = 0;
365 VCFResonanceCtrl.controller = 0;
366 }
367 #endif // ENABLE_FILTER
368
369 // ************************************************
370 // TODO: ARTICULATION DATA HANDLING IS MISSING HERE
371 // ************************************************
372
373 return 0; // success
374 }
375
376 /**
377 * Renders the audio data for this voice for the current audio fragment.
378 * The sample input data can either come from RAM (cached sample or sample
379 * part) or directly from disk. The output signal will be rendered by
380 * resampling / interpolation. If this voice is a disk streaming voice and
381 * the voice completely played back the cached RAM part of the sample, it
382 * will automatically switch to disk playback for the next RenderAudio()
383 * call.
384 *
385 * @param Samples - number of samples to be rendered in this audio fragment cycle
386 */
387 void Voice::Render(uint Samples) {
388
389 // Reset the synthesis parameter matrix
390 ModulationSystem::ResetDestinationParameter(ModulationSystem::destination_vca, this->Volume);
391 ModulationSystem::ResetDestinationParameter(ModulationSystem::destination_vco, this->Pitch);
392 #if ENABLE_FILTER
393 ModulationSystem::ResetDestinationParameter(ModulationSystem::destination_vcfc, VCFCutoffCtrl.fvalue);
394 ModulationSystem::ResetDestinationParameter(ModulationSystem::destination_vcfr, VCFResonanceCtrl.fvalue);
395 #endif // ENABLE_FILTER
396
397
398 // Apply events to the synthesis parameter matrix
399 ProcessEvents(Samples);
400
401
402 // Let all modulators write their parameter changes to the synthesis parameter matrix for the current audio fragment
403 EG1.Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, pTriggerEvent, this->Pos, this->Pitch);
404 pLFO1->Process(Samples);
405 #if ENABLE_FILTER
406 pLFO2->Process(Samples);
407 #endif // ENABLE_FILTER
408 pLFO3->Process(Samples);
409
410
411 switch (this->PlaybackState) {
412
413 case playback_state_ram: {
414 if (RAMLoop) InterpolateAndLoop(Samples, (sample_t*) pSample->GetCache().pStart, Delay);
415 else Interpolate(Samples, (sample_t*) pSample->GetCache().pStart, Delay);
416 if (DiskVoice) {
417 // check if we reached the allowed limit of the sample RAM cache
418 if (Pos > MaxRAMPos) {
419 dmsg(5,("Voice: switching to disk playback (Pos=%f)\n", Pos));
420 this->PlaybackState = playback_state_disk;
421 }
422 }
423 else if (Pos >= pSample->GetCache().Size / pSample->FrameSize) {
424 this->PlaybackState = playback_state_end;
425 }
426 }
427 break;
428
429 case playback_state_disk: {
430 if (!DiskStreamRef.pStream) {
431 // check if the disk thread created our ordered disk stream in the meantime
432 DiskStreamRef.pStream = pDiskThread->AskForCreatedStream(DiskStreamRef.OrderID);
433 if (!DiskStreamRef.pStream) {
434 std::cout << stderr << "Disk stream not available in time!" << std::endl << std::flush;
435 Kill();
436 return;
437 }
438 DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (double_to_int(Pos) - MaxRAMPos));
439 Pos -= double_to_int(Pos);
440 }
441
442 // add silence sample at the end if we reached the end of the stream (for the interpolator)
443 if (DiskStreamRef.State == Stream::state_end && DiskStreamRef.pStream->GetReadSpace() < (MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels) {
444 DiskStreamRef.pStream->WriteSilence((MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels);
445 this->PlaybackState = playback_state_end;
446 }
447
448 sample_t* ptr = DiskStreamRef.pStream->GetReadPtr(); // get the current read_ptr within the ringbuffer where we read the samples from
449 Interpolate(Samples, ptr, Delay);
450 DiskStreamRef.pStream->IncrementReadPos(double_to_int(Pos) * pSample->Channels);
451 Pos -= double_to_int(Pos);
452 }
453 break;
454
455 case playback_state_end:
456 Kill(); // free voice
457 break;
458 }
459
460
461 #if ENABLE_FILTER
462 // Reset synthesis event lists (except VCO, as VCO events apply channel wide currently)
463 pEngine->pSynthesisEvents[ModulationSystem::destination_vcfc]->clear();
464 pEngine->pSynthesisEvents[ModulationSystem::destination_vcfr]->clear();
465 #endif // ENABLE_FILTER
466
467 // Reset delay
468 Delay = 0;
469
470 pTriggerEvent = NULL;
471
472 // If release stage finished, let the voice be killed
473 if (EG1.GetStage() == EG_VCA::stage_end) this->PlaybackState = playback_state_end;
474 }
475
476 /**
477 * Resets voice variables. Should only be called if rendering process is
478 * suspended / not running.
479 */
480 void Voice::Reset() {
481 pLFO1->Reset();
482 pLFO2->Reset();
483 pLFO3->Reset();
484 DiskStreamRef.pStream = NULL;
485 DiskStreamRef.hStream = 0;
486 DiskStreamRef.State = Stream::state_unused;
487 DiskStreamRef.OrderID = 0;
488 Active = false;
489 }
490
491 /**
492 * Process the control change event lists of the engine for the current
493 * audio fragment. Event values will be applied to the synthesis parameter
494 * matrix.
495 *
496 * @param Samples - number of samples to be rendered in this audio fragment cycle
497 */
498 void Voice::ProcessEvents(uint Samples) {
499
500 // dispatch control change events
501 ModulationSystem::Event* pCCEvent = pEngine->pCCEvents->first();
502 while (pCCEvent) {
503 if (pCCEvent->Controller) { // if valid MIDI controller
504 #if ENABLE_FILTER
505 if (pCCEvent->Controller == VCFCutoffCtrl.controller) {
506 pEngine->pSynthesisEvents[ModulationSystem::destination_vcfc]->alloc_assign(*pCCEvent);
507 }
508 if (pCCEvent->Controller == VCFResonanceCtrl.controller) {
509 pEngine->pSynthesisEvents[ModulationSystem::destination_vcfr]->alloc_assign(*pCCEvent);
510 }
511 #endif // ENABLE_FILTER
512 if (pCCEvent->Controller == pLFO1->ExtController) {
513 pLFO1->SendEvent(pCCEvent);
514 }
515 #if ENABLE_FILTER
516 if (pCCEvent->Controller == pLFO2->ExtController) {
517 pLFO2->SendEvent(pCCEvent);
518 }
519 #endif // ENABLE_FILTER
520 if (pCCEvent->Controller == pLFO3->ExtController) {
521 pLFO3->SendEvent(pCCEvent);
522 }
523 }
524
525 pCCEvent = pEngine->pCCEvents->next();
526 }
527
528 // process pitch events
529 RTEList<ModulationSystem::Event>* pVCOEventList = pEngine->pSynthesisEvents[ModulationSystem::destination_vco];
530 ModulationSystem::Event* pVCOEvent = pVCOEventList->first();
531 while (pVCOEvent) {
532 ModulationSystem::Event* pNextVCOEvent = pVCOEventList->next();
533
534 // calculate the influence length of this event (in sample points)
535 uint end = (pNextVCOEvent) ? pNextVCOEvent->FragmentPos() : Samples;
536
537 this->Pitch += ((double) pVCOEvent->Pitch / 8192.0) / 12.0; // +- one semitone
538
539 // apply pitch value to the pitch parameter sequence
540 for (uint i = pVCOEvent->FragmentPos(); i < end; i++) {
541 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vco][i] = this->Pitch;
542 }
543
544 pVCOEvent = pNextVCOEvent;
545 }
546
547 #if ENABLE_FILTER
548 // process filter cutoff events
549 RTEList<ModulationSystem::Event>* pCutoffEventList = pEngine->pSynthesisEvents[ModulationSystem::destination_vcfc];
550 ModulationSystem::Event* pCutoffEvent = pCutoffEventList->first();
551 while (pCutoffEvent) {
552 ModulationSystem::Event* pNextCutoffEvent = pCutoffEventList->next();
553
554 // calculate the influence length of this event (in sample points)
555 uint end = (pNextCutoffEvent) ? pNextCutoffEvent->FragmentPos() : Samples;
556
557 // convert absolute controller value to differential
558 int ctrldelta = pCutoffEvent->Value - VCFCutoffCtrl.value;
559 VCFCutoffCtrl.value = pCutoffEvent->Value;
560
561 float cutoffdelta = (float) ctrldelta * -39.4f; // (20Hz)..5kHz (inverted)
562
563 // apply cutoff frequency to the cutoff parameter sequence
564 for (uint i = pCutoffEvent->FragmentPos(); i < end; i++) {
565 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfc][i] += cutoffdelta;
566 }
567
568 pCutoffEvent = pNextCutoffEvent;
569 }
570 if (pCutoffEventList->last()) VCFCutoffCtrl.fvalue = (float) (127 - pCutoffEventList->last()->Value) * 39.4f; // needed for initialization of parameter matrix next time
571
572 // process filter resonance events
573 RTEList<ModulationSystem::Event>* pResonanceEventList = pEngine->pSynthesisEvents[ModulationSystem::destination_vcfr];
574 ModulationSystem::Event* pResonanceEvent = pResonanceEventList->first();
575 while (pResonanceEvent) {
576 ModulationSystem::Event* pNextResonanceEvent = pResonanceEventList->next();
577
578 // calculate the influence length of this event (in sample points)
579 uint end = (pNextResonanceEvent) ? pNextResonanceEvent->FragmentPos() : Samples;
580
581 // convert absolute controller value to differential
582 int ctrldelta = pResonanceEvent->Value - VCFResonanceCtrl.value;
583 VCFResonanceCtrl.value = pResonanceEvent->Value;
584
585 float resonancedelta = (float) ctrldelta * 0.00787f; // 0.0..1.0
586
587 // apply cutoff frequency to the cutoff parameter sequence
588 for (uint i = pResonanceEvent->FragmentPos(); i < end; i++) {
589 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfr][i] += resonancedelta;
590 }
591
592 pResonanceEvent = pNextResonanceEvent;
593 }
594 if (pResonanceEventList->last()) VCFResonanceCtrl.fvalue = pResonanceEventList->last()->Value * 0.00787f; // needed for initialization of parameter matrix next time
595 #endif // ENABLE_FILTER
596 }
597
598 /**
599 * Interpolates the input audio data (no loop).
600 *
601 * @param Samples - number of sample points to be rendered in this audio
602 * fragment cycle
603 * @param pSrc - pointer to input sample data
604 * @param Skip - number of sample points to skip in output buffer
605 */
606 void Voice::Interpolate(uint Samples, sample_t* pSrc, uint Skip) {
607 int i = Skip;
608
609 // FIXME: assuming either mono or stereo
610 if (this->pSample->Channels == 2) { // Stereo Sample
611 while (i < Samples) {
612 InterpolateOneStep_Stereo(pSrc, i,
613 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vca][i],
614 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vco][i],
615 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfc][i],
616 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfr][i]);
617 }
618
619 #if ENABLE_FILTER
620 // to save the last filter setting for the next render cycle (only needed when we update the filter not-sample-accurate)
621 ForceUpdateFilter_Stereo(ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfc][Samples - 1],
622 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfr][Samples - 1]);
623 #endif // ENABLE_FILTER
624 }
625 else { // Mono Sample
626 while (i < Samples) {
627 InterpolateOneStep_Mono(pSrc, i,
628 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vca][i],
629 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vco][i],
630 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfc][i],
631 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfr][i]);
632 }
633
634 #if ENABLE_FILTER
635 // to save the last filter setting for the next render cycle (only needed when we update the filter not-sample-accurate)
636 ForceUpdateFilter_Mono(ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfc][Samples - 1],
637 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfr][Samples - 1]);
638 #endif // ENABLE_FILTER
639 }
640 }
641
642 /**
643 * Interpolates the input audio data, this method honors looping.
644 *
645 * @param Samples - number of sample points to be rendered in this audio
646 * fragment cycle
647 * @param pSrc - pointer to input sample data
648 * @param Skip - number of sample points to skip in output buffer
649 */
650 void Voice::InterpolateAndLoop(uint Samples, sample_t* pSrc, uint Skip) {
651 int i = Skip;
652
653 // FIXME: assuming either mono or stereo
654 if (pSample->Channels == 2) { // Stereo Sample
655 if (pSample->LoopPlayCount) {
656 // render loop (loop count limited)
657 while (i < Samples && LoopCyclesLeft) {
658 InterpolateOneStep_Stereo(pSrc, i,
659 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vca][i],
660 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vco][i],
661 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfc][i],
662 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfr][i]);
663 if (Pos > pSample->LoopEnd) {
664 Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;
665 LoopCyclesLeft--;
666 }
667 }
668 // render on without loop
669 while (i < Samples) {
670 InterpolateOneStep_Stereo(pSrc, i,
671 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vca][i],
672 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vco][i],
673 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfc][i],
674 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfr][i]);
675 }
676 }
677 else { // render loop (endless loop)
678 while (i < Samples) {
679 InterpolateOneStep_Stereo(pSrc, i,
680 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vca][i],
681 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vco][i],
682 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfc][i],
683 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfr][i]);
684 if (Pos > pSample->LoopEnd) {
685 Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);
686 }
687 }
688 }
689 #if ENABLE_FILTER
690 // to save the last filter setting for the next render cycle (only needed when we update the filter not-sample-accurate)
691 ForceUpdateFilter_Stereo(ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfc][Samples - 1],
692 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfr][Samples - 1]);
693 #endif // ENABLE_FILTER
694 }
695 else { // Mono Sample
696 if (pSample->LoopPlayCount) {
697 // render loop (loop count limited)
698 while (i < Samples && LoopCyclesLeft) {
699 InterpolateOneStep_Mono(pSrc, i,
700 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vca][i],
701 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vco][i],
702 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfc][i],
703 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfr][i]);
704 if (Pos > pSample->LoopEnd) {
705 Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;
706 LoopCyclesLeft--;
707 }
708 }
709 // render on without loop
710 while (i < Samples) {
711 InterpolateOneStep_Mono(pSrc, i,
712 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vca][i],
713 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vco][i],
714 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfc][i],
715 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfr][i]);
716 }
717 }
718 else { // render loop (endless loop)
719 while (i < Samples) {
720 InterpolateOneStep_Mono(pSrc, i,
721 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vca][i],
722 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vco][i],
723 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfc][i],
724 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfr][i]);
725 if (Pos > pSample->LoopEnd) {
726 Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;
727 }
728 }
729 }
730 #if ENABLE_FILTER
731 // to save the last filter setting for the next render cycle (only needed when we update the filter not-sample-accurate)
732 ForceUpdateFilter_Mono(ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfc][Samples - 1],
733 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfr][Samples - 1]);
734 #endif // ENABLE_FILTER
735 }
736 }
737
738 /**
739 * Immediately kill the voice.
740 */
741 void Voice::Kill() {
742 if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {
743 pDiskThread->OrderDeletionOfStream(&DiskStreamRef);
744 }
745 Reset();
746 }

  ViewVC Help
Powered by ViewVC