/[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 3724 - (show annotations) (download)
Thu Jan 23 18:15:37 2020 UTC (4 years, 2 months ago) by schoenebeck
File size: 51048 byte(s)
* Fixed crash when editing key groups (a.k.a. exclusive groups)
  with an instrument editor during playback.

* Bumped version (2.1.1.svn41).

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

  ViewVC Help
Powered by ViewVC