/[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 2953 - (show annotations) (download)
Sat Jul 16 11:24:39 2016 UTC (7 years, 9 months ago) by schoenebeck
File size: 41881 byte(s)
* NKSP: Implemented built-in script function "change_attack()".
* NKSP: Implemented built-in script function "change_decay()".
* NKSP: Implemented built-in script function "change_release()".
* Bumped version (2.0.0.svn19).

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

  ViewVC Help
Powered by ViewVC