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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1843 - (show annotations) (download)
Sat Feb 21 17:08:18 2009 UTC (15 years, 1 month ago) by iliev
File size: 110500 byte(s)
* fixed orphaned pointers when setting maximum voices limit (bug #118)

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 * *
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 <sstream>
25 #include "DiskThread.h"
26 #include "Voice.h"
27 #include "EGADSR.h"
28 #include "../EngineFactory.h"
29
30 #include "Engine.h"
31
32 #include "../../common/global_private.h"
33
34 namespace LinuxSampler { namespace gig {
35
36 InstrumentResourceManager Engine::instruments;
37
38 std::map<AudioOutputDevice*,Engine*> Engine::engines;
39
40 /**
41 * Get a gig::Engine object for the given gig::EngineChannel and the
42 * given AudioOutputDevice. All engine channels which are connected to
43 * the same audio output device will use the same engine instance. This
44 * method will be called by a gig::EngineChannel whenever it's
45 * connecting to a audio output device.
46 *
47 * @param pChannel - engine channel which acquires an engine object
48 * @param pDevice - the audio output device \a pChannel is connected to
49 */
50 Engine* Engine::AcquireEngine(LinuxSampler::gig::EngineChannel* pChannel, AudioOutputDevice* pDevice) {
51 Engine* pEngine = NULL;
52 // check if there's already an engine for the given audio output device
53 if (engines.count(pDevice)) {
54 dmsg(4,("Using existing gig::Engine.\n"));
55 pEngine = engines[pDevice];
56
57 // Disable the engine while the new engine channel is
58 // added and initialized. The engine will be enabled again
59 // in EngineChannel::Connect.
60 pEngine->DisableAndLock();
61 } else { // create a new engine (and disk thread) instance for the given audio output device
62 dmsg(4,("Creating new gig::Engine.\n"));
63 pEngine = (Engine*) EngineFactory::Create("gig");
64 pEngine->Connect(pDevice);
65 engines[pDevice] = pEngine;
66 }
67 // register engine channel to the engine instance
68 pEngine->engineChannels.add(pChannel);
69 // remember index in the ArrayList
70 pChannel->iEngineIndexSelf = pEngine->engineChannels.size() - 1;
71 dmsg(4,("This gig::Engine has now %d EngineChannels.\n",pEngine->engineChannels.size()));
72 return pEngine;
73 }
74
75 /**
76 * Once an engine channel is disconnected from an audio output device,
77 * it will immediately call this method to unregister itself from the
78 * engine instance and if that engine instance is not used by any other
79 * engine channel anymore, then that engine instance will be destroyed.
80 *
81 * @param pChannel - engine channel which wants to disconnect from it's
82 * engine instance
83 * @param pDevice - audio output device \a pChannel was connected to
84 */
85 void Engine::FreeEngine(LinuxSampler::gig::EngineChannel* pChannel, AudioOutputDevice* pDevice) {
86 dmsg(4,("Disconnecting EngineChannel from gig::Engine.\n"));
87 Engine* pEngine = engines[pDevice];
88 // unregister EngineChannel from the Engine instance
89 pEngine->engineChannels.remove(pChannel);
90 // if the used Engine instance is not used anymore, then destroy it
91 if (pEngine->engineChannels.empty()) {
92 pDevice->Disconnect(pEngine);
93 engines.erase(pDevice);
94 delete pEngine;
95 dmsg(4,("Destroying gig::Engine.\n"));
96 }
97 else dmsg(4,("This gig::Engine has now %d EngineChannels.\n",pEngine->engineChannels.size()));
98 }
99
100 /**
101 * Constructor
102 */
103 Engine::Engine() : SuspendedRegions(128) {
104 pAudioOutputDevice = NULL;
105 pDiskThread = NULL;
106 pEventGenerator = NULL;
107 pSysexBuffer = new RingBuffer<uint8_t,false>(CONFIG_SYSEX_BUFFER_SIZE, 0);
108 pEventQueue = new RingBuffer<Event,false>(CONFIG_MAX_EVENTS_PER_FRAGMENT, 0);
109 pEventPool = new Pool<Event>(CONFIG_MAX_EVENTS_PER_FRAGMENT);
110 pVoicePool = new Pool<Voice>(GLOBAL_MAX_VOICES);
111 pDimRegionPool[0] = new Pool< ::gig::DimensionRegion*>(GLOBAL_MAX_VOICES);
112 pDimRegionPool[1] = new Pool< ::gig::DimensionRegion*>(GLOBAL_MAX_VOICES);
113 pVoiceStealingQueue = new RTList<Event>(pEventPool);
114 pGlobalEvents = new RTList<Event>(pEventPool);
115 iMaxDiskStreams = GLOBAL_MAX_STREAMS;
116
117 for (RTList<Voice>::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
118 iterVoice->SetEngine(this);
119 }
120 pVoicePool->clear();
121
122 ResetInternal();
123 ResetScaleTuning();
124 ResetSuspendedRegions();
125 }
126
127 /**
128 * Destructor
129 */
130 Engine::~Engine() {
131 MidiInputPort::RemoveSysexListener(this);
132 if (pDiskThread) {
133 dmsg(1,("Stopping disk thread..."));
134 pDiskThread->StopThread();
135 delete pDiskThread;
136 dmsg(1,("OK\n"));
137 }
138 if (pEventQueue) delete pEventQueue;
139 if (pEventPool) delete pEventPool;
140 if (pVoicePool) {
141 pVoicePool->clear();
142 delete pVoicePool;
143 }
144 if (pEventGenerator) delete pEventGenerator;
145 if (pVoiceStealingQueue) delete pVoiceStealingQueue;
146 if (pSysexBuffer) delete pSysexBuffer;
147 if (pGlobalEvents) delete pGlobalEvents;
148 if (pDimRegionPool[0]) delete pDimRegionPool[0];
149 if (pDimRegionPool[1]) delete pDimRegionPool[1];
150 ResetSuspendedRegions();
151 Unregister();
152 }
153
154 void Engine::Enable() {
155 dmsg(3,("gig::Engine: enabling\n"));
156 EngineDisabled.PushAndUnlock(false, 2); // set condition object 'EngineDisabled' to false (wait max. 2s)
157 dmsg(3,("gig::Engine: enabled (val=%d)\n", EngineDisabled.GetUnsafe()));
158 }
159
160 /**
161 * Temporarily stop the engine to not do anything. The engine will just be
162 * frozen during that time, that means after enabling it again it will
163 * continue where it was, with all its voices and playback state it had at
164 * the point of disabling. Notice that the engine's (audio) thread will
165 * continue to run, it just remains in an inactive loop during that time.
166 *
167 * If you need to be sure that all voices and disk streams are killed as
168 * well, use @c SuspendAll() instead.
169 *
170 * @see Enable(), SuspendAll()
171 */
172 void Engine::Disable() {
173 dmsg(3,("gig::Engine: disabling\n"));
174 bool* pWasDisabled = EngineDisabled.PushAndUnlock(true, 2); // wait max. 2s
175 if (!pWasDisabled) dmsg(3,("gig::Engine warning: Timeout waiting to disable engine.\n"));
176 }
177
178 void Engine::DisableAndLock() {
179 dmsg(3,("gig::Engine: disabling\n"));
180 bool* pWasDisabled = EngineDisabled.Push(true, 2); // wait max. 2s
181 if (!pWasDisabled) dmsg(3,("gig::Engine warning: Timeout waiting to disable engine.\n"));
182 }
183
184 /**
185 * Similar to @c Disable() but this method additionally kills all voices
186 * and disk streams and blocks until all voices and disk streams are actually
187 * killed / deleted.
188 *
189 * @e Note: only the original calling thread is able to re-enable the
190 * engine afterwards by calling @c ResumeAll() later on!
191 */
192 void Engine::SuspendAll() {
193 dmsg(2,("gig::Engine: Suspending all ...\n"));
194 // stop the engine, so we can safely modify the engine's
195 // data structures from this foreign thread
196 DisableAndLock();
197 // we could also use the respective class member variable here,
198 // but this is probably safer and cleaner
199 int iPendingStreamDeletions = 0;
200 // kill all voices on all engine channels the *die hard* way
201 for (int iChannel = 0; iChannel < engineChannels.size(); iChannel++) {
202 EngineChannel* pEngineChannel = engineChannels[iChannel];
203 RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
204 RTList<uint>::Iterator end = pEngineChannel->pActiveKeys->end();
205 for (; iuiKey != end; ++iuiKey) { // iterate through all active keys
206 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
207 RTList<Voice>::Iterator itVoice = pKey->pActiveVoices->first();
208 RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();
209 for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
210 // request a notification from disk thread side for stream deletion
211 const Stream::Handle hStream = itVoice->KillImmediately(true);
212 if (hStream != Stream::INVALID_HANDLE) { // voice actually used a stream
213 iPendingStreamDeletions++;
214 }
215 }
216 }
217 }
218 // wait until all streams were actually deleted by the disk thread
219 while (iPendingStreamDeletions) {
220 while (
221 iPendingStreamDeletions &&
222 pDiskThread->AskForDeletedStream() != Stream::INVALID_HANDLE
223 ) iPendingStreamDeletions--;
224 if (!iPendingStreamDeletions) break;
225 usleep(10000); // sleep for 10ms
226 }
227 dmsg(2,("gig::Engine: Everything suspended.\n"));
228 }
229
230 /**
231 * At the moment same as calling @c Enable() directly, but this might
232 * change in future, so better call this method as counterpart to
233 * @c SuspendAll() instead of @c Enable() !
234 */
235 void Engine::ResumeAll() {
236 Enable();
237 }
238
239 /**
240 * Order the engine to stop rendering audio for the given region.
241 * Additionally this method will block until all voices and their disk
242 * streams associated with that region are actually killed / deleted, so
243 * one can i.e. safely modify the region with an instrument editor after
244 * returning from this method.
245 *
246 * @param pRegion - region the engine shall stop using
247 */
248 void Engine::Suspend(::gig::Region* pRegion) {
249 dmsg(2,("gig::Engine: Suspending Region %x ...\n",pRegion));
250 SuspendedRegionsMutex.Lock();
251 SuspensionChangeOngoing.Set(true);
252 pPendingRegionSuspension = pRegion;
253 SuspensionChangeOngoing.WaitAndUnlockIf(true);
254 SuspendedRegionsMutex.Unlock();
255 dmsg(2,("gig::Engine: Region %x suspended.",pRegion));
256 }
257
258 /**
259 * Orders the engine to resume playing back the given region, previously
260 * suspended with @c Suspend() .
261 *
262 * @param pRegion - region the engine shall be allowed to use again
263 */
264 void Engine::Resume(::gig::Region* pRegion) {
265 dmsg(2,("gig::Engine: Resuming Region %x ...\n",pRegion));
266 SuspendedRegionsMutex.Lock();
267 SuspensionChangeOngoing.Set(true);
268 pPendingRegionResumption = pRegion;
269 SuspensionChangeOngoing.WaitAndUnlockIf(true);
270 SuspendedRegionsMutex.Unlock();
271 dmsg(2,("gig::Engine: Region %x resumed.\n",pRegion));
272 }
273
274 /**
275 * Reset all voices and disk thread and clear input event queue and all
276 * control and status variables.
277 */
278 void Engine::Reset() {
279 DisableAndLock();
280 ResetInternal();
281 ResetScaleTuning();
282 Enable();
283 }
284
285 /**
286 * Reset all voices and disk thread and clear input event queue and all
287 * control and status variables. This method is protected by a mutex.
288 */
289 void Engine::ResetInternal() {
290 ResetInternalMutex.Lock();
291
292 // make sure that the engine does not get any sysex messages
293 // while it's reseting
294 bool sysexDisabled = MidiInputPort::RemoveSysexListener(this);
295 SetVoiceCount(0);
296 ActiveVoiceCountMax = 0;
297
298 // reset voice stealing parameters
299 pVoiceStealingQueue->clear();
300 itLastStolenVoice = RTList<Voice>::Iterator();
301 itLastStolenVoiceGlobally = RTList<Voice>::Iterator();
302 iuiLastStolenKey = RTList<uint>::Iterator();
303 iuiLastStolenKeyGlobally = RTList<uint>::Iterator();
304 pLastStolenChannel = NULL;
305
306 // reset all voices
307 for (RTList<Voice>::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
308 iterVoice->Reset();
309 }
310 pVoicePool->clear();
311
312 // reset disk thread
313 if (pDiskThread) pDiskThread->Reset();
314
315 // delete all input events
316 pEventQueue->init();
317 pSysexBuffer->init();
318 if (sysexDisabled) MidiInputPort::AddSysexListener(this);
319 ResetInternalMutex.Unlock();
320 }
321
322 /**
323 * Reset to normal, chromatic scale (means equal tempered).
324 */
325 void Engine::ResetScaleTuning() {
326 memset(&ScaleTuning[0], 0x00, 12);
327 }
328
329 void Engine::ResetSuspendedRegions() {
330 SuspendedRegions.clear();
331 iPendingStreamDeletions = 0;
332 pPendingRegionSuspension = pPendingRegionResumption = NULL;
333 SuspensionChangeOngoing.Set(false);
334 }
335
336 /**
337 * Connect this engine instance with the given audio output device.
338 * This method will be called when an Engine instance is created.
339 * All of the engine's data structures which are dependant to the used
340 * audio output device / driver will be (re)allocated and / or
341 * adjusted appropriately.
342 *
343 * @param pAudioOut - audio output device to connect to
344 */
345 void Engine::Connect(AudioOutputDevice* pAudioOut) {
346 // caution: don't ignore if connecting to the same device here,
347 // because otherwise SetMaxDiskStreams() implementation won't work anymore!
348
349 pAudioOutputDevice = pAudioOut;
350
351 ResetInternal();
352
353 // inform audio driver for the need of two channels
354 try {
355 pAudioOutputDevice->AcquireChannels(2); // gig engine only stereo
356 }
357 catch (AudioOutputException e) {
358 String msg = "Audio output device unable to provide 2 audio channels, cause: " + e.Message();
359 throw Exception(msg);
360 }
361
362 this->MaxSamplesPerCycle = pAudioOutputDevice->MaxSamplesPerCycle();
363 this->SampleRate = pAudioOutputDevice->SampleRate();
364
365 MinFadeOutSamples = int(double(SampleRate) * CONFIG_EG_MIN_RELEASE_TIME) - 1;
366 if (MaxSamplesPerCycle < MinFadeOutSamples) {
367 std::cerr << "gig::Engine: WARNING, CONFIG_EG_MIN_RELEASE_TIME "
368 << "too big for current audio fragment size & sampling rate! "
369 << "May lead to click sounds if voice stealing chimes in!\n" << std::flush;
370 // force volume ramp downs at the beginning of each fragment
371 MinFadeOutSamples = MaxSamplesPerCycle;
372 // lower minimum release time
373 const float minReleaseTime = (float) MaxSamplesPerCycle / (float) SampleRate;
374 for (RTList<Voice>::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
375 iterVoice->EG1.CalculateFadeOutCoeff(minReleaseTime, SampleRate);
376 }
377 pVoicePool->clear();
378 }
379
380 // (re)create disk thread
381 if (this->pDiskThread) {
382 dmsg(1,("Stopping disk thread..."));
383 this->pDiskThread->StopThread();
384 delete this->pDiskThread;
385 dmsg(1,("OK\n"));
386 }
387 this->pDiskThread =
388 new DiskThread(
389 iMaxDiskStreams,
390 ((pAudioOut->MaxSamplesPerCycle() << CONFIG_MAX_PITCH) << 1) + 6, //FIXME: assuming stereo
391 &instruments
392 );
393
394 if (!pDiskThread) {
395 dmsg(0,("gig::Engine new diskthread = NULL\n"));
396 exit(EXIT_FAILURE);
397 }
398
399 for (RTList<Voice>::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
400 iterVoice->pDiskThread = this->pDiskThread;
401 dmsg(3,("d"));
402 }
403 pVoicePool->clear();
404
405 // (re)create event generator
406 if (pEventGenerator) delete pEventGenerator;
407 pEventGenerator = new EventGenerator(pAudioOut->SampleRate());
408
409 dmsg(1,("Starting disk thread..."));
410 pDiskThread->StartThread();
411 dmsg(1,("OK\n"));
412
413 for (RTList<Voice>::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
414 if (!iterVoice->pDiskThread) {
415 dmsg(0,("Engine -> voice::trigger: !pDiskThread\n"));
416 exit(EXIT_FAILURE);
417 }
418 }
419 pVoicePool->clear();
420 }
421
422 /**
423 * Called by the engine's (audio) thread once per cycle to process requests
424 * from the outer world to suspend or resume a given @c gig::Region .
425 */
426 void Engine::ProcessSuspensionsChanges() {
427 // process request for suspending one region
428 if (pPendingRegionSuspension) {
429 // kill all voices on all engine channels that use this region
430 for (int iChannel = 0; iChannel < engineChannels.size(); iChannel++) {
431 EngineChannel* pEngineChannel = engineChannels[iChannel];
432 RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
433 RTList<uint>::Iterator end = pEngineChannel->pActiveKeys->end();
434 for (; iuiKey != end; ++iuiKey) { // iterate through all active keys
435 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
436 RTList<Voice>::Iterator itVoice = pKey->pActiveVoices->first();
437 // if current key is not associated with this region, skip this key
438 if (itVoice->pDimRgn->GetParent() != pPendingRegionSuspension) continue;
439 RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();
440 for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
441 // request a notification from disk thread side for stream deletion
442 const Stream::Handle hStream = itVoice->KillImmediately(true);
443 if (hStream != Stream::INVALID_HANDLE) { // voice actually used a stream
444 iPendingStreamDeletions++;
445 }
446 }
447 }
448 }
449 // make sure the region is not yet on the list
450 bool bAlreadySuspended = false;
451 RTList< ::gig::Region*>::Iterator iter = SuspendedRegions.first();
452 RTList< ::gig::Region*>::Iterator end = SuspendedRegions.end();
453 for (; iter != end; ++iter) { // iterate through all suspended regions
454 if (*iter == pPendingRegionSuspension) { // found
455 bAlreadySuspended = true;
456 dmsg(1,("gig::Engine: attempt to suspend an already suspended region !!!\n"));
457 break;
458 }
459 }
460 if (!bAlreadySuspended) {
461 // put the region on the list of suspended regions
462 RTList< ::gig::Region*>::Iterator iter = SuspendedRegions.allocAppend();
463 if (iter) {
464 *iter = pPendingRegionSuspension;
465 } else std::cerr << "gig::Engine: Could not suspend Region, list is full. This is a bug!!!\n" << std::flush;
466 }
467 // free request slot for next caller (and to make sure that
468 // we're not going to process the same request in the next cycle)
469 pPendingRegionSuspension = NULL;
470 // if no disk stream deletions are pending, awaken other side, as
471 // we're done in this case
472 if (!iPendingStreamDeletions) SuspensionChangeOngoing.Set(false);
473 }
474
475 // process request for resuming one region
476 if (pPendingRegionResumption) {
477 // remove region from the list of suspended regions
478 RTList< ::gig::Region*>::Iterator iter = SuspendedRegions.first();
479 RTList< ::gig::Region*>::Iterator end = SuspendedRegions.end();
480 for (; iter != end; ++iter) { // iterate through all suspended regions
481 if (*iter == pPendingRegionResumption) { // found
482 SuspendedRegions.free(iter);
483 break; // done
484 }
485 }
486 // free request slot for next caller
487 pPendingRegionResumption = NULL;
488 // awake other side as we're done
489 SuspensionChangeOngoing.Set(false);
490 }
491 }
492
493 /**
494 * Called by the engine's (audio) thread once per cycle to check if
495 * streams of voices that were killed due to suspension request have
496 * finally really been deleted by the disk thread.
497 */
498 void Engine::ProcessPendingStreamDeletions() {
499 if (!iPendingStreamDeletions) return;
500 //TODO: or shall we better store a list with stream handles instead of a scalar amount of streams to be deleted? might be safer
501 while (
502 iPendingStreamDeletions &&
503 pDiskThread->AskForDeletedStream() != Stream::INVALID_HANDLE
504 ) iPendingStreamDeletions--;
505 // just for safety ...
506 while (pDiskThread->AskForDeletedStream() != Stream::INVALID_HANDLE);
507 // now that all disk streams are deleted, awake other side as
508 // we're finally done with suspending the requested region
509 if (!iPendingStreamDeletions) SuspensionChangeOngoing.Set(false);
510 }
511
512 /**
513 * Returns @c true if the given region is currently set to be suspended
514 * from being used, @c false otherwise.
515 */
516 bool Engine::RegionSuspended(::gig::Region* pRegion) {
517 if (SuspendedRegions.isEmpty()) return false;
518 //TODO: or shall we use a sorted container instead of the RTList? might be faster ... or trivial ;-)
519 RTList< ::gig::Region*>::Iterator iter = SuspendedRegions.first();
520 RTList< ::gig::Region*>::Iterator end = SuspendedRegions.end();
521 for (; iter != end; ++iter) // iterate through all suspended regions
522 if (*iter == pRegion) return true;
523 return false;
524 }
525
526 /**
527 * Clear all engine global event lists.
528 */
529 void Engine::ClearEventLists() {
530 pGlobalEvents->clear();
531 }
532
533 /**
534 * Copy all events from the engine's global input queue buffer to the
535 * engine's internal event list. This will be done at the beginning of
536 * each audio cycle (that is each RenderAudio() call) to distinguish
537 * all global events which have to be processed in the current audio
538 * cycle. These events are usually just SysEx messages. Every
539 * EngineChannel has it's own input event queue buffer and event list
540 * to handle common events like NoteOn, NoteOff and ControlChange
541 * events.
542 *
543 * @param Samples - number of sample points to be processed in the
544 * current audio cycle
545 */
546 void Engine::ImportEvents(uint Samples) {
547 RingBuffer<Event,false>::NonVolatileReader eventQueueReader = pEventQueue->get_non_volatile_reader();
548 Event* pEvent;
549 while (true) {
550 // get next event from input event queue
551 if (!(pEvent = eventQueueReader.pop())) break;
552 // if younger event reached, ignore that and all subsequent ones for now
553 if (pEvent->FragmentPos() >= Samples) {
554 eventQueueReader--;
555 dmsg(2,("Younger Event, pos=%d ,Samples=%d!\n",pEvent->FragmentPos(),Samples));
556 pEvent->ResetFragmentPos();
557 break;
558 }
559 // copy event to internal event list
560 if (pGlobalEvents->poolIsEmpty()) {
561 dmsg(1,("Event pool emtpy!\n"));
562 break;
563 }
564 *pGlobalEvents->allocAppend() = *pEvent;
565 }
566 eventQueueReader.free(); // free all copied events from input queue
567 }
568
569 /**
570 * Let this engine proceed to render the given amount of sample points.
571 * The engine will iterate through all engine channels and render audio
572 * for each engine channel independently. The calculated audio data of
573 * all voices of each engine channel will be placed into the audio sum
574 * buffers of the respective audio output device, connected to the
575 * respective engine channel.
576 *
577 * @param Samples - number of sample points to be rendered
578 * @returns 0 on success
579 */
580 int Engine::RenderAudio(uint Samples) {
581 dmsg(8,("RenderAudio(Samples=%d)\n", Samples));
582
583 // return if engine disabled
584 if (EngineDisabled.Pop()) {
585 dmsg(5,("gig::Engine: engine disabled (val=%d)\n",EngineDisabled.GetUnsafe()));
586 EngineDisabled.RttDone();
587 return 0;
588 }
589
590 // process requests for suspending / resuming regions (i.e. to avoid
591 // crashes while these regions are modified by an instrument editor)
592 ProcessSuspensionsChanges();
593
594 // update time of start and end of this audio fragment (as events' time stamps relate to this)
595 pEventGenerator->UpdateFragmentTime(Samples);
596
597 // We only allow the given maximum number of voices to be spawned
598 // in each audio fragment. All subsequent request for spawning new
599 // voices in the same audio fragment will be ignored.
600 VoiceSpawnsLeft = MaxVoices();
601
602 // get all events from the engine's global input event queue which belong to the current fragment
603 // (these are usually just SysEx messages)
604 ImportEvents(Samples);
605
606 // process engine global events (these are currently only MIDI System Exclusive messages)
607 {
608 RTList<Event>::Iterator itEvent = pGlobalEvents->first();
609 RTList<Event>::Iterator end = pGlobalEvents->end();
610 for (; itEvent != end; ++itEvent) {
611 switch (itEvent->Type) {
612 case Event::type_sysex:
613 dmsg(5,("Engine: Sysex received\n"));
614 ProcessSysex(itEvent);
615 break;
616 }
617 }
618 }
619
620 // reset internal voice counter (just for statistic of active voices)
621 ActiveVoiceCountTemp = 0;
622
623 // handle instrument change commands
624 bool instrumentChanged = false;
625 for (int i = 0; i < engineChannels.size(); i++) {
626 EngineChannel* pEngineChannel = engineChannels[i];
627
628 // as we're going to (carefully) write some status to the
629 // synchronized struct, we cast away the const
630 EngineChannel::instrument_change_command_t& cmd =
631 const_cast<EngineChannel::instrument_change_command_t&>(pEngineChannel->InstrumentChangeCommandReader.Lock());
632
633 pEngineChannel->pDimRegionsInUse = cmd.pDimRegionsInUse;
634 pEngineChannel->pDimRegionsInUse->clear();
635
636 if (cmd.bChangeInstrument) {
637 // change instrument
638 dmsg(5,("Engine: instrument change command received\n"));
639 cmd.bChangeInstrument = false;
640 pEngineChannel->pInstrument = cmd.pInstrument;
641 instrumentChanged = true;
642
643 // Iterate through all active voices and mark them as
644 // "orphans", which means that the dimension regions
645 // and samples they use should be released to the
646 // instrument resource manager when the voices die.
647 int i = 0;
648 RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
649 RTList<uint>::Iterator end = pEngineChannel->pActiveKeys->end();
650 while (iuiKey != end) { // iterate through all active keys
651 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
652 ++iuiKey;
653
654 RTList<Voice>::Iterator itVoice = pKey->pActiveVoices->first();
655 RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();
656 for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
657 itVoice->Orphan = true;
658 }
659 }
660 }
661 }
662 if (instrumentChanged) {
663 //TODO: this is a lazy solution ATM and not safe in case somebody is currently editing the instrument we're currently switching to (we should store all suspended regions on instrument manager side and when switching to another instrument copy that list to the engine's local list of suspensions
664 ResetSuspendedRegions();
665 }
666
667 // handle events on all engine channels
668 for (int i = 0; i < engineChannels.size(); i++) {
669 ProcessEvents(engineChannels[i], Samples);
670 }
671
672 // render all 'normal', active voices on all engine channels
673 for (int i = 0; i < engineChannels.size(); i++) {
674 RenderActiveVoices(engineChannels[i], Samples);
675 }
676
677 // now that all ordinary voices on ALL engine channels are rendered, render new stolen voices
678 RenderStolenVoices(Samples);
679
680 // handle audio routing for engine channels with FX sends
681 for (int i = 0; i < engineChannels.size(); i++) {
682 if (engineChannels[i]->fxSends.empty()) continue; // ignore if no FX sends
683 RouteAudio(engineChannels[i], Samples);
684 }
685
686 // handle cleanup on all engine channels for the next audio fragment
687 for (int i = 0; i < engineChannels.size(); i++) {
688 PostProcess(engineChannels[i]);
689 }
690
691
692 // empty the engine's event list for the next audio fragment
693 ClearEventLists();
694
695 // reset voice stealing for the next audio fragment
696 pVoiceStealingQueue->clear();
697
698 // just some statistics about this engine instance
699 SetVoiceCount(ActiveVoiceCountTemp);
700 if (VoiceCount() > ActiveVoiceCountMax) ActiveVoiceCountMax = VoiceCount();
701
702 // in case regions were previously suspended and we killed voices
703 // with disk streams due to that, check if those streams have finally
704 // been deleted by the disk thread
705 if (iPendingStreamDeletions) ProcessPendingStreamDeletions();
706
707 for (int i = 0; i < engineChannels.size(); i++) {
708 engineChannels[i]->InstrumentChangeCommandReader.Unlock();
709 }
710 FrameTime += Samples;
711
712 EngineDisabled.RttDone();
713 return 0;
714 }
715
716 /**
717 * Dispatch and handle all events in this audio fragment for the given
718 * engine channel.
719 *
720 * @param pEngineChannel - engine channel on which events should be
721 * processed
722 * @param Samples - amount of sample points to be processed in
723 * this audio fragment cycle
724 */
725 void Engine::ProcessEvents(EngineChannel* pEngineChannel, uint Samples) {
726 // get all events from the engine channels's input event queue which belong to the current fragment
727 // (these are the common events like NoteOn, NoteOff, ControlChange, etc.)
728 pEngineChannel->ImportEvents(Samples);
729
730 // process events
731 {
732 RTList<Event>::Iterator itEvent = pEngineChannel->pEvents->first();
733 RTList<Event>::Iterator end = pEngineChannel->pEvents->end();
734 for (; itEvent != end; ++itEvent) {
735 switch (itEvent->Type) {
736 case Event::type_note_on:
737 dmsg(5,("Engine: Note on received\n"));
738 ProcessNoteOn((EngineChannel*)itEvent->pEngineChannel, itEvent);
739 break;
740 case Event::type_note_off:
741 dmsg(5,("Engine: Note off received\n"));
742 ProcessNoteOff((EngineChannel*)itEvent->pEngineChannel, itEvent);
743 break;
744 case Event::type_control_change:
745 dmsg(5,("Engine: MIDI CC received\n"));
746 ProcessControlChange((EngineChannel*)itEvent->pEngineChannel, itEvent);
747 break;
748 case Event::type_pitchbend:
749 dmsg(5,("Engine: Pitchbend received\n"));
750 ProcessPitchbend((EngineChannel*)itEvent->pEngineChannel, itEvent);
751 break;
752 }
753 }
754 }
755
756 // reset voice stealing for the next engine channel (or next audio fragment)
757 itLastStolenVoice = RTList<Voice>::Iterator();
758 itLastStolenVoiceGlobally = RTList<Voice>::Iterator();
759 iuiLastStolenKey = RTList<uint>::Iterator();
760 iuiLastStolenKeyGlobally = RTList<uint>::Iterator();
761 pLastStolenChannel = NULL;
762 }
763
764 /**
765 * Render all 'normal' voices (that is voices which were not stolen in
766 * this fragment) on the given engine channel.
767 *
768 * @param pEngineChannel - engine channel on which audio should be
769 * rendered
770 * @param Samples - amount of sample points to be rendered in
771 * this audio fragment cycle
772 */
773 void Engine::RenderActiveVoices(EngineChannel* pEngineChannel, uint Samples) {
774 #if !CONFIG_PROCESS_MUTED_CHANNELS
775 if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
776 #endif
777
778 uint voiceCount = 0;
779 uint streamCount = 0;
780 RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
781 RTList<uint>::Iterator end = pEngineChannel->pActiveKeys->end();
782 while (iuiKey != end) { // iterate through all active keys
783 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
784 ++iuiKey;
785
786 RTList<Voice>::Iterator itVoice = pKey->pActiveVoices->first();
787 RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();
788 for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
789 // now render current voice
790 itVoice->Render(Samples);
791 if (itVoice->IsActive()) { // still active
792 if (!itVoice->Orphan) {
793 *(pEngineChannel->pDimRegionsInUse->allocAppend()) = itVoice->pDimRgn;
794 }
795 ActiveVoiceCountTemp++;
796 voiceCount++;
797
798 if (itVoice->PlaybackState == Voice::playback_state_disk) {
799 if ((itVoice->DiskStreamRef).State != Stream::state_unused) streamCount++;
800 }
801 } else { // voice reached end, is now inactive
802 FreeVoice(pEngineChannel, itVoice); // remove voice from the list of active voices
803 }
804 }
805 }
806
807 pEngineChannel->SetVoiceCount(voiceCount);
808 pEngineChannel->SetDiskStreamCount(streamCount);
809 }
810
811 /**
812 * Render all stolen voices (only voices which were stolen in this
813 * fragment) on the given engine channel. Stolen voices are rendered
814 * after all normal voices have been rendered; this is needed to render
815 * audio of those voices which were selected for voice stealing until
816 * the point were the stealing (that is the take over of the voice)
817 * actually happened.
818 *
819 * @param pEngineChannel - engine channel on which audio should be
820 * rendered
821 * @param Samples - amount of sample points to be rendered in
822 * this audio fragment cycle
823 */
824 void Engine::RenderStolenVoices(uint Samples) {
825 RTList<Event>::Iterator itVoiceStealEvent = pVoiceStealingQueue->first();
826 RTList<Event>::Iterator end = pVoiceStealingQueue->end();
827 for (; itVoiceStealEvent != end; ++itVoiceStealEvent) {
828 EngineChannel* pEngineChannel = (EngineChannel*) itVoiceStealEvent->pEngineChannel;
829 if (!pEngineChannel->pInstrument) continue; // ignore if no instrument loaded
830 Pool<Voice>::Iterator itNewVoice =
831 LaunchVoice(pEngineChannel, itVoiceStealEvent, itVoiceStealEvent->Param.Note.Layer, itVoiceStealEvent->Param.Note.ReleaseTrigger, false, false);
832 if (itNewVoice) {
833 itNewVoice->Render(Samples);
834 if (itNewVoice->IsActive()) { // still active
835 *(pEngineChannel->pDimRegionsInUse->allocAppend()) = itNewVoice->pDimRgn;
836 ActiveVoiceCountTemp++;
837 pEngineChannel->SetVoiceCount(pEngineChannel->GetVoiceCount() + 1);
838
839 if (itNewVoice->PlaybackState == Voice::playback_state_disk) {
840 if (itNewVoice->DiskStreamRef.State != Stream::state_unused) {
841 pEngineChannel->SetDiskStreamCount(pEngineChannel->GetDiskStreamCount() + 1);
842 }
843 }
844 } else { // voice reached end, is now inactive
845 FreeVoice(pEngineChannel, itNewVoice); // remove voice from the list of active voices
846 }
847 }
848 else dmsg(1,("gig::Engine: ERROR, voice stealing didn't work out!\n"));
849
850 // we need to clear the key's event list explicitly here in case key was never active
851 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[itVoiceStealEvent->Param.Note.Key];
852 pKey->VoiceTheftsQueued--;
853 if (!pKey->Active && !pKey->VoiceTheftsQueued) pKey->pEvents->clear();
854 }
855 }
856
857 /**
858 * Will be called in case the respective engine channel sports FX send
859 * channels. In this particular case, engine channel local buffers are
860 * used to render and mix all voices to. This method is responsible for
861 * copying the audio data from those local buffers to the master audio
862 * output channels as well as to the FX send audio output channels with
863 * their respective FX send levels.
864 *
865 * @param pEngineChannel - engine channel from which audio should be
866 * routed
867 * @param Samples - amount of sample points to be routed in
868 * this audio fragment cycle
869 */
870 void Engine::RouteAudio(EngineChannel* pEngineChannel, uint Samples) {
871 // route dry signal
872 {
873 AudioChannel* pDstL = pAudioOutputDevice->Channel(pEngineChannel->AudioDeviceChannelLeft);
874 AudioChannel* pDstR = pAudioOutputDevice->Channel(pEngineChannel->AudioDeviceChannelRight);
875 pEngineChannel->pChannelLeft->MixTo(pDstL, Samples);
876 pEngineChannel->pChannelRight->MixTo(pDstR, Samples);
877 }
878 // route FX send signal
879 {
880 for (int iFxSend = 0; iFxSend < pEngineChannel->GetFxSendCount(); iFxSend++) {
881 FxSend* pFxSend = pEngineChannel->GetFxSend(iFxSend);
882 for (int iChan = 0; iChan < 2; ++iChan) {
883 AudioChannel* pSource =
884 (iChan)
885 ? pEngineChannel->pChannelRight
886 : pEngineChannel->pChannelLeft;
887 const int iDstChan = pFxSend->DestinationChannel(iChan);
888 if (iDstChan < 0) {
889 dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination channel (%d->%d)", ((iChan) ? "R" : "L"), iChan, iDstChan));
890 goto channel_cleanup;
891 }
892 AudioChannel* pDstChan = NULL;
893 if (pFxSend->DestinationMasterEffectChain() >= 0) { // fx send routed to an internal master effect
894 EffectChain* pEffectChain =
895 pAudioOutputDevice->MasterEffectChain(
896 pFxSend->DestinationMasterEffectChain()
897 );
898 if (!pEffectChain) {
899 dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination effect chain %d", ((iChan) ? "R" : "L"), pFxSend->DestinationMasterEffectChain()));
900 goto channel_cleanup;
901 }
902 Effect* pEffect =
903 pEffectChain->GetEffect(
904 pFxSend->DestinationMasterEffect()
905 );
906 if (!pEffect) {
907 dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination effect %d of effect chain %d", ((iChan) ? "R" : "L"), pFxSend->DestinationMasterEffect(), pFxSend->DestinationMasterEffectChain()));
908 goto channel_cleanup;
909 }
910 pDstChan = pEffect->InputChannel(iDstChan);
911 } else { // FX send routed directly to an audio output channel
912 pDstChan = pAudioOutputDevice->Channel(iDstChan);
913 }
914 if (!pDstChan) {
915 dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination channel (%d->%d)", ((iChan) ? "R" : "L"), iChan, iDstChan));
916 goto channel_cleanup;
917 }
918 pSource->MixTo(pDstChan, Samples, pFxSend->Level());
919 }
920 }
921 }
922 channel_cleanup:
923 // reset buffers with silence (zero out) for the next audio cycle
924 pEngineChannel->pChannelLeft->Clear();
925 pEngineChannel->pChannelRight->Clear();
926 }
927
928 /**
929 * Free all keys which have turned inactive in this audio fragment, from
930 * the list of active keys and clear all event lists on that engine
931 * channel.
932 *
933 * @param pEngineChannel - engine channel to cleanup
934 */
935 void Engine::PostProcess(EngineChannel* pEngineChannel) {
936 // free all keys which have no active voices left
937 {
938 RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
939 RTList<uint>::Iterator end = pEngineChannel->pActiveKeys->end();
940 while (iuiKey != end) { // iterate through all active keys
941 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
942 ++iuiKey;
943 if (pKey->pActiveVoices->isEmpty()) FreeKey(pEngineChannel, pKey);
944 #if CONFIG_DEVMODE
945 else { // just a sanity check for debugging
946 RTList<Voice>::Iterator itVoice = pKey->pActiveVoices->first();
947 RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();
948 for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
949 if (itVoice->itKillEvent) {
950 dmsg(1,("gig::Engine: ERROR, killed voice survived !!!\n"));
951 }
952 }
953 }
954 #endif // CONFIG_DEVMODE
955 }
956 }
957
958 // empty the engine channel's own event lists
959 pEngineChannel->ClearEventLists();
960 }
961
962 /**
963 * Will be called by the MIDI input device whenever a MIDI system
964 * exclusive message has arrived.
965 *
966 * @param pData - pointer to sysex data
967 * @param Size - lenght of sysex data (in bytes)
968 * @param pSender - the MIDI input port on which the SysEx message was
969 * received
970 */
971 void Engine::SendSysex(void* pData, uint Size, MidiInputPort* pSender) {
972 Event event = pEventGenerator->CreateEvent();
973 event.Type = Event::type_sysex;
974 event.Param.Sysex.Size = Size;
975 event.pEngineChannel = NULL; // as Engine global event
976 event.pMidiInputPort = pSender;
977 if (pEventQueue->write_space() > 0) {
978 if (pSysexBuffer->write_space() >= Size) {
979 // copy sysex data to input buffer
980 uint toWrite = Size;
981 uint8_t* pPos = (uint8_t*) pData;
982 while (toWrite) {
983 const uint writeNow = RTMath::Min(toWrite, pSysexBuffer->write_space_to_end());
984 pSysexBuffer->write(pPos, writeNow);
985 toWrite -= writeNow;
986 pPos += writeNow;
987
988 }
989 // finally place sysex event into input event queue
990 pEventQueue->push(&event);
991 }
992 else dmsg(1,("Engine: Sysex message too large (%d byte) for input buffer (%d byte)!",Size,CONFIG_SYSEX_BUFFER_SIZE));
993 }
994 else dmsg(1,("Engine: Input event queue full!"));
995 }
996
997 /**
998 * Assigns and triggers a new voice for the respective MIDI key.
999 *
1000 * @param pEngineChannel - engine channel on which this event occured on
1001 * @param itNoteOnEvent - key, velocity and time stamp of the event
1002 */
1003 void Engine::ProcessNoteOn(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent) {
1004 #if !CONFIG_PROCESS_MUTED_CHANNELS
1005 if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
1006 #endif
1007
1008 if (!pEngineChannel->pInstrument) return; // ignore if no instrument loaded
1009
1010 //HACK: we should better add the transpose value only to the most mandatory places (like for retrieving the region and calculating the tuning), because otherwise voices will unintendedly survive when changing transpose while playing
1011 itNoteOnEvent->Param.Note.Key += pEngineChannel->GlobalTranspose;
1012
1013 const int key = itNoteOnEvent->Param.Note.Key;
1014 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[key];
1015
1016 // move note on event to the key's own event list
1017 RTList<Event>::Iterator itNoteOnEventOnKeyList = itNoteOnEvent.moveToEndOf(pKey->pEvents);
1018
1019 // if Solo Mode then kill all already active voices
1020 if (pEngineChannel->SoloMode) {
1021 Pool<uint>::Iterator itYoungestKey = pEngineChannel->pActiveKeys->last();
1022 if (itYoungestKey) {
1023 const int iYoungestKey = *itYoungestKey;
1024 const midi_key_info_t* pOtherKey = &pEngineChannel->pMIDIKeyInfo[iYoungestKey];
1025 if (pOtherKey->Active) {
1026 // get final portamento position of currently active voice
1027 if (pEngineChannel->PortamentoMode) {
1028 RTList<Voice>::Iterator itVoice = pOtherKey->pActiveVoices->last();
1029 if (itVoice) itVoice->UpdatePortamentoPos(itNoteOnEventOnKeyList);
1030 }
1031 // kill all voices on the (other) key
1032 RTList<Voice>::Iterator itVoiceToBeKilled = pOtherKey->pActiveVoices->first();
1033 RTList<Voice>::Iterator end = pOtherKey->pActiveVoices->end();
1034 for (; itVoiceToBeKilled != end; ++itVoiceToBeKilled) {
1035 if (itVoiceToBeKilled->Type != Voice::type_release_trigger)
1036 itVoiceToBeKilled->Kill(itNoteOnEventOnKeyList);
1037 }
1038 }
1039 }
1040 // set this key as 'currently active solo key'
1041 pEngineChannel->SoloKey = key;
1042 }
1043
1044 // Change key dimension value if key is in keyswitching area
1045 {
1046 const ::gig::Instrument* pInstrument = pEngineChannel->pInstrument;
1047 if (key >= pInstrument->DimensionKeyRange.low && key <= pInstrument->DimensionKeyRange.high)
1048 pEngineChannel->CurrentKeyDimension = float(key - pInstrument->DimensionKeyRange.low) /
1049 (pInstrument->DimensionKeyRange.high - pInstrument->DimensionKeyRange.low + 1);
1050 }
1051
1052 pKey->KeyPressed = true; // the MIDI key was now pressed down
1053 pKey->Velocity = itNoteOnEventOnKeyList->Param.Note.Velocity;
1054 pKey->NoteOnTime = FrameTime + itNoteOnEventOnKeyList->FragmentPos(); // will be used to calculate note length
1055
1056 // cancel release process of voices on this key if needed
1057 if (pKey->Active && !pEngineChannel->SustainPedal) {
1058 RTList<Event>::Iterator itCancelReleaseEvent = pKey->pEvents->allocAppend();
1059 if (itCancelReleaseEvent) {
1060 *itCancelReleaseEvent = *itNoteOnEventOnKeyList; // copy event
1061 itCancelReleaseEvent->Type = Event::type_cancel_release; // transform event type
1062 }
1063 else dmsg(1,("Event pool emtpy!\n"));
1064 }
1065
1066 // allocate and trigger new voice(s) for the key
1067 {
1068 // first, get total amount of required voices (dependant on amount of layers)
1069 ::gig::Region* pRegion = pEngineChannel->pInstrument->GetRegion(itNoteOnEventOnKeyList->Param.Note.Key);
1070 if (pRegion && !RegionSuspended(pRegion)) {
1071 int voicesRequired = pRegion->Layers;
1072 // now launch the required amount of voices
1073 for (int i = 0; i < voicesRequired; i++)
1074 LaunchVoice(pEngineChannel, itNoteOnEventOnKeyList, i, false, true, true);
1075 }
1076 }
1077
1078 // if neither a voice was spawned or postponed then remove note on event from key again
1079 if (!pKey->Active && !pKey->VoiceTheftsQueued)
1080 pKey->pEvents->free(itNoteOnEventOnKeyList);
1081
1082 if (!pEngineChannel->SoloMode || pEngineChannel->PortamentoPos < 0.0f) pEngineChannel->PortamentoPos = (float) key;
1083 pKey->RoundRobinIndex++;
1084 }
1085
1086 /**
1087 * Releases the voices on the given key if sustain pedal is not pressed.
1088 * If sustain is pressed, the release of the note will be postponed until
1089 * sustain pedal will be released or voice turned inactive by itself (e.g.
1090 * due to completion of sample playback).
1091 *
1092 * @param pEngineChannel - engine channel on which this event occured on
1093 * @param itNoteOffEvent - key, velocity and time stamp of the event
1094 */
1095 void Engine::ProcessNoteOff(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOffEvent) {
1096 #if !CONFIG_PROCESS_MUTED_CHANNELS
1097 if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
1098 #endif
1099
1100 //HACK: we should better add the transpose value only to the most mandatory places (like for retrieving the region and calculating the tuning), because otherwise voices will unintendedly survive when changing transpose while playing
1101 itNoteOffEvent->Param.Note.Key += pEngineChannel->GlobalTranspose;
1102
1103 const int iKey = itNoteOffEvent->Param.Note.Key;
1104 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[iKey];
1105 pKey->KeyPressed = false; // the MIDI key was now released
1106
1107 // move event to the key's own event list
1108 RTList<Event>::Iterator itNoteOffEventOnKeyList = itNoteOffEvent.moveToEndOf(pKey->pEvents);
1109
1110 bool bShouldRelease = pKey->Active && ShouldReleaseVoice(pEngineChannel, itNoteOffEventOnKeyList->Param.Note.Key);
1111
1112 // in case Solo Mode is enabled, kill all voices on this key and respawn a voice on the highest pressed key (if any)
1113 if (pEngineChannel->SoloMode && pEngineChannel->pInstrument) { //TODO: this feels like too much code just for handling solo mode :P
1114 bool bOtherKeysPressed = false;
1115 if (iKey == pEngineChannel->SoloKey) {
1116 pEngineChannel->SoloKey = -1;
1117 // if there's still a key pressed down, respawn a voice (group) on the highest key
1118 for (int i = 127; i > 0; i--) {
1119 midi_key_info_t* pOtherKey = &pEngineChannel->pMIDIKeyInfo[i];
1120 if (pOtherKey->KeyPressed) {
1121 bOtherKeysPressed = true;
1122 // make the other key the new 'currently active solo key'
1123 pEngineChannel->SoloKey = i;
1124 // get final portamento position of currently active voice
1125 if (pEngineChannel->PortamentoMode) {
1126 RTList<Voice>::Iterator itVoice = pKey->pActiveVoices->first();
1127 if (itVoice) itVoice->UpdatePortamentoPos(itNoteOffEventOnKeyList);
1128 }
1129 // create a pseudo note on event
1130 RTList<Event>::Iterator itPseudoNoteOnEvent = pOtherKey->pEvents->allocAppend();
1131 if (itPseudoNoteOnEvent) {
1132 // copy event
1133 *itPseudoNoteOnEvent = *itNoteOffEventOnKeyList;
1134 // transform event to a note on event
1135 itPseudoNoteOnEvent->Type = Event::type_note_on;
1136 itPseudoNoteOnEvent->Param.Note.Key = i;
1137 itPseudoNoteOnEvent->Param.Note.Velocity = pOtherKey->Velocity;
1138 // allocate and trigger new voice(s) for the other key
1139 {
1140 // first, get total amount of required voices (dependant on amount of layers)
1141 ::gig::Region* pRegion = pEngineChannel->pInstrument->GetRegion(i);
1142 if (pRegion) {
1143 int voicesRequired = pRegion->Layers;
1144 // now launch the required amount of voices
1145 for (int iLayer = 0; iLayer < voicesRequired; iLayer++)
1146 LaunchVoice(pEngineChannel, itPseudoNoteOnEvent, iLayer, false, true, false);
1147 }
1148 }
1149 // if neither a voice was spawned or postponed then remove note on event from key again
1150 if (!pOtherKey->Active && !pOtherKey->VoiceTheftsQueued)
1151 pOtherKey->pEvents->free(itPseudoNoteOnEvent);
1152
1153 } else dmsg(1,("Could not respawn voice, no free event left\n"));
1154 break; // done
1155 }
1156 }
1157 }
1158 if (bOtherKeysPressed) {
1159 if (pKey->Active) { // kill all voices on this key
1160 bShouldRelease = false; // no need to release, as we kill it here
1161 RTList<Voice>::Iterator itVoiceToBeKilled = pKey->pActiveVoices->first();
1162 RTList<Voice>::Iterator end = pKey->pActiveVoices->end();
1163 for (; itVoiceToBeKilled != end; ++itVoiceToBeKilled) {
1164 if (itVoiceToBeKilled->Type != Voice::type_release_trigger)
1165 itVoiceToBeKilled->Kill(itNoteOffEventOnKeyList);
1166 }
1167 }
1168 } else pEngineChannel->PortamentoPos = -1.0f;
1169 }
1170
1171 // if no solo mode (the usual case) or if solo mode and no other key pressed, then release voices on this key if needed
1172 if (bShouldRelease) {
1173 itNoteOffEventOnKeyList->Type = Event::type_release; // transform event type
1174
1175 // spawn release triggered voice(s) if needed
1176 if (pKey->ReleaseTrigger && pEngineChannel->pInstrument) {
1177 // first, get total amount of required voices (dependant on amount of layers)
1178 ::gig::Region* pRegion = pEngineChannel->pInstrument->GetRegion(itNoteOffEventOnKeyList->Param.Note.Key);
1179 if (pRegion) {
1180 int voicesRequired = pRegion->Layers;
1181
1182 // MIDI note-on velocity is used instead of note-off velocity
1183 itNoteOffEventOnKeyList->Param.Note.Velocity = pKey->Velocity;
1184
1185 // now launch the required amount of voices
1186 for (int i = 0; i < voicesRequired; i++)
1187 LaunchVoice(pEngineChannel, itNoteOffEventOnKeyList, i, true, false, false); //FIXME: for the moment we don't perform voice stealing for release triggered samples
1188 }
1189 pKey->ReleaseTrigger = false;
1190 }
1191 }
1192
1193 // if neither a voice was spawned or postponed on this key then remove note off event from key again
1194 if (!pKey->Active && !pKey->VoiceTheftsQueued)
1195 pKey->pEvents->free(itNoteOffEventOnKeyList);
1196 }
1197
1198 /**
1199 * Moves pitchbend event from the general (input) event list to the engine
1200 * channel's event list. It will actually processed later by the
1201 * respective voice.
1202 *
1203 * @param pEngineChannel - engine channel on which this event occured on
1204 * @param itPitchbendEvent - absolute pitch value and time stamp of the event
1205 */
1206 void Engine::ProcessPitchbend(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itPitchbendEvent) {
1207 pEngineChannel->Pitch = itPitchbendEvent->Param.Pitch.Pitch; // store current pitch value
1208 }
1209
1210 /**
1211 * Allocates and triggers a new voice. This method will usually be
1212 * called by the ProcessNoteOn() method and by the voices itself
1213 * (e.g. to spawn further voices on the same key for layered sounds).
1214 *
1215 * @param pEngineChannel - engine channel on which this event occured on
1216 * @param itNoteOnEvent - key, velocity and time stamp of the event
1217 * @param iLayer - layer index for the new voice (optional - only
1218 * in case of layered sounds of course)
1219 * @param ReleaseTriggerVoice - if new voice is a release triggered voice
1220 * (optional, default = false)
1221 * @param VoiceStealing - if voice stealing should be performed
1222 * when there is no free voice
1223 * (optional, default = true)
1224 * @param HandleKeyGroupConflicts - if voices should be killed due to a
1225 * key group conflict
1226 * @returns pointer to new voice or NULL if there was no free voice or
1227 * if the voice wasn't triggered (for example when no region is
1228 * defined for the given key).
1229 */
1230 Pool<Voice>::Iterator Engine::LaunchVoice(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent, int iLayer, bool ReleaseTriggerVoice, bool VoiceStealing, bool HandleKeyGroupConflicts) {
1231 int MIDIKey = itNoteOnEvent->Param.Note.Key;
1232 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[MIDIKey];
1233 ::gig::Region* pRegion = pEngineChannel->pInstrument->GetRegion(MIDIKey);
1234
1235 // if nothing defined for this key
1236 if (!pRegion) return Pool<Voice>::Iterator(); // nothing to do
1237
1238 // only mark the first voice of a layered voice (group) to be in a
1239 // key group, so the layered voices won't kill each other
1240 int iKeyGroup = (iLayer == 0 && !ReleaseTriggerVoice) ? pRegion->KeyGroup : 0;
1241
1242 // handle key group (a.k.a. exclusive group) conflicts
1243 if (HandleKeyGroupConflicts) {
1244 if (iKeyGroup) { // if this voice / key belongs to a key group
1245 uint** ppKeyGroup = &pEngineChannel->ActiveKeyGroups[iKeyGroup];
1246 if (*ppKeyGroup) { // if there's already an active key in that key group
1247 midi_key_info_t* pOtherKey = &pEngineChannel->pMIDIKeyInfo[**ppKeyGroup];
1248 // kill all voices on the (other) key
1249 RTList<Voice>::Iterator itVoiceToBeKilled = pOtherKey->pActiveVoices->first();
1250 RTList<Voice>::Iterator end = pOtherKey->pActiveVoices->end();
1251 for (; itVoiceToBeKilled != end; ++itVoiceToBeKilled) {
1252 if (itVoiceToBeKilled->Type != Voice::type_release_trigger) {
1253 itVoiceToBeKilled->Kill(itNoteOnEvent);
1254 --VoiceSpawnsLeft; //FIXME: just a hack, we should better check in StealVoice() if the voice was killed due to key conflict
1255 }
1256 }
1257 }
1258 }
1259 }
1260
1261 Voice::type_t VoiceType = Voice::type_normal;
1262
1263 // get current dimension values to select the right dimension region
1264 //TODO: for stolen voices this dimension region selection block is processed twice, this should be changed
1265 //FIXME: controller values for selecting the dimension region here are currently not sample accurate
1266 uint DimValues[8] = { 0 };
1267 for (int i = pRegion->Dimensions - 1; i >= 0; i--) {
1268 switch (pRegion->pDimensionDefinitions[i].dimension) {
1269 case ::gig::dimension_samplechannel:
1270 DimValues[i] = 0; //TODO: we currently ignore this dimension
1271 break;
1272 case ::gig::dimension_layer:
1273 DimValues[i] = iLayer;
1274 break;
1275 case ::gig::dimension_velocity:
1276 DimValues[i] = itNoteOnEvent->Param.Note.Velocity;
1277 break;
1278 case ::gig::dimension_channelaftertouch:
1279 DimValues[i] = pEngineChannel->ControllerTable[128];
1280 break;
1281 case ::gig::dimension_releasetrigger:
1282 VoiceType = (ReleaseTriggerVoice) ? Voice::type_release_trigger : (!iLayer) ? Voice::type_release_trigger_required : Voice::type_normal;
1283 DimValues[i] = (uint) ReleaseTriggerVoice;
1284 break;
1285 case ::gig::dimension_keyboard:
1286 DimValues[i] = (uint) (pEngineChannel->CurrentKeyDimension * pRegion->pDimensionDefinitions[i].zones);
1287 break;
1288 case ::gig::dimension_roundrobin:
1289 DimValues[i] = (uint) pEngineChannel->pMIDIKeyInfo[MIDIKey].RoundRobinIndex; // incremented for each note on
1290 break;
1291 case ::gig::dimension_random:
1292 RandomSeed = RandomSeed * 1103515245 + 12345; // classic pseudo random number generator
1293 DimValues[i] = (uint) RandomSeed >> (32 - pRegion->pDimensionDefinitions[i].bits); // highest bits are most random
1294 break;
1295 case ::gig::dimension_modwheel:
1296 DimValues[i] = pEngineChannel->ControllerTable[1];
1297 break;
1298 case ::gig::dimension_breath:
1299 DimValues[i] = pEngineChannel->ControllerTable[2];
1300 break;
1301 case ::gig::dimension_foot:
1302 DimValues[i] = pEngineChannel->ControllerTable[4];
1303 break;
1304 case ::gig::dimension_portamentotime:
1305 DimValues[i] = pEngineChannel->ControllerTable[5];
1306 break;
1307 case ::gig::dimension_effect1:
1308 DimValues[i] = pEngineChannel->ControllerTable[12];
1309 break;
1310 case ::gig::dimension_effect2:
1311 DimValues[i] = pEngineChannel->ControllerTable[13];
1312 break;
1313 case ::gig::dimension_genpurpose1:
1314 DimValues[i] = pEngineChannel->ControllerTable[16];
1315 break;
1316 case ::gig::dimension_genpurpose2:
1317 DimValues[i] = pEngineChannel->ControllerTable[17];
1318 break;
1319 case ::gig::dimension_genpurpose3:
1320 DimValues[i] = pEngineChannel->ControllerTable[18];
1321 break;
1322 case ::gig::dimension_genpurpose4:
1323 DimValues[i] = pEngineChannel->ControllerTable[19];
1324 break;
1325 case ::gig::dimension_sustainpedal:
1326 DimValues[i] = pEngineChannel->ControllerTable[64];
1327 break;
1328 case ::gig::dimension_portamento:
1329 DimValues[i] = pEngineChannel->ControllerTable[65];
1330 break;
1331 case ::gig::dimension_sostenutopedal:
1332 DimValues[i] = pEngineChannel->ControllerTable[66];
1333 break;
1334 case ::gig::dimension_softpedal:
1335 DimValues[i] = pEngineChannel->ControllerTable[67];
1336 break;
1337 case ::gig::dimension_genpurpose5:
1338 DimValues[i] = pEngineChannel->ControllerTable[80];
1339 break;
1340 case ::gig::dimension_genpurpose6:
1341 DimValues[i] = pEngineChannel->ControllerTable[81];
1342 break;
1343 case ::gig::dimension_genpurpose7:
1344 DimValues[i] = pEngineChannel->ControllerTable[82];
1345 break;
1346 case ::gig::dimension_genpurpose8:
1347 DimValues[i] = pEngineChannel->ControllerTable[83];
1348 break;
1349 case ::gig::dimension_effect1depth:
1350 DimValues[i] = pEngineChannel->ControllerTable[91];
1351 break;
1352 case ::gig::dimension_effect2depth:
1353 DimValues[i] = pEngineChannel->ControllerTable[92];
1354 break;
1355 case ::gig::dimension_effect3depth:
1356 DimValues[i] = pEngineChannel->ControllerTable[93];
1357 break;
1358 case ::gig::dimension_effect4depth:
1359 DimValues[i] = pEngineChannel->ControllerTable[94];
1360 break;
1361 case ::gig::dimension_effect5depth:
1362 DimValues[i] = pEngineChannel->ControllerTable[95];
1363 break;
1364 case ::gig::dimension_none:
1365 std::cerr << "gig::Engine::LaunchVoice() Error: dimension=none\n" << std::flush;
1366 break;
1367 default:
1368 std::cerr << "gig::Engine::LaunchVoice() Error: Unknown dimension\n" << std::flush;
1369 }
1370 }
1371
1372 // return if this is a release triggered voice and there is no
1373 // releasetrigger dimension (could happen if an instrument
1374 // change has occured between note on and off)
1375 if (ReleaseTriggerVoice && VoiceType != Voice::type_release_trigger) return Pool<Voice>::Iterator();
1376
1377 ::gig::DimensionRegion* pDimRgn = pRegion->GetDimensionRegionByValue(DimValues);
1378
1379 // no need to continue if sample is silent
1380 if (!pDimRgn->pSample || !pDimRgn->pSample->SamplesTotal) return Pool<Voice>::Iterator();
1381
1382 // allocate a new voice for the key
1383 Pool<Voice>::Iterator itNewVoice = pKey->pActiveVoices->allocAppend();
1384 if (itNewVoice) {
1385 // launch the new voice
1386 if (itNewVoice->Trigger(pEngineChannel, itNoteOnEvent, pEngineChannel->Pitch, pDimRgn, VoiceType, iKeyGroup) < 0) {
1387 dmsg(4,("Voice not triggered\n"));
1388 pKey->pActiveVoices->free(itNewVoice);
1389 }
1390 else { // on success
1391 --VoiceSpawnsLeft;
1392 if (!pKey->Active) { // mark as active key
1393 pKey->Active = true;
1394 pKey->itSelf = pEngineChannel->pActiveKeys->allocAppend();
1395 *pKey->itSelf = itNoteOnEvent->Param.Note.Key;
1396 }
1397 if (itNewVoice->KeyGroup) {
1398 uint** ppKeyGroup = &pEngineChannel->ActiveKeyGroups[itNewVoice->KeyGroup];
1399 *ppKeyGroup = &*pKey->itSelf; // put key as the (new) active key to its key group
1400 }
1401 if (itNewVoice->Type == Voice::type_release_trigger_required) pKey->ReleaseTrigger = true; // mark key for the need of release triggered voice(s)
1402 return itNewVoice; // success
1403 }
1404 }
1405 else if (VoiceStealing) {
1406 // try to steal one voice
1407 int result = StealVoice(pEngineChannel, itNoteOnEvent);
1408 if (!result) { // voice stolen successfully
1409 // put note-on event into voice-stealing queue, so it will be reprocessed after killed voice died
1410 RTList<Event>::Iterator itStealEvent = pVoiceStealingQueue->allocAppend();
1411 if (itStealEvent) {
1412 *itStealEvent = *itNoteOnEvent; // copy event
1413 itStealEvent->Param.Note.Layer = iLayer;
1414 itStealEvent->Param.Note.ReleaseTrigger = ReleaseTriggerVoice;
1415 pKey->VoiceTheftsQueued++;
1416 }
1417 else dmsg(1,("Voice stealing queue full!\n"));
1418 }
1419 }
1420
1421 return Pool<Voice>::Iterator(); // no free voice or error
1422 }
1423
1424 /**
1425 * Will be called by LaunchVoice() method in case there are no free
1426 * voices left. This method will select and kill one old voice for
1427 * voice stealing and postpone the note-on event until the selected
1428 * voice actually died.
1429 *
1430 * @param pEngineChannel - engine channel on which this event occured on
1431 * @param itNoteOnEvent - key, velocity and time stamp of the event
1432 * @returns 0 on success, a value < 0 if no active voice could be picked for voice stealing
1433 */
1434 int Engine::StealVoice(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent) {
1435 if (VoiceSpawnsLeft <= 0) {
1436 dmsg(1,("Max. voice thefts per audio fragment reached (you may raise CONFIG_MAX_VOICES).\n"));
1437 return -1;
1438 }
1439 if (!pEventPool->poolIsEmpty()) {
1440
1441 RTList<Voice>::Iterator itSelectedVoice;
1442
1443 // Select one voice for voice stealing
1444 switch (CONFIG_VOICE_STEAL_ALGO) {
1445
1446 // try to pick the oldest voice on the key where the new
1447 // voice should be spawned, if there is no voice on that
1448 // key, or no voice left to kill, then procceed with
1449 // 'oldestkey' algorithm
1450 case voice_steal_algo_oldestvoiceonkey: {
1451 midi_key_info_t* pSelectedKey = &pEngineChannel->pMIDIKeyInfo[itNoteOnEvent->Param.Note.Key];
1452 itSelectedVoice = pSelectedKey->pActiveVoices->first();
1453 // proceed iterating if voice was created in this fragment cycle
1454 while (itSelectedVoice && !itSelectedVoice->IsStealable()) ++itSelectedVoice;
1455 // if we haven't found a voice then proceed with algorithm 'oldestkey'
1456 if (itSelectedVoice && itSelectedVoice->IsStealable()) break;
1457 } // no break - intentional !
1458
1459 // try to pick the oldest voice on the oldest active key
1460 // from the same engine channel
1461 // (caution: must stay after 'oldestvoiceonkey' algorithm !)
1462 case voice_steal_algo_oldestkey: {
1463 // if we already stole in this fragment, try to proceed on same key
1464 if (this->itLastStolenVoice) {
1465 itSelectedVoice = this->itLastStolenVoice;
1466 do {
1467 ++itSelectedVoice;
1468 } while (itSelectedVoice && !itSelectedVoice->IsStealable()); // proceed iterating if voice was created in this fragment cycle
1469 // found a "stealable" voice ?
1470 if (itSelectedVoice && itSelectedVoice->IsStealable()) {
1471 // remember which voice we stole, so we can simply proceed on next voice stealing
1472 this->itLastStolenVoice = itSelectedVoice;
1473 break; // selection succeeded
1474 }
1475 }
1476 // get (next) oldest key
1477 RTList<uint>::Iterator iuiSelectedKey = (this->iuiLastStolenKey) ? ++this->iuiLastStolenKey : pEngineChannel->pActiveKeys->first();
1478 while (iuiSelectedKey) {
1479 midi_key_info_t* pSelectedKey = &pEngineChannel->pMIDIKeyInfo[*iuiSelectedKey];
1480 itSelectedVoice = pSelectedKey->pActiveVoices->first();
1481 // proceed iterating if voice was created in this fragment cycle
1482 while (itSelectedVoice && !itSelectedVoice->IsStealable()) ++itSelectedVoice;
1483 // found a "stealable" voice ?
1484 if (itSelectedVoice && itSelectedVoice->IsStealable()) {
1485 // remember which voice on which key we stole, so we can simply proceed on next voice stealing
1486 this->iuiLastStolenKey = iuiSelectedKey;
1487 this->itLastStolenVoice = itSelectedVoice;
1488 break; // selection succeeded
1489 }
1490 ++iuiSelectedKey; // get next oldest key
1491 }
1492 break;
1493 }
1494
1495 // don't steal anything
1496 case voice_steal_algo_none:
1497 default: {
1498 dmsg(1,("No free voice (voice stealing disabled)!\n"));
1499 return -1;
1500 }
1501 }
1502
1503 // if we couldn't steal a voice from the same engine channel then
1504 // steal oldest voice on the oldest key from any other engine channel
1505 // (the smaller engine channel number, the higher priority)
1506 if (!itSelectedVoice || !itSelectedVoice->IsStealable()) {
1507 EngineChannel* pSelectedChannel;
1508 int iChannelIndex;
1509 // select engine channel
1510 if (pLastStolenChannel) {
1511 pSelectedChannel = pLastStolenChannel;
1512 iChannelIndex = pSelectedChannel->iEngineIndexSelf;
1513 } else { // pick the engine channel followed by this engine channel
1514 iChannelIndex = (pEngineChannel->iEngineIndexSelf + 1) % engineChannels.size();
1515 pSelectedChannel = engineChannels[iChannelIndex];
1516 }
1517
1518 // if we already stole in this fragment, try to proceed on same key
1519 if (this->itLastStolenVoiceGlobally) {
1520 itSelectedVoice = this->itLastStolenVoiceGlobally;
1521 do {
1522 ++itSelectedVoice;
1523 } while (itSelectedVoice && !itSelectedVoice->IsStealable()); // proceed iterating if voice was created in this fragment cycle
1524 }
1525
1526 #if CONFIG_DEVMODE
1527 EngineChannel* pBegin = pSelectedChannel; // to detect endless loop
1528 #endif // CONFIG_DEVMODE
1529
1530 // did we find a 'stealable' voice?
1531 if (itSelectedVoice && itSelectedVoice->IsStealable()) {
1532 // remember which voice we stole, so we can simply proceed on next voice stealing
1533 this->itLastStolenVoiceGlobally = itSelectedVoice;
1534 } else while (true) { // iterate through engine channels
1535 // get (next) oldest key
1536 RTList<uint>::Iterator iuiSelectedKey = (this->iuiLastStolenKeyGlobally) ? ++this->iuiLastStolenKeyGlobally : pSelectedChannel->pActiveKeys->first();
1537 this->iuiLastStolenKeyGlobally = RTList<uint>::Iterator(); // to prevent endless loop (see line above)
1538 while (iuiSelectedKey) {
1539 midi_key_info_t* pSelectedKey = &pSelectedChannel->pMIDIKeyInfo[*iuiSelectedKey];
1540 itSelectedVoice = pSelectedKey->pActiveVoices->first();
1541 // proceed iterating if voice was created in this fragment cycle
1542 while (itSelectedVoice && !itSelectedVoice->IsStealable()) ++itSelectedVoice;
1543 // found a "stealable" voice ?
1544 if (itSelectedVoice && itSelectedVoice->IsStealable()) {
1545 // remember which voice on which key on which engine channel we stole, so we can simply proceed on next voice stealing
1546 this->iuiLastStolenKeyGlobally = iuiSelectedKey;
1547 this->itLastStolenVoiceGlobally = itSelectedVoice;
1548 this->pLastStolenChannel = pSelectedChannel;
1549 goto stealable_voice_found; // selection succeeded
1550 }
1551 ++iuiSelectedKey; // get next key on current engine channel
1552 }
1553 // get next engine channel
1554 iChannelIndex = (iChannelIndex + 1) % engineChannels.size();
1555 pSelectedChannel = engineChannels[iChannelIndex];
1556
1557 #if CONFIG_DEVMODE
1558 if (pSelectedChannel == pBegin) {
1559 dmsg(1,("FATAL ERROR: voice stealing endless loop!\n"));
1560 dmsg(1,("VoiceSpawnsLeft=%d.\n", VoiceSpawnsLeft));
1561 dmsg(1,("Exiting.\n"));
1562 exit(-1);
1563 }
1564 #endif // CONFIG_DEVMODE
1565 }
1566 }
1567
1568 // jump point if a 'stealable' voice was found
1569 stealable_voice_found:
1570
1571 #if CONFIG_DEVMODE
1572 if (!itSelectedVoice->IsActive()) {
1573 dmsg(1,("gig::Engine: ERROR, tried to steal a voice which was not active !!!\n"));
1574 return -1;
1575 }
1576 #endif // CONFIG_DEVMODE
1577
1578 // now kill the selected voice
1579 itSelectedVoice->Kill(itNoteOnEvent);
1580
1581 --VoiceSpawnsLeft;
1582
1583 return 0; // success
1584 }
1585 else {
1586 dmsg(1,("Event pool emtpy!\n"));
1587 return -1;
1588 }
1589 }
1590
1591 /**
1592 * Removes the given voice from the MIDI key's list of active voices.
1593 * This method will be called when a voice went inactive, e.g. because
1594 * it finished to playback its sample, finished its release stage or
1595 * just was killed.
1596 *
1597 * @param pEngineChannel - engine channel on which this event occured on
1598 * @param itVoice - points to the voice to be freed
1599 */
1600 void Engine::FreeVoice(EngineChannel* pEngineChannel, Pool<Voice>::Iterator& itVoice) {
1601 if (itVoice) {
1602 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[itVoice->MIDIKey];
1603
1604 uint keygroup = itVoice->KeyGroup;
1605
1606 // if the sample and dimension region belong to an
1607 // instrument that is unloaded, tell the disk thread to
1608 // release them
1609 if (itVoice->Orphan) {
1610 pDiskThread->OrderDeletionOfDimreg(itVoice->pDimRgn);
1611 }
1612
1613 // free the voice object
1614 pVoicePool->free(itVoice);
1615
1616 // if no other voices left and member of a key group, remove from key group
1617 if (pKey->pActiveVoices->isEmpty() && keygroup) {
1618 uint** ppKeyGroup = &pEngineChannel->ActiveKeyGroups[keygroup];
1619 if (*ppKeyGroup == &*pKey->itSelf) *ppKeyGroup = NULL; // remove key from key group
1620 }
1621 }
1622 else std::cerr << "Couldn't release voice! (!itVoice)\n" << std::flush;
1623 }
1624
1625 /**
1626 * Called when there's no more voice left on a key, this call will
1627 * update the key info respectively.
1628 *
1629 * @param pEngineChannel - engine channel on which this event occured on
1630 * @param pKey - key which is now inactive
1631 */
1632 void Engine::FreeKey(EngineChannel* pEngineChannel, midi_key_info_t* pKey) {
1633 if (pKey->pActiveVoices->isEmpty()) {
1634 pKey->Active = false;
1635 pEngineChannel->pActiveKeys->free(pKey->itSelf); // remove key from list of active keys
1636 pKey->itSelf = RTList<uint>::Iterator();
1637 pKey->ReleaseTrigger = false;
1638 pKey->pEvents->clear();
1639 dmsg(3,("Key has no more voices now\n"));
1640 }
1641 else dmsg(1,("gig::Engine: Oops, tried to free a key which contains voices.\n"));
1642 }
1643
1644 /**
1645 * Reacts on supported control change commands (e.g. pitch bend wheel,
1646 * modulation wheel, aftertouch).
1647 *
1648 * @param pEngineChannel - engine channel on which this event occured on
1649 * @param itControlChangeEvent - controller, value and time stamp of the event
1650 */
1651 void Engine::ProcessControlChange(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itControlChangeEvent) {
1652 dmsg(4,("Engine::ContinuousController cc=%d v=%d\n", itControlChangeEvent->Param.CC.Controller, itControlChangeEvent->Param.CC.Value));
1653
1654 // handle the "control triggered" MIDI rule: a control change
1655 // event can trigger a new note on or note off event
1656 if (pEngineChannel->pInstrument) {
1657
1658 ::gig::MidiRule* rule;
1659 for (int i = 0 ; (rule = pEngineChannel->pInstrument->GetMidiRule(i)) ; i++) {
1660
1661 if (::gig::MidiRuleCtrlTrigger* ctrlTrigger =
1662 dynamic_cast< ::gig::MidiRuleCtrlTrigger*>(rule)) {
1663 if (itControlChangeEvent->Param.CC.Controller ==
1664 ctrlTrigger->ControllerNumber) {
1665
1666 uint8_t oldCCValue = pEngineChannel->ControllerTable[
1667 itControlChangeEvent->Param.CC.Controller];
1668 uint8_t newCCValue = itControlChangeEvent->Param.CC.Value;
1669
1670 for (int i = 0 ; i < ctrlTrigger->Triggers ; i++) {
1671 ::gig::MidiRuleCtrlTrigger::trigger_t* pTrigger =
1672 &ctrlTrigger->pTriggers[i];
1673
1674 // check if the controller has passed the
1675 // trigger point in the right direction
1676 if ((pTrigger->Descending &&
1677 oldCCValue > pTrigger->TriggerPoint &&
1678 newCCValue <= pTrigger->TriggerPoint) ||
1679 (!pTrigger->Descending &&
1680 oldCCValue < pTrigger->TriggerPoint &&
1681 newCCValue >= pTrigger->TriggerPoint)) {
1682
1683 RTList<Event>::Iterator itNewEvent = pGlobalEvents->allocAppend();
1684 if (itNewEvent) {
1685 *itNewEvent = *itControlChangeEvent;
1686 itNewEvent->Param.Note.Key = pTrigger->Key;
1687
1688 if (pTrigger->NoteOff || pTrigger->Velocity == 0) {
1689 itNewEvent->Type = Event::type_note_off;
1690 itNewEvent->Param.Note.Velocity = 100;
1691
1692 ProcessNoteOff(pEngineChannel, itNewEvent);
1693 } else {
1694 itNewEvent->Type = Event::type_note_on;
1695 //TODO: if Velocity is 255, the triggered velocity should
1696 // depend on how fast the controller is moving
1697 itNewEvent->Param.Note.Velocity =
1698 pTrigger->Velocity == 255 ? 100 :
1699 pTrigger->Velocity;
1700
1701 ProcessNoteOn(pEngineChannel, itNewEvent);
1702 }
1703 }
1704 else dmsg(1,("Event pool emtpy!\n"));
1705 }
1706 }
1707 }
1708 }
1709 }
1710 }
1711
1712 // update controller value in the engine channel's controller table
1713 pEngineChannel->ControllerTable[itControlChangeEvent->Param.CC.Controller] = itControlChangeEvent->Param.CC.Value;
1714
1715 // handle hard coded MIDI controllers
1716 switch (itControlChangeEvent->Param.CC.Controller) {
1717 case 5: { // portamento time
1718 pEngineChannel->PortamentoTime = (float) itControlChangeEvent->Param.CC.Value / 127.0f * (float) CONFIG_PORTAMENTO_TIME_MAX + (float) CONFIG_PORTAMENTO_TIME_MIN;
1719 break;
1720 }
1721 case 6: { // data entry (currently only used for RPN controllers)
1722 if (pEngineChannel->GetMidiRpnController() == 2) { // coarse tuning in half tones
1723 int transpose = (int) itControlChangeEvent->Param.CC.Value - 64;
1724 // limit to +- two octaves for now
1725 transpose = RTMath::Min(transpose, 24);
1726 transpose = RTMath::Max(transpose, -24);
1727 pEngineChannel->GlobalTranspose = transpose;
1728 // workaround, so we won't have hanging notes
1729 ReleaseAllVoices(pEngineChannel, itControlChangeEvent);
1730 }
1731 // to avoid other MIDI CC #6 messages to be misenterpreted as RPN controller data
1732 pEngineChannel->ResetMidiRpnController();
1733 break;
1734 }
1735 case 7: { // volume
1736 //TODO: not sample accurate yet
1737 pEngineChannel->MidiVolume = VolumeCurve[itControlChangeEvent->Param.CC.Value];
1738 pEngineChannel->bStatusChanged = true; // engine channel status has changed, so set notify flag
1739 break;
1740 }
1741 case 10: { // panpot
1742 //TODO: not sample accurate yet
1743 pEngineChannel->GlobalPanLeft = PanCurve[128 - itControlChangeEvent->Param.CC.Value];
1744 pEngineChannel->GlobalPanRight = PanCurve[itControlChangeEvent->Param.CC.Value];
1745 pEngineChannel->iLastPanRequest = itControlChangeEvent->Param.CC.Value;
1746 break;
1747 }
1748 case 64: { // sustain
1749 if (itControlChangeEvent->Param.CC.Value >= 64 && !pEngineChannel->SustainPedal) {
1750 dmsg(4,("DAMPER (RIGHT) PEDAL DOWN\n"));
1751 pEngineChannel->SustainPedal = true;
1752
1753 #if !CONFIG_PROCESS_MUTED_CHANNELS
1754 if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
1755 #endif
1756
1757 // cancel release process of voices if necessary
1758 RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
1759 for (; iuiKey; ++iuiKey) {
1760 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
1761 if (!pKey->KeyPressed) {
1762 RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
1763 if (itNewEvent) {
1764 *itNewEvent = *itControlChangeEvent; // copy event to the key's own event list
1765 itNewEvent->Type = Event::type_cancel_release; // transform event type
1766 }
1767 else dmsg(1,("Event pool emtpy!\n"));
1768 }
1769 }
1770 }
1771 if (itControlChangeEvent->Param.CC.Value < 64 && pEngineChannel->SustainPedal) {
1772 dmsg(4,("DAMPER (RIGHT) PEDAL UP\n"));
1773 pEngineChannel->SustainPedal = false;
1774
1775 #if !CONFIG_PROCESS_MUTED_CHANNELS
1776 if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
1777 #endif
1778
1779 // release voices if their respective key is not pressed
1780 RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
1781 for (; iuiKey; ++iuiKey) {
1782 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
1783 if (!pKey->KeyPressed && ShouldReleaseVoice(pEngineChannel, *iuiKey)) {
1784 RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
1785 if (itNewEvent) {
1786 *itNewEvent = *itControlChangeEvent; // copy event to the key's own event list
1787 itNewEvent->Type = Event::type_release; // transform event type
1788 }
1789 else dmsg(1,("Event pool emtpy!\n"));
1790 }
1791 }
1792 }
1793 break;
1794 }
1795 case 65: { // portamento on / off
1796 const bool bPortamento = itControlChangeEvent->Param.CC.Value >= 64;
1797 if (bPortamento != pEngineChannel->PortamentoMode)
1798 KillAllVoices(pEngineChannel, itControlChangeEvent);
1799 pEngineChannel->PortamentoMode = bPortamento;
1800 break;
1801 }
1802 case 66: { // sostenuto
1803 if (itControlChangeEvent->Param.CC.Value >= 64 && !pEngineChannel->SostenutoPedal) {
1804 dmsg(4,("SOSTENUTO (CENTER) PEDAL DOWN\n"));
1805 pEngineChannel->SostenutoPedal = true;
1806
1807 #if !CONFIG_PROCESS_MUTED_CHANNELS
1808 if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
1809 #endif
1810
1811 SostenutoKeyCount = 0;
1812 // Remeber the pressed keys
1813 RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
1814 for (; iuiKey; ++iuiKey) {
1815 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
1816 if (pKey->KeyPressed && SostenutoKeyCount < 128) SostenutoKeys[SostenutoKeyCount++] = *iuiKey;
1817 }
1818 }
1819 if (itControlChangeEvent->Param.CC.Value < 64 && pEngineChannel->SostenutoPedal) {
1820 dmsg(4,("SOSTENUTO (CENTER) PEDAL UP\n"));
1821 pEngineChannel->SostenutoPedal = false;
1822
1823 #if !CONFIG_PROCESS_MUTED_CHANNELS
1824 if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
1825 #endif
1826
1827 // release voices if the damper pedal is up and their respective key is not pressed
1828 for (int i = 0; i < SostenutoKeyCount; i++) {
1829 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[SostenutoKeys[i]];
1830 if (!pKey->KeyPressed && !pEngineChannel->SustainPedal) {
1831 RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
1832 if (itNewEvent) {
1833 *itNewEvent = *itControlChangeEvent; // copy event to the key's own event list
1834 itNewEvent->Type = Event::type_release; // transform event type
1835 }
1836 else dmsg(1,("Event pool emtpy!\n"));
1837 }
1838 }
1839 }
1840 break;
1841 }
1842 case 100: { // RPN controller LSB
1843 pEngineChannel->SetMidiRpnControllerLsb(itControlChangeEvent->Param.CC.Value);
1844 break;
1845 }
1846 case 101: { // RPN controller MSB
1847 pEngineChannel->SetMidiRpnControllerMsb(itControlChangeEvent->Param.CC.Value);
1848 break;
1849 }
1850
1851
1852 // Channel Mode Messages
1853
1854 case 120: { // all sound off
1855 KillAllVoices(pEngineChannel, itControlChangeEvent);
1856 break;
1857 }
1858 case 121: { // reset all controllers
1859 pEngineChannel->ResetControllers();
1860 break;
1861 }
1862 case 123: { // all notes off
1863 #if CONFIG_PROCESS_ALL_NOTES_OFF
1864 ReleaseAllVoices(pEngineChannel, itControlChangeEvent);
1865 #endif // CONFIG_PROCESS_ALL_NOTES_OFF
1866 break;
1867 }
1868 case 126: { // mono mode on
1869 if (!pEngineChannel->SoloMode)
1870 KillAllVoices(pEngineChannel, itControlChangeEvent);
1871 pEngineChannel->SoloMode = true;
1872 break;
1873 }
1874 case 127: { // poly mode on
1875 if (pEngineChannel->SoloMode)
1876 KillAllVoices(pEngineChannel, itControlChangeEvent);
1877 pEngineChannel->SoloMode = false;
1878 break;
1879 }
1880 }
1881
1882 // handle FX send controllers
1883 if (!pEngineChannel->fxSends.empty()) {
1884 for (int iFxSend = 0; iFxSend < pEngineChannel->GetFxSendCount(); iFxSend++) {
1885 FxSend* pFxSend = pEngineChannel->GetFxSend(iFxSend);
1886 if (pFxSend->MidiController() == itControlChangeEvent->Param.CC.Controller) {
1887 pFxSend->SetLevel(itControlChangeEvent->Param.CC.Value);
1888 pFxSend->SetInfoChanged(true);
1889 }
1890 }
1891 }
1892 }
1893
1894 /**
1895 * Reacts on MIDI system exclusive messages.
1896 *
1897 * @param itSysexEvent - sysex data size and time stamp of the sysex event
1898 */
1899 void Engine::ProcessSysex(Pool<Event>::Iterator& itSysexEvent) {
1900 RingBuffer<uint8_t,false>::NonVolatileReader reader = pSysexBuffer->get_non_volatile_reader();
1901
1902 uint8_t exclusive_status, id;
1903 if (!reader.pop(&exclusive_status)) goto free_sysex_data;
1904 if (!reader.pop(&id)) goto free_sysex_data;
1905 if (exclusive_status != 0xF0) goto free_sysex_data;
1906
1907 switch (id) {
1908 case 0x7f: { // (Realtime) Universal Sysex (GM Standard)
1909 uint8_t sysex_channel, sub_id1, sub_id2, val_msb, val_lsb;;
1910 if (!reader.pop(&sysex_channel)) goto free_sysex_data;
1911 if (!reader.pop(&sub_id1)) goto free_sysex_data;
1912 if (!reader.pop(&sub_id2)) goto free_sysex_data;
1913 if (!reader.pop(&val_lsb)) goto free_sysex_data;
1914 if (!reader.pop(&val_msb)) goto free_sysex_data;
1915 //TODO: for now we simply ignore the sysex channel, seldom used anyway
1916 switch (sub_id1) {
1917 case 0x04: // Device Control
1918 switch (sub_id2) {
1919 case 0x01: { // Master Volume
1920 const double volume =
1921 double((uint(val_msb)<<7) | uint(val_lsb)) / 16383.0;
1922 #if CONFIG_MASTER_VOLUME_SYSEX_BY_PORT
1923 // apply volume to all sampler channels that
1924 // are connected to the same MIDI input port
1925 // this sysex message arrived on
1926 for (int i = 0; i < engineChannels.size(); ++i) {
1927 EngineChannel* pEngineChannel = engineChannels[i];
1928 if (pEngineChannel->GetMidiInputPort() ==
1929 itSysexEvent->pMidiInputPort)
1930 {
1931 pEngineChannel->Volume(volume);
1932 }
1933 }
1934 #else
1935 // apply volume globally to the whole sampler
1936 GLOBAL_VOLUME = volume;
1937 #endif // CONFIG_MASTER_VOLUME_SYSEX_BY_PORT
1938 break;
1939 }
1940 }
1941 break;
1942 }
1943 break;
1944 }
1945 case 0x41: { // Roland
1946 dmsg(3,("Roland Sysex\n"));
1947 uint8_t device_id, model_id, cmd_id;
1948 if (!reader.pop(&device_id)) goto free_sysex_data;
1949 if (!reader.pop(&model_id)) goto free_sysex_data;
1950 if (!reader.pop(&cmd_id)) goto free_sysex_data;
1951 if (model_id != 0x42 /*GS*/) goto free_sysex_data;
1952 if (cmd_id != 0x12 /*DT1*/) goto free_sysex_data;
1953
1954 // command address
1955 uint8_t addr[3]; // 2 byte addr MSB, followed by 1 byte addr LSB)
1956 const RingBuffer<uint8_t,false>::NonVolatileReader checksum_reader = reader; // so we can calculate the check sum later
1957 if (reader.read(&addr[0], 3) != 3) goto free_sysex_data;
1958 if (addr[0] == 0x40 && addr[1] == 0x00) { // System Parameters
1959 dmsg(3,("\tSystem Parameter\n"));
1960 }
1961 else if (addr[0] == 0x40 && addr[1] == 0x01) { // Common Parameters
1962 dmsg(3,("\tCommon Parameter\n"));
1963 }
1964 else if (addr[0] == 0x40 && (addr[1] & 0xf0) == 0x10) { // Part Parameters (1)
1965 dmsg(3,("\tPart Parameter\n"));
1966 switch (addr[2]) {
1967 case 0x40: { // scale tuning
1968 dmsg(3,("\t\tScale Tuning\n"));
1969 uint8_t scale_tunes[12]; // detuning of all 12 semitones of an octave
1970 if (reader.read(&scale_tunes[0], 12) != 12) goto free_sysex_data;
1971 uint8_t checksum;
1972 if (!reader.pop(&checksum)) goto free_sysex_data;
1973 #if CONFIG_ASSERT_GS_SYSEX_CHECKSUM
1974 if (GSCheckSum(checksum_reader, 12)) goto free_sysex_data;
1975 #endif // CONFIG_ASSERT_GS_SYSEX_CHECKSUM
1976 for (int i = 0; i < 12; i++) scale_tunes[i] -= 64;
1977 AdjustScale((int8_t*) scale_tunes);
1978 dmsg(3,("\t\t\tNew scale applied.\n"));
1979 break;
1980 }
1981 case 0x15: { // chromatic / drumkit mode
1982 dmsg(3,("\t\tMIDI Instrument Map Switch\n"));
1983 uint8_t part = addr[1] & 0x0f;
1984 uint8_t map;
1985 if (!reader.pop(&map)) goto free_sysex_data;
1986 for (int i = 0; i < engineChannels.size(); ++i) {
1987 EngineChannel* pEngineChannel = engineChannels[i];
1988 if (
1989 (pEngineChannel->midiChannel == part ||
1990 pEngineChannel->midiChannel == midi_chan_all) &&
1991 pEngineChannel->GetMidiInputPort() == itSysexEvent->pMidiInputPort
1992 ) {
1993 try {
1994 pEngineChannel->SetMidiInstrumentMap(map);
1995 } catch (Exception e) {
1996 dmsg(2,("\t\t\tCould not apply MIDI instrument map %d to part %d: %s\n", map, part, e.Message().c_str()));
1997 goto free_sysex_data;
1998 } catch (...) {
1999 dmsg(2,("\t\t\tCould not apply MIDI instrument map %d to part %d (unknown exception)\n", map, part));
2000 goto free_sysex_data;
2001 }
2002 }
2003 }
2004 dmsg(3,("\t\t\tApplied MIDI instrument map %d to part %d.\n", map, part));
2005 break;
2006 }
2007 }
2008 }
2009 else if (addr[0] == 0x40 && (addr[1] & 0xf0) == 0x20) { // Part Parameters (2)
2010 }
2011 else if (addr[0] == 0x41) { // Drum Setup Parameters
2012 }
2013 break;
2014 }
2015 }
2016
2017 free_sysex_data: // finally free sysex data
2018 pSysexBuffer->increment_read_ptr(itSysexEvent->Param.Sysex.Size);
2019 }
2020
2021 /**
2022 * Calculates the Roland GS sysex check sum.
2023 *
2024 * @param AddrReader - reader which currently points to the first GS
2025 * command address byte of the GS sysex message in
2026 * question
2027 * @param DataSize - size of the GS message data (in bytes)
2028 */
2029 uint8_t Engine::GSCheckSum(const RingBuffer<uint8_t,false>::NonVolatileReader AddrReader, uint DataSize) {
2030 RingBuffer<uint8_t,false>::NonVolatileReader reader = AddrReader;
2031 uint bytes = 3 /*addr*/ + DataSize;
2032 uint8_t addr_and_data[bytes];
2033 reader.read(&addr_and_data[0], bytes);
2034 uint8_t sum = 0;
2035 for (uint i = 0; i < bytes; i++) sum += addr_and_data[i];
2036 return 128 - sum % 128;
2037 }
2038
2039 /**
2040 * Allows to tune each of the twelve semitones of an octave.
2041 *
2042 * @param ScaleTunes - detuning of all twelve semitones (in cents)
2043 */
2044 void Engine::AdjustScale(int8_t ScaleTunes[12]) {
2045 memcpy(&this->ScaleTuning[0], &ScaleTunes[0], 12); //TODO: currently not sample accurate
2046 }
2047
2048 /**
2049 * Releases all voices on an engine channel. All voices will go into
2050 * the release stage and thus it might take some time (e.g. dependant to
2051 * their envelope release time) until they actually die.
2052 *
2053 * @param pEngineChannel - engine channel on which all voices should be released
2054 * @param itReleaseEvent - event which caused this releasing of all voices
2055 */
2056 void Engine::ReleaseAllVoices(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itReleaseEvent) {
2057 RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
2058 while (iuiKey) {
2059 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
2060 ++iuiKey;
2061 // append a 'release' event to the key's own event list
2062 RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
2063 if (itNewEvent) {
2064 *itNewEvent = *itReleaseEvent; // copy original event (to the key's event list)
2065 itNewEvent->Type = Event::type_release; // transform event type
2066 }
2067 else dmsg(1,("Event pool emtpy!\n"));
2068 }
2069 }
2070
2071 /**
2072 * Kills all voices on an engine channel as soon as possible. Voices
2073 * won't get into release state, their volume level will be ramped down
2074 * as fast as possible.
2075 *
2076 * @param pEngineChannel - engine channel on which all voices should be killed
2077 * @param itKillEvent - event which caused this killing of all voices
2078 */
2079 void Engine::KillAllVoices(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itKillEvent) {
2080 RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
2081 RTList<uint>::Iterator end = pEngineChannel->pActiveKeys->end();
2082 while (iuiKey != end) { // iterate through all active keys
2083 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
2084 ++iuiKey;
2085 RTList<Voice>::Iterator itVoice = pKey->pActiveVoices->first();
2086 RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();
2087 for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
2088 itVoice->Kill(itKillEvent);
2089 --VoiceSpawnsLeft; //FIXME: just a temporary workaround, we should check the cause in StealVoice() instead
2090 }
2091 }
2092 }
2093
2094 /**
2095 * Determines whether the specified voice should be released.
2096 *
2097 * @param pEngineChannel - The engine channel on which the voice should be checked
2098 * @param Key - The key number
2099 * @returns true if the specified should be released, false otherwise.
2100 */
2101 bool Engine::ShouldReleaseVoice(EngineChannel* pEngineChannel, int Key) {
2102 if (pEngineChannel->SustainPedal) return false;
2103
2104 if (pEngineChannel->SostenutoPedal) {
2105 for (int i = 0; i < SostenutoKeyCount; i++)
2106 if (Key == SostenutoKeys[i]) return false;
2107 }
2108
2109 return true;
2110 }
2111
2112 uint Engine::VoiceCount() {
2113 return atomic_read(&ActiveVoiceCount);
2114 }
2115
2116 void Engine::SetVoiceCount(uint Count) {
2117 atomic_set(&ActiveVoiceCount, Count);
2118 }
2119
2120 uint Engine::VoiceCountMax() {
2121 return ActiveVoiceCountMax;
2122 }
2123
2124 int Engine::MaxVoices() {
2125 return pVoicePool->poolSize();
2126 }
2127
2128 void Engine::SetMaxVoices(int iVoices) throw (Exception) {
2129 if (iVoices < 1)
2130 throw Exception("Maximum voices for an engine cannot be set lower than 1");
2131
2132 SuspendAll();
2133
2134 // NOTE: we need to clear pDimRegionsInUse before deleting pDimRegionPool,
2135 // otherwise memory corruption will occur if there are active voices (see bug #118)
2136 for (int iChannel = 0; iChannel < engineChannels.size(); iChannel++) {
2137 engineChannels[iChannel]->ClearDimRegionsInUse();
2138 }
2139
2140 if (pDimRegionPool[0]) delete pDimRegionPool[0];
2141 if (pDimRegionPool[1]) delete pDimRegionPool[1];
2142
2143 pDimRegionPool[0] = new Pool< ::gig::DimensionRegion*>(iVoices);
2144 pDimRegionPool[1] = new Pool< ::gig::DimensionRegion*>(iVoices);
2145
2146 for (int iChannel = 0; iChannel < engineChannels.size(); iChannel++) {
2147 engineChannels[iChannel]->ResetDimRegionsInUse();
2148 }
2149
2150 try {
2151 pVoicePool->resizePool(iVoices);
2152 } catch (...) {
2153 throw Exception("FATAL: Could not resize voice pool!");
2154 }
2155
2156 for (RTList<Voice>::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
2157 iterVoice->SetEngine(this);
2158 iterVoice->pDiskThread = this->pDiskThread;
2159 }
2160 pVoicePool->clear();
2161
2162 ResumeAll();
2163 }
2164
2165 bool Engine::DiskStreamSupported() {
2166 return true;
2167 }
2168
2169 uint Engine::DiskStreamCount() {
2170 return (pDiskThread) ? pDiskThread->GetActiveStreamCount() : 0;
2171 }
2172
2173 uint Engine::DiskStreamCountMax() {
2174 return (pDiskThread) ? pDiskThread->ActiveStreamCountMax : 0;
2175 }
2176
2177 int Engine::MaxDiskStreams() {
2178 return iMaxDiskStreams;
2179 }
2180
2181 void Engine::SetMaxDiskStreams(int iStreams) throw (Exception) {
2182 if (iStreams < 0)
2183 throw Exception("Maximum disk streams for an engine cannot be set lower than 0");
2184
2185 SuspendAll();
2186
2187 iMaxDiskStreams = iStreams;
2188
2189 // reconnect to audio output device, because that will automatically
2190 // recreate the disk thread with the required amount of streams
2191 if (pAudioOutputDevice) Connect(pAudioOutputDevice);
2192
2193 ResumeAll();
2194 }
2195
2196 String Engine::DiskStreamBufferFillBytes() {
2197 return pDiskThread->GetBufferFillBytes();
2198 }
2199
2200 String Engine::DiskStreamBufferFillPercentage() {
2201 return pDiskThread->GetBufferFillPercentage();
2202 }
2203
2204 String Engine::EngineName() {
2205 return LS_GIG_ENGINE_NAME;
2206 }
2207
2208 String Engine::Description() {
2209 return "Gigasampler Format Engine";
2210 }
2211
2212 String Engine::Version() {
2213 String s = "$Revision: 1.100 $";
2214 return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword
2215 }
2216
2217 InstrumentManager* Engine::GetInstrumentManager() {
2218 return &instruments;
2219 }
2220
2221 // static constant initializers
2222 const Engine::FloatTable Engine::VolumeCurve(InitVolumeCurve());
2223 const Engine::FloatTable Engine::PanCurve(InitPanCurve());
2224 const Engine::FloatTable Engine::CrossfadeCurve(InitCrossfadeCurve());
2225
2226 float* Engine::InitVolumeCurve() {
2227 // line-segment approximation
2228 const float segments[] = {
2229 0, 0, 2, 0.0046, 16, 0.016, 31, 0.051, 45, 0.115, 54.5, 0.2,
2230 64.5, 0.39, 74, 0.74, 92, 1.03, 114, 1.94, 119.2, 2.2, 127, 2.2
2231 };
2232 return InitCurve(segments);
2233 }
2234
2235 float* Engine::InitPanCurve() {
2236 // line-segment approximation
2237 const float segments[] = {
2238 0, 0, 1, 0,
2239 2, 0.05, 31.5, 0.7, 51, 0.851, 74.5, 1.12,
2240 127, 1.41, 128, 1.41
2241 };
2242 return InitCurve(segments, 129);
2243 }
2244
2245 float* Engine::InitCrossfadeCurve() {
2246 // line-segment approximation
2247 const float segments[] = {
2248 0, 0, 1, 0.03, 10, 0.1, 51, 0.58, 127, 1
2249 };
2250 return InitCurve(segments);
2251 }
2252
2253 float* Engine::InitCurve(const float* segments, int size) {
2254 float* y = new float[size];
2255 for (int x = 0 ; x < size ; x++) {
2256 if (x > segments[2]) segments += 2;
2257 y[x] = segments[1] + (x - segments[0]) *
2258 (segments[3] - segments[1]) / (segments[2] - segments[0]);
2259 }
2260 return y;
2261 }
2262
2263 }} // namespace LinuxSampler::gig

  ViewVC Help
Powered by ViewVC