/[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 1764 - (show annotations) (download)
Sat Sep 6 14:55:18 2008 UTC (15 years, 6 months ago) by persson
File size: 108070 byte(s)
* rewrote the ConditionServer class to make it possible to create
  multiple sample channels when the audio thread isn't running

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

  ViewVC Help
Powered by ViewVC