/[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 1555 - (show annotations) (download)
Thu Dec 6 01:39:24 2007 UTC (16 years, 4 months ago) by schoenebeck
File size: 99839 byte(s)
- slightly changed gig engine description

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

  ViewVC Help
Powered by ViewVC