/[svn]/linuxsampler/trunk/src/engines/gig/Voice.cpp
ViewVC logotype

Contents of /linuxsampler/trunk/src/engines/gig/Voice.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 865 - (show annotations) (download)
Sun May 14 07:15:52 2006 UTC (14 years, 2 months ago) by persson
File size: 48300 byte(s)
* sample loop parameters are now taken from the DimensionRegion
  instead of the wave chunk
* fixed keyswitching for v3 gigs with a number of keyswitch splits not
  equal to a power of two

1 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 * Copyright (C) 2005, 2006 Christian Schoenebeck *
7 * *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the Free Software *
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21 * MA 02111-1307 USA *
22 ***************************************************************************/
23
24 #include "../../common/Features.h"
25 #include "Synthesizer.h"
26 #include "Profiler.h"
27
28 #include "Voice.h"
29
30 namespace LinuxSampler { namespace gig {
31
32 const float Voice::FILTER_CUTOFF_COEFF(CalculateFilterCutoffCoeff());
33
34 float Voice::CalculateFilterCutoffCoeff() {
35 return log(CONFIG_FILTER_CUTOFF_MAX / CONFIG_FILTER_CUTOFF_MIN);
36 }
37
38 Voice::Voice() {
39 pEngine = NULL;
40 pDiskThread = NULL;
41 PlaybackState = playback_state_end;
42 pLFO1 = new LFOUnsigned(1.0f); // amplitude EG (0..1 range)
43 pLFO2 = new LFOUnsigned(1.0f); // filter EG (0..1 range)
44 pLFO3 = new LFOSigned(1200.0f); // pitch EG (-1200..+1200 range)
45 KeyGroup = 0;
46 SynthesisMode = 0; // set all mode bits to 0 first
47 // select synthesis implementation (currently either pure C++ or MMX+SSE(1))
48 #if CONFIG_ASM && ARCH_X86
49 SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, Features::supportsMMX() && Features::supportsSSE());
50 #else
51 SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, false);
52 #endif
53 SYNTHESIS_MODE_SET_PROFILING(SynthesisMode, Profiler::isEnabled());
54
55 finalSynthesisParameters.filterLeft.Reset();
56 finalSynthesisParameters.filterRight.Reset();
57 }
58
59 Voice::~Voice() {
60 if (pLFO1) delete pLFO1;
61 if (pLFO2) delete pLFO2;
62 if (pLFO3) delete pLFO3;
63 }
64
65 void Voice::SetEngine(Engine* pEngine) {
66 this->pEngine = pEngine;
67 this->pDiskThread = pEngine->pDiskThread;
68 dmsg(6,("Voice::SetEngine()\n"));
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 pDimRgn - points to the dimension 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 Voice::Trigger(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent, int PitchBend, ::gig::DimensionRegion* pDimRgn, type_t VoiceType, int iKeyGroup) {
86 this->pEngineChannel = pEngineChannel;
87 this->pDimRgn = pDimRgn;
88
89 #if CONFIG_DEVMODE
90 if (itNoteOnEvent->FragmentPos() > pEngine->MaxSamplesPerCycle) { // just a sanity check for debugging
91 dmsg(1,("Voice::Trigger(): ERROR, TriggerDelay > Totalsamples\n"));
92 }
93 #endif // CONFIG_DEVMODE
94
95 Type = VoiceType;
96 MIDIKey = itNoteOnEvent->Param.Note.Key;
97 PlaybackState = playback_state_init; // mark voice as triggered, but no audio rendered yet
98 Delay = itNoteOnEvent->FragmentPos();
99 itTriggerEvent = itNoteOnEvent;
100 itKillEvent = Pool<Event>::Iterator();
101 KeyGroup = iKeyGroup;
102 pSample = pDimRgn->pSample; // sample won't change until the voice is finished
103
104 // calculate volume
105 const double velocityAttenuation = pDimRgn->GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity);
106
107 float volume = velocityAttenuation / 32768.0f; // we downscale by 32768 to convert from int16 value range to DSP value range (which is -1.0..1.0)
108
109 volume *= pDimRgn->SampleAttenuation;
110
111 // the volume of release triggered samples depends on note length
112 if (Type == type_release_trigger) {
113 float noteLength = float(pEngine->FrameTime + Delay -
114 pEngineChannel->pMIDIKeyInfo[MIDIKey].NoteOnTime) / pEngine->SampleRate;
115 float attenuation = 1 - 0.01053 * (256 >> pDimRgn->ReleaseTriggerDecay) * noteLength;
116 if (attenuation <= 0) return -1;
117 volume *= attenuation;
118 }
119
120 // select channel mode (mono or stereo)
121 SYNTHESIS_MODE_SET_CHANNELS(SynthesisMode, pSample->Channels == 2);
122
123 // get starting crossfade volume level
124 float crossfadeVolume;
125 switch (pDimRgn->AttenuationController.type) {
126 case ::gig::attenuation_ctrl_t::type_channelaftertouch:
127 crossfadeVolume = 1.0f; //TODO: aftertouch not supported yet
128 break;
129 case ::gig::attenuation_ctrl_t::type_velocity:
130 crossfadeVolume = Engine::CrossfadeCurve[CrossfadeAttenuation(itNoteOnEvent->Param.Note.Velocity)];
131 break;
132 case ::gig::attenuation_ctrl_t::type_controlchange: //FIXME: currently not sample accurate
133 crossfadeVolume = Engine::CrossfadeCurve[CrossfadeAttenuation(pEngineChannel->ControllerTable[pDimRgn->AttenuationController.controller_number])];
134 break;
135 case ::gig::attenuation_ctrl_t::type_none: // no crossfade defined
136 default:
137 crossfadeVolume = 1.0f;
138 }
139
140 VolumeLeft = volume * Engine::PanCurve[64 - pDimRgn->Pan];
141 VolumeRight = volume * Engine::PanCurve[64 + pDimRgn->Pan];
142
143 float subfragmentRate = pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE;
144 CrossfadeSmoother.trigger(crossfadeVolume, subfragmentRate);
145 VolumeSmoother.trigger(pEngineChannel->GlobalVolume, subfragmentRate);
146 PanLeftSmoother.trigger(pEngineChannel->GlobalPanLeft, subfragmentRate);
147 PanRightSmoother.trigger(pEngineChannel->GlobalPanRight, subfragmentRate);
148
149 finalSynthesisParameters.dPos = pDimRgn->SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)
150 Pos = pDimRgn->SampleStartOffset;
151
152 // Check if the sample needs disk streaming or is too short for that
153 long cachedsamples = pSample->GetCache().Size / pSample->FrameSize;
154 DiskVoice = cachedsamples < pSample->SamplesTotal;
155
156 const DLS::sample_loop_t& loopinfo = pDimRgn->pSampleLoops[0];
157
158 if (DiskVoice) { // voice to be streamed from disk
159 MaxRAMPos = cachedsamples - (pEngine->MaxSamplesPerCycle << CONFIG_MAX_PITCH) / pSample->Channels; //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)
160
161 // check if there's a loop defined which completely fits into the cached (RAM) part of the sample
162 RAMLoop = (pDimRgn->SampleLoops && (loopinfo.LoopStart + loopinfo.LoopLength) <= MaxRAMPos);
163
164 if (pDiskThread->OrderNewStream(&DiskStreamRef, pDimRgn, MaxRAMPos, !RAMLoop) < 0) {
165 dmsg(1,("Disk stream order failed!\n"));
166 KillImmediately();
167 return -1;
168 }
169 dmsg(4,("Disk voice launched (cached samples: %d, total Samples: %d, MaxRAMPos: %d, RAMLooping: %s)\n", cachedsamples, pSample->SamplesTotal, MaxRAMPos, (RAMLoop) ? "yes" : "no"));
170 }
171 else { // RAM only voice
172 MaxRAMPos = cachedsamples;
173 RAMLoop = (pDimRgn->SampleLoops != 0);
174 dmsg(4,("RAM only voice launched (Looping: %s)\n", (RAMLoop) ? "yes" : "no"));
175 }
176 if (RAMLoop) {
177 loop.uiTotalCycles = pSample->LoopPlayCount;
178 loop.uiCyclesLeft = pSample->LoopPlayCount;
179 loop.uiStart = loopinfo.LoopStart;
180 loop.uiEnd = loopinfo.LoopStart + loopinfo.LoopLength;
181 loop.uiSize = loopinfo.LoopLength;
182 }
183
184 // calculate initial pitch value
185 {
186 double pitchbasecents = pDimRgn->FineTune + (int) pEngine->ScaleTuning[MIDIKey % 12];
187 if (pDimRgn->PitchTrack) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;
188 this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents) * (double(pSample->SamplesPerSecond) / double(pEngine->SampleRate));
189 this->PitchBend = RTMath::CentsToFreqRatio(((double) PitchBend / 8192.0) * 200.0); // pitchbend wheel +-2 semitones = 200 cents
190 }
191
192 // the length of the decay and release curves are dependent on the velocity
193 const double velrelease = 1 / pDimRgn->GetVelocityRelease(itNoteOnEvent->Param.Note.Velocity);
194
195 // setup EG 1 (VCA EG)
196 {
197 // get current value of EG1 controller
198 double eg1controllervalue;
199 switch (pDimRgn->EG1Controller.type) {
200 case ::gig::eg1_ctrl_t::type_none: // no controller defined
201 eg1controllervalue = 0;
202 break;
203 case ::gig::eg1_ctrl_t::type_channelaftertouch:
204 eg1controllervalue = 0; // TODO: aftertouch not yet supported
205 break;
206 case ::gig::eg1_ctrl_t::type_velocity:
207 eg1controllervalue = itNoteOnEvent->Param.Note.Velocity;
208 break;
209 case ::gig::eg1_ctrl_t::type_controlchange: // MIDI control change controller
210 eg1controllervalue = pEngineChannel->ControllerTable[pDimRgn->EG1Controller.controller_number];
211 break;
212 }
213 if (pDimRgn->EG1ControllerInvert) eg1controllervalue = 127 - eg1controllervalue;
214
215 // calculate influence of EG1 controller on EG1's parameters
216 // (eg1attack is different from the others)
217 double eg1attack = (pDimRgn->EG1ControllerAttackInfluence) ?
218 1 + 0.031 * (double) (pDimRgn->EG1ControllerAttackInfluence == 1 ?
219 1 : 1 << pDimRgn->EG1ControllerAttackInfluence) * eg1controllervalue : 1.0;
220 double eg1decay = (pDimRgn->EG1ControllerDecayInfluence) ? 1 + 0.00775 * (double) (1 << pDimRgn->EG1ControllerDecayInfluence) * eg1controllervalue : 1.0;
221 double eg1release = (pDimRgn->EG1ControllerReleaseInfluence) ? 1 + 0.00775 * (double) (1 << pDimRgn->EG1ControllerReleaseInfluence) * eg1controllervalue : 1.0;
222
223 EG1.trigger(pDimRgn->EG1PreAttack,
224 pDimRgn->EG1Attack * eg1attack,
225 pDimRgn->EG1Hold,
226 pDimRgn->EG1Decay1 * eg1decay * velrelease,
227 pDimRgn->EG1Decay2 * eg1decay * velrelease,
228 pDimRgn->EG1InfiniteSustain,
229 pDimRgn->EG1Sustain,
230 pDimRgn->EG1Release * eg1release * velrelease,
231 velocityAttenuation,
232 pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
233 }
234
235 #ifdef CONFIG_INTERPOLATE_VOLUME
236 // setup initial volume in synthesis parameters
237 #ifdef CONFIG_PROCESS_MUTED_CHANNELS
238 if (pEngineChannel->GetMute()) {
239 finalSynthesisParameters.fFinalVolumeLeft = 0;
240 finalSynthesisParameters.fFinalVolumeRight = 0;
241 }
242 else
243 #else
244 {
245 float finalVolume = pEngineChannel->GlobalVolume * crossfadeVolume * EG1.getLevel();
246
247 finalSynthesisParameters.fFinalVolumeLeft = finalVolume * VolumeLeft * pEngineChannel->GlobalPanLeft;
248 finalSynthesisParameters.fFinalVolumeRight = finalVolume * VolumeRight * pEngineChannel->GlobalPanRight;
249 }
250 #endif
251 #endif
252
253 // setup EG 2 (VCF Cutoff EG)
254 {
255 // get current value of EG2 controller
256 double eg2controllervalue;
257 switch (pDimRgn->EG2Controller.type) {
258 case ::gig::eg2_ctrl_t::type_none: // no controller defined
259 eg2controllervalue = 0;
260 break;
261 case ::gig::eg2_ctrl_t::type_channelaftertouch:
262 eg2controllervalue = 0; // TODO: aftertouch not yet supported
263 break;
264 case ::gig::eg2_ctrl_t::type_velocity:
265 eg2controllervalue = itNoteOnEvent->Param.Note.Velocity;
266 break;
267 case ::gig::eg2_ctrl_t::type_controlchange: // MIDI control change controller
268 eg2controllervalue = pEngineChannel->ControllerTable[pDimRgn->EG2Controller.controller_number];
269 break;
270 }
271 if (pDimRgn->EG2ControllerInvert) eg2controllervalue = 127 - eg2controllervalue;
272
273 // calculate influence of EG2 controller on EG2's parameters
274 double eg2attack = (pDimRgn->EG2ControllerAttackInfluence) ? 1 + 0.00775 * (double) (1 << pDimRgn->EG2ControllerAttackInfluence) * eg2controllervalue : 1.0;
275 double eg2decay = (pDimRgn->EG2ControllerDecayInfluence) ? 1 + 0.00775 * (double) (1 << pDimRgn->EG2ControllerDecayInfluence) * eg2controllervalue : 1.0;
276 double eg2release = (pDimRgn->EG2ControllerReleaseInfluence) ? 1 + 0.00775 * (double) (1 << pDimRgn->EG2ControllerReleaseInfluence) * eg2controllervalue : 1.0;
277
278 EG2.trigger(pDimRgn->EG2PreAttack,
279 pDimRgn->EG2Attack * eg2attack,
280 false,
281 pDimRgn->EG2Decay1 * eg2decay * velrelease,
282 pDimRgn->EG2Decay2 * eg2decay * velrelease,
283 pDimRgn->EG2InfiniteSustain,
284 pDimRgn->EG2Sustain,
285 pDimRgn->EG2Release * eg2release * velrelease,
286 velocityAttenuation,
287 pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
288 }
289
290
291 // setup EG 3 (VCO EG)
292 {
293 // if portamento mode is on, we dedicate EG3 purely for portamento, otherwise if portamento is off we do as told by the patch
294 bool bPortamento = pEngineChannel->PortamentoMode && pEngineChannel->PortamentoPos >= 0.0f;
295 float eg3depth = (bPortamento)
296 ? RTMath::CentsToFreqRatio((pEngineChannel->PortamentoPos - (float) MIDIKey) * 100)
297 : RTMath::CentsToFreqRatio(pDimRgn->EG3Depth);
298 float eg3time = (bPortamento)
299 ? pEngineChannel->PortamentoTime
300 : pDimRgn->EG3Attack;
301 EG3.trigger(eg3depth, eg3time, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
302 dmsg(5,("PortamentoPos=%f, depth=%f, time=%f\n", pEngineChannel->PortamentoPos, eg3depth, eg3time));
303 }
304
305
306 // setup LFO 1 (VCA LFO)
307 {
308 uint16_t lfo1_internal_depth;
309 switch (pDimRgn->LFO1Controller) {
310 case ::gig::lfo1_ctrl_internal:
311 lfo1_internal_depth = pDimRgn->LFO1InternalDepth;
312 pLFO1->ExtController = 0; // no external controller
313 bLFO1Enabled = (lfo1_internal_depth > 0);
314 break;
315 case ::gig::lfo1_ctrl_modwheel:
316 lfo1_internal_depth = 0;
317 pLFO1->ExtController = 1; // MIDI controller 1
318 bLFO1Enabled = (pDimRgn->LFO1ControlDepth > 0);
319 break;
320 case ::gig::lfo1_ctrl_breath:
321 lfo1_internal_depth = 0;
322 pLFO1->ExtController = 2; // MIDI controller 2
323 bLFO1Enabled = (pDimRgn->LFO1ControlDepth > 0);
324 break;
325 case ::gig::lfo1_ctrl_internal_modwheel:
326 lfo1_internal_depth = pDimRgn->LFO1InternalDepth;
327 pLFO1->ExtController = 1; // MIDI controller 1
328 bLFO1Enabled = (lfo1_internal_depth > 0 || pDimRgn->LFO1ControlDepth > 0);
329 break;
330 case ::gig::lfo1_ctrl_internal_breath:
331 lfo1_internal_depth = pDimRgn->LFO1InternalDepth;
332 pLFO1->ExtController = 2; // MIDI controller 2
333 bLFO1Enabled = (lfo1_internal_depth > 0 || pDimRgn->LFO1ControlDepth > 0);
334 break;
335 default:
336 lfo1_internal_depth = 0;
337 pLFO1->ExtController = 0; // no external controller
338 bLFO1Enabled = false;
339 }
340 if (bLFO1Enabled) {
341 pLFO1->trigger(pDimRgn->LFO1Frequency,
342 start_level_max,
343 lfo1_internal_depth,
344 pDimRgn->LFO1ControlDepth,
345 pDimRgn->LFO1FlipPhase,
346 pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
347 pLFO1->update(pLFO1->ExtController ? pEngineChannel->ControllerTable[pLFO1->ExtController] : 0);
348 }
349 }
350
351
352 // setup LFO 2 (VCF Cutoff LFO)
353 {
354 uint16_t lfo2_internal_depth;
355 switch (pDimRgn->LFO2Controller) {
356 case ::gig::lfo2_ctrl_internal:
357 lfo2_internal_depth = pDimRgn->LFO2InternalDepth;
358 pLFO2->ExtController = 0; // no external controller
359 bLFO2Enabled = (lfo2_internal_depth > 0);
360 break;
361 case ::gig::lfo2_ctrl_modwheel:
362 lfo2_internal_depth = 0;
363 pLFO2->ExtController = 1; // MIDI controller 1
364 bLFO2Enabled = (pDimRgn->LFO2ControlDepth > 0);
365 break;
366 case ::gig::lfo2_ctrl_foot:
367 lfo2_internal_depth = 0;
368 pLFO2->ExtController = 4; // MIDI controller 4
369 bLFO2Enabled = (pDimRgn->LFO2ControlDepth > 0);
370 break;
371 case ::gig::lfo2_ctrl_internal_modwheel:
372 lfo2_internal_depth = pDimRgn->LFO2InternalDepth;
373 pLFO2->ExtController = 1; // MIDI controller 1
374 bLFO2Enabled = (lfo2_internal_depth > 0 || pDimRgn->LFO2ControlDepth > 0);
375 break;
376 case ::gig::lfo2_ctrl_internal_foot:
377 lfo2_internal_depth = pDimRgn->LFO2InternalDepth;
378 pLFO2->ExtController = 4; // MIDI controller 4
379 bLFO2Enabled = (lfo2_internal_depth > 0 || pDimRgn->LFO2ControlDepth > 0);
380 break;
381 default:
382 lfo2_internal_depth = 0;
383 pLFO2->ExtController = 0; // no external controller
384 bLFO2Enabled = false;
385 }
386 if (bLFO2Enabled) {
387 pLFO2->trigger(pDimRgn->LFO2Frequency,
388 start_level_max,
389 lfo2_internal_depth,
390 pDimRgn->LFO2ControlDepth,
391 pDimRgn->LFO2FlipPhase,
392 pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
393 pLFO2->update(pLFO2->ExtController ? pEngineChannel->ControllerTable[pLFO2->ExtController] : 0);
394 }
395 }
396
397
398 // setup LFO 3 (VCO LFO)
399 {
400 uint16_t lfo3_internal_depth;
401 switch (pDimRgn->LFO3Controller) {
402 case ::gig::lfo3_ctrl_internal:
403 lfo3_internal_depth = pDimRgn->LFO3InternalDepth;
404 pLFO3->ExtController = 0; // no external controller
405 bLFO3Enabled = (lfo3_internal_depth > 0);
406 break;
407 case ::gig::lfo3_ctrl_modwheel:
408 lfo3_internal_depth = 0;
409 pLFO3->ExtController = 1; // MIDI controller 1
410 bLFO3Enabled = (pDimRgn->LFO3ControlDepth > 0);
411 break;
412 case ::gig::lfo3_ctrl_aftertouch:
413 lfo3_internal_depth = 0;
414 pLFO3->ExtController = 0; // TODO: aftertouch not implemented yet
415 bLFO3Enabled = false; // see TODO comment in line above
416 break;
417 case ::gig::lfo3_ctrl_internal_modwheel:
418 lfo3_internal_depth = pDimRgn->LFO3InternalDepth;
419 pLFO3->ExtController = 1; // MIDI controller 1
420 bLFO3Enabled = (lfo3_internal_depth > 0 || pDimRgn->LFO3ControlDepth > 0);
421 break;
422 case ::gig::lfo3_ctrl_internal_aftertouch:
423 lfo3_internal_depth = pDimRgn->LFO3InternalDepth;
424 pLFO1->ExtController = 0; // TODO: aftertouch not implemented yet
425 bLFO3Enabled = (lfo3_internal_depth > 0 /*|| pDimRgn->LFO3ControlDepth > 0*/); // see TODO comment in line above
426 break;
427 default:
428 lfo3_internal_depth = 0;
429 pLFO3->ExtController = 0; // no external controller
430 bLFO3Enabled = false;
431 }
432 if (bLFO3Enabled) {
433 pLFO3->trigger(pDimRgn->LFO3Frequency,
434 start_level_mid,
435 lfo3_internal_depth,
436 pDimRgn->LFO3ControlDepth,
437 false,
438 pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
439 pLFO3->update(pLFO3->ExtController ? pEngineChannel->ControllerTable[pLFO3->ExtController] : 0);
440 }
441 }
442
443
444 #if CONFIG_FORCE_FILTER
445 const bool bUseFilter = true;
446 #else // use filter only if instrument file told so
447 const bool bUseFilter = pDimRgn->VCFEnabled;
448 #endif // CONFIG_FORCE_FILTER
449 SYNTHESIS_MODE_SET_FILTER(SynthesisMode, bUseFilter);
450 if (bUseFilter) {
451 #ifdef CONFIG_OVERRIDE_CUTOFF_CTRL
452 VCFCutoffCtrl.controller = CONFIG_OVERRIDE_CUTOFF_CTRL;
453 #else // use the one defined in the instrument file
454 switch (pDimRgn->VCFCutoffController) {
455 case ::gig::vcf_cutoff_ctrl_modwheel:
456 VCFCutoffCtrl.controller = 1;
457 break;
458 case ::gig::vcf_cutoff_ctrl_effect1:
459 VCFCutoffCtrl.controller = 12;
460 break;
461 case ::gig::vcf_cutoff_ctrl_effect2:
462 VCFCutoffCtrl.controller = 13;
463 break;
464 case ::gig::vcf_cutoff_ctrl_breath:
465 VCFCutoffCtrl.controller = 2;
466 break;
467 case ::gig::vcf_cutoff_ctrl_foot:
468 VCFCutoffCtrl.controller = 4;
469 break;
470 case ::gig::vcf_cutoff_ctrl_sustainpedal:
471 VCFCutoffCtrl.controller = 64;
472 break;
473 case ::gig::vcf_cutoff_ctrl_softpedal:
474 VCFCutoffCtrl.controller = 67;
475 break;
476 case ::gig::vcf_cutoff_ctrl_genpurpose7:
477 VCFCutoffCtrl.controller = 82;
478 break;
479 case ::gig::vcf_cutoff_ctrl_genpurpose8:
480 VCFCutoffCtrl.controller = 83;
481 break;
482 case ::gig::vcf_cutoff_ctrl_aftertouch: //TODO: not implemented yet
483 case ::gig::vcf_cutoff_ctrl_none:
484 default:
485 VCFCutoffCtrl.controller = 0;
486 break;
487 }
488 #endif // CONFIG_OVERRIDE_CUTOFF_CTRL
489
490 #ifdef CONFIG_OVERRIDE_RESONANCE_CTRL
491 VCFResonanceCtrl.controller = CONFIG_OVERRIDE_RESONANCE_CTRL;
492 #else // use the one defined in the instrument file
493 switch (pDimRgn->VCFResonanceController) {
494 case ::gig::vcf_res_ctrl_genpurpose3:
495 VCFResonanceCtrl.controller = 18;
496 break;
497 case ::gig::vcf_res_ctrl_genpurpose4:
498 VCFResonanceCtrl.controller = 19;
499 break;
500 case ::gig::vcf_res_ctrl_genpurpose5:
501 VCFResonanceCtrl.controller = 80;
502 break;
503 case ::gig::vcf_res_ctrl_genpurpose6:
504 VCFResonanceCtrl.controller = 81;
505 break;
506 case ::gig::vcf_res_ctrl_none:
507 default:
508 VCFResonanceCtrl.controller = 0;
509 }
510 #endif // CONFIG_OVERRIDE_RESONANCE_CTRL
511
512 #ifndef CONFIG_OVERRIDE_FILTER_TYPE
513 finalSynthesisParameters.filterLeft.SetType(pDimRgn->VCFType);
514 finalSynthesisParameters.filterRight.SetType(pDimRgn->VCFType);
515 #else // override filter type
516 FilterLeft.SetType(CONFIG_OVERRIDE_FILTER_TYPE);
517 FilterRight.SetType(CONFIG_OVERRIDE_FILTER_TYPE);
518 #endif // CONFIG_OVERRIDE_FILTER_TYPE
519
520 VCFCutoffCtrl.value = pEngineChannel->ControllerTable[VCFCutoffCtrl.controller];
521 VCFResonanceCtrl.value = pEngineChannel->ControllerTable[VCFResonanceCtrl.controller];
522
523 // calculate cutoff frequency
524 float cutoff = pDimRgn->GetVelocityCutoff(itNoteOnEvent->Param.Note.Velocity);
525 if (pDimRgn->VCFKeyboardTracking) {
526 cutoff *= exp((itNoteOnEvent->Param.Note.Key - pDimRgn->VCFKeyboardTrackingBreakpoint) * 0.057762265f); // (ln(2) / 12)
527 }
528 CutoffBase = cutoff;
529
530 int cvalue;
531 if (VCFCutoffCtrl.controller) {
532 cvalue = pEngineChannel->ControllerTable[VCFCutoffCtrl.controller];
533 if (pDimRgn->VCFCutoffControllerInvert) cvalue = 127 - cvalue;
534 // VCFVelocityScale in this case means Minimum cutoff
535 if (cvalue < pDimRgn->VCFVelocityScale) cvalue = pDimRgn->VCFVelocityScale;
536 }
537 else {
538 cvalue = pDimRgn->VCFCutoff;
539 }
540 cutoff *= float(cvalue) * 0.00787402f; // (1 / 127)
541 if (cutoff > 1.0) cutoff = 1.0;
542 cutoff = (cutoff < 0.5 ? cutoff * 4826 - 1 : cutoff * 5715 - 449);
543 if (cutoff < 1.0) cutoff = 1.0;
544
545 // calculate resonance
546 float resonance = (float) (VCFResonanceCtrl.controller ? VCFResonanceCtrl.value : pDimRgn->VCFResonance) * 0.00787f; // 0.0..1.0
547
548 VCFCutoffCtrl.fvalue = cutoff - 1.0;
549 VCFResonanceCtrl.fvalue = resonance;
550 }
551 else {
552 VCFCutoffCtrl.controller = 0;
553 VCFResonanceCtrl.controller = 0;
554 }
555
556 return 0; // success
557 }
558
559 /**
560 * Renders the audio data for this voice for the current audio fragment.
561 * The sample input data can either come from RAM (cached sample or sample
562 * part) or directly from disk. The output signal will be rendered by
563 * resampling / interpolation. If this voice is a disk streaming voice and
564 * the voice completely played back the cached RAM part of the sample, it
565 * will automatically switch to disk playback for the next RenderAudio()
566 * call.
567 *
568 * @param Samples - number of samples to be rendered in this audio fragment cycle
569 */
570 void Voice::Render(uint Samples) {
571
572 // select default values for synthesis mode bits
573 SYNTHESIS_MODE_SET_LOOP(SynthesisMode, false);
574
575 switch (this->PlaybackState) {
576
577 case playback_state_init:
578 this->PlaybackState = playback_state_ram; // we always start playback from RAM cache and switch then to disk if needed
579 // no break - continue with playback_state_ram
580
581 case playback_state_ram: {
582 if (RAMLoop) SYNTHESIS_MODE_SET_LOOP(SynthesisMode, true); // enable looping
583
584 // render current fragment
585 Synthesize(Samples, (sample_t*) pSample->GetCache().pStart, Delay);
586
587 if (DiskVoice) {
588 // check if we reached the allowed limit of the sample RAM cache
589 if (finalSynthesisParameters.dPos > MaxRAMPos) {
590 dmsg(5,("Voice: switching to disk playback (Pos=%f)\n", finalSynthesisParameters.dPos));
591 this->PlaybackState = playback_state_disk;
592 }
593 } else if (finalSynthesisParameters.dPos >= pSample->GetCache().Size / pSample->FrameSize) {
594 this->PlaybackState = playback_state_end;
595 }
596 }
597 break;
598
599 case playback_state_disk: {
600 if (!DiskStreamRef.pStream) {
601 // check if the disk thread created our ordered disk stream in the meantime
602 DiskStreamRef.pStream = pDiskThread->AskForCreatedStream(DiskStreamRef.OrderID);
603 if (!DiskStreamRef.pStream) {
604 std::cout << stderr << "Disk stream not available in time!" << std::endl << std::flush;
605 KillImmediately();
606 return;
607 }
608 DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (int(finalSynthesisParameters.dPos) - MaxRAMPos));
609 finalSynthesisParameters.dPos -= int(finalSynthesisParameters.dPos);
610 RealSampleWordsLeftToRead = -1; // -1 means no silence has been added yet
611 }
612
613 const int sampleWordsLeftToRead = DiskStreamRef.pStream->GetReadSpace();
614
615 // add silence sample at the end if we reached the end of the stream (for the interpolator)
616 if (DiskStreamRef.State == Stream::state_end) {
617 const int maxSampleWordsPerCycle = (pEngine->MaxSamplesPerCycle << CONFIG_MAX_PITCH) * pSample->Channels + 6; // +6 for the interpolator algorithm
618 if (sampleWordsLeftToRead <= maxSampleWordsPerCycle) {
619 // remember how many sample words there are before any silence has been added
620 if (RealSampleWordsLeftToRead < 0) RealSampleWordsLeftToRead = sampleWordsLeftToRead;
621 DiskStreamRef.pStream->WriteSilence(maxSampleWordsPerCycle - sampleWordsLeftToRead);
622 }
623 }
624
625 sample_t* ptr = DiskStreamRef.pStream->GetReadPtr(); // get the current read_ptr within the ringbuffer where we read the samples from
626
627 // render current audio fragment
628 Synthesize(Samples, ptr, Delay);
629
630 const int iPos = (int) finalSynthesisParameters.dPos;
631 const int readSampleWords = iPos * pSample->Channels; // amount of sample words actually been read
632 DiskStreamRef.pStream->IncrementReadPos(readSampleWords);
633 finalSynthesisParameters.dPos -= iPos; // just keep fractional part of playback position
634
635 // change state of voice to 'end' if we really reached the end of the sample data
636 if (RealSampleWordsLeftToRead >= 0) {
637 RealSampleWordsLeftToRead -= readSampleWords;
638 if (RealSampleWordsLeftToRead <= 0) this->PlaybackState = playback_state_end;
639 }
640 }
641 break;
642
643 case playback_state_end:
644 std::cerr << "gig::Voice::Render(): entered with playback_state_end, this is a bug!\n" << std::flush;
645 break;
646 }
647
648 // Reset delay
649 Delay = 0;
650
651 itTriggerEvent = Pool<Event>::Iterator();
652
653 // If sample stream or release stage finished, kill the voice
654 if (PlaybackState == playback_state_end || EG1.getSegmentType() == EGADSR::segment_end) KillImmediately();
655 }
656
657 /**
658 * Resets voice variables. Should only be called if rendering process is
659 * suspended / not running.
660 */
661 void Voice::Reset() {
662 finalSynthesisParameters.filterLeft.Reset();
663 finalSynthesisParameters.filterRight.Reset();
664 DiskStreamRef.pStream = NULL;
665 DiskStreamRef.hStream = 0;
666 DiskStreamRef.State = Stream::state_unused;
667 DiskStreamRef.OrderID = 0;
668 PlaybackState = playback_state_end;
669 itTriggerEvent = Pool<Event>::Iterator();
670 itKillEvent = Pool<Event>::Iterator();
671 }
672
673 /**
674 * Process given list of MIDI note on, note off and sustain pedal events
675 * for the given time.
676 *
677 * @param itEvent - iterator pointing to the next event to be processed
678 * @param End - youngest time stamp where processing should be stopped
679 */
680 void Voice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) {
681 for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
682 if (itEvent->Type == Event::type_release) {
683 EG1.update(EGADSR::event_release, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
684 EG2.update(EGADSR::event_release, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
685 } else if (itEvent->Type == Event::type_cancel_release) {
686 EG1.update(EGADSR::event_cancel_release, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
687 EG2.update(EGADSR::event_cancel_release, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
688 }
689 }
690 }
691
692 /**
693 * Process given list of MIDI control change and pitch bend events for
694 * the given time.
695 *
696 * @param itEvent - iterator pointing to the next event to be processed
697 * @param End - youngest time stamp where processing should be stopped
698 */
699 void Voice::processCCEvents(RTList<Event>::Iterator& itEvent, uint End) {
700 for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
701 if (itEvent->Type == Event::type_control_change &&
702 itEvent->Param.CC.Controller) { // if (valid) MIDI control change event
703 if (itEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {
704 processCutoffEvent(itEvent);
705 }
706 if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {
707 processResonanceEvent(itEvent);
708 }
709 if (itEvent->Param.CC.Controller == pLFO1->ExtController) {
710 pLFO1->update(itEvent->Param.CC.Value);
711 }
712 if (itEvent->Param.CC.Controller == pLFO2->ExtController) {
713 pLFO2->update(itEvent->Param.CC.Value);
714 }
715 if (itEvent->Param.CC.Controller == pLFO3->ExtController) {
716 pLFO3->update(itEvent->Param.CC.Value);
717 }
718 if (pDimRgn->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange &&
719 itEvent->Param.CC.Controller == pDimRgn->AttenuationController.controller_number) {
720 CrossfadeSmoother.update(Engine::CrossfadeCurve[CrossfadeAttenuation(itEvent->Param.CC.Value)]);
721 }
722 if (itEvent->Param.CC.Controller == 7) { // volume
723 VolumeSmoother.update(Engine::VolumeCurve[itEvent->Param.CC.Value] * CONFIG_GLOBAL_ATTENUATION);
724 } else if (itEvent->Param.CC.Controller == 10) { // panpot
725 PanLeftSmoother.update(Engine::PanCurve[128 - itEvent->Param.CC.Value]);
726 PanRightSmoother.update(Engine::PanCurve[itEvent->Param.CC.Value]);
727 }
728 } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event
729 processPitchEvent(itEvent);
730 }
731 }
732 }
733
734 void Voice::processPitchEvent(RTList<Event>::Iterator& itEvent) {
735 const float pitch = RTMath::CentsToFreqRatio(((double) itEvent->Param.Pitch.Pitch / 8192.0) * 200.0); // +-two semitones = +-200 cents
736 finalSynthesisParameters.fFinalPitch *= pitch;
737 PitchBend = pitch;
738 }
739
740 void Voice::processCutoffEvent(RTList<Event>::Iterator& itEvent) {
741 int ccvalue = itEvent->Param.CC.Value;
742 if (VCFCutoffCtrl.value == ccvalue) return;
743 VCFCutoffCtrl.value == ccvalue;
744 if (pDimRgn->VCFCutoffControllerInvert) ccvalue = 127 - ccvalue;
745 if (ccvalue < pDimRgn->VCFVelocityScale) ccvalue = pDimRgn->VCFVelocityScale;
746 float cutoff = CutoffBase * float(ccvalue) * 0.00787402f; // (1 / 127)
747 if (cutoff > 1.0) cutoff = 1.0;
748 cutoff = (cutoff < 0.5 ? cutoff * 4826 - 1 : cutoff * 5715 - 449);
749 if (cutoff < 1.0) cutoff = 1.0;
750
751 VCFCutoffCtrl.fvalue = cutoff - 1.0; // needed for initialization of fFinalCutoff next time
752 fFinalCutoff = cutoff;
753 }
754
755 void Voice::processResonanceEvent(RTList<Event>::Iterator& itEvent) {
756 // convert absolute controller value to differential
757 const int ctrldelta = itEvent->Param.CC.Value - VCFResonanceCtrl.value;
758 VCFResonanceCtrl.value = itEvent->Param.CC.Value;
759 const float resonancedelta = (float) ctrldelta * 0.00787f; // 0.0..1.0
760 fFinalResonance += resonancedelta;
761 // needed for initialization of parameter
762 VCFResonanceCtrl.fvalue = itEvent->Param.CC.Value * 0.00787f;
763 }
764
765 /**
766 * Synthesizes the current audio fragment for this voice.
767 *
768 * @param Samples - number of sample points to be rendered in this audio
769 * fragment cycle
770 * @param pSrc - pointer to input sample data
771 * @param Skip - number of sample points to skip in output buffer
772 */
773 void Voice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {
774 finalSynthesisParameters.pOutLeft = &pEngineChannel->pOutputLeft[Skip];
775 finalSynthesisParameters.pOutRight = &pEngineChannel->pOutputRight[Skip];
776 finalSynthesisParameters.pSrc = pSrc;
777
778 RTList<Event>::Iterator itCCEvent = pEngineChannel->pEvents->first();
779 RTList<Event>::Iterator itNoteEvent = pEngineChannel->pMIDIKeyInfo[MIDIKey].pEvents->first();
780
781 if (Skip) { // skip events that happened before this voice was triggered
782 while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;
783 while (itNoteEvent && itNoteEvent->FragmentPos() <= Skip) ++itNoteEvent;
784 }
785
786 uint killPos;
787 if (itKillEvent) killPos = RTMath::Min(itKillEvent->FragmentPos(), pEngine->MaxFadeOutPos);
788
789 uint i = Skip;
790 while (i < Samples) {
791 int iSubFragmentEnd = RTMath::Min(i + CONFIG_DEFAULT_SUBFRAGMENT_SIZE, Samples);
792
793 // initialize all final synthesis parameters
794 finalSynthesisParameters.fFinalPitch = PitchBase * PitchBend;
795 fFinalCutoff = VCFCutoffCtrl.fvalue;
796 fFinalResonance = VCFResonanceCtrl.fvalue;
797
798 // process MIDI control change and pitchbend events for this subfragment
799 processCCEvents(itCCEvent, iSubFragmentEnd);
800
801 float fFinalVolume = VolumeSmoother.render() * CrossfadeSmoother.render();
802 #ifdef CONFIG_PROCESS_MUTED_CHANNELS
803 if (pEngineChannel->GetMute()) fFinalVolume = 0;
804 #endif
805
806 // process transition events (note on, note off & sustain pedal)
807 processTransitionEvents(itNoteEvent, iSubFragmentEnd);
808
809 // if the voice was killed in this subfragment switch EG1 to fade out stage
810 if (itKillEvent && killPos <= iSubFragmentEnd) {
811 EG1.enterFadeOutStage();
812 itKillEvent = Pool<Event>::Iterator();
813 }
814
815 // process envelope generators
816 switch (EG1.getSegmentType()) {
817 case EGADSR::segment_lin:
818 fFinalVolume *= EG1.processLin();
819 break;
820 case EGADSR::segment_exp:
821 fFinalVolume *= EG1.processExp();
822 break;
823 case EGADSR::segment_end:
824 fFinalVolume *= EG1.getLevel();
825 break; // noop
826 }
827 switch (EG2.getSegmentType()) {
828 case EGADSR::segment_lin:
829 fFinalCutoff *= EG2.processLin();
830 break;
831 case EGADSR::segment_exp:
832 fFinalCutoff *= EG2.processExp();
833 break;
834 case EGADSR::segment_end:
835 fFinalCutoff *= EG2.getLevel();
836 break; // noop
837 }
838 if (EG3.active()) finalSynthesisParameters.fFinalPitch *= EG3.render();
839
840 // process low frequency oscillators
841 if (bLFO1Enabled) fFinalVolume *= pLFO1->render();
842 if (bLFO2Enabled) fFinalCutoff *= pLFO2->render();
843 if (bLFO3Enabled) finalSynthesisParameters.fFinalPitch *= RTMath::CentsToFreqRatio(pLFO3->render());
844
845 // if filter enabled then update filter coefficients
846 if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode)) {
847 finalSynthesisParameters.filterLeft.SetParameters(fFinalCutoff + 1.0, fFinalResonance, pEngine->SampleRate);
848 finalSynthesisParameters.filterRight.SetParameters(fFinalCutoff + 1.0, fFinalResonance, pEngine->SampleRate);
849 }
850
851 // do we need resampling?
852 const float __PLUS_ONE_CENT = 1.000577789506554859250142541782224725466f;
853 const float __MINUS_ONE_CENT = 0.9994225441413807496009516495583113737666f;
854 const bool bResamplingRequired = !(finalSynthesisParameters.fFinalPitch <= __PLUS_ONE_CENT &&
855 finalSynthesisParameters.fFinalPitch >= __MINUS_ONE_CENT);
856 SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, bResamplingRequired);
857
858 // prepare final synthesis parameters structure
859 finalSynthesisParameters.uiToGo = iSubFragmentEnd - i;
860 #ifdef CONFIG_INTERPOLATE_VOLUME
861 finalSynthesisParameters.fFinalVolumeDeltaLeft =
862 (fFinalVolume * VolumeLeft * PanLeftSmoother.render() -
863 finalSynthesisParameters.fFinalVolumeLeft) / finalSynthesisParameters.uiToGo;
864 finalSynthesisParameters.fFinalVolumeDeltaRight =
865 (fFinalVolume * VolumeRight * PanRightSmoother.render() -
866 finalSynthesisParameters.fFinalVolumeRight) / finalSynthesisParameters.uiToGo;
867 #else
868 finalSynthesisParameters.fFinalVolumeLeft =
869 fFinalVolume * VolumeLeft * PanLeftSmoother.render();
870 finalSynthesisParameters.fFinalVolumeRight =
871 fFinalVolume * VolumeRight * PanRightSmoother.render();
872 #endif
873 // render audio for one subfragment
874 RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop);
875
876 // stop the rendering if volume EG is finished
877 if (EG1.getSegmentType() == EGADSR::segment_end) break;
878
879 const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch;
880
881 // increment envelopes' positions
882 if (EG1.active()) {
883
884 // 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
885 if (pDimRgn->SampleLoops && Pos <= pDimRgn->pSampleLoops[0].LoopStart && pDimRgn->pSampleLoops[0].LoopStart < newPos) {
886 EG1.update(EGADSR::event_hold_end, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
887 }
888
889 EG1.increment(1);
890 if (!EG1.toStageEndLeft()) EG1.update(EGADSR::event_stage_end, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
891 }
892 if (EG2.active()) {
893 EG2.increment(1);
894 if (!EG2.toStageEndLeft()) EG2.update(EGADSR::event_stage_end, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
895 }
896 EG3.increment(1);
897 if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached
898
899 Pos = newPos;
900 i = iSubFragmentEnd;
901 }
902 }
903
904 /** @brief Update current portamento position.
905 *
906 * Will be called when portamento mode is enabled to get the final
907 * portamento position of this active voice from where the next voice(s)
908 * might continue to slide on.
909 *
910 * @param itNoteOffEvent - event which causes this voice to die soon
911 */
912 void Voice::UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent) {
913 const float fFinalEG3Level = EG3.level(itNoteOffEvent->FragmentPos());
914 pEngineChannel->PortamentoPos = (float) MIDIKey + RTMath::FreqRatioToCents(fFinalEG3Level) * 0.01f;
915 }
916
917 /**
918 * Immediately kill the voice. This method should not be used to kill
919 * a normal, active voice, because it doesn't take care of things like
920 * fading down the volume level to avoid clicks and regular processing
921 * until the kill event actually occured!
922 *
923 * @see Kill()
924 */
925 void Voice::KillImmediately() {
926 if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {
927 pDiskThread->OrderDeletionOfStream(&DiskStreamRef);
928 }
929 Reset();
930 }
931
932 /**
933 * Kill the voice in regular sense. Let the voice render audio until
934 * the kill event actually occured and then fade down the volume level
935 * very quickly and let the voice die finally. Unlike a normal release
936 * of a voice, a kill process cannot be cancalled and is therefore
937 * usually used for voice stealing and key group conflicts.
938 *
939 * @param itKillEvent - event which caused the voice to be killed
940 */
941 void Voice::Kill(Pool<Event>::Iterator& itKillEvent) {
942 #if CONFIG_DEVMODE
943 if (!itKillEvent) dmsg(1,("gig::Voice::Kill(): ERROR, !itKillEvent !!!\n"));
944 if (itKillEvent && !itKillEvent.isValid()) dmsg(1,("gig::Voice::Kill(): ERROR, itKillEvent invalid !!!\n"));
945 #endif // CONFIG_DEVMODE
946
947 if (itTriggerEvent && itKillEvent->FragmentPos() <= itTriggerEvent->FragmentPos()) return;
948 this->itKillEvent = itKillEvent;
949 }
950
951 }} // namespace LinuxSampler::gig

  ViewVC Help
Powered by ViewVC