/[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 2218 - (show annotations) (download)
Thu Jul 28 08:05:57 2011 UTC (12 years, 8 months ago) by iliev
File size: 35264 byte(s)
* sfz engine: use the newly introduced signal units model

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 PlaybackState = playback_state_init; // mark voice as triggered, but no audio rendered yet
104 Delay = itNoteOnEvent->FragmentPos();
105 itTriggerEvent = itNoteOnEvent;
106 itKillEvent = Pool<Event>::Iterator();
107 MidiKeyBase* pKeyInfo = GetMidiKeyInfo(MIDIKey);
108
109 pGroupEvents = iKeyGroup ? pEngineChannel->ActiveKeyGroups[iKeyGroup] : 0;
110
111 SmplInfo = GetSampleInfo();
112 RgnInfo = GetRegionInfo();
113 InstrInfo = GetInstrumentInfo();
114
115 AboutToTrigger();
116
117 // calculate volume
118 const double velocityAttenuation = GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity);
119 float volume = CalculateVolume(velocityAttenuation) * pKeyInfo->Volume;
120 if (volume <= 0) return -1;
121
122 // select channel mode (mono or stereo)
123 SYNTHESIS_MODE_SET_CHANNELS(SynthesisMode, SmplInfo.ChannelCount == 2);
124 // select bit depth (16 or 24)
125 SYNTHESIS_MODE_SET_BITDEPTH24(SynthesisMode, SmplInfo.BitDepth == 24);
126
127 // get starting crossfade volume level
128 float crossfadeVolume = CalculateCrossfadeVolume(itNoteOnEvent->Param.Note.Velocity);
129
130 VolumeLeft = volume * pKeyInfo->PanLeft * AbstractEngine::PanCurve[64 - RgnInfo.Pan];
131 VolumeRight = volume * pKeyInfo->PanRight * AbstractEngine::PanCurve[64 + RgnInfo.Pan];
132
133 float subfragmentRate = GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;
134 CrossfadeSmoother.trigger(crossfadeVolume, subfragmentRate);
135 VolumeSmoother.trigger(pEngineChannel->MidiVolume, subfragmentRate);
136 PanLeftSmoother.trigger(pEngineChannel->GlobalPanLeft, subfragmentRate);
137 PanRightSmoother.trigger(pEngineChannel->GlobalPanRight, subfragmentRate);
138
139 // Check if the sample needs disk streaming or is too short for that
140 long cachedsamples = GetSampleCacheSize() / SmplInfo.FrameSize;
141 DiskVoice = cachedsamples < SmplInfo.TotalFrameCount;
142
143 SetSampleStartOffset();
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 (pSignalUnitRack == 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 pSignalUnitRack->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 (pSignalUnitRack == NULL) {
205 finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pEG1->getLevel();
206 } else {
207 finalVolume = pEngineChannel->MidiVolume * crossfadeVolume * pSignalUnitRack->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 (pSignalUnitRack == 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 void AbstractVoice::SetSampleStartOffset() {
300 finalSynthesisParameters.dPos = RgnInfo.SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)
301 Pos = RgnInfo.SampleStartOffset;
302 }
303
304 /**
305 * Synthesizes the current audio fragment for this voice.
306 *
307 * @param Samples - number of sample points to be rendered in this audio
308 * fragment cycle
309 * @param pSrc - pointer to input sample data
310 * @param Skip - number of sample points to skip in output buffer
311 */
312 void AbstractVoice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {
313 AbstractEngineChannel* pChannel = pEngineChannel;
314 MidiKeyBase* pMidiKeyInfo = GetMidiKeyInfo(MIDIKey);
315
316 const bool bVoiceRequiresDedicatedRouting =
317 pEngineChannel->GetFxSendCount() > 0 &&
318 (pMidiKeyInfo->ReverbSend || pMidiKeyInfo->ChorusSend);
319
320 if (bVoiceRequiresDedicatedRouting) {
321 finalSynthesisParameters.pOutLeft = &GetEngine()->pDedicatedVoiceChannelLeft->Buffer()[Skip];
322 finalSynthesisParameters.pOutRight = &GetEngine()->pDedicatedVoiceChannelRight->Buffer()[Skip];
323 } else {
324 finalSynthesisParameters.pOutLeft = &pChannel->pChannelLeft->Buffer()[Skip];
325 finalSynthesisParameters.pOutRight = &pChannel->pChannelRight->Buffer()[Skip];
326 }
327 finalSynthesisParameters.pSrc = pSrc;
328
329 RTList<Event>::Iterator itCCEvent = pChannel->pEvents->first();
330 RTList<Event>::Iterator itNoteEvent;
331 GetFirstEventOnKey(MIDIKey, itNoteEvent);
332
333 RTList<Event>::Iterator itGroupEvent;
334 if (pGroupEvents) itGroupEvent = pGroupEvents->first();
335
336 if (itTriggerEvent) { // skip events that happened before this voice was triggered
337 while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;
338 while (itGroupEvent && itGroupEvent->FragmentPos() <= Skip) ++itGroupEvent;
339
340 // we can't simply compare the timestamp here, because note events
341 // might happen on the same time stamp, so we have to deal on the
342 // actual sequence the note events arrived instead (see bug #112)
343 for (; itNoteEvent; ++itNoteEvent) {
344 if (itTriggerEvent == itNoteEvent) {
345 ++itNoteEvent;
346 break;
347 }
348 }
349 }
350
351 uint killPos;
352 if (itKillEvent) {
353 int maxFadeOutPos = Samples - GetEngine()->GetMinFadeOutSamples();
354 if (maxFadeOutPos < 0) {
355 // There's not enough space in buffer to do a fade out
356 // from max volume (this can only happen for audio
357 // drivers that use Samples < MaxSamplesPerCycle).
358 // End the EG1 here, at pos 0, with a shorter max fade
359 // out time.
360 if (pSignalUnitRack == NULL) {
361 pEG1->enterFadeOutStage(Samples / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
362 } else {
363 // TODO:
364 }
365 itKillEvent = Pool<Event>::Iterator();
366 } else {
367 killPos = RTMath::Min(itKillEvent->FragmentPos(), maxFadeOutPos);
368 }
369 }
370
371 uint i = Skip;
372 while (i < Samples) {
373 int iSubFragmentEnd = RTMath::Min(i + CONFIG_DEFAULT_SUBFRAGMENT_SIZE, Samples);
374
375 // initialize all final synthesis parameters
376 fFinalCutoff = VCFCutoffCtrl.fvalue;
377 fFinalResonance = VCFResonanceCtrl.fvalue;
378
379 // process MIDI control change and pitchbend events for this subfragment
380 processCCEvents(itCCEvent, iSubFragmentEnd);
381
382 finalSynthesisParameters.fFinalPitch = Pitch.PitchBase * Pitch.PitchBend;
383 float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render();
384 #ifdef CONFIG_PROCESS_MUTED_CHANNELS
385 if (pChannel->GetMute()) fFinalVolume = 0;
386 #endif
387
388 // process transition events (note on, note off & sustain pedal)
389 processTransitionEvents(itNoteEvent, iSubFragmentEnd);
390 processGroupEvents(itGroupEvent, iSubFragmentEnd);
391
392 if (pSignalUnitRack == NULL) {
393 // if the voice was killed in this subfragment, or if the
394 // filter EG is finished, switch EG1 to fade out stage
395 if ((itKillEvent && killPos <= iSubFragmentEnd) ||
396 (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&
397 pEG2->getSegmentType() == EG::segment_end)) {
398 pEG1->enterFadeOutStage();
399 itKillEvent = Pool<Event>::Iterator();
400 }
401
402 // process envelope generators
403 switch (pEG1->getSegmentType()) {
404 case EG::segment_lin:
405 fFinalVolume *= pEG1->processLin();
406 break;
407 case EG::segment_exp:
408 fFinalVolume *= pEG1->processExp();
409 break;
410 case EG::segment_end:
411 fFinalVolume *= pEG1->getLevel();
412 break; // noop
413 case EG::segment_pow:
414 fFinalVolume *= pEG1->processPow();
415 break;
416 }
417 switch (pEG2->getSegmentType()) {
418 case EG::segment_lin:
419 fFinalCutoff *= pEG2->processLin();
420 break;
421 case EG::segment_exp:
422 fFinalCutoff *= pEG2->processExp();
423 break;
424 case EG::segment_end:
425 fFinalCutoff *= pEG2->getLevel();
426 break; // noop
427 case EG::segment_pow:
428 fFinalCutoff *= pEG2->processPow();
429 break;
430 }
431 if (EG3.active()) finalSynthesisParameters.fFinalPitch *= EG3.render();
432
433 // process low frequency oscillators
434 if (bLFO1Enabled) fFinalVolume *= (1.0f - pLFO1->render());
435 if (bLFO2Enabled) fFinalCutoff *= pLFO2->render();
436 if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());
437 } else {
438 // if the voice was killed in this subfragment, or if the
439 // filter EG is finished, switch EG1 to fade out stage
440 /*if ((itKillEvent && killPos <= iSubFragmentEnd) ||
441 (SYNTHESIS_MODE_GET_FILTER(SynthesisMode) &&
442 pEG2->getSegmentType() == EG::segment_end)) {
443 pEG1->enterFadeOutStage();
444 itKillEvent = Pool<Event>::Iterator();
445 }*/
446 // TODO: ^^^
447
448 fFinalVolume *= pSignalUnitRack->GetEndpointUnit()->GetVolume();
449 fFinalCutoff = pSignalUnitRack->GetEndpointUnit()->CalculateFilterCutoff(fFinalCutoff);
450 fFinalResonance = pSignalUnitRack->GetEndpointUnit()->CalculateResonance(fFinalResonance);
451
452 finalSynthesisParameters.fFinalPitch =
453 pSignalUnitRack->GetEndpointUnit()->CalculatePitch(finalSynthesisParameters.fFinalPitch);
454
455 }
456
457 // limit the pitch so we don't read outside the buffer
458 finalSynthesisParameters.fFinalPitch = RTMath::Min(finalSynthesisParameters.fFinalPitch, float(1 << CONFIG_MAX_PITCH));
459
460 // if filter enabled then update filter coefficients
461 if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode)) {
462 finalSynthesisParameters.filterLeft.SetParameters(fFinalCutoff, fFinalResonance, GetEngine()->SampleRate);
463 finalSynthesisParameters.filterRight.SetParameters(fFinalCutoff, fFinalResonance, GetEngine()->SampleRate);
464 }
465
466 // do we need resampling?
467 const float __PLUS_ONE_CENT = 1.000577789506554859250142541782224725466f;
468 const float __MINUS_ONE_CENT = 0.9994225441413807496009516495583113737666f;
469 const bool bResamplingRequired = !(finalSynthesisParameters.fFinalPitch <= __PLUS_ONE_CENT &&
470 finalSynthesisParameters.fFinalPitch >= __MINUS_ONE_CENT);
471 SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, bResamplingRequired);
472
473 // prepare final synthesis parameters structure
474 finalSynthesisParameters.uiToGo = iSubFragmentEnd - i;
475 #ifdef CONFIG_INTERPOLATE_VOLUME
476 finalSynthesisParameters.fFinalVolumeDeltaLeft =
477 (fFinalVolume * VolumeLeft * PanLeftSmoother.render() -
478 finalSynthesisParameters.fFinalVolumeLeft) / finalSynthesisParameters.uiToGo;
479 finalSynthesisParameters.fFinalVolumeDeltaRight =
480 (fFinalVolume * VolumeRight * PanRightSmoother.render() -
481 finalSynthesisParameters.fFinalVolumeRight) / finalSynthesisParameters.uiToGo;
482 #else
483 finalSynthesisParameters.fFinalVolumeLeft =
484 fFinalVolume * VolumeLeft * PanLeftSmoother.render();
485 finalSynthesisParameters.fFinalVolumeRight =
486 fFinalVolume * VolumeRight * PanRightSmoother.render();
487 #endif
488 // render audio for one subfragment
489 RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);
490
491 if (pSignalUnitRack == NULL) {
492 // stop the rendering if volume EG is finished
493 if (pEG1->getSegmentType() == EG::segment_end) break;
494 } else {
495 // stop the rendering if the endpoint unit is not active
496 if (!pSignalUnitRack->GetEndpointUnit()->Active()) break;
497 }
498
499 const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;
500
501 if (pSignalUnitRack == NULL) {
502 // increment envelopes' positions
503 if (pEG1->active()) {
504
505 // 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
506 if (SmplInfo.HasLoops && Pos <= SmplInfo.LoopStart && SmplInfo.LoopStart < newPos) {
507 pEG1->update(EG::event_hold_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
508 }
509
510 pEG1->increment(1);
511 if (!pEG1->toStageEndLeft()) pEG1->update(EG::event_stage_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
512 }
513 if (pEG2->active()) {
514 pEG2->increment(1);
515 if (!pEG2->toStageEndLeft()) pEG2->update(EG::event_stage_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
516 }
517 EG3.increment(1);
518 if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached
519 } else {
520 // 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
521 /*if (SmplInfo.HasLoops && Pos <= SmplInfo.LoopStart && SmplInfo.LoopStart < newPos) {
522 pEG1->update(EG::event_hold_end, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
523 }*/
524 // TODO: ^^^
525
526 pSignalUnitRack->Increment();
527 }
528
529 Pos = newPos;
530 i = iSubFragmentEnd;
531 }
532
533 if (bVoiceRequiresDedicatedRouting) {
534 optional<float> effectSendLevels[2] = {
535 pMidiKeyInfo->ReverbSend,
536 pMidiKeyInfo->ChorusSend
537 };
538 GetEngine()->RouteDedicatedVoiceChannels(pEngineChannel, effectSendLevels, Samples);
539 }
540 }
541
542 /**
543 * Process given list of MIDI control change and pitch bend events for
544 * the given time.
545 *
546 * @param itEvent - iterator pointing to the next event to be processed
547 * @param End - youngest time stamp where processing should be stopped
548 */
549 void AbstractVoice::processCCEvents(RTList<Event>::Iterator& itEvent, uint End) {
550 for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
551 if (itEvent->Type == Event::type_control_change && itEvent->Param.CC.Controller) { // if (valid) MIDI control change event
552 if (itEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {
553 ProcessCutoffEvent(itEvent);
554 }
555 if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {
556 processResonanceEvent(itEvent);
557 }
558 if (pSignalUnitRack == NULL) {
559 if (itEvent->Param.CC.Controller == pLFO1->ExtController) {
560 pLFO1->update(itEvent->Param.CC.Value);
561 }
562 if (itEvent->Param.CC.Controller == pLFO2->ExtController) {
563 pLFO2->update(itEvent->Param.CC.Value);
564 }
565 if (itEvent->Param.CC.Controller == pLFO3->ExtController) {
566 pLFO3->update(itEvent->Param.CC.Value);
567 }
568 }
569 if (itEvent->Param.CC.Controller == 7) { // volume
570 VolumeSmoother.update(AbstractEngine::VolumeCurve[itEvent->Param.CC.Value]);
571 } else if (itEvent->Param.CC.Controller == 10) { // panpot
572 PanLeftSmoother.update(AbstractEngine::PanCurve[128 - itEvent->Param.CC.Value]);
573 PanRightSmoother.update(AbstractEngine::PanCurve[itEvent->Param.CC.Value]);
574 }
575 } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event
576 processPitchEvent(itEvent);
577 }
578
579 ProcessCCEvent(itEvent);
580 if (pSignalUnitRack != NULL) {
581 pSignalUnitRack->ProcessCCEvent(itEvent);
582 }
583 }
584 }
585
586 void AbstractVoice::processPitchEvent(RTList<Event>::Iterator& itEvent) {
587 Pitch.PitchBend = RTMath::CentsToFreqRatio(itEvent->Param.Pitch.Pitch * Pitch.PitchBendRange);
588 }
589
590 void AbstractVoice::processResonanceEvent(RTList<Event>::Iterator& itEvent) {
591 // convert absolute controller value to differential
592 const int ctrldelta = itEvent->Param.CC.Value - VCFResonanceCtrl.value;
593 VCFResonanceCtrl.value = itEvent->Param.CC.Value;
594 const float resonancedelta = (float) ctrldelta;
595 fFinalResonance += resonancedelta;
596 // needed for initialization of parameter
597 VCFResonanceCtrl.fvalue = itEvent->Param.CC.Value;
598 }
599
600 /**
601 * Process given list of MIDI note on, note off and sustain pedal events
602 * for the given time.
603 *
604 * @param itEvent - iterator pointing to the next event to be processed
605 * @param End - youngest time stamp where processing should be stopped
606 */
607 void AbstractVoice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) {
608 for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
609 // some voice types ignore note off
610 if (!(Type & (Voice::type_one_shot | Voice::type_release_trigger | Voice::type_controller_triggered))) {
611 if (itEvent->Type == Event::type_release) {
612 EnterReleaseStage();
613 } else if (itEvent->Type == Event::type_cancel_release) {
614 if (pSignalUnitRack == NULL) {
615 pEG1->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
616 pEG2->update(EG::event_cancel_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
617 } else {
618 pSignalUnitRack->CancelRelease();
619 }
620 }
621 }
622 }
623 }
624
625 /**
626 * Process given list of events aimed at all voices in a key group.
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::processGroupEvents(RTList<Event>::Iterator& itEvent, uint End) {
632 for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
633 ProcessGroupEvent(itEvent);
634 }
635 }
636
637 /** @brief Update current portamento position.
638 *
639 * Will be called when portamento mode is enabled to get the final
640 * portamento position of this active voice from where the next voice(s)
641 * might continue to slide on.
642 *
643 * @param itNoteOffEvent - event which causes this voice to die soon
644 */
645 void AbstractVoice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {
646 if (pSignalUnitRack == NULL) {
647 const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());
648 pEngineChannel->PortamentoPos = (float) MIDIKey + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;
649 } else {
650 // TODO:
651 }
652 }
653
654 /**
655 * Kill the voice in regular sense. Let the voice render audio until
656 * the kill event actually occured and then fade down the volume level
657 * very quickly and let the voice die finally. Unlike a normal release
658 * of a voice, a kill process cannot be cancalled and is therefore
659 * usually used for voice stealing and key group conflicts.
660 *
661 * @param itKillEvent - event which caused the voice to be killed
662 */
663 void AbstractVoice::Kill(Pool<Event>::Iterator& itKillEvent) {
664 #if CONFIG_DEVMODE
665 if (!itKillEvent) dmsg(1,("AbstractVoice::Kill(): ERROR, !itKillEvent !!!\n"));
666 if (itKillEvent && !itKillEvent.isValid()) dmsg(1,("AbstractVoice::Kill(): ERROR, itKillEvent invalid !!!\n"));
667 #endif // CONFIG_DEVMODE
668
669 if (itTriggerEvent && itKillEvent->FragmentPos() <= itTriggerEvent->FragmentPos()) return;
670 this->itKillEvent = itKillEvent;
671 }
672
673 Voice::PitchInfo AbstractVoice::CalculatePitchInfo(int PitchBend) {
674 PitchInfo pitch;
675 double pitchbasecents = InstrInfo.FineTune + RgnInfo.FineTune + GetEngine()->ScaleTuning[MIDIKey % 12];
676
677 // GSt behaviour: maximum transpose up is 40 semitones. If
678 // MIDI key is more than 40 semitones above unity note,
679 // the transpose is not done.
680 if (!SmplInfo.Unpitched && (MIDIKey - (int) RgnInfo.UnityNote) < 40) pitchbasecents += (MIDIKey - (int) RgnInfo.UnityNote) * 100;
681
682 pitch.PitchBase = RTMath::CentsToFreqRatioUnlimited(pitchbasecents) * (double(SmplInfo.SampleRate) / double(GetEngine()->SampleRate));
683 pitch.PitchBendRange = 1.0 / 8192.0 * 100.0 * InstrInfo.PitchbendRange;
684 pitch.PitchBend = RTMath::CentsToFreqRatio(PitchBend * pitch.PitchBendRange);
685
686 return pitch;
687 }
688
689 double AbstractVoice::CalculateVolume(double velocityAttenuation) {
690 // For 16 bit samples, we downscale by 32768 to convert from
691 // int16 value range to DSP value range (which is
692 // -1.0..1.0). For 24 bit, we downscale from int32.
693 float volume = velocityAttenuation / (SmplInfo.BitDepth == 16 ? 32768.0f : 32768.0f * 65536.0f);
694
695 volume *= GetSampleAttenuation() * pEngineChannel->GlobalVolume * GLOBAL_VOLUME;
696
697 // the volume of release triggered samples depends on note length
698 if (Type & Voice::type_release_trigger) {
699 float noteLength = float(GetEngine()->FrameTime + Delay -
700 GetNoteOnTime(MIDIKey) ) / GetEngine()->SampleRate;
701
702 volume *= GetReleaseTriggerAttenuation(noteLength);
703 }
704
705 return volume;
706 }
707
708 float AbstractVoice::GetReleaseTriggerAttenuation(float noteLength) {
709 return 1 - RgnInfo.ReleaseTriggerDecay * noteLength;
710 }
711
712 void AbstractVoice::EnterReleaseStage() {
713 if (pSignalUnitRack == NULL) {
714 pEG1->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
715 pEG2->update(EG::event_release, GetEngine()->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
716 } else {
717 pSignalUnitRack->EnterReleaseStage();
718 }
719 }
720
721 bool AbstractVoice::EG1Finished() {
722 if (pSignalUnitRack == NULL) {
723 return pEG1->getSegmentType() == EG::segment_end;
724 } else {
725 return !pSignalUnitRack->GetEndpointUnit()->Active();
726 }
727 }
728
729 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC