/[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 2045 - (show annotations) (download)
Sun Jan 10 13:22:19 2010 UTC (14 years, 3 months ago) by persson
File size: 30098 byte(s)
* VST bugfix: If the host called resume() before and after changing
  sample rate or block size, the number of channels was incorrectly
  set to two. This caused silence in Cubase 5.
* removed compiler warnings

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

  ViewVC Help
Powered by ViewVC