/[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 1751 - (show annotations) (download)
Mon Jul 28 07:36:35 2008 UTC (15 years, 8 months ago) by schoenebeck
File size: 106921 byte(s)
* bugfix: process chromatic / drumkit mode sysex message only for
  the respective engine channels that are connected to the MIDI
  input port on which the message was received

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

  ViewVC Help
Powered by ViewVC