/[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 2879 - (show annotations) (download)
Tue Apr 19 14:07:53 2016 UTC (7 years, 11 months ago) by schoenebeck
File size: 39194 byte(s)
* All engines: Active voices are now internally grouped to "Note" objects,
  instead of being directly assigned to a keyboard key. This allows more
  fine graded processing of voices, which is i.e. required for certain
  instrument script features.
* Built-in script function "play_note()": Added support for passing
  special value -1 for "duration-us" argument, which will cause the
  triggered note to be released once the original note was released.
* Bumped version (2.0.0.svn3).

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

  ViewVC Help
Powered by ViewVC