/[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 1933 - (show annotations) (download)
Thu Jul 9 17:37:41 2009 UTC (14 years, 8 months ago) by persson
File size: 111460 byte(s)
* fixed low-level ConditionServer usage bug that caused lockups on
  Windows

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

  ViewVC Help
Powered by ViewVC