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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.13  
changed lines
  Added in v.40

  ViewVC Help
Powered by ViewVC