/[svn]/linuxsampler/trunk/src/engines/gig/Voice.cpp
ViewVC logotype

Annotation of /linuxsampler/trunk/src/engines/gig/Voice.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 236 - (hide 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 schoenebeck 53 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5 schoenebeck 56 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 schoenebeck 53 * *
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 schoenebeck 233 // TODO: no support for crossfades yet
31 schoenebeck 53
32     const float Voice::FILTER_CUTOFF_COEFF(CalculateFilterCutoffCoeff());
33    
34 schoenebeck 80 const int Voice::FILTER_UPDATE_MASK(CalculateFilterUpdateMask());
35    
36 schoenebeck 53 float Voice::CalculateFilterCutoffCoeff() {
37     return log(FILTER_CUTOFF_MIN / FILTER_CUTOFF_MAX);
38     }
39    
40 schoenebeck 80 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 schoenebeck 53 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 schoenebeck 64 dmsg(6,("Voice::SetEngine()\n"));
101 schoenebeck 53 }
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 schoenebeck 233 * @param iLayer - layer number this voice refers to (only if this is a layered sound of course)
111 schoenebeck 53 * @returns 0 on success, a value < 0 if something failed
112     */
113 schoenebeck 233 int Voice::Trigger(Event* pNoteOnEvent, int PitchBend, ::gig::Instrument* pInstrument, int iLayer) {
114 schoenebeck 53 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 schoenebeck 230 std::cerr << "gig::Voice: No Region defined for MIDI key " << MIDIKey << std::endl << std::flush;
128 schoenebeck 53 Kill();
129     return -1;
130     }
131    
132 schoenebeck 230 // 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 schoenebeck 233 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 schoenebeck 230 break;
147     case ::gig::dimension_velocity:
148 schoenebeck 53 DimValues[i] = pNoteOnEvent->Velocity;
149 schoenebeck 230 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 schoenebeck 53 }
234     }
235 schoenebeck 236 pDimRgn = pRegion->GetDimensionRegionByValue(DimValues[4],DimValues[3],DimValues[2],DimValues[1],DimValues[0]);
236 schoenebeck 53
237 schoenebeck 236 // 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 schoenebeck 53 pSample = pDimRgn->pSample; // sample won't change until the voice is finished
254    
255 schoenebeck 236 Pos = pDimRgn->SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)
256    
257 schoenebeck 53 // 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 schoenebeck 225 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 schoenebeck 53
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 schoenebeck 233 this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents) * (double(pSample->SamplesPerSecond) / double(pEngine->pAudioOutputDevice->SampleRate()));
294 schoenebeck 53 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 schoenebeck 225 pEngine->SampleRate,
420 schoenebeck 53 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 schoenebeck 225 pEngine->SampleRate,
458 schoenebeck 53 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 schoenebeck 225 pEngine->SampleRate,
496 schoenebeck 53 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 schoenebeck 225 FilterLeft.SetParameters(cutoff, resonance, pEngine->SampleRate);
594     FilterRight.SetParameters(cutoff, resonance, pEngine->SampleRate);
595 schoenebeck 53
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 schoenebeck 236 pEngine->ResetSynthesisParameters(Event::destination_vca, this->Volume * this->CrossfadeVolume * pEngine->GlobalVolume);
626 schoenebeck 53 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 schoenebeck 80 #if ENABLE_FILTER
651     CalculateBiquadParameters(Samples); // calculate the final biquad filter parameters
652     #endif // ENABLE_FILTER
653    
654    
655 schoenebeck 53 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 schoenebeck 225 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 schoenebeck 53 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 schoenebeck 236 // Reset synthesis event lists (except VCO, as VCO events apply channel wide currently)
706     pEngine->pSynthesisEvents[Event::destination_vca]->clear();
707 schoenebeck 53 #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 schoenebeck 236 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 schoenebeck 53 }
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 schoenebeck 236 // 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 schoenebeck 53
825 schoenebeck 236 // 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 schoenebeck 53 #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 schoenebeck 80 #if ENABLE_FILTER
901 schoenebeck 53 /**
902 schoenebeck 80 * 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 schoenebeck 225 FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);
914 schoenebeck 80 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 schoenebeck 225 FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);
925 schoenebeck 80 }
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 schoenebeck 53 * 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 schoenebeck 80 pEngine->pBasicFilterParameters[i],
964     pEngine->pMainFilterParameters[i]);
965 schoenebeck 53 }
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 schoenebeck 80 pEngine->pBasicFilterParameters[i],
973     pEngine->pMainFilterParameters[i]);
974 schoenebeck 53 }
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 schoenebeck 80 pEngine->pBasicFilterParameters[i],
998     pEngine->pMainFilterParameters[i]);
999 schoenebeck 53 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 schoenebeck 80 pEngine->pBasicFilterParameters[i],
1010     pEngine->pMainFilterParameters[i]);
1011 schoenebeck 53 }
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 schoenebeck 80 pEngine->pBasicFilterParameters[i],
1019     pEngine->pMainFilterParameters[i]);
1020 schoenebeck 53 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 schoenebeck 80 pEngine->pBasicFilterParameters[i],
1034     pEngine->pMainFilterParameters[i]);
1035 schoenebeck 53 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 schoenebeck 80 pEngine->pBasicFilterParameters[i],
1046     pEngine->pMainFilterParameters[i]);
1047 schoenebeck 53 }
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 schoenebeck 80 pEngine->pBasicFilterParameters[i],
1055     pEngine->pMainFilterParameters[i]);
1056 schoenebeck 53 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