/[svn]/linuxsampler/trunk/src/engines/common/AbstractVoice.cpp
ViewVC logotype

Annotation of /linuxsampler/trunk/src/engines/common/AbstractVoice.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2032 - (hide annotations) (download)
Fri Nov 20 20:13:08 2009 UTC (14 years, 4 months ago) by persson
File size: 30082 byte(s)
* bugfix: release samples could cause loud noises

1 iliev 2015 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5     * Copyright (C) 2003,2004 by Benno Senoner and Christian Schoenebeck *
6     * Copyright (C) 2005-2009 Christian Schoenebeck *
7     * Copyright (C) 2009 Grigor Iliev *
8     * *
9     * This program is free software; you can redistribute it and/or modify *
10     * it under the terms of the GNU General Public License as published by *
11     * the Free Software Foundation; either version 2 of the License, or *
12     * (at your option) any later version. *
13     * *
14     * This program is distributed in the hope that it will be useful, *
15     * but WITHOUT ANY WARRANTY; without even the implied warranty of *
16     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
17     * GNU General Public License for more details. *
18     * *
19     * You should have received a copy of the GNU General Public License *
20     * along with this program; if not, write to the Free Software *
21     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
22     * MA 02111-1307 USA *
23     ***************************************************************************/
24    
25     #include "AbstractVoice.h"
26    
27     namespace LinuxSampler {
28    
29     AbstractVoice::AbstractVoice() {
30     pEngineChannel = NULL;
31     pLFO1 = new LFOUnsigned(1.0f); // amplitude EG (0..1 range)
32     pLFO2 = new LFOUnsigned(1.0f); // filter EG (0..1 range)
33     pLFO3 = new LFOSigned(1200.0f); // pitch EG (-1200..+1200 range)
34     PlaybackState = playback_state_end;
35     KeyGroup = 0;
36     SynthesisMode = 0; // set all mode bits to 0 first
37     // select synthesis implementation (asm core is not supported ATM)
38     #if 0 // CONFIG_ASM && ARCH_X86
39     SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, Features::supportsMMX() && Features::supportsSSE());
40     #else
41     SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, false);
42     #endif
43     SYNTHESIS_MODE_SET_PROFILING(SynthesisMode, gig::Profiler::isEnabled());
44    
45     finalSynthesisParameters.filterLeft.Reset();
46     finalSynthesisParameters.filterRight.Reset();
47     }
48    
49     AbstractVoice::~AbstractVoice() {
50     if (pLFO1) delete pLFO1;
51     if (pLFO2) delete pLFO2;
52     if (pLFO3) delete pLFO3;
53     }
54    
55     /**
56     * Resets voice variables. Should only be called if rendering process is
57     * suspended / not running.
58     */
59     void AbstractVoice::Reset() {
60     finalSynthesisParameters.filterLeft.Reset();
61     finalSynthesisParameters.filterRight.Reset();
62     DiskStreamRef.pStream = NULL;
63     DiskStreamRef.hStream = 0;
64     DiskStreamRef.State = Stream::state_unused;
65     DiskStreamRef.OrderID = 0;
66     PlaybackState = playback_state_end;
67     itTriggerEvent = Pool<Event>::Iterator();
68     itKillEvent = Pool<Event>::Iterator();
69     }
70    
71     /**
72     * Initializes and triggers the voice, a disk stream will be launched if
73     * needed.
74     *
75     * @param pEngineChannel - engine channel on which this voice was ordered
76     * @param itNoteOnEvent - event that caused triggering of this voice
77     * @param PitchBend - MIDI detune factor (-8192 ... +8191)
78     * @param pRegion- points to the region which provides sample wave(s) and articulation data
79     * @param VoiceType - type of this voice
80     * @param iKeyGroup - a value > 0 defines a key group in which this voice is member of
81     * @returns 0 on success, a value < 0 if the voice wasn't triggered
82     * (either due to an error or e.g. because no region is
83     * defined for the given key)
84     */
85     int AbstractVoice::Trigger (
86     AbstractEngineChannel* pEngineChannel,
87     Pool<Event>::Iterator& itNoteOnEvent,
88     int PitchBend,
89     type_t VoiceType,
90     int iKeyGroup
91     ) {
92     this->pEngineChannel = pEngineChannel;
93     Orphan = false;
94    
95     #if CONFIG_DEVMODE
96     if (itNoteOnEvent->FragmentPos() > GetEngine()->MaxSamplesPerCycle) { // just a sanity check for debugging
97     dmsg(1,("Voice::Trigger(): ERROR, TriggerDelay > Totalsamples\n"));
98     }
99     #endif // CONFIG_DEVMODE
100    
101     Type = VoiceType;
102     MIDIKey = itNoteOnEvent->Param.Note.Key;
103     PlaybackState = playback_state_init; // mark voice as triggered, but no audio rendered yet
104     Delay = itNoteOnEvent->FragmentPos();
105     itTriggerEvent = itNoteOnEvent;
106     itKillEvent = Pool<Event>::Iterator();
107     KeyGroup = iKeyGroup;
108    
109     SmplInfo = GetSampleInfo();
110     RgnInfo = GetRegionInfo();
111     InstrInfo = GetInstrumentInfo();
112    
113     // calculate volume
114     const double velocityAttenuation = GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity);
115     float volume = CalculateVolume(velocityAttenuation);
116 persson 2032 if (volume <= 0) return -1;
117 iliev 2015
118     // select channel mode (mono or stereo)
119     SYNTHESIS_MODE_SET_CHANNELS(SynthesisMode, SmplInfo.ChannelCount == 2);
120     // select bit depth (16 or 24)
121     SYNTHESIS_MODE_SET_BITDEPTH24(SynthesisMode, SmplInfo.BitDepth == 24);
122    
123     // get starting crossfade volume level
124     float crossfadeVolume = CalculateCrossfadeVolume(itNoteOnEvent->Param.Note.Velocity);
125    
126     VolumeLeft = volume * AbstractEngine::PanCurve[64 - RgnInfo.Pan];
127     VolumeRight = volume * AbstractEngine::PanCurve[64 + RgnInfo.Pan];
128    
129     float subfragmentRate = GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;
130     CrossfadeSmoother.trigger(crossfadeVolume, subfragmentRate);
131     VolumeSmoother.trigger(pEngineChannel->MidiVolume, subfragmentRate);
132     PanLeftSmoother.trigger(pEngineChannel->GlobalPanLeft, subfragmentRate);
133     PanRightSmoother.trigger(pEngineChannel->GlobalPanRight, subfragmentRate);
134    
135     finalSynthesisParameters.dPos = RgnInfo.SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)
136     Pos = RgnInfo.SampleStartOffset;
137    
138     // Check if the sample needs disk streaming or is too short for that
139     long cachedsamples = GetSampleCacheSize() / SmplInfo.FrameSize;
140     DiskVoice = cachedsamples < SmplInfo.TotalFrameCount;
141    
142     if (DiskVoice) { // voice to be streamed from disk
143     if (cachedsamples > (GetEngine()->MaxSamplesPerCycle << CONFIG_MAX_PITCH)) {
144     MaxRAMPos = cachedsamples - (GetEngine()->MaxSamplesPerCycle << CONFIG_MAX_PITCH) / SmplInfo.ChannelCount; //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)
145     } else {
146     // The cache is too small to fit a max sample buffer.
147     // Setting MaxRAMPos to 0 will probably cause a click
148     // in the audio, but it's better than not handling
149     // this case at all, which would have caused the
150     // unsigned MaxRAMPos to be set to a negative number.
151     MaxRAMPos = 0;
152     }
153    
154     // check if there's a loop defined which completely fits into the cached (RAM) part of the sample
155     RAMLoop = (SmplInfo.HasLoops && (SmplInfo.LoopStart + SmplInfo.LoopLength) <= MaxRAMPos);
156    
157     if (OrderNewStream()) return -1;
158     dmsg(4,("Disk voice launched (cached samples: %d, total Samples: %d, MaxRAMPos: %d, RAMLooping: %s)\n", cachedsamples, SmplInfo.TotalFrameCount, MaxRAMPos, (RAMLoop) ? "yes" : "no"));
159     }
160     else { // RAM only voice
161     MaxRAMPos = cachedsamples;
162     RAMLoop = (SmplInfo.HasLoops);
163     dmsg(4,("RAM only voice launched (Looping: %s)\n", (RAMLoop) ? "yes" : "no"));
164     }
165     if (RAMLoop) {
166     loop.uiTotalCycles = SmplInfo.LoopPlayCount;
167     loop.uiCyclesLeft = SmplInfo.LoopPlayCount;
168     loop.uiStart = SmplInfo.LoopStart;
169     loop.uiEnd = SmplInfo.LoopStart + SmplInfo.LoopLength;
170     loop.uiSize = SmplInfo.LoopLength;
171     }
172    
173     Pitch = CalculatePitchInfo(PitchBend);
174    
175     // the length of the decay and release curves are dependent on the velocity
176     const double velrelease = 1 / GetVelocityRelease(itNoteOnEvent->Param.Note.Velocity);
177    
178     // setup EG 1 (VCA EG)
179     {
180     // get current value of EG1 controller
181     double eg1controllervalue = GetEG1ControllerValue(itNoteOnEvent->Param.Note.Velocity);
182    
183     // calculate influence of EG1 controller on EG1's parameters
184     EGInfo egInfo = CalculateEG1ControllerInfluence(eg1controllervalue);
185    
186     EG1.trigger (
187     RgnInfo.EG1PreAttack,
188     RgnInfo.EG1Attack * egInfo.Attack,
189     RgnInfo.EG1Hold,
190     RgnInfo.EG1Decay1 * egInfo.Decay * velrelease,
191     RgnInfo.EG1Decay2 * egInfo.Decay * velrelease,
192     RgnInfo.EG1InfiniteSustain,
193     RgnInfo.EG1Sustain,
194     RgnInfo.EG1Release * egInfo.Release * velrelease,
195     velocityAttenuation,
196     GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE
197     );
198     }
199    
200     #ifdef CONFIG_INTERPOLATE_VOLUME
201     // setup initial volume in synthesis parameters
202     #ifdef CONFIG_PROCESS_MUTED_CHANNELS
203     if (pEngineChannel->GetMute()) {
204     finalSynthesisParameters.fFinalVolumeLeft = 0;
205     finalSynthesisParameters.fFinalVolumeRight = 0;
206     }
207     else
208     #else
209     {
210     float finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * EG1.getLevel();
211    
212     finalSynthesisParameters.fFinalVolumeLeft = finalVolume * VolumeLeft * pEngineChannel->GlobalPanLeft;
213     finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * pEngineChannel->GlobalPanRight;
214     }
215     #endif
216     #endif
217    
218     // setup EG 2 (VCF Cutoff EG)
219     {
220     // get current value of EG2 controller
221     double eg2controllervalue = GetEG2ControllerValue(itNoteOnEvent->Param.Note.Velocity);
222    
223     // calculate influence of EG2 controller on EG2's parameters
224     EGInfo egInfo = CalculateEG2ControllerInfluence(eg2controllervalue);
225    
226     EG2.trigger (
227     RgnInfo.EG2PreAttack,
228     RgnInfo.EG2Attack * egInfo.Attack,
229     false,
230     RgnInfo.EG2Decay1 * egInfo.Decay * velrelease,
231     RgnInfo.EG2Decay2 * egInfo.Decay * velrelease,
232     RgnInfo.EG2InfiniteSustain,
233     RgnInfo.EG2Sustain,
234     RgnInfo.EG2Release * egInfo.Release * velrelease,
235     velocityAttenuation,
236     GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE
237     );
238     }
239    
240    
241     // setup EG 3 (VCO EG)
242     {
243     // if portamento mode is on, we dedicate EG3 purely for portamento, otherwise if portamento is off we do as told by the patch
244     bool bPortamento = pEngineChannel->PortamentoMode && pEngineChannel->PortamentoPos >= 0.0f;
245     float eg3depth = (bPortamento)
246     ? RTMath::CentsToFreqRatio((pEngineChannel->PortamentoPos - (float) MIDIKey) * 100)
247     : RTMath::CentsToFreqRatio(RgnInfo.EG3Depth);
248     float eg3time = (bPortamento)
249     ? pEngineChannel->PortamentoTime
250     : RgnInfo.EG3Attack;
251     EG3.trigger(eg3depth, eg3time, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
252     dmsg(5,("PortamentoPos=%f, depth=%f, time=%f\n", pEngineChannel->PortamentoPos, eg3depth, eg3time));
253     }
254    
255    
256     // setup LFO 1 (VCA LFO)
257     InitLFO1();
258     // setup LFO 2 (VCF Cutoff LFO)
259     InitLFO2();
260     // setup LFO 3 (VCO LFO)
261     InitLFO3();
262    
263    
264     #if CONFIG_FORCE_FILTER
265     const bool bUseFilter = true;
266     #else // use filter only if instrument file told so
267     const bool bUseFilter = RgnInfo.VCFEnabled;
268     #endif // CONFIG_FORCE_FILTER
269     SYNTHESIS_MODE_SET_FILTER(SynthesisMode, bUseFilter);
270     if (bUseFilter) {
271     #ifdef CONFIG_OVERRIDE_CUTOFF_CTRL
272     VCFCutoffCtrl.controller = CONFIG_OVERRIDE_CUTOFF_CTRL;
273     #else // use the one defined in the instrument file
274     VCFCutoffCtrl.controller = GetVCFCutoffCtrl();
275     #endif // CONFIG_OVERRIDE_CUTOFF_CTRL
276    
277     #ifdef CONFIG_OVERRIDE_RESONANCE_CTRL
278     VCFResonanceCtrl.controller = CONFIG_OVERRIDE_RESONANCE_CTRL;
279     #else // use the one defined in the instrument file
280     VCFResonanceCtrl.controller = GetVCFResonanceCtrl();
281     #endif // CONFIG_OVERRIDE_RESONANCE_CTRL
282    
283     #ifndef CONFIG_OVERRIDE_FILTER_TYPE
284     finalSynthesisParameters.filterLeft.SetType(RgnInfo.VCFType);
285     finalSynthesisParameters.filterRight.SetType(RgnInfo.VCFType);
286     #else // override filter type
287     finalSynthesisParameters.filterLeft.SetType(CONFIG_OVERRIDE_FILTER_TYPE);
288     finalSynthesisParameters.filterRight.SetType(CONFIG_OVERRIDE_FILTER_TYPE);
289     #endif // CONFIG_OVERRIDE_FILTER_TYPE
290    
291     VCFCutoffCtrl.value = pEngineChannel->ControllerTable[VCFCutoffCtrl.controller];
292     VCFResonanceCtrl.value = pEngineChannel->ControllerTable[VCFResonanceCtrl.controller];
293    
294     // calculate cutoff frequency
295     CutoffBase = CalculateCutoffBase(itNoteOnEvent->Param.Note.Velocity);
296    
297     VCFCutoffCtrl.fvalue = CalculateFinalCutoff(CutoffBase);
298    
299     // calculate resonance
300     float resonance = (float) (VCFResonanceCtrl.controller ? VCFResonanceCtrl.value : RgnInfo.VCFResonance);
301     VCFResonanceCtrl.fvalue = resonance;
302     } else {
303     VCFCutoffCtrl.controller = 0;
304     VCFResonanceCtrl.controller = 0;
305     }
306    
307     return 0; // success
308     }
309    
310     /**
311     * Synthesizes the current audio fragment for this voice.
312     *
313     * @param Samples - number of sample points to be rendered in this audio
314     * fragment cycle
315     * @param pSrc - pointer to input sample data
316     * @param Skip - number of sample points to skip in output buffer
317     */
318     void AbstractVoice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {
319     AbstractEngineChannel* pChannel = pEngineChannel;
320     finalSynthesisParameters.pOutLeft = &pChannel->pChannelLeft->Buffer()[Skip];
321     finalSynthesisParameters.pOutRight = &pChannel->pChannelRight->Buffer()[Skip];
322     finalSynthesisParameters.pSrc = pSrc;
323    
324     RTList<Event>::Iterator itCCEvent = pChannel->pEvents->first();
325     RTList<Event>::Iterator itNoteEvent;
326     GetFirstEventOnKey(MIDIKey, itNoteEvent);
327    
328     if (itTriggerEvent) { // skip events that happened before this voice was triggered
329     while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;
330     // we can't simply compare the timestamp here, because note events
331     // might happen on the same time stamp, so we have to deal on the
332     // actual sequence the note events arrived instead (see bug #112)
333     for (; itNoteEvent; ++itNoteEvent) {
334     if (itTriggerEvent == itNoteEvent) {
335     ++itNoteEvent;
336     break;
337     }
338     }
339     }
340    
341     uint killPos;
342     if (itKillEvent) {
343     int maxFadeOutPos = Samples - GetEngine()->GetMinFadeOutSamples();
344     if (maxFadeOutPos < 0) {
345     // There's not enough space in buffer to do a fade out
346     // from max volume (this can only happen for audio
347     // drivers that use Samples < MaxSamplesPerCycle).
348     // End the EG1 here, at pos 0, with a shorter max fade
349     // out time.
350     EG1.enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
351     itKillEvent = Pool<Event>::Iterator();
352     } else {
353     killPos = RTMath::Min(itKillEvent->FragmentPos(), maxFadeOutPos);
354     }
355     }
356    
357     uint i = Skip;
358     while (i < Samples) {
359     int iSubFragmentEnd = RTMath::Min(i + CONFIG_DEFAULT_SUBFRAGMENT_SIZE, Samples);
360    
361     // initialize all final synthesis parameters
362     fFinalCutoff = VCFCutoffCtrl.fvalue;
363     fFinalResonance = VCFResonanceCtrl.fvalue;
364    
365     // process MIDI control change and pitchbend events for this subfragment
366     processCCEvents(itCCEvent, iSubFragmentEnd);
367    
368     finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend;
369     float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render();
370     #ifdef CONFIG_PROCESS_MUTED_CHANNELS
371     if (pChannel->GetMute()) fFinalVolume = 0;
372     #endif
373    
374     // process transition events (note on, note off & sustain pedal)
375     processTransitionEvents(itNoteEvent, iSubFragmentEnd);
376    
377     // if the voice was killed in this subfragment, or if the
378     // filter EG is finished, switch EG1 to fade out stage
379     if ((itKillEvent && killPos <= iSubFragmentEnd) ||
380     (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&
381     EG2.getSegmentType() == gig::EGADSR::segment_end)) {
382     EG1.enterFadeOutStage();
383     itKillEvent = Pool<Event>::Iterator();
384     }
385    
386     // process envelope generators
387     switch (EG1.getSegmentType()) {
388     case gig::EGADSR::segment_lin:
389     fFinalVolume *= EG1.processLin();
390     break;
391     case gig::EGADSR::segment_exp:
392     fFinalVolume *= EG1.processExp();
393     break;
394     case gig::EGADSR::segment_end:
395     fFinalVolume *= EG1.getLevel();
396     break; // noop
397     }
398     switch (EG2.getSegmentType()) {
399     case gig::EGADSR::segment_lin:
400     fFinalCutoff *= EG2.processLin();
401     break;
402     case gig::EGADSR::segment_exp:
403     fFinalCutoff *= EG2.processExp();
404     break;
405     case gig::EGADSR::segment_end:
406     fFinalCutoff *= EG2.getLevel();
407     break; // noop
408     }
409     if (EG3.active()) finalSynthesisParameters.fFinalPitch *= EG3.render();
410    
411     // process low frequency oscillators
412     if (bLFO1Enabled) fFinalVolume *= (1.0f - pLFO1->render());
413     if (bLFO2Enabled) fFinalCutoff *= pLFO2->render();
414     if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());
415    
416     // limit the pitch so we don't read outside the buffer
417     finalSynthesisParameters.fFinalPitch = RTMath::Min(finalSynthesisParameters.fFinalPitch, float(1 << CONFIG_MAX_PITCH));
418    
419     // if filter enabled then update filter coefficients
420     if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode)) {
421     finalSynthesisParameters.filterLeft.SetParameters(fFinalCutoff, fFinalResonance, GetEngine()->SampleRate);
422     finalSynthesisParameters.filterRight.SetParameters(fFinalCutoff, fFinalResonance, GetEngine()->SampleRate);
423     }
424    
425     // do we need resampling?
426     const float __PLUS_ONE_CENT = 1.000577789506554859250142541782224725466f;
427     const float __MINUS_ONE_CENT = 0.9994225441413807496009516495583113737666f;
428     const bool bResamplingRequired = !(finalSynthesisParameters.fFinalPitch <= __PLUS_ONE_CENT &&
429     finalSynthesisParameters.fFinalPitch >= __MINUS_ONE_CENT);
430     SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, bResamplingRequired);
431    
432     // prepare final synthesis parameters structure
433     finalSynthesisParameters.uiToGo = iSubFragmentEnd - i;
434     #ifdef CONFIG_INTERPOLATE_VOLUME
435     finalSynthesisParameters.fFinalVolumeDeltaLeft =
436     (fFinalVolume * VolumeLeft * PanLeftSmoother.render() -
437     finalSynthesisParameters.fFinalVolumeLeft) / finalSynthesisParameters.uiToGo;
438     finalSynthesisParameters.fFinalVolumeDeltaRight =
439     (fFinalVolume * VolumeRight * PanRightSmoother.render() -
440     finalSynthesisParameters.fFinalVolumeRight) / finalSynthesisParameters.uiToGo;
441     #else
442     finalSynthesisParameters.fFinalVolumeLeft =
443     fFinalVolume * VolumeLeft * PanLeftSmoother.render();
444     finalSynthesisParameters.fFinalVolumeRight =
445     fFinalVolume * VolumeRight * PanRightSmoother.render();
446     #endif
447     // render audio for one subfragment
448     RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);
449    
450     // stop the rendering if volume EG is finished
451     if (EG1.getSegmentType() == gig::EGADSR::segment_end) break;
452    
453     const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;
454    
455     // increment envelopes' positions
456     if (EG1.active()) {
457    
458     // if sample has a loop and loop start has been reached in this subfragment, send a special event to EG1 to let it finish the attack hold stage
459     if (SmplInfo.HasLoops && Pos <= SmplInfo.LoopStart && SmplInfo.LoopStart < newPos) {
460     EG1.update(gig::EGADSR::event_hold_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
461     }
462    
463     EG1.increment(1);
464     if (!EG1.toStageEndLeft()) EG1.update(gig::EGADSR::event_stage_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
465     }
466     if (EG2.active()) {
467     EG2.increment(1);
468     if (!EG2.toStageEndLeft()) EG2.update(gig::EGADSR::event_stage_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
469     }
470     EG3.increment(1);
471     if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached
472    
473     Pos = newPos;
474     i = iSubFragmentEnd;
475     }
476     }
477    
478     /**
479     * Process given list of MIDI control change and pitch bend events for
480     * the given time.
481     *
482     * @param itEvent - iterator pointing to the next event to be processed
483     * @param End - youngest time stamp where processing should be stopped
484     */
485     void AbstractVoice::processCCEvents(RTList<Event>::Iterator& itEvent, uint End) {
486     for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
487     if (itEvent->Type == Event::type_control_change && itEvent->Param.CC.Controller) { // if (valid) MIDI control change event
488     if (itEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {
489     ProcessCutoffEvent(itEvent);
490     }
491     if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {
492     processResonanceEvent(itEvent);
493     }
494     if (itEvent->Param.CC.Controller == pLFO1->ExtController) {
495     pLFO1->update(itEvent->Param.CC.Value);
496     }
497     if (itEvent->Param.CC.Controller == pLFO2->ExtController) {
498     pLFO2->update(itEvent->Param.CC.Value);
499     }
500     if (itEvent->Param.CC.Controller == pLFO3->ExtController) {
501     pLFO3->update(itEvent->Param.CC.Value);
502     }
503     if (itEvent->Param.CC.Controller == 7) { // volume
504     VolumeSmoother.update(AbstractEngine::VolumeCurve[itEvent->Param.CC.Value]);
505     } else if (itEvent->Param.CC.Controller == 10) { // panpot
506     PanLeftSmoother.update(AbstractEngine::PanCurve[128 - itEvent->Param.CC.Value]);
507     PanRightSmoother.update(AbstractEngine::PanCurve[itEvent->Param.CC.Value]);
508     }
509     } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event
510     processPitchEvent(itEvent);
511     }
512    
513     ProcessCCEvent(itEvent);
514     }
515     }
516    
517     void AbstractVoice::processPitchEvent(RTList<Event>::Iterator& itEvent) {
518     Pitch.PitchBend = RTMath::CentsToFreqRatio(itEvent->Param.Pitch.Pitch * Pitch.PitchBendRange);
519     }
520    
521     void AbstractVoice::processResonanceEvent(RTList<Event>::Iterator& itEvent) {
522     // convert absolute controller value to differential
523     const int ctrldelta = itEvent->Param.CC.Value - VCFResonanceCtrl.value;
524     VCFResonanceCtrl.value = itEvent->Param.CC.Value;
525     const float resonancedelta = (float) ctrldelta;
526     fFinalResonance += resonancedelta;
527     // needed for initialization of parameter
528     VCFResonanceCtrl.fvalue = itEvent->Param.CC.Value;
529     }
530    
531     /**
532     * Process given list of MIDI note on, note off and sustain pedal events
533     * for the given time.
534     *
535     * @param itEvent - iterator pointing to the next event to be processed
536     * @param End - youngest time stamp where processing should be stopped
537     */
538     void AbstractVoice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) {
539     for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
540     if (itEvent->Type == Event::type_release) {
541     EG1.update(gig::EGADSR::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
542     EG2.update(gig::EGADSR::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
543     } else if (itEvent->Type == Event::type_cancel_release) {
544     EG1.update(gig::EGADSR::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
545     EG2.update(gig::EGADSR::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
546     }
547     }
548     }
549    
550     /** @brief Update current portamento position.
551     *
552     * Will be called when portamento mode is enabled to get the final
553     * portamento position of this active voice from where the next voice(s)
554     * might continue to slide on.
555     *
556     * @param itNoteOffEvent - event which causes this voice to die soon
557     */
558     void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {
559     const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());
560     pEngineChannel->PortamentoPos = (float) MIDIKey + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;
561     }
562    
563     /**
564     * Kill the voice in regular sense. Let the voice render audio until
565     * the kill event actually occured and then fade down the volume level
566     * very quickly and let the voice die finally. Unlike a normal release
567     * of a voice, a kill process cannot be cancalled and is therefore
568     * usually used for voice stealing and key group conflicts.
569     *
570     * @param itKillEvent - event which caused the voice to be killed
571     */
572     void AbstractVoice::Kill(Pool<Event>::Iterator& itKillEvent) {
573     #if CONFIG_DEVMODE
574     if (!itKillEvent) dmsg(1,("AbstractVoice::Kill(): ERROR, !itKillEvent !!!\n"));
575     if (itKillEvent && !itKillEvent.isValid()) dmsg(1,("AbstractVoice::Kill(): ERROR, itKillEvent invalid !!!\n"));
576     #endif // CONFIG_DEVMODE
577    
578     if (itTriggerEvent && itKillEvent->FragmentPos() <= itTriggerEvent->FragmentPos()) return;
579     this->itKillEvent = itKillEvent;
580     }
581    
582     Voice::PitchInfo AbstractVoice::CalculatePitchInfo(int PitchBend) {
583     PitchInfo pitch;
584     double pitchbasecents = InstrInfo.FineTune + RgnInfo.FineTune + GetEngine()->ScaleTuning[MIDIKey % 12];
585    
586     // GSt behaviour: maximum transpose up is 40 semitones. If
587     // MIDI key is more than 40 semitones above unity note,
588     // the transpose is not done.
589     if (!SmplInfo.Unpitched && (MIDIKey - (int) RgnInfo.UnityNote) < 40) pitchbasecents += (MIDIKey - (int) RgnInfo.UnityNote) * 100;
590    
591     pitch.PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(SmplInfo.SampleRate) / double(GetEngine()->SampleRate));
592     pitch.PitchBendRange = 1.0 / 8192.0 * 100.0 * InstrInfo.PitchbendRange;
593     pitch.PitchBend = RTMath::CentsToFreqRatio(PitchBend * pitch.PitchBendRange);
594    
595     return pitch;
596     }
597    
598     double AbstractVoice::CalculateVolume(double velocityAttenuation) {
599     // For 16 bit samples, we downscale by 32768 to convert from
600     // int16 value range to DSP value range (which is
601     // -1.0..1.0). For 24 bit, we downscale from int32.
602     float volume = velocityAttenuation / (SmplInfo.BitDepth == 16 ? 32768.0f : 32768.0f * 65536.0f);
603    
604     volume *= GetSampleAttenuation() * pEngineChannel->GlobalVolume * GLOBAL_VOLUME;
605    
606     // the volume of release triggered samples depends on note length
607     if (Type == Voice::type_release_trigger) {
608     float noteLength = float(GetEngine()->FrameTime + Delay -
609     GetNoteOnTime(MIDIKey) ) / GetEngine()->SampleRate;
610    
611     float attenuation = 1 - 0.01053 * (256 >> RgnInfo.ReleaseTriggerDecay) * noteLength;
612     volume *= attenuation;
613     }
614    
615     return volume;
616     }
617     } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC