/[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 2205 - (show annotations) (download)
Mon Jul 11 17:52:01 2011 UTC (12 years, 8 months ago) by iliev
File size: 35165 byte(s)
* Introduced Signal Units and Signal Unit Racks, which hopefully will meet
  the demands of the new engines for flexible signal processing.
* sf2: Initial implementation of vibrato LFO, fixes in modulation EG and
  and volume EG (work in progress)

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

  ViewVC Help
Powered by ViewVC