/[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 2938 - (show annotations) (download)
Mon Jul 11 17:10:40 2016 UTC (3 years, 3 months ago) by schoenebeck
File size: 41667 byte(s)
* Fixed behavior of built-in instrument script functions play_note()
  and note_off(), which must be distinguished engine internally
  from "real" MIDI note on/off events in order to avoid
  misbehaviors like hanging notes.
* Bumped version (2.0.0.svn13).

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 TriggerEG1(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity);
204 } else {
205 pSignalUnitRack->Trigger();
206 }
207
208 const uint8_t pan = (pSignalUnitRack) ? pSignalUnitRack->GetEndpointUnit()->CalculatePan(MIDIPan) : MIDIPan;
209 NotePanLeft = (pNote) ? AbstractEngine::PanCurveValueNorm(pNote->Override.Pan, 0 /*left*/ ) : 1.f;
210 NotePanRight = (pNote) ? AbstractEngine::PanCurveValueNorm(pNote->Override.Pan, 1 /*right*/) : 1.f;
211 PanLeftSmoother.trigger(
212 AbstractEngine::PanCurve[128 - pan] * NotePanLeft,
213 subfragmentRate
214 );
215 PanRightSmoother.trigger(
216 AbstractEngine::PanCurve[pan] * NotePanRight,
217 subfragmentRate
218 );
219
220 #ifdef CONFIG_INTERPOLATE_VOLUME
221 // setup initial volume in synthesis parameters
222 #ifdef CONFIG_PROCESS_MUTED_CHANNELS
223 if (pEngineChannel->GetMute()) {
224 finalSynthesisParameters.fFinalVolumeLeft = 0;
225 finalSynthesisParameters.fFinalVolumeRight = 0;
226 }
227 else
228 #else
229 {
230 float finalVolume;
231 if (pSignalUnitRack == NULL) {
232 finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pEG1->getLevel();
233 } else {
234 finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pSignalUnitRack->GetEndpointUnit()->GetVolume();
235 }
236
237 finalSynthesisParameters.fFinalVolumeLeft = finalVolume * VolumeLeft * PanLeftSmoother.render();
238 finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * PanRightSmoother.render();
239 }
240 #endif
241 #endif
242
243 if (pSignalUnitRack == NULL) {
244 // setup EG 2 (VCF Cutoff EG)
245 {
246 // get current value of EG2 controller
247 double eg2controllervalue = GetEG2ControllerValue(itNoteOnEvent->Param.Note.Velocity);
248
249 // calculate influence of EG2 controller on EG2's parameters
250 EGInfo egInfo = CalculateEG2ControllerInfluence(eg2controllervalue);
251
252 TriggerEG2(egInfo, velrelease, velocityAttenuation, GetEngine()->SampleRate, itNoteOnEvent->Param.Note.Velocity);
253 }
254
255
256 // setup EG 3 (VCO EG)
257 {
258 // if portamento mode is on, we dedicate EG3 purely for portamento, otherwise if portamento is off we do as told by the patch
259 bool bPortamento = pEngineChannel->PortamentoMode && pEngineChannel->PortamentoPos >= 0.0f;
260 float eg3depth = (bPortamento)
261 ? RTMath::CentsToFreqRatio((pEngineChannel->PortamentoPos - (float) MIDIKey()) * 100)
262 : RTMath::CentsToFreqRatio(RgnInfo.EG3Depth);
263 float eg3time = (bPortamento)
264 ? pEngineChannel->PortamentoTime
265 : RgnInfo.EG3Attack;
266 EG3.trigger(eg3depth, eg3time, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
267 dmsg(5,("PortamentoPos=%f, depth=%f, time=%f\n", pEngineChannel->PortamentoPos, eg3depth, eg3time));
268 }
269
270
271 // setup LFO 1 (VCA LFO)
272 InitLFO1();
273 // setup LFO 2 (VCF Cutoff LFO)
274 InitLFO2();
275 // setup LFO 3 (VCO LFO)
276 InitLFO3();
277 }
278
279
280 #if CONFIG_FORCE_FILTER
281 const bool bUseFilter = true;
282 #else // use filter only if instrument file told so
283 const bool bUseFilter = RgnInfo.VCFEnabled;
284 #endif // CONFIG_FORCE_FILTER
285 SYNTHESIS_MODE_SET_FILTER(SynthesisMode, bUseFilter);
286 if (bUseFilter) {
287 #ifdef CONFIG_OVERRIDE_CUTOFF_CTRL
288 VCFCutoffCtrl.controller = CONFIG_OVERRIDE_CUTOFF_CTRL;
289 #else // use the one defined in the instrument file
290 VCFCutoffCtrl.controller = GetVCFCutoffCtrl();
291 #endif // CONFIG_OVERRIDE_CUTOFF_CTRL
292
293 #ifdef CONFIG_OVERRIDE_RESONANCE_CTRL
294 VCFResonanceCtrl.controller = CONFIG_OVERRIDE_RESONANCE_CTRL;
295 #else // use the one defined in the instrument file
296 VCFResonanceCtrl.controller = GetVCFResonanceCtrl();
297 #endif // CONFIG_OVERRIDE_RESONANCE_CTRL
298
299 #ifndef CONFIG_OVERRIDE_FILTER_TYPE
300 finalSynthesisParameters.filterLeft.SetType(RgnInfo.VCFType);
301 finalSynthesisParameters.filterRight.SetType(RgnInfo.VCFType);
302 #else // override filter type
303 finalSynthesisParameters.filterLeft.SetType(CONFIG_OVERRIDE_FILTER_TYPE);
304 finalSynthesisParameters.filterRight.SetType(CONFIG_OVERRIDE_FILTER_TYPE);
305 #endif // CONFIG_OVERRIDE_FILTER_TYPE
306
307 VCFCutoffCtrl.value = pEngineChannel->ControllerTable[VCFCutoffCtrl.controller];
308 VCFResonanceCtrl.value = pEngineChannel->ControllerTable[VCFResonanceCtrl.controller];
309
310 // calculate cutoff frequency
311 CutoffBase = CalculateCutoffBase(itNoteOnEvent->Param.Note.Velocity);
312
313 VCFCutoffCtrl.fvalue = CalculateFinalCutoff(CutoffBase);
314
315 // calculate resonance
316 float resonance = (float) (VCFResonanceCtrl.controller ? VCFResonanceCtrl.value : RgnInfo.VCFResonance);
317 VCFResonanceCtrl.fvalue = resonance;
318 } else {
319 VCFCutoffCtrl.controller = 0;
320 VCFResonanceCtrl.controller = 0;
321 }
322
323 const bool bEq =
324 pSignalUnitRack != NULL && pSignalUnitRack->HasEq() && pEq->HasSupport();
325
326 if (bEq) {
327 pEq->GetInChannelLeft()->Clear();
328 pEq->GetInChannelRight()->Clear();
329 pEq->RenderAudio(GetEngine()->pAudioOutputDevice->MaxSamplesPerCycle());
330 }
331
332 return 0; // success
333 }
334
335 void AbstractVoice::SetSampleStartOffset() {
336 finalSynthesisParameters.dPos = RgnInfo.SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)
337 Pos = RgnInfo.SampleStartOffset;
338 }
339
340 /**
341 * Synthesizes the current audio fragment for this voice.
342 *
343 * @param Samples - number of sample points to be rendered in this audio
344 * fragment cycle
345 * @param pSrc - pointer to input sample data
346 * @param Skip - number of sample points to skip in output buffer
347 */
348 void AbstractVoice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {
349 bool delay = false; // Whether the voice playback should be delayed for this call
350
351 if (pSignalUnitRack != NULL) {
352 uint delaySteps = pSignalUnitRack->GetEndpointUnit()->DelayTrigger();
353 if (delaySteps > 0) { // delay on the endpoint unit means delay of the voice playback
354 if (delaySteps >= Samples) {
355 pSignalUnitRack->GetEndpointUnit()->DecreaseDelay(Samples);
356 delay = true;
357 } else {
358 pSignalUnitRack->GetEndpointUnit()->DecreaseDelay(delaySteps);
359 Samples -= delaySteps;
360 Skip += delaySteps;
361 }
362 }
363 }
364
365 AbstractEngineChannel* pChannel = pEngineChannel;
366 MidiKeyBase* pMidiKeyInfo = GetMidiKeyInfo(MIDIKey());
367
368 const bool bVoiceRequiresDedicatedRouting =
369 pEngineChannel->GetFxSendCount() > 0 &&
370 (pMidiKeyInfo->ReverbSend || pMidiKeyInfo->ChorusSend);
371
372 const bool bEq =
373 pSignalUnitRack != NULL && pSignalUnitRack->HasEq() && pEq->HasSupport();
374
375 if (bEq) {
376 pEq->GetInChannelLeft()->Clear();
377 pEq->GetInChannelRight()->Clear();
378 finalSynthesisParameters.pOutLeft = &pEq->GetInChannelLeft()->Buffer()[Skip];
379 finalSynthesisParameters.pOutRight = &pEq->GetInChannelRight()->Buffer()[Skip];
380 pSignalUnitRack->UpdateEqSettings(pEq);
381 } else if (bVoiceRequiresDedicatedRouting) {
382 finalSynthesisParameters.pOutLeft = &GetEngine()->pDedicatedVoiceChannelLeft->Buffer()[Skip];
383 finalSynthesisParameters.pOutRight = &GetEngine()->pDedicatedVoiceChannelRight->Buffer()[Skip];
384 } else {
385 finalSynthesisParameters.pOutLeft = &pChannel->pChannelLeft->Buffer()[Skip];
386 finalSynthesisParameters.pOutRight = &pChannel->pChannelRight->Buffer()[Skip];
387 }
388 finalSynthesisParameters.pSrc = pSrc;
389
390 RTList<Event>::Iterator itCCEvent = pChannel->pEvents->first();
391 RTList<Event>::Iterator itNoteEvent;
392 GetFirstEventOnKey(HostKey(), itNoteEvent);
393
394 RTList<Event>::Iterator itGroupEvent;
395 if (pGroupEvents && !Orphan) itGroupEvent = pGroupEvents->first();
396
397 if (itTriggerEvent) { // skip events that happened before this voice was triggered
398 while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;
399 while (itGroupEvent && itGroupEvent->FragmentPos() <= Skip) ++itGroupEvent;
400
401 // we can't simply compare the timestamp here, because note events
402 // might happen on the same time stamp, so we have to deal on the
403 // actual sequence the note events arrived instead (see bug #112)
404 for (; itNoteEvent; ++itNoteEvent) {
405 if (itTriggerEvent == itNoteEvent) {
406 ++itNoteEvent;
407 break;
408 }
409 }
410 }
411
412 uint killPos;
413 if (itKillEvent) {
414 int maxFadeOutPos = Samples - GetEngine()->GetMinFadeOutSamples();
415 if (maxFadeOutPos < 0) {
416 // There's not enough space in buffer to do a fade out
417 // from max volume (this can only happen for audio
418 // drivers that use Samples < MaxSamplesPerCycle).
419 // End the EG1 here, at pos 0, with a shorter max fade
420 // out time.
421 if (pSignalUnitRack == NULL) {
422 pEG1->enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
423 } else {
424 pSignalUnitRack->EnterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
425 }
426 itKillEvent = Pool<Event>::Iterator();
427 } else {
428 killPos = RTMath::Min(itKillEvent->FragmentPos(), maxFadeOutPos);
429 }
430 }
431
432 uint i = Skip;
433 while (i < Samples) {
434 int iSubFragmentEnd = RTMath::Min(i + CONFIG_DEFAULT_SUBFRAGMENT_SIZE, Samples);
435
436 // initialize all final synthesis parameters
437 fFinalCutoff = VCFCutoffCtrl.fvalue;
438 fFinalResonance = VCFResonanceCtrl.fvalue;
439
440 // process MIDI control change, aftertouch and pitchbend events for this subfragment
441 processCCEvents(itCCEvent, iSubFragmentEnd);
442 uint8_t pan = MIDIPan;
443 if (pSignalUnitRack != NULL) pan = pSignalUnitRack->GetEndpointUnit()->CalculatePan(MIDIPan);
444
445 PanLeftSmoother.update(AbstractEngine::PanCurve[128 - pan] * NotePanLeft);
446 PanRightSmoother.update(AbstractEngine::PanCurve[pan] * NotePanRight);
447
448 finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend * NotePitch;
449
450 float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render() * NoteVolumeSmoother.render();
451 #ifdef CONFIG_PROCESS_MUTED_CHANNELS
452 if (pChannel->GetMute()) fFinalVolume = 0;
453 #endif
454
455 // process transition events (note on, note off & sustain pedal)
456 processTransitionEvents(itNoteEvent, iSubFragmentEnd);
457 processGroupEvents(itGroupEvent, iSubFragmentEnd);
458
459 if (pSignalUnitRack == NULL) {
460 // if the voice was killed in this subfragment, or if the
461 // filter EG is finished, switch EG1 to fade out stage
462 if ((itKillEvent && killPos <= iSubFragmentEnd) ||
463 (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&
464 pEG2->getSegmentType() == EG::segment_end)) {
465 pEG1->enterFadeOutStage();
466 itKillEvent = Pool<Event>::Iterator();
467 }
468
469 // process envelope generators
470 switch (pEG1->getSegmentType()) {
471 case EG::segment_lin:
472 fFinalVolume *= pEG1->processLin();
473 break;
474 case EG::segment_exp:
475 fFinalVolume *= pEG1->processExp();
476 break;
477 case EG::segment_end:
478 fFinalVolume *= pEG1->getLevel();
479 break; // noop
480 case EG::segment_pow:
481 fFinalVolume *= pEG1->processPow();
482 break;
483 }
484 switch (pEG2->getSegmentType()) {
485 case EG::segment_lin:
486 fFinalCutoff *= pEG2->processLin();
487 break;
488 case EG::segment_exp:
489 fFinalCutoff *= pEG2->processExp();
490 break;
491 case EG::segment_end:
492 fFinalCutoff *= pEG2->getLevel();
493 break; // noop
494 case EG::segment_pow:
495 fFinalCutoff *= pEG2->processPow();
496 break;
497 }
498 if (EG3.active()) finalSynthesisParameters.fFinalPitch *= EG3.render();
499
500 // process low frequency oscillators
501 if (bLFO1Enabled) fFinalVolume *= (1.0f - pLFO1->render());
502 if (bLFO2Enabled) fFinalCutoff *= (1.0f - pLFO2->render());
503 if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());
504 } else {
505 // if the voice was killed in this subfragment, enter fade out stage
506 if (itKillEvent && killPos <= iSubFragmentEnd) {
507 pSignalUnitRack->EnterFadeOutStage();
508 itKillEvent = Pool<Event>::Iterator();
509 }
510
511 // if the filter EG is finished, switch EG1 to fade out stage
512 /*if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&
513 pEG2->getSegmentType() == EG::segment_end) {
514 pEG1->enterFadeOutStage();
515 itKillEvent = Pool<Event>::Iterator();
516 }*/
517 // TODO: ^^^
518
519 fFinalVolume *= pSignalUnitRack->GetEndpointUnit()->GetVolume();
520 fFinalCutoff = pSignalUnitRack->GetEndpointUnit()->CalculateFilterCutoff(fFinalCutoff);
521 fFinalResonance = pSignalUnitRack->GetEndpointUnit()->CalculateResonance(fFinalResonance);
522
523 finalSynthesisParameters.fFinalPitch =
524 pSignalUnitRack->GetEndpointUnit()->CalculatePitch(finalSynthesisParameters.fFinalPitch);
525
526 }
527
528 fFinalCutoff *= NoteCutoff;
529 fFinalResonance *= NoteResonance;
530
531 // limit the pitch so we don't read outside the buffer
532 finalSynthesisParameters.fFinalPitch = RTMath::Min(finalSynthesisParameters.fFinalPitch, float(1 << CONFIG_MAX_PITCH));
533
534 // if filter enabled then update filter coefficients
535 if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode)) {
536 finalSynthesisParameters.filterLeft.SetParameters(fFinalCutoff, fFinalResonance, GetEngine()->SampleRate);
537 finalSynthesisParameters.filterRight.SetParameters(fFinalCutoff, fFinalResonance, GetEngine()->SampleRate);
538 }
539
540 // do we need resampling?
541 const float __PLUS_ONE_CENT = 1.000577789506554859250142541782224725466f;
542 const float __MINUS_ONE_CENT = 0.9994225441413807496009516495583113737666f;
543 const bool bResamplingRequired = !(finalSynthesisParameters.fFinalPitch <= __PLUS_ONE_CENT &&
544 finalSynthesisParameters.fFinalPitch >= __MINUS_ONE_CENT);
545 SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, bResamplingRequired);
546
547 // prepare final synthesis parameters structure
548 finalSynthesisParameters.uiToGo = iSubFragmentEnd - i;
549 #ifdef CONFIG_INTERPOLATE_VOLUME
550 finalSynthesisParameters.fFinalVolumeDeltaLeft =
551 (fFinalVolume * VolumeLeft * PanLeftSmoother.render() -
552 finalSynthesisParameters.fFinalVolumeLeft) / finalSynthesisParameters.uiToGo;
553 finalSynthesisParameters.fFinalVolumeDeltaRight =
554 (fFinalVolume * VolumeRight * PanRightSmoother.render() -
555 finalSynthesisParameters.fFinalVolumeRight) / finalSynthesisParameters.uiToGo;
556 #else
557 finalSynthesisParameters.fFinalVolumeLeft =
558 fFinalVolume * VolumeLeft * PanLeftSmoother.render();
559 finalSynthesisParameters.fFinalVolumeRight =
560 fFinalVolume * VolumeRight * PanRightSmoother.render();
561 #endif
562 // render audio for one subfragment
563 if (!delay) RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);
564
565 if (pSignalUnitRack == NULL) {
566 // stop the rendering if volume EG is finished
567 if (pEG1->getSegmentType() == EG::segment_end) break;
568 } else {
569 // stop the rendering if the endpoint unit is not active
570 if (!pSignalUnitRack->GetEndpointUnit()->Active()) break;
571 }
572
573 const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;
574
575 if (pSignalUnitRack == NULL) {
576 // increment envelopes' positions
577 if (pEG1->active()) {
578
579 // 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
580 if (SmplInfo.HasLoops && Pos <= SmplInfo.LoopStart && SmplInfo.LoopStart < newPos) {
581 pEG1->update(EG::event_hold_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
582 }
583
584 pEG1->increment(1);
585 if (!pEG1->toStageEndLeft()) pEG1->update(EG::event_stage_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
586 }
587 if (pEG2->active()) {
588 pEG2->increment(1);
589 if (!pEG2->toStageEndLeft()) pEG2->update(EG::event_stage_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
590 }
591 EG3.increment(1);
592 if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached
593 } else {
594 // 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
595 /*if (SmplInfo.HasLoops && Pos <= SmplInfo.LoopStart && SmplInfo.LoopStart < newPos) {
596 pEG1->update(EG::event_hold_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
597 }*/
598 // TODO: ^^^
599
600 if (!delay) pSignalUnitRack->Increment();
601 }
602
603 Pos = newPos;
604 i = iSubFragmentEnd;
605 }
606
607 if (delay) return;
608
609 if (bVoiceRequiresDedicatedRouting) {
610 if (bEq) {
611 pEq->RenderAudio(Samples);
612 pEq->GetOutChannelLeft()->CopyTo(GetEngine()->pDedicatedVoiceChannelLeft, Samples);
613 pEq->GetOutChannelRight()->CopyTo(GetEngine()->pDedicatedVoiceChannelRight, Samples);
614 }
615 optional<float> effectSendLevels[2] = {
616 pMidiKeyInfo->ReverbSend,
617 pMidiKeyInfo->ChorusSend
618 };
619 GetEngine()->RouteDedicatedVoiceChannels(pEngineChannel, effectSendLevels, Samples);
620 } else if (bEq) {
621 pEq->RenderAudio(Samples);
622 pEq->GetOutChannelLeft()->MixTo(pChannel->pChannelLeft, Samples);
623 pEq->GetOutChannelRight()->MixTo(pChannel->pChannelRight, Samples);
624 }
625 }
626
627 /**
628 * Process given list of MIDI control change, aftertouch and pitch bend
629 * events for the given time.
630 *
631 * @param itEvent - iterator pointing to the next event to be processed
632 * @param End - youngest time stamp where processing should be stopped
633 */
634 void AbstractVoice::processCCEvents(RTList<Event>::Iterator& itEvent, uint End) {
635 for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
636 if (itEvent->Type == Event::type_control_change && itEvent->Param.CC.Controller) { // if (valid) MIDI control change event
637 if (itEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {
638 ProcessCutoffEvent(itEvent);
639 }
640 if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {
641 processResonanceEvent(itEvent);
642 }
643 if (pSignalUnitRack == NULL) {
644 if (itEvent->Param.CC.Controller == pLFO1->ExtController) {
645 pLFO1->update(itEvent->Param.CC.Value);
646 }
647 if (itEvent->Param.CC.Controller == pLFO2->ExtController) {
648 pLFO2->update(itEvent->Param.CC.Value);
649 }
650 if (itEvent->Param.CC.Controller == pLFO3->ExtController) {
651 pLFO3->update(itEvent->Param.CC.Value);
652 }
653 }
654 if (itEvent->Param.CC.Controller == 7) { // volume
655 VolumeSmoother.update(AbstractEngine::VolumeCurve[itEvent->Param.CC.Value]);
656 } else if (itEvent->Param.CC.Controller == 10) { // panpot
657 MIDIPan = CalculatePan(itEvent->Param.CC.Value);
658 }
659 } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event
660 processPitchEvent(itEvent);
661 } else if (itEvent->Type == Event::type_channel_pressure) {
662 ProcessChannelPressureEvent(itEvent);
663 } else if (itEvent->Type == Event::type_note_pressure) {
664 ProcessPolyphonicKeyPressureEvent(itEvent);
665 }
666
667 ProcessCCEvent(itEvent);
668 if (pSignalUnitRack != NULL) {
669 pSignalUnitRack->ProcessCCEvent(itEvent);
670 }
671 }
672 }
673
674 void AbstractVoice::processPitchEvent(RTList<Event>::Iterator& itEvent) {
675 Pitch.PitchBend = RTMath::CentsToFreqRatio(itEvent->Param.Pitch.Pitch * Pitch.PitchBendRange);
676 }
677
678 void AbstractVoice::processResonanceEvent(RTList<Event>::Iterator& itEvent) {
679 // convert absolute controller value to differential
680 const int ctrldelta = itEvent->Param.CC.Value - VCFResonanceCtrl.value;
681 VCFResonanceCtrl.value = itEvent->Param.CC.Value;
682 const float resonancedelta = (float) ctrldelta;
683 fFinalResonance += resonancedelta;
684 // needed for initialization of parameter
685 VCFResonanceCtrl.fvalue = itEvent->Param.CC.Value;
686 }
687
688 /**
689 * Process given list of MIDI note on, note off, sustain pedal events and
690 * note synthesis parameter events for the given time.
691 *
692 * @param itEvent - iterator pointing to the next event to be processed
693 * @param End - youngest time stamp where processing should be stopped
694 */
695 void AbstractVoice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) {
696 for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
697 // some voice types ignore note off
698 if (!(Type & (Voice::type_one_shot | Voice::type_release_trigger | Voice::type_controller_triggered))) {
699 if (itEvent->Type == Event::type_release_key) {
700 EnterReleaseStage();
701 } else if (itEvent->Type == Event::type_cancel_release_key) {
702 if (pSignalUnitRack == NULL) {
703 pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
704 pEG2->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
705 } else {
706 pSignalUnitRack->CancelRelease();
707 }
708 }
709 }
710 // process stop-note events (caused by built-in instrument script function note_off())
711 if (itEvent->Type == Event::type_release_note && pNote &&
712 pEngineChannel->pEngine->NoteByID( itEvent->Param.Note.ID ) == pNote)
713 {
714 EnterReleaseStage();
715 }
716 // process synthesis parameter events (caused by built-in realt-time instrument script functions)
717 if (itEvent->Type == Event::type_note_synth_param && pNote &&
718 pEngineChannel->pEngine->NoteByID( itEvent->Param.NoteSynthParam.NoteID ) == pNote)
719 {
720 switch (itEvent->Param.NoteSynthParam.Type) {
721 case Event::synth_param_volume:
722 NoteVolumeSmoother.update(itEvent->Param.NoteSynthParam.AbsValue);
723 break;
724 case Event::synth_param_pitch:
725 NotePitch = itEvent->Param.NoteSynthParam.AbsValue;
726 break;
727 case Event::synth_param_pan:
728 NotePanLeft = AbstractEngine::PanCurveValueNorm(itEvent->Param.NoteSynthParam.AbsValue, 0 /*left*/);
729 NotePanRight = AbstractEngine::PanCurveValueNorm(itEvent->Param.NoteSynthParam.AbsValue, 1 /*right*/);
730 break;
731 case Event::synth_param_cutoff:
732 NoteCutoff = itEvent->Param.NoteSynthParam.AbsValue;
733 break;
734 case Event::synth_param_resonance:
735 NoteResonance = itEvent->Param.NoteSynthParam.AbsValue;
736 break;
737 }
738 }
739 }
740 }
741
742 /**
743 * Process given list of events aimed at all voices in a key group.
744 *
745 * @param itEvent - iterator pointing to the next event to be processed
746 * @param End - youngest time stamp where processing should be stopped
747 */
748 void AbstractVoice::processGroupEvents(RTList<Event>::Iterator& itEvent, uint End) {
749 for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
750 ProcessGroupEvent(itEvent);
751 }
752 }
753
754 /** @brief Update current portamento position.
755 *
756 * Will be called when portamento mode is enabled to get the final
757 * portamento position of this active voice from where the next voice(s)
758 * might continue to slide on.
759 *
760 * @param itNoteOffEvent - event which causes this voice to die soon
761 */
762 void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {
763 if (pSignalUnitRack == NULL) {
764 const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());
765 pEngineChannel->PortamentoPos = (float) MIDIKey() + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;
766 } else {
767 // TODO:
768 }
769 }
770
771 /**
772 * Kill the voice in regular sense. Let the voice render audio until
773 * the kill event actually occured and then fade down the volume level
774 * very quickly and let the voice die finally. Unlike a normal release
775 * of a voice, a kill process cannot be cancalled and is therefore
776 * usually used for voice stealing and key group conflicts.
777 *
778 * @param itKillEvent - event which caused the voice to be killed
779 */
780 void AbstractVoice::Kill(Pool<Event>::Iterator& itKillEvent) {
781 #if CONFIG_DEVMODE
782 if (!itKillEvent) dmsg(1,("AbstractVoice::Kill(): ERROR, !itKillEvent !!!\n"));
783 if (itKillEvent && !itKillEvent.isValid()) dmsg(1,("AbstractVoice::Kill(): ERROR, itKillEvent invalid !!!\n"));
784 #endif // CONFIG_DEVMODE
785
786 if (itTriggerEvent && itKillEvent->FragmentPos() <= itTriggerEvent->FragmentPos()) return;
787 this->itKillEvent = itKillEvent;
788 }
789
790 Voice::PitchInfo AbstractVoice::CalculatePitchInfo(int PitchBend) {
791 PitchInfo pitch;
792 double pitchbasecents = InstrInfo.FineTune + RgnInfo.FineTune + GetEngine()->ScaleTuning[MIDIKey() % 12];
793
794 // GSt behaviour: maximum transpose up is 40 semitones. If
795 // MIDI key is more than 40 semitones above unity note,
796 // the transpose is not done.
797 if (!SmplInfo.Unpitched && (MIDIKey() - (int) RgnInfo.UnityNote) < 40) pitchbasecents += (MIDIKey() - (int) RgnInfo.UnityNote) * 100;
798
799 pitch.PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(SmplInfo.SampleRate) / double(GetEngine()->SampleRate));
800 pitch.PitchBendRange = 1.0 / 8192.0 * 100.0 * InstrInfo.PitchbendRange;
801 pitch.PitchBend = RTMath::CentsToFreqRatio(PitchBend * pitch.PitchBendRange);
802
803 return pitch;
804 }
805
806 void AbstractVoice::onScaleTuningChanged() {
807 PitchInfo pitch = this->Pitch;
808 double pitchbasecents = InstrInfo.FineTune + RgnInfo.FineTune + GetEngine()->ScaleTuning[MIDIKey() % 12];
809
810 // GSt behaviour: maximum transpose up is 40 semitones. If
811 // MIDI key is more than 40 semitones above unity note,
812 // the transpose is not done.
813 if (!SmplInfo.Unpitched && (MIDIKey() - (int) RgnInfo.UnityNote) < 40) pitchbasecents += (MIDIKey() - (int) RgnInfo.UnityNote) * 100;
814
815 pitch.PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(SmplInfo.SampleRate) / double(GetEngine()->SampleRate));
816 this->Pitch = pitch;
817 }
818
819 double AbstractVoice::CalculateVolume(double velocityAttenuation) {
820 // For 16 bit samples, we downscale by 32768 to convert from
821 // int16 value range to DSP value range (which is
822 // -1.0..1.0). For 24 bit, we downscale from int32.
823 float volume = velocityAttenuation / (SmplInfo.BitDepth == 16 ? 32768.0f : 32768.0f * 65536.0f);
824
825 volume *= GetSampleAttenuation() * pEngineChannel->GlobalVolume * GLOBAL_VOLUME;
826
827 // the volume of release triggered samples depends on note length
828 if (Type & Voice::type_release_trigger) {
829 float noteLength = float(GetEngine()->FrameTime + Delay -
830 GetNoteOnTime(MIDIKey()) ) / GetEngine()->SampleRate;
831
832 volume *= GetReleaseTriggerAttenuation(noteLength);
833 }
834
835 return volume;
836 }
837
838 float AbstractVoice::GetReleaseTriggerAttenuation(float noteLength) {
839 return 1 - RgnInfo.ReleaseTriggerDecay * noteLength;
840 }
841
842 void AbstractVoice::EnterReleaseStage() {
843 if (pSignalUnitRack == NULL) {
844 pEG1->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
845 pEG2->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
846 } else {
847 pSignalUnitRack->EnterReleaseStage();
848 }
849 }
850
851 bool AbstractVoice::EG1Finished() {
852 if (pSignalUnitRack == NULL) {
853 return pEG1->getSegmentType() == EG::segment_end;
854 } else {
855 return !pSignalUnitRack->GetEndpointUnit()->Active();
856 }
857 }
858
859 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC