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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3360 - (show annotations) (download)
Fri Oct 27 21:19:18 2017 UTC (6 years, 6 months ago) by schoenebeck
File size: 48152 byte(s)
* NKSP: Added built-in script function "change_cutoff_attack()".
* NKSP: Added built-in script function "change_cutoff_decay()".
* NKSP: Added built-in script function "change_cutoff_sustain()".
* NKSP: Added built-in script function "change_cutoff_release()".
* NKSP: Added built-in script function "change_cutoff_lfo_depth()".
* NKSP: Added built-in script function "change_cutoff_lfo_freq()".
* Bumped version (2.0.0.svn77).

1 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003,2004 by Benno Senoner and Christian Schoenebeck *
6 * Copyright (C) 2005-2008 Christian Schoenebeck *
7 * Copyright (C) 2009-2012 Christian Schoenebeck and Grigor Iliev *
8 * Copyright (C) 2013-2017 Christian Schoenebeck and Andreas Persson *
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
19 * *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the Free Software *
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
23 * MA 02111-1307 USA *
24 ***************************************************************************/
25
26 #include "AbstractVoice.h"
27
28 namespace LinuxSampler {
29
30 AbstractVoice::AbstractVoice(SignalUnitRack* pRack): pSignalUnitRack(pRack) {
31 pEngineChannel = NULL;
32 pLFO1 = new LFOUnsigned(1.0f); // amplitude LFO (0..1 range)
33 pLFO2 = new LFOUnsigned(1.0f); // filter LFO (0..1 range)
34 pLFO3 = new LFOSigned(1200.0f); // pitch LFO (-1200..+1200 range)
35 PlaybackState = playback_state_end;
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 pEq = NULL;
49 bEqSupport = false;
50 }
51
52 AbstractVoice::~AbstractVoice() {
53 if (pLFO1) delete pLFO1;
54 if (pLFO2) delete pLFO2;
55 if (pLFO3) delete pLFO3;
56
57 if(pEq != NULL) delete pEq;
58 }
59
60 void AbstractVoice::CreateEq() {
61 if(!bEqSupport) return;
62 if(pEq != NULL) delete pEq;
63 pEq = new EqSupport;
64 pEq->InitEffect(GetEngine()->pAudioOutputDevice);
65 }
66
67 /**
68 * Resets voice variables. Should only be called if rendering process is
69 * suspended / not running.
70 */
71 void AbstractVoice::Reset() {
72 finalSynthesisParameters.filterLeft.Reset();
73 finalSynthesisParameters.filterRight.Reset();
74 DiskStreamRef.pStream = NULL;
75 DiskStreamRef.hStream = 0;
76 DiskStreamRef.State = Stream::state_unused;
77 DiskStreamRef.OrderID = 0;
78 PlaybackState = playback_state_end;
79 itTriggerEvent = Pool<Event>::Iterator();
80 itKillEvent = Pool<Event>::Iterator();
81 }
82
83 /**
84 * Initializes and triggers the voice, a disk stream will be launched if
85 * needed.
86 *
87 * @param pEngineChannel - engine channel on which this voice was ordered
88 * @param itNoteOnEvent - event that caused triggering of this voice
89 * @param PitchBend - MIDI detune factor (-8192 ... +8191)
90 * @param pRegion- points to the region which provides sample wave(s) and articulation data
91 * @param VoiceType - type of this voice
92 * @param iKeyGroup - a value > 0 defines a key group in which this voice is member of
93 * @returns 0 on success, a value < 0 if the voice wasn't triggered
94 * (either due to an error or e.g. because no region is
95 * defined for the given key)
96 */
97 int AbstractVoice::Trigger (
98 AbstractEngineChannel* pEngineChannel,
99 Pool<Event>::Iterator& itNoteOnEvent,
100 int PitchBend,
101 type_t VoiceType,
102 int iKeyGroup
103 ) {
104 this->pEngineChannel = pEngineChannel;
105 Orphan = false;
106
107 #if CONFIG_DEVMODE
108 if (itNoteOnEvent->FragmentPos() > GetEngine()->MaxSamplesPerCycle) { // just a sanity check for debugging
109 dmsg(1,("Voice::Trigger(): ERROR, TriggerDelay > Totalsamples\n"));
110 }
111 #endif // CONFIG_DEVMODE
112
113 Type = VoiceType;
114 pNote = pEngineChannel->pEngine->NoteByID( itNoteOnEvent->Param.Note.ID );
115 PlaybackState = playback_state_init; // mark voice as triggered, but no audio rendered yet
116 Delay = itNoteOnEvent->FragmentPos();
117 itTriggerEvent = itNoteOnEvent;
118 itKillEvent = Pool<Event>::Iterator();
119 MidiKeyBase* pKeyInfo = GetMidiKeyInfo(MIDIKey());
120
121 pGroupEvents = iKeyGroup ? pEngineChannel->ActiveKeyGroups[iKeyGroup] : 0;
122
123 SmplInfo = GetSampleInfo();
124 RgnInfo = GetRegionInfo();
125 InstrInfo = GetInstrumentInfo();
126
127 MIDIPan = CalculatePan(pEngineChannel->iLastPanRequest);
128
129 AboutToTrigger();
130
131 // calculate volume
132 const double velocityAttenuation = GetVelocityAttenuation(MIDIVelocity());
133 float volume = CalculateVolume(velocityAttenuation) * pKeyInfo->Volume;
134 if (volume <= 0) return -1;
135
136 // select channel mode (mono or stereo)
137 SYNTHESIS_MODE_SET_CHANNELS(SynthesisMode, SmplInfo.ChannelCount == 2);
138 // select bit depth (16 or 24)
139 SYNTHESIS_MODE_SET_BITDEPTH24(SynthesisMode, SmplInfo.BitDepth == 24);
140
141 // get starting crossfade volume level
142 float crossfadeVolume = CalculateCrossfadeVolume(MIDIVelocity());
143
144 VolumeLeft = volume * pKeyInfo->PanLeft;
145 VolumeRight = volume * pKeyInfo->PanRight;
146
147 // this rate is used for rather mellow volume fades
148 const float subfragmentRate = GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;
149 // this rate is used for very fast volume fades
150 const float quickRampRate = RTMath::Min(subfragmentRate, GetEngine()->SampleRate * 0.001f /* approx. 13ms */);
151 CrossfadeSmoother.trigger(crossfadeVolume, subfragmentRate);
152
153 VolumeSmoother.trigger(pEngineChannel->MidiVolume, subfragmentRate);
154 NoteVolume.setCurveOnly(pNote ? pNote->Override.VolumeCurve : DEFAULT_FADE_CURVE);
155 NoteVolume.setCurrentValue(pNote ? pNote->Override.Volume : 1.f);
156 NoteVolume.setDefaultDuration(pNote ? pNote->Override.VolumeTime : DEFAULT_NOTE_VOLUME_TIME_S);
157
158 // Check if the sample needs disk streaming or is too short for that
159 long cachedsamples = GetSampleCacheSize() / SmplInfo.FrameSize;
160 DiskVoice = cachedsamples < SmplInfo.TotalFrameCount;
161
162 SetSampleStartOffset();
163
164 if (DiskVoice) { // voice to be streamed from disk
165 if (cachedsamples > (GetEngine()->MaxSamplesPerCycle << CONFIG_MAX_PITCH)) {
166 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)
167 } else {
168 // The cache is too small to fit a max sample buffer.
169 // Setting MaxRAMPos to 0 will probably cause a click
170 // in the audio, but it's better than not handling
171 // this case at all, which would have caused the
172 // unsigned MaxRAMPos to be set to a negative number.
173 MaxRAMPos = 0;
174 }
175
176 // check if there's a loop defined which completely fits into the cached (RAM) part of the sample
177 RAMLoop = (SmplInfo.HasLoops && (SmplInfo.LoopStart + SmplInfo.LoopLength) <= MaxRAMPos);
178
179 if (OrderNewStream()) return -1;
180 dmsg(4,("Disk voice launched (cached samples: %ld, total Samples: %d, MaxRAMPos: %lu, RAMLooping: %s)\n", cachedsamples, SmplInfo.TotalFrameCount, MaxRAMPos, (RAMLoop) ? "yes" : "no"));
181 }
182 else { // RAM only voice
183 MaxRAMPos = cachedsamples;
184 RAMLoop = (SmplInfo.HasLoops);
185 dmsg(4,("RAM only voice launched (Looping: %s)\n", (RAMLoop) ? "yes" : "no"));
186 }
187 if (RAMLoop) {
188 loop.uiTotalCycles = SmplInfo.LoopPlayCount;
189 loop.uiCyclesLeft = SmplInfo.LoopPlayCount;
190 loop.uiStart = SmplInfo.LoopStart;
191 loop.uiEnd = SmplInfo.LoopStart + SmplInfo.LoopLength;
192 loop.uiSize = SmplInfo.LoopLength;
193 }
194
195 Pitch = CalculatePitchInfo(PitchBend);
196 NotePitch.setCurveOnly(pNote ? pNote->Override.PitchCurve : DEFAULT_FADE_CURVE);
197 NotePitch.setCurrentValue(pNote ? pNote->Override.Pitch : 1.0f);
198 NotePitch.setDefaultDuration(pNote ? pNote->Override.PitchTime : DEFAULT_NOTE_PITCH_TIME_S);
199 NoteCutoff = (pNote) ? pNote->Override.Cutoff : 1.0f;
200 NoteResonance = (pNote) ? pNote->Override.Resonance : 1.0f;
201
202 // the length of the decay and release curves are dependent on the velocity
203 const double velrelease = 1 / GetVelocityRelease(MIDIVelocity());
204
205 if (pSignalUnitRack == NULL) { // setup EG 1 (VCA EG)
206 // get current value of EG1 controller
207 double eg1controllervalue = GetEG1ControllerValue(MIDIVelocity());
208
209 // calculate influence of EG1 controller on EG1's parameters
210 EGInfo egInfo = CalculateEG1ControllerInfluence(eg1controllervalue);
211
212 if (pNote) {
213 egInfo.Attack *= pNote->Override.Attack;
214 egInfo.Decay *= pNote->Override.Decay;
215 egInfo.Release *= pNote->Override.Release;
216 }
217
218 TriggerEG1(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, MIDIVelocity());
219 } else {
220 pSignalUnitRack->Trigger();
221 }
222
223 const uint8_t pan = (pSignalUnitRack) ? pSignalUnitRack->GetEndpointUnit()->CalculatePan(MIDIPan) : MIDIPan;
224 for (int c = 0; c < 2; ++c) {
225 float value = (pNote) ? AbstractEngine::PanCurveValueNorm(pNote->Override.Pan, c) : 1.f;
226 NotePan[c].setCurveOnly(pNote ? pNote->Override.PanCurve : DEFAULT_FADE_CURVE);
227 NotePan[c].setCurrentValue(value);
228 NotePan[c].setDefaultDuration(pNote ? pNote->Override.PanTime : DEFAULT_NOTE_PAN_TIME_S);
229 }
230
231 PanLeftSmoother.trigger(
232 AbstractEngine::PanCurve[128 - pan],
233 quickRampRate //NOTE: maybe we should have 2 separate pan smoothers, one for MIDI CC10 (with slow rate) and one for instrument script change_pan() calls (with fast rate)
234 );
235 PanRightSmoother.trigger(
236 AbstractEngine::PanCurve[pan],
237 quickRampRate //NOTE: maybe we should have 2 separate pan smoothers, one for MIDI CC10 (with slow rate) and one for instrument script change_pan() calls (with fast rate)
238 );
239
240 #ifdef CONFIG_INTERPOLATE_VOLUME
241 // setup initial volume in synthesis parameters
242 #ifdef CONFIG_PROCESS_MUTED_CHANNELS
243 if (pEngineChannel->GetMute()) {
244 finalSynthesisParameters.fFinalVolumeLeft = 0;
245 finalSynthesisParameters.fFinalVolumeRight = 0;
246 }
247 else
248 #else
249 {
250 float finalVolume;
251 if (pSignalUnitRack == NULL) {
252 finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pEG1->getLevel();
253 } else {
254 finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pSignalUnitRack->GetEndpointUnit()->GetVolume();
255 }
256 finalVolume *= NoteVolume.currentValue();
257
258 finalSynthesisParameters.fFinalVolumeLeft = finalVolume * VolumeLeft * PanLeftSmoother.render() * NotePan[0].currentValue();
259 finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * PanRightSmoother.render() * NotePan[1].currentValue();
260 }
261 #endif
262 #endif
263
264 if (pSignalUnitRack == NULL) {
265 // setup EG 2 (VCF Cutoff EG)
266 {
267 // get current value of EG2 controller
268 double eg2controllervalue = GetEG2ControllerValue(MIDIVelocity());
269
270 // calculate influence of EG2 controller on EG2's parameters
271 EGInfo egInfo = CalculateEG2ControllerInfluence(eg2controllervalue);
272
273 if (pNote) {
274 egInfo.Attack *= pNote->Override.CutoffAttack;
275 egInfo.Decay *= pNote->Override.CutoffDecay;
276 egInfo.Release *= pNote->Override.CutoffRelease;
277 }
278
279 TriggerEG2(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, MIDIVelocity());
280 }
281
282
283 // setup EG 3 (VCO EG)
284 {
285 // if portamento mode is on, we dedicate EG3 purely for portamento, otherwise if portamento is off we do as told by the patch
286 bool bPortamento = pEngineChannel->PortamentoMode && pEngineChannel->PortamentoPos >= 0.0f;
287 float eg3depth = (bPortamento)
288 ? RTMath::CentsToFreqRatio((pEngineChannel->PortamentoPos - (float) MIDIKey()) * 100)
289 : RTMath::CentsToFreqRatio(RgnInfo.EG3Depth);
290 float eg3time = (bPortamento)
291 ? pEngineChannel->PortamentoTime
292 : RgnInfo.EG3Attack;
293 EG3.trigger(eg3depth, eg3time, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
294 dmsg(5,("PortamentoPos=%f, depth=%f, time=%f\n", pEngineChannel->PortamentoPos, eg3depth, eg3time));
295 }
296
297
298 // setup LFO 1 (VCA LFO)
299 InitLFO1();
300 // setup LFO 2 (VCF Cutoff LFO)
301 InitLFO2();
302 // setup LFO 3 (VCO LFO)
303 InitLFO3();
304 }
305
306
307 #if CONFIG_FORCE_FILTER
308 const bool bUseFilter = true;
309 #else // use filter only if instrument file told so
310 const bool bUseFilter = RgnInfo.VCFEnabled;
311 #endif // CONFIG_FORCE_FILTER
312 SYNTHESIS_MODE_SET_FILTER(SynthesisMode, bUseFilter);
313 if (bUseFilter) {
314 #ifdef CONFIG_OVERRIDE_CUTOFF_CTRL
315 VCFCutoffCtrl.controller = CONFIG_OVERRIDE_CUTOFF_CTRL;
316 #else // use the one defined in the instrument file
317 VCFCutoffCtrl.controller = GetVCFCutoffCtrl();
318 #endif // CONFIG_OVERRIDE_CUTOFF_CTRL
319
320 #ifdef CONFIG_OVERRIDE_RESONANCE_CTRL
321 VCFResonanceCtrl.controller = CONFIG_OVERRIDE_RESONANCE_CTRL;
322 #else // use the one defined in the instrument file
323 VCFResonanceCtrl.controller = GetVCFResonanceCtrl();
324 #endif // CONFIG_OVERRIDE_RESONANCE_CTRL
325
326 #ifndef CONFIG_OVERRIDE_FILTER_TYPE
327 finalSynthesisParameters.filterLeft.SetType(RgnInfo.VCFType);
328 finalSynthesisParameters.filterRight.SetType(RgnInfo.VCFType);
329 #else // override filter type
330 finalSynthesisParameters.filterLeft.SetType(CONFIG_OVERRIDE_FILTER_TYPE);
331 finalSynthesisParameters.filterRight.SetType(CONFIG_OVERRIDE_FILTER_TYPE);
332 #endif // CONFIG_OVERRIDE_FILTER_TYPE
333
334 VCFCutoffCtrl.value = pEngineChannel->ControllerTable[VCFCutoffCtrl.controller];
335 VCFResonanceCtrl.value = pEngineChannel->ControllerTable[VCFResonanceCtrl.controller];
336
337 // calculate cutoff frequency
338 CutoffBase = CalculateCutoffBase(MIDIVelocity());
339
340 VCFCutoffCtrl.fvalue = CalculateFinalCutoff(CutoffBase);
341
342 // calculate resonance
343 float resonance = (float) (VCFResonanceCtrl.controller ? VCFResonanceCtrl.value : RgnInfo.VCFResonance);
344 VCFResonanceCtrl.fvalue = resonance;
345 } else {
346 VCFCutoffCtrl.controller = 0;
347 VCFResonanceCtrl.controller = 0;
348 }
349
350 const bool bEq =
351 pSignalUnitRack != NULL && pSignalUnitRack->HasEq() && pEq->HasSupport();
352
353 if (bEq) {
354 pEq->GetInChannelLeft()->Clear();
355 pEq->GetInChannelRight()->Clear();
356 pEq->RenderAudio(GetEngine()->pAudioOutputDevice->MaxSamplesPerCycle());
357 }
358
359 return 0; // success
360 }
361
362 void AbstractVoice::SetSampleStartOffset() {
363 double pos = RgnInfo.SampleStartOffset; // offset where we should start playback of sample
364
365 // if another sample playback start position was requested by instrument
366 // script (built-in script function play_note())
367 if (pNote && pNote->Override.SampleOffset >= 0) {
368 double overridePos =
369 double(SmplInfo.SampleRate) * double(pNote->Override.SampleOffset) / 1000000.0;
370 if (overridePos < SmplInfo.TotalFrameCount)
371 pos = overridePos;
372 }
373
374 finalSynthesisParameters.dPos = pos;
375 Pos = pos;
376 }
377
378 /**
379 * Synthesizes the current audio fragment for this voice.
380 *
381 * @param Samples - number of sample points to be rendered in this audio
382 * fragment cycle
383 * @param pSrc - pointer to input sample data
384 * @param Skip - number of sample points to skip in output buffer
385 */
386 void AbstractVoice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {
387 bool delay = false; // Whether the voice playback should be delayed for this call
388
389 if (pSignalUnitRack != NULL) {
390 uint delaySteps = pSignalUnitRack->GetEndpointUnit()->DelayTrigger();
391 if (delaySteps > 0) { // delay on the endpoint unit means delay of the voice playback
392 if (delaySteps >= Samples) {
393 pSignalUnitRack->GetEndpointUnit()->DecreaseDelay(Samples);
394 delay = true;
395 } else {
396 pSignalUnitRack->GetEndpointUnit()->DecreaseDelay(delaySteps);
397 Samples -= delaySteps;
398 Skip += delaySteps;
399 }
400 }
401 }
402
403 AbstractEngineChannel* pChannel = pEngineChannel;
404 MidiKeyBase* pMidiKeyInfo = GetMidiKeyInfo(MIDIKey());
405
406 const bool bVoiceRequiresDedicatedRouting =
407 pEngineChannel->GetFxSendCount() > 0 &&
408 (pMidiKeyInfo->ReverbSend || pMidiKeyInfo->ChorusSend);
409
410 const bool bEq =
411 pSignalUnitRack != NULL && pSignalUnitRack->HasEq() && pEq->HasSupport();
412
413 if (bEq) {
414 pEq->GetInChannelLeft()->Clear();
415 pEq->GetInChannelRight()->Clear();
416 finalSynthesisParameters.pOutLeft = &pEq->GetInChannelLeft()->Buffer()[Skip];
417 finalSynthesisParameters.pOutRight = &pEq->GetInChannelRight()->Buffer()[Skip];
418 pSignalUnitRack->UpdateEqSettings(pEq);
419 } else if (bVoiceRequiresDedicatedRouting) {
420 finalSynthesisParameters.pOutLeft = &GetEngine()->pDedicatedVoiceChannelLeft->Buffer()[Skip];
421 finalSynthesisParameters.pOutRight = &GetEngine()->pDedicatedVoiceChannelRight->Buffer()[Skip];
422 } else {
423 finalSynthesisParameters.pOutLeft = &pChannel->pChannelLeft->Buffer()[Skip];
424 finalSynthesisParameters.pOutRight = &pChannel->pChannelRight->Buffer()[Skip];
425 }
426 finalSynthesisParameters.pSrc = pSrc;
427
428 RTList<Event>::Iterator itCCEvent = pChannel->pEvents->first();
429 RTList<Event>::Iterator itNoteEvent;
430 GetFirstEventOnKey(HostKey(), itNoteEvent);
431
432 RTList<Event>::Iterator itGroupEvent;
433 if (pGroupEvents && !Orphan) itGroupEvent = pGroupEvents->first();
434
435 if (itTriggerEvent) { // skip events that happened before this voice was triggered
436 while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;
437 while (itGroupEvent && itGroupEvent->FragmentPos() <= Skip) ++itGroupEvent;
438
439 // we can't simply compare the timestamp here, because note events
440 // might happen on the same time stamp, so we have to deal on the
441 // actual sequence the note events arrived instead (see bug #112)
442 for (; itNoteEvent; ++itNoteEvent) {
443 if (itTriggerEvent == itNoteEvent) {
444 ++itNoteEvent;
445 break;
446 }
447 }
448 }
449
450 uint killPos = 0;
451 if (itKillEvent) {
452 int maxFadeOutPos = Samples - GetEngine()->GetMinFadeOutSamples();
453 if (maxFadeOutPos < 0) {
454 // There's not enough space in buffer to do a fade out
455 // from max volume (this can only happen for audio
456 // drivers that use Samples < MaxSamplesPerCycle).
457 // End the EG1 here, at pos 0, with a shorter max fade
458 // out time.
459 if (pSignalUnitRack == NULL) {
460 pEG1->enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
461 } else {
462 pSignalUnitRack->EnterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
463 }
464 itKillEvent = Pool<Event>::Iterator();
465 } else {
466 killPos = RTMath::Min(itKillEvent->FragmentPos(), maxFadeOutPos);
467 }
468 }
469
470 uint i = Skip;
471 while (i < Samples) {
472 int iSubFragmentEnd = RTMath::Min(i + CONFIG_DEFAULT_SUBFRAGMENT_SIZE, Samples);
473
474 // initialize all final synthesis parameters
475 fFinalCutoff = VCFCutoffCtrl.fvalue;
476 fFinalResonance = VCFResonanceCtrl.fvalue;
477
478 // process MIDI control change, aftertouch and pitchbend events for this subfragment
479 processCCEvents(itCCEvent, iSubFragmentEnd);
480 uint8_t pan = MIDIPan;
481 if (pSignalUnitRack != NULL) pan = pSignalUnitRack->GetEndpointUnit()->CalculatePan(MIDIPan);
482
483 PanLeftSmoother.update(AbstractEngine::PanCurve[128 - pan]);
484 PanRightSmoother.update(AbstractEngine::PanCurve[pan]);
485
486 finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend * NotePitch.render();
487
488 float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render() * NoteVolume.render();
489 #ifdef CONFIG_PROCESS_MUTED_CHANNELS
490 if (pChannel->GetMute()) fFinalVolume = 0;
491 #endif
492
493 // process transition events (note on, note off & sustain pedal)
494 processTransitionEvents(itNoteEvent, iSubFragmentEnd);
495 processGroupEvents(itGroupEvent, iSubFragmentEnd);
496
497 if (pSignalUnitRack == NULL) {
498 // if the voice was killed in this subfragment, or if the
499 // filter EG is finished, switch EG1 to fade out stage
500 if ((itKillEvent && killPos <= iSubFragmentEnd) ||
501 (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&
502 pEG2->getSegmentType() == EG::segment_end)) {
503 pEG1->enterFadeOutStage();
504 itKillEvent = Pool<Event>::Iterator();
505 }
506
507 // process envelope generators
508 switch (pEG1->getSegmentType()) {
509 case EG::segment_lin:
510 fFinalVolume *= pEG1->processLin();
511 break;
512 case EG::segment_exp:
513 fFinalVolume *= pEG1->processExp();
514 break;
515 case EG::segment_end:
516 fFinalVolume *= pEG1->getLevel();
517 break; // noop
518 case EG::segment_pow:
519 fFinalVolume *= pEG1->processPow();
520 break;
521 }
522 switch (pEG2->getSegmentType()) {
523 case EG::segment_lin:
524 fFinalCutoff *= pEG2->processLin();
525 break;
526 case EG::segment_exp:
527 fFinalCutoff *= pEG2->processExp();
528 break;
529 case EG::segment_end:
530 fFinalCutoff *= pEG2->getLevel();
531 break; // noop
532 case EG::segment_pow:
533 fFinalCutoff *= pEG2->processPow();
534 break;
535 }
536 if (EG3.active()) finalSynthesisParameters.fFinalPitch *= EG3.render();
537
538 // process low frequency oscillators
539 if (bLFO1Enabled) fFinalVolume *= (1.0f - pLFO1->render());
540 if (bLFO2Enabled) fFinalCutoff *= (1.0f - pLFO2->render());
541 if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());
542 } else {
543 // if the voice was killed in this subfragment, enter fade out stage
544 if (itKillEvent && killPos <= iSubFragmentEnd) {
545 pSignalUnitRack->EnterFadeOutStage();
546 itKillEvent = Pool<Event>::Iterator();
547 }
548
549 // if the filter EG is finished, switch EG1 to fade out stage
550 /*if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&
551 pEG2->getSegmentType() == EG::segment_end) {
552 pEG1->enterFadeOutStage();
553 itKillEvent = Pool<Event>::Iterator();
554 }*/
555 // TODO: ^^^
556
557 fFinalVolume *= pSignalUnitRack->GetEndpointUnit()->GetVolume();
558 fFinalCutoff = pSignalUnitRack->GetEndpointUnit()->CalculateFilterCutoff(fFinalCutoff);
559 fFinalResonance = pSignalUnitRack->GetEndpointUnit()->CalculateResonance(fFinalResonance);
560
561 finalSynthesisParameters.fFinalPitch =
562 pSignalUnitRack->GetEndpointUnit()->CalculatePitch(finalSynthesisParameters.fFinalPitch);
563
564 }
565
566 fFinalCutoff *= NoteCutoff;
567 fFinalResonance *= NoteResonance;
568
569 // limit the pitch so we don't read outside the buffer
570 finalSynthesisParameters.fFinalPitch = RTMath::Min(finalSynthesisParameters.fFinalPitch, float(1 << CONFIG_MAX_PITCH));
571
572 // if filter enabled then update filter coefficients
573 if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode)) {
574 finalSynthesisParameters.filterLeft.SetParameters(fFinalCutoff, fFinalResonance, GetEngine()->SampleRate);
575 finalSynthesisParameters.filterRight.SetParameters(fFinalCutoff, fFinalResonance, GetEngine()->SampleRate);
576 }
577
578 // do we need resampling?
579 const float __PLUS_ONE_CENT = 1.000577789506554859250142541782224725466f;
580 const float __MINUS_ONE_CENT = 0.9994225441413807496009516495583113737666f;
581 const bool bResamplingRequired = !(finalSynthesisParameters.fFinalPitch <= __PLUS_ONE_CENT &&
582 finalSynthesisParameters.fFinalPitch >= __MINUS_ONE_CENT);
583 SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, bResamplingRequired);
584
585 // prepare final synthesis parameters structure
586 finalSynthesisParameters.uiToGo = iSubFragmentEnd - i;
587 #ifdef CONFIG_INTERPOLATE_VOLUME
588 finalSynthesisParameters.fFinalVolumeDeltaLeft =
589 (fFinalVolume * VolumeLeft * PanLeftSmoother.render() * NotePan[0].render() -
590 finalSynthesisParameters.fFinalVolumeLeft) / finalSynthesisParameters.uiToGo;
591 finalSynthesisParameters.fFinalVolumeDeltaRight =
592 (fFinalVolume * VolumeRight * PanRightSmoother.render() * NotePan[1].render() -
593 finalSynthesisParameters.fFinalVolumeRight) / finalSynthesisParameters.uiToGo;
594 #else
595 finalSynthesisParameters.fFinalVolumeLeft =
596 fFinalVolume * VolumeLeft * PanLeftSmoother.render() * NotePan[0].render();
597 finalSynthesisParameters.fFinalVolumeRight =
598 fFinalVolume * VolumeRight * PanRightSmoother.render() * NotePan[1].render();
599 #endif
600 // render audio for one subfragment
601 if (!delay) RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);
602
603 if (pSignalUnitRack == NULL) {
604 // stop the rendering if volume EG is finished
605 if (pEG1->getSegmentType() == EG::segment_end) break;
606 } else {
607 // stop the rendering if the endpoint unit is not active
608 if (!pSignalUnitRack->GetEndpointUnit()->Active()) break;
609 }
610
611 const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;
612
613 if (pSignalUnitRack == NULL) {
614 // increment envelopes' positions
615 if (pEG1->active()) {
616
617 // 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
618 if (SmplInfo.HasLoops && Pos <= SmplInfo.LoopStart && SmplInfo.LoopStart < newPos) {
619 pEG1->update(EG::event_hold_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
620 }
621
622 pEG1->increment(1);
623 if (!pEG1->toStageEndLeft()) pEG1->update(EG::event_stage_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
624 }
625 if (pEG2->active()) {
626 pEG2->increment(1);
627 if (!pEG2->toStageEndLeft()) pEG2->update(EG::event_stage_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
628 }
629 EG3.increment(1);
630 if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached
631 } else {
632 // 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
633 /*if (SmplInfo.HasLoops && Pos <= SmplInfo.LoopStart && SmplInfo.LoopStart < newPos) {
634 pEG1->update(EG::event_hold_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
635 }*/
636 // TODO: ^^^
637
638 if (!delay) pSignalUnitRack->Increment();
639 }
640
641 Pos = newPos;
642 i = iSubFragmentEnd;
643 }
644
645 if (delay) return;
646
647 if (bVoiceRequiresDedicatedRouting) {
648 if (bEq) {
649 pEq->RenderAudio(Samples);
650 pEq->GetOutChannelLeft()->CopyTo(GetEngine()->pDedicatedVoiceChannelLeft, Samples);
651 pEq->GetOutChannelRight()->CopyTo(GetEngine()->pDedicatedVoiceChannelRight, Samples);
652 }
653 optional<float> effectSendLevels[2] = {
654 pMidiKeyInfo->ReverbSend,
655 pMidiKeyInfo->ChorusSend
656 };
657 GetEngine()->RouteDedicatedVoiceChannels(pEngineChannel, effectSendLevels, Samples);
658 } else if (bEq) {
659 pEq->RenderAudio(Samples);
660 pEq->GetOutChannelLeft()->MixTo(pChannel->pChannelLeft, Samples);
661 pEq->GetOutChannelRight()->MixTo(pChannel->pChannelRight, Samples);
662 }
663 }
664
665 /**
666 * Process given list of MIDI control change, aftertouch and pitch bend
667 * events for the given time.
668 *
669 * @param itEvent - iterator pointing to the next event to be processed
670 * @param End - youngest time stamp where processing should be stopped
671 */
672 void AbstractVoice::processCCEvents(RTList<Event>::Iterator& itEvent, uint End) {
673 for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
674 if ((itEvent->Type == Event::type_control_change || itEvent->Type == Event::type_channel_pressure)
675 && itEvent->Param.CC.Controller) // if (valid) MIDI control change event
676 {
677 if (itEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {
678 ProcessCutoffEvent(itEvent);
679 }
680 if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {
681 processResonanceEvent(itEvent);
682 }
683 if (itEvent->Param.CC.Controller == CTRL_TABLE_IDX_AFTERTOUCH ||
684 itEvent->Type == Event::type_channel_pressure)
685 {
686 ProcessChannelPressureEvent(itEvent);
687 }
688 if (pSignalUnitRack == NULL) {
689 if (itEvent->Param.CC.Controller == pLFO1->ExtController) {
690 pLFO1->updateByMIDICtrlValue(itEvent->Param.CC.Value);
691 }
692 if (itEvent->Param.CC.Controller == pLFO2->ExtController) {
693 pLFO2->updateByMIDICtrlValue(itEvent->Param.CC.Value);
694 }
695 if (itEvent->Param.CC.Controller == pLFO3->ExtController) {
696 pLFO3->updateByMIDICtrlValue(itEvent->Param.CC.Value);
697 }
698 }
699 if (itEvent->Param.CC.Controller == 7) { // volume
700 VolumeSmoother.update(AbstractEngine::VolumeCurve[itEvent->Param.CC.Value]);
701 } else if (itEvent->Param.CC.Controller == 10) { // panpot
702 MIDIPan = CalculatePan(itEvent->Param.CC.Value);
703 }
704 } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event
705 processPitchEvent(itEvent);
706 } else if (itEvent->Type == Event::type_note_pressure) {
707 ProcessPolyphonicKeyPressureEvent(itEvent);
708 }
709
710 ProcessCCEvent(itEvent);
711 if (pSignalUnitRack != NULL) {
712 pSignalUnitRack->ProcessCCEvent(itEvent);
713 }
714 }
715 }
716
717 void AbstractVoice::processPitchEvent(RTList<Event>::Iterator& itEvent) {
718 Pitch.PitchBend = RTMath::CentsToFreqRatio(itEvent->Param.Pitch.Pitch * Pitch.PitchBendRange);
719 }
720
721 void AbstractVoice::processResonanceEvent(RTList<Event>::Iterator& itEvent) {
722 // convert absolute controller value to differential
723 const int ctrldelta = itEvent->Param.CC.Value - VCFResonanceCtrl.value;
724 VCFResonanceCtrl.value = itEvent->Param.CC.Value;
725 const float resonancedelta = (float) ctrldelta;
726 fFinalResonance += resonancedelta;
727 // needed for initialization of parameter
728 VCFResonanceCtrl.fvalue = itEvent->Param.CC.Value;
729 }
730
731 /**
732 * Process given list of MIDI note on, note off, sustain pedal events and
733 * note synthesis parameter events for the given time.
734 *
735 * @param itEvent - iterator pointing to the next event to be processed
736 * @param End - youngest time stamp where processing should be stopped
737 */
738 void AbstractVoice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) {
739 for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
740 // some voice types ignore note off
741 if (!(Type & (Voice::type_one_shot | Voice::type_release_trigger | Voice::type_controller_triggered))) {
742 if (itEvent->Type == Event::type_release_key) {
743 EnterReleaseStage();
744 } else if (itEvent->Type == Event::type_cancel_release_key) {
745 if (pSignalUnitRack == NULL) {
746 pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
747 pEG2->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
748 } else {
749 pSignalUnitRack->CancelRelease();
750 }
751 }
752 }
753 // process stop-note events (caused by built-in instrument script function note_off())
754 if (itEvent->Type == Event::type_release_note && pNote &&
755 pEngineChannel->pEngine->NoteByID( itEvent->Param.Note.ID ) == pNote)
756 {
757 EnterReleaseStage();
758 }
759 // process kill-note events (caused by built-in instrument script function fade_out())
760 if (itEvent->Type == Event::type_kill_note && pNote &&
761 pEngineChannel->pEngine->NoteByID( itEvent->Param.Note.ID ) == pNote)
762 {
763 Kill(itEvent);
764 }
765 // process synthesis parameter events (caused by built-in realt-time instrument script functions)
766 if (itEvent->Type == Event::type_note_synth_param && pNote &&
767 pEngineChannel->pEngine->NoteByID( itEvent->Param.NoteSynthParam.NoteID ) == pNote)
768 {
769 switch (itEvent->Param.NoteSynthParam.Type) {
770 case Event::synth_param_volume:
771 NoteVolume.fadeTo(itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
772 break;
773 case Event::synth_param_volume_time:
774 NoteVolume.setDefaultDuration(itEvent->Param.NoteSynthParam.AbsValue);
775 break;
776 case Event::synth_param_volume_curve:
777 NoteVolume.setCurve((fade_curve_t)itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
778 break;
779 case Event::synth_param_pitch:
780 NotePitch.fadeTo(itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
781 break;
782 case Event::synth_param_pitch_time:
783 NotePitch.setDefaultDuration(itEvent->Param.NoteSynthParam.AbsValue);
784 break;
785 case Event::synth_param_pitch_curve:
786 NotePitch.setCurve((fade_curve_t)itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
787 break;
788 case Event::synth_param_pan:
789 NotePan[0].fadeTo(
790 AbstractEngine::PanCurveValueNorm(itEvent->Param.NoteSynthParam.AbsValue, 0 /*left*/),
791 GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE
792 );
793 NotePan[1].fadeTo(
794 AbstractEngine::PanCurveValueNorm(itEvent->Param.NoteSynthParam.AbsValue, 1 /*right*/),
795 GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE
796 );
797 break;
798 case Event::synth_param_pan_time:
799 NotePan[0].setDefaultDuration(itEvent->Param.NoteSynthParam.AbsValue);
800 NotePan[1].setDefaultDuration(itEvent->Param.NoteSynthParam.AbsValue);
801 break;
802 case Event::synth_param_pan_curve:
803 NotePan[0].setCurve((fade_curve_t)itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
804 NotePan[1].setCurve((fade_curve_t)itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
805 break;
806 case Event::synth_param_cutoff:
807 NoteCutoff = itEvent->Param.NoteSynthParam.AbsValue;
808 break;
809 case Event::synth_param_resonance:
810 NoteResonance = itEvent->Param.NoteSynthParam.AbsValue;
811 break;
812 case Event::synth_param_amp_lfo_depth:
813 pLFO1->setScriptDepthFactor(itEvent->Param.NoteSynthParam.AbsValue);
814 break;
815 case Event::synth_param_amp_lfo_freq:
816 pLFO1->setScriptFrequencyFactor(itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
817 break;
818 case Event::synth_param_cutoff_lfo_depth:
819 pLFO2->setScriptDepthFactor(itEvent->Param.NoteSynthParam.AbsValue);
820 break;
821 case Event::synth_param_cutoff_lfo_freq:
822 pLFO2->setScriptFrequencyFactor(itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
823 break;
824 case Event::synth_param_pitch_lfo_depth:
825 pLFO3->setScriptDepthFactor(itEvent->Param.NoteSynthParam.AbsValue);
826 break;
827 case Event::synth_param_pitch_lfo_freq:
828 pLFO3->setScriptFrequencyFactor(itEvent->Param.NoteSynthParam.AbsValue, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
829 break;
830
831 case Event::synth_param_attack:
832 case Event::synth_param_decay:
833 case Event::synth_param_sustain:
834 case Event::synth_param_release:
835 break; // noop
836 }
837 }
838 }
839 }
840
841 /**
842 * Process given list of events aimed at all voices in a key group.
843 *
844 * @param itEvent - iterator pointing to the next event to be processed
845 * @param End - youngest time stamp where processing should be stopped
846 */
847 void AbstractVoice::processGroupEvents(RTList<Event>::Iterator& itEvent, uint End) {
848 for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
849 ProcessGroupEvent(itEvent);
850 }
851 }
852
853 /** @brief Update current portamento position.
854 *
855 * Will be called when portamento mode is enabled to get the final
856 * portamento position of this active voice from where the next voice(s)
857 * might continue to slide on.
858 *
859 * @param itNoteOffEvent - event which causes this voice to die soon
860 */
861 void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {
862 if (pSignalUnitRack == NULL) {
863 const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());
864 pEngineChannel->PortamentoPos = (float) MIDIKey() + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;
865 } else {
866 // TODO:
867 }
868 }
869
870 /**
871 * Kill the voice in regular sense. Let the voice render audio until
872 * the kill event actually occured and then fade down the volume level
873 * very quickly and let the voice die finally. Unlike a normal release
874 * of a voice, a kill process cannot be cancalled and is therefore
875 * usually used for voice stealing and key group conflicts.
876 *
877 * @param itKillEvent - event which caused the voice to be killed
878 */
879 void AbstractVoice::Kill(Pool<Event>::Iterator& itKillEvent) {
880 #if CONFIG_DEVMODE
881 if (!itKillEvent) dmsg(1,("AbstractVoice::Kill(): ERROR, !itKillEvent !!!\n"));
882 if (itKillEvent && !itKillEvent.isValid()) dmsg(1,("AbstractVoice::Kill(): ERROR, itKillEvent invalid !!!\n"));
883 #endif // CONFIG_DEVMODE
884
885 if (itTriggerEvent && itKillEvent->FragmentPos() <= itTriggerEvent->FragmentPos()) return;
886 this->itKillEvent = itKillEvent;
887 }
888
889 Voice::PitchInfo AbstractVoice::CalculatePitchInfo(int PitchBend) {
890 PitchInfo pitch;
891 double pitchbasecents = InstrInfo.FineTune + RgnInfo.FineTune + GetEngine()->ScaleTuning[MIDIKey() % 12];
892
893 // GSt behaviour: maximum transpose up is 40 semitones. If
894 // MIDI key is more than 40 semitones above unity note,
895 // the transpose is not done.
896 //
897 // Update: Removed this GSt misbehavior. I don't think that any stock
898 // gig sound requires it to resemble its original sound.
899 // -- Christian, 2017-07-09
900 if (!SmplInfo.Unpitched /* && (MIDIKey() - (int) RgnInfo.UnityNote) < 40*/)
901 pitchbasecents += (MIDIKey() - (int) RgnInfo.UnityNote) * 100;
902
903 pitch.PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(SmplInfo.SampleRate) / double(GetEngine()->SampleRate));
904 pitch.PitchBendRange = 1.0 / 8192.0 * 100.0 * InstrInfo.PitchbendRange;
905 pitch.PitchBend = RTMath::CentsToFreqRatio(PitchBend * pitch.PitchBendRange);
906
907 return pitch;
908 }
909
910 void AbstractVoice::onScaleTuningChanged() {
911 PitchInfo pitch = this->Pitch;
912 double pitchbasecents = InstrInfo.FineTune + RgnInfo.FineTune + GetEngine()->ScaleTuning[MIDIKey() % 12];
913
914 // GSt behaviour: maximum transpose up is 40 semitones. If
915 // MIDI key is more than 40 semitones above unity note,
916 // the transpose is not done.
917 //
918 // Update: Removed this GSt misbehavior. I don't think that any stock
919 // gig sound requires it to resemble its original sound.
920 // -- Christian, 2017-07-09
921 if (!SmplInfo.Unpitched /* && (MIDIKey() - (int) RgnInfo.UnityNote) < 40*/)
922 pitchbasecents += (MIDIKey() - (int) RgnInfo.UnityNote) * 100;
923
924 pitch.PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(SmplInfo.SampleRate) / double(GetEngine()->SampleRate));
925 this->Pitch = pitch;
926 }
927
928 double AbstractVoice::CalculateVolume(double velocityAttenuation) {
929 // For 16 bit samples, we downscale by 32768 to convert from
930 // int16 value range to DSP value range (which is
931 // -1.0..1.0). For 24 bit, we downscale from int32.
932 float volume = velocityAttenuation / (SmplInfo.BitDepth == 16 ? 32768.0f : 32768.0f * 65536.0f);
933
934 volume *= GetSampleAttenuation() * pEngineChannel->GlobalVolume * GLOBAL_VOLUME;
935
936 // the volume of release triggered samples depends on note length
937 if (Type & Voice::type_release_trigger) {
938 float noteLength = float(GetEngine()->FrameTime + Delay -
939 GetNoteOnTime(MIDIKey()) ) / GetEngine()->SampleRate;
940
941 volume *= GetReleaseTriggerAttenuation(noteLength);
942 }
943
944 return volume;
945 }
946
947 float AbstractVoice::GetReleaseTriggerAttenuation(float noteLength) {
948 return 1 - RgnInfo.ReleaseTriggerDecay * noteLength;
949 }
950
951 void AbstractVoice::EnterReleaseStage() {
952 if (pSignalUnitRack == NULL) {
953 pEG1->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
954 pEG2->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
955 } else {
956 pSignalUnitRack->EnterReleaseStage();
957 }
958 }
959
960 bool AbstractVoice::EG1Finished() {
961 if (pSignalUnitRack == NULL) {
962 return pEG1->getSegmentType() == EG::segment_end;
963 } else {
964 return !pSignalUnitRack->GetEndpointUnit()->Active();
965 }
966 }
967
968 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC