/[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 3616 - (show annotations) (download)
Tue Oct 1 10:50:29 2019 UTC (6 months ago) by schoenebeck
File size: 50256 byte(s)
* Gig engine: Changed default wave form for all 3 LFOs to sine
  (instead of triangle; see discussion "GigaStudio LFO
  compatibility" on mailing list from 2019-09-26 for details).
* Bumped version (2.1.1.svn21).

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

  ViewVC Help
Powered by ViewVC