/[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 2217 - (show annotations) (download)
Tue Jul 26 15:51:30 2011 UTC (12 years, 8 months ago) by iliev
File size: 35202 byte(s)
* removed helper classes SignalUnitBase,
  EndpointSignalUnitBase, SignalUnitRackBase
* clean up sf2::Voice
* bumped version to 1.0.0.cvs12

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

  ViewVC Help
Powered by ViewVC