/[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 1399 - (show annotations) (download)
Thu Oct 11 18:53:29 2007 UTC (16 years, 6 months ago) by schoenebeck
File size: 99790 byte(s)
* the following LSCP command return escape sequences in at least one
  of their LSCP response fields: "GET ENGINE INFO", "GET CHANNEL INFO",
  "GET MIDI_INSTRUMENT INFO", "GET MIDI_INSTRUMENT_MAP INFO",
  "GET FX_SEND INFO", "GET SERVER INFO"
* listed all LSCP commands in the LSCP specs which may use escape
  sequences in at least on of their response fields
* hide instrument editor related debug messages in the gig::Engine when
  using the default debug level (which is 1)
* bumped version to 0.4.0.8cvs

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

  ViewVC Help
Powered by ViewVC