/[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 230 - (hide annotations) (download)
Thu Sep 2 21:52:29 2004 UTC (19 years, 7 months ago) by schoenebeck
File size: 48007 byte(s)
* src/engines/gig/Voice.cpp: dimension region selection takes current
  MIDI controller values into account

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

  ViewVC Help
Powered by ViewVC