/[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 2296 - (show annotations) (download)
Thu Dec 8 20:03:47 2011 UTC (12 years, 4 months ago) by iliev
File size: 36762 byte(s)
* fixed crash when trying to create an effect instance with controls
  which min and/or max values depend on the sample rate
* experimental support for per voice equalization (work in progress)
* sfz engine: implemented opcodes eq1_freq, eq2_freq, eq3_freq,
  eq1_freqccN, eq2_freqccN, eq3_freqccN, eq1_bw, eq2_bw, eq3_bw,
  eq1_bwccN, eq2_bwccN, eq3_bwccN, eq1_gain, eq2_gain, eq3_gain,
  eq1_gainccN, eq2_gainccN, eq3_gainccN

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

  ViewVC Help
Powered by ViewVC