/[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 1893 - (show annotations) (download)
Sat May 2 18:57:49 2009 UTC (14 years, 11 months ago) by schoenebeck
File size: 111419 byte(s)
* fixed crash which occured when max. voices / streams limits were altered
  while voices were still active

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

  ViewVC Help
Powered by ViewVC