/[svn]/linuxsampler/tags/v0_1_0/src/voice.cpp
ViewVC logotype

Annotation of /linuxsampler/tags/v0_1_0/src/voice.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 39 - (hide annotations) (download)
Sun Mar 21 16:09:43 2004 UTC (20 years, 2 months ago) by schoenebeck
Original Path: linuxsampler/trunk/src/voice.cpp
File size: 35452 byte(s)
* implemented all three low frequency oscillators (LFO1 = volume,
  LFO2 = filter cutoff frequency, LFO3 = pitch) for accurate .gig playback

1 schoenebeck 9 /***************************************************************************
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 schoenebeck 32 DiskThread* Voice::pDiskThread = NULL;
28     AudioThread* Voice::pEngine = NULL;
29 schoenebeck 9
30 schoenebeck 32 Voice::Voice() {
31     Active = false;
32 schoenebeck 39 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 schoenebeck 9 }
36    
37     Voice::~Voice() {
38 schoenebeck 39 if (pLFO1) delete pLFO1;
39     if (pLFO2) delete pLFO2;
40     if (pLFO3) delete pLFO3;
41 schoenebeck 9 }
42    
43 schoenebeck 18 /**
44     * Initializes and triggers the voice, a disk stream will be launched if
45     * needed.
46     *
47 schoenebeck 33 * @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 schoenebeck 18 */
52 schoenebeck 33 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 schoenebeck 9
62     if (!pRegion) {
63     std::cerr << "Audio Thread: No Region defined for MIDI key " << MIDIKey << std::endl << std::flush;
64 schoenebeck 18 Kill();
65     return -1;
66 schoenebeck 9 }
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 schoenebeck 33 DimValues[i] = pNoteOnEvent->Velocity;
74 schoenebeck 9 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 schoenebeck 26 if (DiskVoice) { // voice to be streamed from disk
89 schoenebeck 32 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 schoenebeck 26
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 schoenebeck 18 dmsg(1,("Disk stream order failed!\n"));
100     Kill();
101     return -1;
102     }
103 schoenebeck 31 dmsg(4,("Disk voice launched (cached samples: %d, total Samples: %d, MaxRAMPos: %d, RAMLooping: %s)\n", cachedsamples, pSample->SamplesTotal, MaxRAMPos, (RAMLoop) ? "yes" : "no"));
104 schoenebeck 9 }
105 schoenebeck 26 else { // RAM only voice
106 schoenebeck 9 MaxRAMPos = cachedsamples;
107 schoenebeck 26 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 schoenebeck 9 }
114    
115    
116 schoenebeck 32 // Pitch according to keyboard position (if 'PitchTrack' is set) and given detune factor
117 schoenebeck 37 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 schoenebeck 30
120 schoenebeck 33 Volume = pDimRgn->GetVelocityAttenuation(pNoteOnEvent->Velocity);
121 schoenebeck 39
122 schoenebeck 37 // 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 schoenebeck 39
140 schoenebeck 37 // 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 schoenebeck 39
145 schoenebeck 33 EG1.Trigger(pDimRgn->EG1PreAttack,
146 schoenebeck 37 pDimRgn->EG1Attack + eg1attack,
147 schoenebeck 33 pDimRgn->EG1Hold,
148     pSample->LoopStart,
149 schoenebeck 37 pDimRgn->EG1Decay1 + eg1decay,
150     pDimRgn->EG1Decay2 + eg1decay,
151 schoenebeck 33 pDimRgn->EG1InfiniteSustain,
152     pDimRgn->EG1Sustain,
153 schoenebeck 37 pDimRgn->EG1Release + eg1release,
154 schoenebeck 33 Delay);
155 schoenebeck 30
156 schoenebeck 39 // 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 schoenebeck 38 #if ENABLE_FILTER
193 schoenebeck 39 // 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 schoenebeck 38 #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 schoenebeck 39 switch (pDimRgn->VCFCutoffController) {
277 schoenebeck 38 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 schoenebeck 39
312 schoenebeck 38 #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 schoenebeck 39
334 schoenebeck 38 #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 schoenebeck 39
342 schoenebeck 38 VCFCutoffCtrl.value = pEngine->ControllerTable[VCFCutoffCtrl.controller];
343     VCFResonanceCtrl.value = pEngine->ControllerTable[VCFResonanceCtrl.controller];
344 schoenebeck 39
345 schoenebeck 38 // calculate cutoff frequency
346     float cutoff = (!VCFCutoffCtrl.controller && pDimRgn->VCFVelocityScale)
347 schoenebeck 39 ? (float) pNoteOnEvent->Velocity * pDimRgn->VCFVelocityScale * 0.31f // up to 5kHz
348     : (float) (127 - VCFCutoffCtrl.value) * 39.4f; // up to 5kHz (inverted)
349    
350 schoenebeck 38 // 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 schoenebeck 39
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 schoenebeck 38 }
363     else {
364     VCFCutoffCtrl.controller = 0;
365     VCFResonanceCtrl.controller = 0;
366     }
367     #endif // ENABLE_FILTER
368    
369 schoenebeck 9 // ************************************************
370     // TODO: ARTICULATION DATA HANDLING IS MISSING HERE
371     // ************************************************
372 schoenebeck 18
373     return 0; // success
374 schoenebeck 9 }
375    
376 schoenebeck 26 /**
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 schoenebeck 32 *
385     * @param Samples - number of samples to be rendered in this audio fragment cycle
386 schoenebeck 26 */
387 schoenebeck 31 void Voice::Render(uint Samples) {
388 schoenebeck 9
389 schoenebeck 32 // Reset the synthesis parameter matrix
390     ModulationSystem::ResetDestinationParameter(ModulationSystem::destination_vca, this->Volume);
391     ModulationSystem::ResetDestinationParameter(ModulationSystem::destination_vco, this->Pitch);
392 schoenebeck 39 #if ENABLE_FILTER
393     ModulationSystem::ResetDestinationParameter(ModulationSystem::destination_vcfc, VCFCutoffCtrl.fvalue);
394     ModulationSystem::ResetDestinationParameter(ModulationSystem::destination_vcfr, VCFResonanceCtrl.fvalue);
395     #endif // ENABLE_FILTER
396 schoenebeck 32
397    
398     // Apply events to the synthesis parameter matrix
399     ProcessEvents(Samples);
400    
401    
402 schoenebeck 38 // Let all modulators write their parameter changes to the synthesis parameter matrix for the current audio fragment
403 schoenebeck 39 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 schoenebeck 30
410    
411 schoenebeck 9 switch (this->PlaybackState) {
412    
413     case playback_state_ram: {
414 schoenebeck 32 if (RAMLoop) InterpolateAndLoop(Samples, (sample_t*) pSample->GetCache().pStart, Delay);
415     else Interpolate(Samples, (sample_t*) pSample->GetCache().pStart, Delay);
416 schoenebeck 9 if (DiskVoice) {
417     // check if we reached the allowed limit of the sample RAM cache
418     if (Pos > MaxRAMPos) {
419 schoenebeck 12 dmsg(5,("Voice: switching to disk playback (Pos=%f)\n", Pos));
420 schoenebeck 9 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 schoenebeck 18 Kill();
436 schoenebeck 9 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 schoenebeck 31 if (DiskStreamRef.State == Stream::state_end && DiskStreamRef.pStream->GetReadSpace() < (MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels) {
444     DiskStreamRef.pStream->WriteSilence((MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels);
445 schoenebeck 9 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 schoenebeck 32 Interpolate(Samples, ptr, Delay);
450 schoenebeck 9 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 schoenebeck 13 Kill(); // free voice
457 schoenebeck 9 break;
458     }
459 schoenebeck 30
460 schoenebeck 32
461 schoenebeck 39 #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 schoenebeck 32 // Reset delay
468     Delay = 0;
469    
470 schoenebeck 33 pTriggerEvent = NULL;
471 schoenebeck 32
472 schoenebeck 30 // If release stage finished, let the voice be killed
473     if (EG1.GetStage() == EG_VCA::stage_end) this->PlaybackState = playback_state_end;
474 schoenebeck 9 }
475    
476 schoenebeck 26 /**
477 schoenebeck 35 * Resets voice variables. Should only be called if rendering process is
478     * suspended / not running.
479     */
480     void Voice::Reset() {
481 schoenebeck 39 pLFO1->Reset();
482     pLFO2->Reset();
483     pLFO3->Reset();
484 schoenebeck 35 DiskStreamRef.pStream = NULL;
485     DiskStreamRef.hStream = 0;
486     DiskStreamRef.State = Stream::state_unused;
487     DiskStreamRef.OrderID = 0;
488     Active = false;
489     }
490    
491     /**
492 schoenebeck 32 * 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 schoenebeck 39
500 schoenebeck 38 // dispatch control change events
501     ModulationSystem::Event* pCCEvent = pEngine->pCCEvents->first();
502     while (pCCEvent) {
503 schoenebeck 39 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 schoenebeck 38 }
524    
525     pCCEvent = pEngine->pCCEvents->next();
526     }
527    
528 schoenebeck 32 // process pitch events
529 schoenebeck 38 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 schoenebeck 32
534     // calculate the influence length of this event (in sample points)
535 schoenebeck 38 uint end = (pNextVCOEvent) ? pNextVCOEvent->FragmentPos() : Samples;
536 schoenebeck 39
537 schoenebeck 38 this->Pitch += ((double) pVCOEvent->Pitch / 8192.0) / 12.0; // +- one semitone
538 schoenebeck 32
539     // apply pitch value to the pitch parameter sequence
540 schoenebeck 38 for (uint i = pVCOEvent->FragmentPos(); i < end; i++) {
541 schoenebeck 32 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vco][i] = this->Pitch;
542     }
543    
544 schoenebeck 38 pVCOEvent = pNextVCOEvent;
545 schoenebeck 32 }
546 schoenebeck 38
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 schoenebeck 39
561 schoenebeck 38 float cutoffdelta = (float) ctrldelta * -39.4f; // (20Hz)..5kHz (inverted)
562 schoenebeck 39
563 schoenebeck 38 // 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 schoenebeck 39 if (pCutoffEventList->last()) VCFCutoffCtrl.fvalue = (float) (127 - pCutoffEventList->last()->Value) * 39.4f; // needed for initialization of parameter matrix next time
571    
572 schoenebeck 38 // 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 schoenebeck 39
581 schoenebeck 38 // 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 schoenebeck 39
587 schoenebeck 38 // 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 schoenebeck 39 if (pResonanceEventList->last()) VCFResonanceCtrl.fvalue = pResonanceEventList->last()->Value * 0.00787f; // needed for initialization of parameter matrix next time
595 schoenebeck 38 #endif // ENABLE_FILTER
596 schoenebeck 32 }
597    
598     /**
599 schoenebeck 26 * Interpolates the input audio data (no loop).
600     *
601 schoenebeck 32 * @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 schoenebeck 26 */
606 schoenebeck 32 void Voice::Interpolate(uint Samples, sample_t* pSrc, uint Skip) {
607     int i = Skip;
608 schoenebeck 9
609     // FIXME: assuming either mono or stereo
610     if (this->pSample->Channels == 2) { // Stereo Sample
611 schoenebeck 31 while (i < Samples) {
612 schoenebeck 32 InterpolateOneStep_Stereo(pSrc, i,
613     ModulationSystem::pDestinationParameter[ModulationSystem::destination_vca][i],
614 schoenebeck 38 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vco][i],
615     ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfc][i],
616     ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfr][i]);
617 schoenebeck 9 }
618 schoenebeck 39
619     #if ENABLE_FILTER
620 schoenebeck 38 // 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 schoenebeck 9 }
625     else { // Mono Sample
626 schoenebeck 31 while (i < Samples) {
627 schoenebeck 32 InterpolateOneStep_Mono(pSrc, i,
628     ModulationSystem::pDestinationParameter[ModulationSystem::destination_vca][i],
629 schoenebeck 38 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vco][i],
630     ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfc][i],
631     ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfr][i]);
632 schoenebeck 26 }
633 schoenebeck 39
634     #if ENABLE_FILTER
635 schoenebeck 38 // 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 schoenebeck 39 }
640 schoenebeck 26 }
641 schoenebeck 18
642 schoenebeck 26 /**
643     * Interpolates the input audio data, this method honors looping.
644     *
645 schoenebeck 32 * @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 schoenebeck 26 */
650 schoenebeck 32 void Voice::InterpolateAndLoop(uint Samples, sample_t* pSrc, uint Skip) {
651     int i = Skip;
652 schoenebeck 9
653 schoenebeck 26 // FIXME: assuming either mono or stereo
654     if (pSample->Channels == 2) { // Stereo Sample
655     if (pSample->LoopPlayCount) {
656     // render loop (loop count limited)
657 schoenebeck 31 while (i < Samples && LoopCyclesLeft) {
658 schoenebeck 32 InterpolateOneStep_Stereo(pSrc, i,
659     ModulationSystem::pDestinationParameter[ModulationSystem::destination_vca][i],
660 schoenebeck 38 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vco][i],
661     ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfc][i],
662     ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfr][i]);
663 schoenebeck 26 if (Pos > pSample->LoopEnd) {
664     Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;
665     LoopCyclesLeft--;
666     }
667     }
668     // render on without loop
669 schoenebeck 31 while (i < Samples) {
670 schoenebeck 32 InterpolateOneStep_Stereo(pSrc, i,
671     ModulationSystem::pDestinationParameter[ModulationSystem::destination_vca][i],
672 schoenebeck 38 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vco][i],
673     ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfc][i],
674     ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfr][i]);
675 schoenebeck 26 }
676 schoenebeck 9 }
677 schoenebeck 26 else { // render loop (endless loop)
678 schoenebeck 31 while (i < Samples) {
679 schoenebeck 32 InterpolateOneStep_Stereo(pSrc, i,
680     ModulationSystem::pDestinationParameter[ModulationSystem::destination_vca][i],
681 schoenebeck 38 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vco][i],
682     ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfc][i],
683     ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfr][i]);
684 schoenebeck 26 if (Pos > pSample->LoopEnd) {
685     Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);
686     }
687     }
688     }
689 schoenebeck 39 #if ENABLE_FILTER
690 schoenebeck 38 // 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 schoenebeck 39 #endif // ENABLE_FILTER
694 schoenebeck 9 }
695 schoenebeck 26 else { // Mono Sample
696     if (pSample->LoopPlayCount) {
697     // render loop (loop count limited)
698 schoenebeck 31 while (i < Samples && LoopCyclesLeft) {
699 schoenebeck 32 InterpolateOneStep_Mono(pSrc, i,
700     ModulationSystem::pDestinationParameter[ModulationSystem::destination_vca][i],
701 schoenebeck 38 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vco][i],
702     ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfc][i],
703     ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfr][i]);
704 schoenebeck 26 if (Pos > pSample->LoopEnd) {
705     Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;
706     LoopCyclesLeft--;
707     }
708     }
709     // render on without loop
710 schoenebeck 31 while (i < Samples) {
711 schoenebeck 32 InterpolateOneStep_Mono(pSrc, i,
712     ModulationSystem::pDestinationParameter[ModulationSystem::destination_vca][i],
713 schoenebeck 38 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vco][i],
714     ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfc][i],
715     ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfr][i]);
716 schoenebeck 26 }
717     }
718     else { // render loop (endless loop)
719 schoenebeck 31 while (i < Samples) {
720 schoenebeck 32 InterpolateOneStep_Mono(pSrc, i,
721     ModulationSystem::pDestinationParameter[ModulationSystem::destination_vca][i],
722 schoenebeck 38 ModulationSystem::pDestinationParameter[ModulationSystem::destination_vco][i],
723     ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfc][i],
724     ModulationSystem::pDestinationParameter[ModulationSystem::destination_vcfr][i]);
725 schoenebeck 26 if (Pos > pSample->LoopEnd) {
726     Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;
727     }
728     }
729     }
730 schoenebeck 39 #if ENABLE_FILTER
731 schoenebeck 38 // 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 schoenebeck 39 #endif // ENABLE_FILTER
735     }
736 schoenebeck 9 }
737    
738 schoenebeck 26 /**
739     * Immediately kill the voice.
740     */
741 schoenebeck 9 void Voice::Kill() {
742     if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {
743     pDiskThread->OrderDeletionOfStream(&DiskStreamRef);
744     }
745 schoenebeck 35 Reset();
746 schoenebeck 9 }

  ViewVC Help
Powered by ViewVC