/[svn]/linuxsampler/trunk/src/engines/gig/Engine.cpp
ViewVC logotype

Annotation of /linuxsampler/trunk/src/engines/gig/Engine.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1321 - (hide annotations) (download)
Tue Sep 4 01:12:49 2007 UTC (16 years, 7 months ago) by schoenebeck
File size: 99572 byte(s)
* added highly experimental code for synchronizing instrument editors
  hosted in the sampler's process to safely edit instruments while playing
  without a crash (hopefully) by either suspending single regions wherever
  possible or - if unavoidable - whole engine(s)
* disk thread: queue sizes are now proportional to CONFIG_MAX_STREAMS
  instead of fix values
* removed legacy Makefiles in meanwhile deleted src/lib directory and its
  subdirectories
* bumped version to 0.4.0.7cvs

1 schoenebeck 53 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5 capela 1012 * Copyright (C) 2003,2004 by Benno Senoner and Christian Schoenebeck *
6     * Copyright (C) 2005-2007 Christian Schoenebeck *
7 schoenebeck 53 * *
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 schoenebeck 285 #include "EGADSR.h"
28 schoenebeck 420 #include "../EngineFactory.h"
29 schoenebeck 53
30     #include "Engine.h"
31    
32     namespace LinuxSampler { namespace gig {
33    
34 schoenebeck 411 InstrumentResourceManager Engine::instruments;
35 schoenebeck 53
36 schoenebeck 411 std::map<AudioOutputDevice*,Engine*> Engine::engines;
37    
38 schoenebeck 412 /**
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 schoenebeck 411 Engine* Engine::AcquireEngine(LinuxSampler::gig::EngineChannel* pChannel, AudioOutputDevice* pDevice) {
49 schoenebeck 412 Engine* pEngine = NULL;
50     // check if there's already an engine for the given audio output device
51 schoenebeck 411 if (engines.count(pDevice)) {
52 schoenebeck 412 dmsg(4,("Using existing gig::Engine.\n"));
53 persson 438 pEngine = engines[pDevice];
54 persson 1039
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 schoenebeck 412 } else { // create a new engine (and disk thread) instance for the given audio output device
60     dmsg(4,("Creating new gig::Engine.\n"));
61 schoenebeck 420 pEngine = (Engine*) EngineFactory::Create("gig");
62 schoenebeck 411 pEngine->Connect(pDevice);
63 persson 438 engines[pDevice] = pEngine;
64 schoenebeck 411 }
65 schoenebeck 412 // register engine channel to the engine instance
66 schoenebeck 460 pEngine->engineChannels.add(pChannel);
67     // remember index in the ArrayList
68     pChannel->iEngineIndexSelf = pEngine->engineChannels.size() - 1;
69 schoenebeck 412 dmsg(4,("This gig::Engine has now %d EngineChannels.\n",pEngine->engineChannels.size()));
70 schoenebeck 411 return pEngine;
71     }
72    
73 schoenebeck 412 /**
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 schoenebeck 411 void Engine::FreeEngine(LinuxSampler::gig::EngineChannel* pChannel, AudioOutputDevice* pDevice) {
84 schoenebeck 412 dmsg(4,("Disconnecting EngineChannel from gig::Engine.\n"));
85 schoenebeck 411 Engine* pEngine = engines[pDevice];
86 schoenebeck 412 // 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 schoenebeck 411 }
97    
98 schoenebeck 473 /**
99     * Constructor
100     */
101 schoenebeck 1321 Engine::Engine() : SuspendedRegions(128) {
102 schoenebeck 53 pAudioOutputDevice = NULL;
103     pDiskThread = NULL;
104     pEventGenerator = NULL;
105 schoenebeck 970 pSysexBuffer = new RingBuffer<uint8_t,false>(CONFIG_SYSEX_BUFFER_SIZE, 0);
106     pEventQueue = new RingBuffer<Event,false>(CONFIG_MAX_EVENTS_PER_FRAGMENT, 0);
107 schoenebeck 554 pEventPool = new Pool<Event>(CONFIG_MAX_EVENTS_PER_FRAGMENT);
108     pVoicePool = new Pool<Voice>(CONFIG_MAX_VOICES);
109 persson 1038 pDimRegionsInUse = new ::gig::DimensionRegion*[CONFIG_MAX_VOICES + 1];
110 schoenebeck 271 pVoiceStealingQueue = new RTList<Event>(pEventPool);
111 schoenebeck 460 pGlobalEvents = new RTList<Event>(pEventPool);
112 persson 1038 InstrumentChangeQueue = new RingBuffer<instrument_change_command_t,false>(1, 0);
113     InstrumentChangeReplyQueue = new RingBuffer<instrument_change_reply_t,false>(1, 0);
114    
115 schoenebeck 271 for (RTList<Voice>::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
116     iterVoice->SetEngine(this);
117 schoenebeck 53 }
118     pVoicePool->clear();
119    
120     ResetInternal();
121 schoenebeck 659 ResetScaleTuning();
122 schoenebeck 1321 ResetSuspendedRegions();
123 schoenebeck 53 }
124    
125 schoenebeck 473 /**
126     * Destructor
127     */
128 schoenebeck 53 Engine::~Engine() {
129 persson 846 MidiInputPort::RemoveSysexListener(this);
130 schoenebeck 53 if (pDiskThread) {
131 senkov 329 dmsg(1,("Stopping disk thread..."));
132 schoenebeck 53 pDiskThread->StopThread();
133     delete pDiskThread;
134 senkov 329 dmsg(1,("OK\n"));
135 schoenebeck 53 }
136     if (pEventQueue) delete pEventQueue;
137     if (pEventPool) delete pEventPool;
138 schoenebeck 411 if (pVoicePool) {
139     pVoicePool->clear();
140     delete pVoicePool;
141     }
142 schoenebeck 53 if (pEventGenerator) delete pEventGenerator;
143 schoenebeck 250 if (pVoiceStealingQueue) delete pVoiceStealingQueue;
144 schoenebeck 411 if (pSysexBuffer) delete pSysexBuffer;
145 persson 1248 if (pGlobalEvents) delete pGlobalEvents;
146     if (InstrumentChangeQueue) delete InstrumentChangeQueue;
147     if (InstrumentChangeReplyQueue) delete InstrumentChangeReplyQueue;
148     if (pDimRegionsInUse) delete[] pDimRegionsInUse;
149 schoenebeck 1321 ResetSuspendedRegions();
150 capela 1012 Unregister();
151 schoenebeck 53 }
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 schoenebeck 64 dmsg(3,("gig::Engine: enabled (val=%d)\n", EngineDisabled.GetUnsafe()));
157 schoenebeck 53 }
158    
159 schoenebeck 1321 /**
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 schoenebeck 53 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 schoenebeck 1321 * 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(1,("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(1,("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(1,("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(1,("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(1,("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(1,("gig::Engine: Region %x resumed.\n",pRegion));
271     }
272    
273     /**
274 schoenebeck 53 * 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 schoenebeck 659 ResetScaleTuning();
281 schoenebeck 53 Enable();
282     }
283    
284     /**
285     * Reset all voices and disk thread and clear input event queue and all
286 persson 846 * control and status variables. This method is protected by a mutex.
287 schoenebeck 53 */
288     void Engine::ResetInternal() {
289 persson 846 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 schoenebeck 53 ActiveVoiceCount = 0;
295     ActiveVoiceCountMax = 0;
296    
297 schoenebeck 250 // reset voice stealing parameters
298     pVoiceStealingQueue->clear();
299 schoenebeck 649 itLastStolenVoice = RTList<Voice>::Iterator();
300     itLastStolenVoiceGlobally = RTList<Voice>::Iterator();
301     iuiLastStolenKey = RTList<uint>::Iterator();
302     iuiLastStolenKeyGlobally = RTList<uint>::Iterator();
303     pLastStolenChannel = NULL;
304 schoenebeck 250
305 schoenebeck 53 // reset all voices
306 schoenebeck 271 for (RTList<Voice>::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
307     iterVoice->Reset();
308 schoenebeck 53 }
309     pVoicePool->clear();
310    
311     // reset disk thread
312     if (pDiskThread) pDiskThread->Reset();
313    
314     // delete all input events
315     pEventQueue->init();
316 schoenebeck 775 pSysexBuffer->init();
317 persson 846 if (sysexDisabled) MidiInputPort::AddSysexListener(this);
318     ResetInternalMutex.Unlock();
319 persson 438 }
320 schoenebeck 53
321 schoenebeck 473 /**
322 schoenebeck 659 * Reset to normal, chromatic scale (means equal tempered).
323     */
324     void Engine::ResetScaleTuning() {
325     memset(&ScaleTuning[0], 0x00, 12);
326     }
327    
328 schoenebeck 1321 void Engine::ResetSuspendedRegions() {
329     SuspendedRegions.clear();
330     iPendingStreamDeletions = 0;
331     pPendingRegionSuspension = pPendingRegionResumption = NULL;
332     SuspensionChangeOngoing.Set(false);
333     }
334    
335 schoenebeck 659 /**
336 schoenebeck 473 * 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 schoenebeck 53 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 schoenebeck 880 throw Exception(msg);
356 schoenebeck 53 }
357 persson 438
358 schoenebeck 460 this->MaxSamplesPerCycle = pAudioOutputDevice->MaxSamplesPerCycle();
359     this->SampleRate = pAudioOutputDevice->SampleRate();
360 schoenebeck 225
361 schoenebeck 285 // FIXME: audio drivers with varying fragment sizes might be a problem here
362 schoenebeck 554 MaxFadeOutPos = MaxSamplesPerCycle - int(double(SampleRate) * CONFIG_EG_MIN_RELEASE_TIME) - 1;
363 schoenebeck 688 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 schoenebeck 690 << "May lead to click sounds if voice stealing chimes in!\n" << std::flush;
367 schoenebeck 688 // 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 schoenebeck 738 iterVoice->EG1.CalculateFadeOutCoeff(minReleaseTime, SampleRate);
373 schoenebeck 688 }
374     pVoicePool->clear();
375     }
376 schoenebeck 285
377 schoenebeck 53 // (re)create disk thread
378     if (this->pDiskThread) {
379 senkov 329 dmsg(1,("Stopping disk thread..."));
380 schoenebeck 53 this->pDiskThread->StopThread();
381     delete this->pDiskThread;
382 senkov 329 dmsg(1,("OK\n"));
383 schoenebeck 53 }
384 persson 1038 this->pDiskThread = new DiskThread(((pAudioOut->MaxSamplesPerCycle() << CONFIG_MAX_PITCH) << 1) + 6, //FIXME: assuming stereo
385     &instruments);
386 schoenebeck 53 if (!pDiskThread) {
387     dmsg(0,("gig::Engine new diskthread = NULL\n"));
388     exit(EXIT_FAILURE);
389     }
390    
391 schoenebeck 271 for (RTList<Voice>::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
392     iterVoice->pDiskThread = this->pDiskThread;
393 schoenebeck 53 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 schoenebeck 271 for (RTList<Voice>::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
406     if (!iterVoice->pDiskThread) {
407 schoenebeck 53 dmsg(0,("Engine -> voice::trigger: !pDiskThread\n"));
408     exit(EXIT_FAILURE);
409     }
410     }
411     }
412    
413 schoenebeck 473 /**
414 schoenebeck 1321 * 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 schoenebeck 473 * Clear all engine global event lists.
519     */
520 schoenebeck 412 void Engine::ClearEventLists() {
521 schoenebeck 460 pGlobalEvents->clear();
522 schoenebeck 412 }
523    
524 schoenebeck 53 /**
525 schoenebeck 460 * 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 schoenebeck 412 *
534 schoenebeck 460 * @param Samples - number of sample points to be processed in the
535     * current audio cycle
536 schoenebeck 412 */
537 schoenebeck 460 void Engine::ImportEvents(uint Samples) {
538 schoenebeck 970 RingBuffer<Event,false>::NonVolatileReader eventQueueReader = pEventQueue->get_non_volatile_reader();
539 schoenebeck 412 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 schoenebeck 460 if (pGlobalEvents->poolIsEmpty()) {
552 schoenebeck 412 dmsg(1,("Event pool emtpy!\n"));
553     break;
554     }
555 schoenebeck 460 *pGlobalEvents->allocAppend() = *pEvent;
556 schoenebeck 412 }
557     eventQueueReader.free(); // free all copied events from input queue
558 persson 438 }
559 schoenebeck 412
560     /**
561 schoenebeck 924 * 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 schoenebeck 53 *
568     * @param Samples - number of sample points to be rendered
569     * @returns 0 on success
570     */
571 schoenebeck 412 int Engine::RenderAudio(uint Samples) {
572 schoenebeck 947 dmsg(7,("RenderAudio(Samples=%d)\n", Samples));
573 schoenebeck 53
574 schoenebeck 412 // return if engine disabled
575 schoenebeck 53 if (EngineDisabled.Pop()) {
576     dmsg(5,("gig::Engine: engine disabled (val=%d)\n",EngineDisabled.GetUnsafe()));
577     return 0;
578     }
579    
580 schoenebeck 1321 // 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 schoenebeck 293 // update time of start and end of this audio fragment (as events' time stamps relate to this)
585     pEventGenerator->UpdateFragmentTime(Samples);
586    
587 schoenebeck 663 // 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 schoenebeck 412 // 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 schoenebeck 460 ImportEvents(Samples);
595 schoenebeck 412
596     // process engine global events (these are currently only MIDI System Exclusive messages)
597     {
598 schoenebeck 460 RTList<Event>::Iterator itEvent = pGlobalEvents->first();
599     RTList<Event>::Iterator end = pGlobalEvents->end();
600 schoenebeck 412 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 schoenebeck 53 }
609 schoenebeck 412
610     // reset internal voice counter (just for statistic of active voices)
611     ActiveVoiceCountTemp = 0;
612    
613 persson 1038 // 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 schoenebeck 1321 //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 persson 1038 // 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 schoenebeck 466 // handle events on all engine channels
650 schoenebeck 460 for (int i = 0; i < engineChannels.size(); i++) {
651     ProcessEvents(engineChannels[i], Samples);
652 schoenebeck 466 }
653    
654     // render all 'normal', active voices on all engine channels
655     for (int i = 0; i < engineChannels.size(); i++) {
656 schoenebeck 460 RenderActiveVoices(engineChannels[i], Samples);
657 schoenebeck 412 }
658    
659 schoenebeck 460 // now that all ordinary voices on ALL engine channels are rendered, render new stolen voices
660     RenderStolenVoices(Samples);
661    
662 schoenebeck 1001 // 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 schoenebeck 460 // 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 schoenebeck 412 // just some statistics about this engine instance
681     ActiveVoiceCount = ActiveVoiceCountTemp;
682     if (ActiveVoiceCount > ActiveVoiceCountMax) ActiveVoiceCountMax = ActiveVoiceCount;
683    
684 schoenebeck 1321 // 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 persson 630 FrameTime += Samples;
690    
691 schoenebeck 412 return 0;
692     }
693    
694 schoenebeck 473 /**
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 schoenebeck 460 void Engine::ProcessEvents(EngineChannel* pEngineChannel, uint Samples) {
704 schoenebeck 412 // 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 schoenebeck 460 pEngineChannel->ImportEvents(Samples);
707 schoenebeck 53
708     // process events
709 schoenebeck 271 {
710 schoenebeck 460 RTList<Event>::Iterator itEvent = pEngineChannel->pEvents->first();
711     RTList<Event>::Iterator end = pEngineChannel->pEvents->end();
712 schoenebeck 271 for (; itEvent != end; ++itEvent) {
713     switch (itEvent->Type) {
714     case Event::type_note_on:
715     dmsg(5,("Engine: Note on received\n"));
716 schoenebeck 412 ProcessNoteOn((EngineChannel*)itEvent->pEngineChannel, itEvent);
717 schoenebeck 271 break;
718     case Event::type_note_off:
719     dmsg(5,("Engine: Note off received\n"));
720 schoenebeck 412 ProcessNoteOff((EngineChannel*)itEvent->pEngineChannel, itEvent);
721 schoenebeck 271 break;
722     case Event::type_control_change:
723     dmsg(5,("Engine: MIDI CC received\n"));
724 schoenebeck 412 ProcessControlChange((EngineChannel*)itEvent->pEngineChannel, itEvent);
725 schoenebeck 271 break;
726     case Event::type_pitchbend:
727     dmsg(5,("Engine: Pitchbend received\n"));
728 schoenebeck 412 ProcessPitchbend((EngineChannel*)itEvent->pEngineChannel, itEvent);
729 schoenebeck 271 break;
730     }
731 schoenebeck 53 }
732     }
733 schoenebeck 649
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 schoenebeck 460 }
741 schoenebeck 53
742 schoenebeck 473 /**
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 schoenebeck 460 void Engine::RenderActiveVoices(EngineChannel* pEngineChannel, uint Samples) {
752 iliev 716 #if !CONFIG_PROCESS_MUTED_CHANNELS
753 schoenebeck 705 if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
754 iliev 716 #endif
755 schoenebeck 705
756 iliev 1305 uint voiceCount = 0;
757     uint streamCount = 0;
758 schoenebeck 460 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 schoenebeck 53
764 schoenebeck 460 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 iliev 1297 if (itVoice->IsActive()) { // still active
770     ActiveVoiceCountTemp++;
771 iliev 1305 voiceCount++;
772 iliev 1297
773     if (itVoice->PlaybackState == Voice::playback_state_disk) {
774 iliev 1305 if ((itVoice->DiskStreamRef).State == Stream::state_active) streamCount++;
775 iliev 1297 }
776     } else { // voice reached end, is now inactive
777 schoenebeck 460 FreeVoice(pEngineChannel, itVoice); // remove voice from the list of active voices
778 schoenebeck 53 }
779     }
780     }
781 iliev 1297
782 iliev 1305 pEngineChannel->SetVoiceCount(voiceCount);
783     pEngineChannel->SetDiskStreamCount(streamCount);
784 schoenebeck 460 }
785 schoenebeck 53
786 schoenebeck 473 /**
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 schoenebeck 460 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 persson 1038 if (!pEngineChannel->pInstrument) continue; // ignore if no instrument loaded
805 schoenebeck 460 Pool<Voice>::Iterator itNewVoice =
806 schoenebeck 668 LaunchVoice(pEngineChannel, itVoiceStealEvent, itVoiceStealEvent->Param.Note.Layer, itVoiceStealEvent->Param.Note.ReleaseTrigger, false, false);
807 schoenebeck 460 if (itNewVoice) {
808     itNewVoice->Render(Samples);
809 iliev 1297 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 schoenebeck 460 FreeVoice(pEngineChannel, itNewVoice); // remove voice from the list of active voices
820 schoenebeck 250 }
821     }
822 schoenebeck 460 else dmsg(1,("gig::Engine: ERROR, voice stealing didn't work out!\n"));
823 schoenebeck 473
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 schoenebeck 250 }
829 schoenebeck 460 }
830 schoenebeck 250
831 schoenebeck 473 /**
832 schoenebeck 1001 * 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 schoenebeck 1037 pEngineChannel->pChannelLeft->MixTo(pDstL, Samples);
850     pEngineChannel->pChannelRight->MixTo(pDstR, Samples);
851 schoenebeck 1001 }
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 schoenebeck 1037 } else pEngineChannel->pChannelLeft->MixTo(pDstL, Samples, pFxSend->Level());
865 schoenebeck 1001 }
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 schoenebeck 1037 } else pEngineChannel->pChannelRight->MixTo(pDstR, Samples, pFxSend->Level());
875 schoenebeck 1001 }
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 schoenebeck 473 * 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 schoenebeck 460 void Engine::PostProcess(EngineChannel* pEngineChannel) {
891 schoenebeck 287 // free all keys which have no active voices left
892     {
893 schoenebeck 411 RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
894     RTList<uint>::Iterator end = pEngineChannel->pActiveKeys->end();
895 schoenebeck 287 while (iuiKey != end) { // iterate through all active keys
896 schoenebeck 411 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
897 schoenebeck 287 ++iuiKey;
898 schoenebeck 411 if (pKey->pActiveVoices->isEmpty()) FreeKey(pEngineChannel, pKey);
899 schoenebeck 554 #if CONFIG_DEVMODE
900 schoenebeck 563 else { // just a sanity check for debugging
901 schoenebeck 287 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 schoenebeck 554 #endif // CONFIG_DEVMODE
910 schoenebeck 287 }
911     }
912 schoenebeck 460
913     // empty the engine channel's own event lists
914     pEngineChannel->ClearEventLists();
915 schoenebeck 412 }
916 schoenebeck 287
917 schoenebeck 53 /**
918 schoenebeck 244 * 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 schoenebeck 246 Event event = pEventGenerator->CreateEvent();
926     event.Type = Event::type_sysex;
927     event.Param.Sysex.Size = Size;
928 schoenebeck 412 event.pEngineChannel = NULL; // as Engine global event
929 schoenebeck 244 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 schoenebeck 554 else dmsg(1,("Engine: Sysex message too large (%d byte) for input buffer (%d byte)!",Size,CONFIG_SYSEX_BUFFER_SIZE));
945 schoenebeck 244 }
946     else dmsg(1,("Engine: Input event queue full!"));
947     }
948    
949     /**
950 schoenebeck 53 * Assigns and triggers a new voice for the respective MIDI key.
951     *
952 schoenebeck 411 * @param pEngineChannel - engine channel on which this event occured on
953 schoenebeck 271 * @param itNoteOnEvent - key, velocity and time stamp of the event
954 schoenebeck 53 */
955 schoenebeck 411 void Engine::ProcessNoteOn(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent) {
956 iliev 716 #if !CONFIG_PROCESS_MUTED_CHANNELS
957     if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
958     #endif
959 persson 438
960 persson 1038 if (!pEngineChannel->pInstrument) return; // ignore if no instrument loaded
961    
962 schoenebeck 1041 //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 schoenebeck 354 const int key = itNoteOnEvent->Param.Note.Key;
966 schoenebeck 829 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[key];
967 schoenebeck 354
968 schoenebeck 829 // 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 schoenebeck 354 // Change key dimension value if key is in keyswitching area
997 schoenebeck 411 {
998     const ::gig::Instrument* pInstrument = pEngineChannel->pInstrument;
999     if (key >= pInstrument->DimensionKeyRange.low && key <= pInstrument->DimensionKeyRange.high)
1000 persson 865 pEngineChannel->CurrentKeyDimension = float(key - pInstrument->DimensionKeyRange.low) /
1001 schoenebeck 411 (pInstrument->DimensionKeyRange.high - pInstrument->DimensionKeyRange.low + 1);
1002     }
1003 schoenebeck 354
1004 schoenebeck 53 pKey->KeyPressed = true; // the MIDI key was now pressed down
1005 schoenebeck 829 pKey->Velocity = itNoteOnEventOnKeyList->Param.Note.Velocity;
1006     pKey->NoteOnTime = FrameTime + itNoteOnEventOnKeyList->FragmentPos(); // will be used to calculate note length
1007 schoenebeck 53
1008     // cancel release process of voices on this key if needed
1009 schoenebeck 411 if (pKey->Active && !pEngineChannel->SustainPedal) {
1010 schoenebeck 271 RTList<Event>::Iterator itCancelReleaseEvent = pKey->pEvents->allocAppend();
1011     if (itCancelReleaseEvent) {
1012 schoenebeck 829 *itCancelReleaseEvent = *itNoteOnEventOnKeyList; // copy event
1013 schoenebeck 271 itCancelReleaseEvent->Type = Event::type_cancel_release; // transform event type
1014 schoenebeck 239 }
1015     else dmsg(1,("Event pool emtpy!\n"));
1016 schoenebeck 53 }
1017    
1018 schoenebeck 460 // 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 schoenebeck 1321 if (pRegion && !RegionSuspended(pRegion)) {
1023 schoenebeck 460 int voicesRequired = pRegion->Layers;
1024     // now launch the required amount of voices
1025     for (int i = 0; i < voicesRequired; i++)
1026 schoenebeck 668 LaunchVoice(pEngineChannel, itNoteOnEventOnKeyList, i, false, true, true);
1027 schoenebeck 460 }
1028     }
1029 persson 438
1030 schoenebeck 473 // 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 schoenebeck 829 if (!pEngineChannel->SoloMode || pEngineChannel->PortamentoPos < 0.0f) pEngineChannel->PortamentoPos = (float) key;
1035 persson 438 pKey->RoundRobinIndex++;
1036 schoenebeck 53 }
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 schoenebeck 411 * @param pEngineChannel - engine channel on which this event occured on
1045 schoenebeck 271 * @param itNoteOffEvent - key, velocity and time stamp of the event
1046 schoenebeck 53 */
1047 schoenebeck 411 void Engine::ProcessNoteOff(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOffEvent) {
1048 iliev 716 #if !CONFIG_PROCESS_MUTED_CHANNELS
1049 schoenebeck 705 if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
1050 iliev 716 #endif
1051 schoenebeck 705
1052 schoenebeck 1041 //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 schoenebeck 829 const int iKey = itNoteOffEvent->Param.Note.Key;
1056     midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[iKey];
1057 schoenebeck 53 pKey->KeyPressed = false; // the MIDI key was now released
1058    
1059 schoenebeck 829 // move event to the key's own event list
1060     RTList<Event>::Iterator itNoteOffEventOnKeyList = itNoteOffEvent.moveToEndOf(pKey->pEvents);
1061 schoenebeck 242
1062 schoenebeck 829 bool bShouldRelease = pKey->Active && ShouldReleaseVoice(pEngineChannel, itNoteOffEventOnKeyList->Param.Note.Key);
1063 schoenebeck 271
1064 schoenebeck 829 // in case Solo Mode is enabled, kill all voices on this key and respawn a voice on the highest pressed key (if any)
1065 persson 1038 if (pEngineChannel->SoloMode && pEngineChannel->pInstrument) { //TODO: this feels like too much code just for handling solo mode :P
1066 schoenebeck 829 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 persson 497 // spawn release triggered voice(s) if needed
1128 persson 1038 if (pKey->ReleaseTrigger && pEngineChannel->pInstrument) {
1129 persson 497 // 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 persson 630
1134     // MIDI note-on velocity is used instead of note-off velocity
1135     itNoteOffEventOnKeyList->Param.Note.Velocity = pKey->Velocity;
1136    
1137 persson 497 // now launch the required amount of voices
1138     for (int i = 0; i < voicesRequired; i++)
1139 schoenebeck 668 LaunchVoice(pEngineChannel, itNoteOffEventOnKeyList, i, true, false, false); //FIXME: for the moment we don't perform voice stealing for release triggered samples
1140 persson 497 }
1141     pKey->ReleaseTrigger = false;
1142 schoenebeck 460 }
1143 schoenebeck 829 }
1144 persson 497
1145 schoenebeck 829 // 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 schoenebeck 53 }
1149    
1150     /**
1151 schoenebeck 738 * 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 schoenebeck 53 *
1155 schoenebeck 411 * @param pEngineChannel - engine channel on which this event occured on
1156 schoenebeck 271 * @param itPitchbendEvent - absolute pitch value and time stamp of the event
1157 schoenebeck 53 */
1158 schoenebeck 411 void Engine::ProcessPitchbend(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itPitchbendEvent) {
1159     pEngineChannel->Pitch = itPitchbendEvent->Param.Pitch.Pitch; // store current pitch value
1160 schoenebeck 53 }
1161    
1162     /**
1163 schoenebeck 233 * 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 schoenebeck 411 * @param pEngineChannel - engine channel on which this event occured on
1168 schoenebeck 271 * @param itNoteOnEvent - key, velocity and time stamp of the event
1169 schoenebeck 242 * @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 schoenebeck 250 * @param VoiceStealing - if voice stealing should be performed
1174     * when there is no free voice
1175     * (optional, default = true)
1176 schoenebeck 668 * @param HandleKeyGroupConflicts - if voices should be killed due to a
1177     * key group conflict
1178 schoenebeck 250 * @returns pointer to new voice or NULL if there was no free voice or
1179 schoenebeck 354 * if the voice wasn't triggered (for example when no region is
1180     * defined for the given key).
1181 schoenebeck 233 */
1182 schoenebeck 668 Pool<Voice>::Iterator Engine::LaunchVoice(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent, int iLayer, bool ReleaseTriggerVoice, bool VoiceStealing, bool HandleKeyGroupConflicts) {
1183 schoenebeck 669 int MIDIKey = itNoteOnEvent->Param.Note.Key;
1184     midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[MIDIKey];
1185     ::gig::Region* pRegion = pEngineChannel->pInstrument->GetRegion(MIDIKey);
1186 schoenebeck 233
1187 schoenebeck 668 // if nothing defined for this key
1188     if (!pRegion) return Pool<Voice>::Iterator(); // nothing to do
1189    
1190 schoenebeck 669 // 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 schoenebeck 668 // 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 schoenebeck 669 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 persson 903 DimValues[i] = pEngineChannel->ControllerTable[128];
1232 schoenebeck 669 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 persson 865 DimValues[i] = (uint) (pEngineChannel->CurrentKeyDimension * pRegion->pDimensionDefinitions[i].zones);
1239 schoenebeck 669 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 persson 1038
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 schoenebeck 669 ::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 schoenebeck 233 // allocate a new voice for the key
1335 schoenebeck 271 Pool<Voice>::Iterator itNewVoice = pKey->pActiveVoices->allocAppend();
1336     if (itNewVoice) {
1337 schoenebeck 233 // launch the new voice
1338 schoenebeck 669 if (itNewVoice->Trigger(pEngineChannel, itNoteOnEvent, pEngineChannel->Pitch, pDimRgn, VoiceType, iKeyGroup) < 0) {
1339 schoenebeck 354 dmsg(4,("Voice not triggered\n"));
1340 schoenebeck 271 pKey->pActiveVoices->free(itNewVoice);
1341 schoenebeck 233 }
1342 schoenebeck 239 else { // on success
1343 schoenebeck 663 --VoiceSpawnsLeft;
1344 schoenebeck 239 if (!pKey->Active) { // mark as active key
1345     pKey->Active = true;
1346 schoenebeck 411 pKey->itSelf = pEngineChannel->pActiveKeys->allocAppend();
1347 schoenebeck 271 *pKey->itSelf = itNoteOnEvent->Param.Note.Key;
1348 schoenebeck 239 }
1349 schoenebeck 271 if (itNewVoice->KeyGroup) {
1350 schoenebeck 668 uint** ppKeyGroup = &pEngineChannel->ActiveKeyGroups[itNewVoice->KeyGroup];
1351 schoenebeck 271 *ppKeyGroup = &*pKey->itSelf; // put key as the (new) active key to its key group
1352 schoenebeck 239 }
1353 schoenebeck 271 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 schoenebeck 233 }
1356     }
1357 schoenebeck 285 else if (VoiceStealing) {
1358 schoenebeck 460 // try to steal one voice
1359 schoenebeck 473 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 schoenebeck 285 }
1371     }
1372    
1373 schoenebeck 271 return Pool<Voice>::Iterator(); // no free voice or error
1374 schoenebeck 233 }
1375    
1376     /**
1377 schoenebeck 250 * 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 schoenebeck 411 * @param pEngineChannel - engine channel on which this event occured on
1383 schoenebeck 285 * @param itNoteOnEvent - key, velocity and time stamp of the event
1384 schoenebeck 473 * @returns 0 on success, a value < 0 if no active voice could be picked for voice stealing
1385 schoenebeck 250 */
1386 schoenebeck 473 int Engine::StealVoice(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent) {
1387 schoenebeck 663 if (VoiceSpawnsLeft <= 0) {
1388 schoenebeck 554 dmsg(1,("Max. voice thefts per audio fragment reached (you may raise CONFIG_MAX_VOICES).\n"));
1389 schoenebeck 473 return -1;
1390 schoenebeck 460 }
1391 schoenebeck 271 if (!pEventPool->poolIsEmpty()) {
1392 schoenebeck 250
1393 schoenebeck 460 RTList<Voice>::Iterator itSelectedVoice;
1394 schoenebeck 250
1395     // Select one voice for voice stealing
1396 schoenebeck 554 switch (CONFIG_VOICE_STEAL_ALGO) {
1397 schoenebeck 250
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 schoenebeck 563 // key, or no voice left to kill, then procceed with
1401 schoenebeck 250 // 'oldestkey' algorithm
1402 schoenebeck 460 case voice_steal_algo_oldestvoiceonkey: {
1403     midi_key_info_t* pSelectedKey = &pEngineChannel->pMIDIKeyInfo[itNoteOnEvent->Param.Note.Key];
1404 schoenebeck 563 itSelectedVoice = pSelectedKey->pActiveVoices->first();
1405     // proceed iterating if voice was created in this fragment cycle
1406 schoenebeck 663 while (itSelectedVoice && !itSelectedVoice->IsStealable()) ++itSelectedVoice;
1407 schoenebeck 563 // if we haven't found a voice then proceed with algorithm 'oldestkey'
1408 schoenebeck 663 if (itSelectedVoice && itSelectedVoice->IsStealable()) break;
1409 schoenebeck 250 } // no break - intentional !
1410    
1411     // try to pick the oldest voice on the oldest active key
1412 schoenebeck 563 // from the same engine channel
1413 schoenebeck 460 // (caution: must stay after 'oldestvoiceonkey' algorithm !)
1414 schoenebeck 250 case voice_steal_algo_oldestkey: {
1415 schoenebeck 649 // if we already stole in this fragment, try to proceed on same key
1416 schoenebeck 460 if (this->itLastStolenVoice) {
1417     itSelectedVoice = this->itLastStolenVoice;
1418 schoenebeck 649 do {
1419     ++itSelectedVoice;
1420 schoenebeck 663 } while (itSelectedVoice && !itSelectedVoice->IsStealable()); // proceed iterating if voice was created in this fragment cycle
1421 schoenebeck 649 // found a "stealable" voice ?
1422 schoenebeck 663 if (itSelectedVoice && itSelectedVoice->IsStealable()) {
1423 schoenebeck 649 // remember which voice we stole, so we can simply proceed on next voice stealing
1424     this->itLastStolenVoice = itSelectedVoice;
1425 schoenebeck 460 break; // selection succeeded
1426 schoenebeck 250 }
1427     }
1428 schoenebeck 649 // 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 schoenebeck 659 itSelectedVoice = pSelectedKey->pActiveVoices->first();
1433 schoenebeck 649 // proceed iterating if voice was created in this fragment cycle
1434 schoenebeck 663 while (itSelectedVoice && !itSelectedVoice->IsStealable()) ++itSelectedVoice;
1435 schoenebeck 649 // found a "stealable" voice ?
1436 schoenebeck 663 if (itSelectedVoice && itSelectedVoice->IsStealable()) {
1437 schoenebeck 649 // 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 schoenebeck 250 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 schoenebeck 473 return -1;
1452 schoenebeck 250 }
1453     }
1454    
1455 schoenebeck 563 // 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 schoenebeck 649 // (the smaller engine channel number, the higher priority)
1458 schoenebeck 663 if (!itSelectedVoice || !itSelectedVoice->IsStealable()) {
1459 schoenebeck 649 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 schoenebeck 663
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 schoenebeck 649 // get (next) oldest key
1488 schoenebeck 663 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 schoenebeck 649 while (iuiSelectedKey) {
1491 schoenebeck 663 midi_key_info_t* pSelectedKey = &pSelectedChannel->pMIDIKeyInfo[*iuiSelectedKey];
1492 schoenebeck 649 itSelectedVoice = pSelectedKey->pActiveVoices->first();
1493     // proceed iterating if voice was created in this fragment cycle
1494 schoenebeck 663 while (itSelectedVoice && !itSelectedVoice->IsStealable()) ++itSelectedVoice;
1495 schoenebeck 649 // found a "stealable" voice ?
1496 schoenebeck 663 if (itSelectedVoice && itSelectedVoice->IsStealable()) {
1497 schoenebeck 649 // 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 schoenebeck 665 goto stealable_voice_found; // selection succeeded
1502 schoenebeck 649 }
1503     ++iuiSelectedKey; // get next key on current engine channel
1504     }
1505     // get next engine channel
1506 schoenebeck 460 iChannelIndex = (iChannelIndex + 1) % engineChannels.size();
1507 schoenebeck 649 pSelectedChannel = engineChannels[iChannelIndex];
1508 schoenebeck 663
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 schoenebeck 460 }
1518     }
1519    
1520 schoenebeck 665 // jump point if a 'stealable' voice was found
1521     stealable_voice_found:
1522    
1523 schoenebeck 563 #if CONFIG_DEVMODE
1524 schoenebeck 473 if (!itSelectedVoice->IsActive()) {
1525     dmsg(1,("gig::Engine: ERROR, tried to steal a voice which was not active !!!\n"));
1526     return -1;
1527     }
1528 schoenebeck 563 #endif // CONFIG_DEVMODE
1529 schoenebeck 287
1530 schoenebeck 250 // now kill the selected voice
1531 schoenebeck 659 itSelectedVoice->Kill(itNoteOnEvent);
1532 schoenebeck 460
1533 schoenebeck 663 --VoiceSpawnsLeft;
1534 schoenebeck 473
1535     return 0; // success
1536 schoenebeck 250 }
1537 schoenebeck 473 else {
1538     dmsg(1,("Event pool emtpy!\n"));
1539     return -1;
1540     }
1541 schoenebeck 250 }
1542    
1543     /**
1544 schoenebeck 285 * 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 schoenebeck 53 *
1549 schoenebeck 411 * @param pEngineChannel - engine channel on which this event occured on
1550 schoenebeck 285 * @param itVoice - points to the voice to be freed
1551 schoenebeck 53 */
1552 schoenebeck 411 void Engine::FreeVoice(EngineChannel* pEngineChannel, Pool<Voice>::Iterator& itVoice) {
1553 schoenebeck 271 if (itVoice) {
1554 schoenebeck 411 midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[itVoice->MIDIKey];
1555 schoenebeck 53
1556 schoenebeck 271 uint keygroup = itVoice->KeyGroup;
1557    
1558 persson 1038 // 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 schoenebeck 53 // free the voice object
1566 schoenebeck 271 pVoicePool->free(itVoice);
1567 schoenebeck 53
1568 schoenebeck 287 // if no other voices left and member of a key group, remove from key group
1569     if (pKey->pActiveVoices->isEmpty() && keygroup) {
1570 schoenebeck 411 uint** ppKeyGroup = &pEngineChannel->ActiveKeyGroups[keygroup];
1571 schoenebeck 287 if (*ppKeyGroup == &*pKey->itSelf) *ppKeyGroup = NULL; // remove key from key group
1572 schoenebeck 53 }
1573     }
1574 schoenebeck 285 else std::cerr << "Couldn't release voice! (!itVoice)\n" << std::flush;
1575 schoenebeck 53 }
1576    
1577     /**
1578 schoenebeck 287 * Called when there's no more voice left on a key, this call will
1579     * update the key info respectively.
1580     *
1581 schoenebeck 411 * @param pEngineChannel - engine channel on which this event occured on
1582 schoenebeck 287 * @param pKey - key which is now inactive
1583     */
1584 schoenebeck 411 void Engine::FreeKey(EngineChannel* pEngineChannel, midi_key_info_t* pKey) {
1585 schoenebeck 287 if (pKey->pActiveVoices->isEmpty()) {
1586     pKey->Active = false;
1587 schoenebeck 411 pEngineChannel->pActiveKeys->free(pKey->itSelf); // remove key from list of active keys
1588 schoenebeck 287 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 schoenebeck 53 * Reacts on supported control change commands (e.g. pitch bend wheel,
1598     * modulation wheel, aftertouch).
1599     *
1600 schoenebeck 411 * @param pEngineChannel - engine channel on which this event occured on
1601 schoenebeck 271 * @param itControlChangeEvent - controller, value and time stamp of the event
1602 schoenebeck 53 */
1603 schoenebeck 411 void Engine::ProcessControlChange(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itControlChangeEvent) {
1604 schoenebeck 271 dmsg(4,("Engine::ContinuousController cc=%d v=%d\n", itControlChangeEvent->Param.CC.Controller, itControlChangeEvent->Param.CC.Value));
1605 schoenebeck 53
1606 schoenebeck 473 // update controller value in the engine channel's controller table
1607     pEngineChannel->ControllerTable[itControlChangeEvent->Param.CC.Controller] = itControlChangeEvent->Param.CC.Value;
1608    
1609 schoenebeck 1001 // handle hard coded MIDI controllers
1610 schoenebeck 769 switch (itControlChangeEvent->Param.CC.Controller) {
1611 schoenebeck 829 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 schoenebeck 1041 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 schoenebeck 1043 // workaround, so we won't have hanging notes
1623     ReleaseAllVoices(pEngineChannel, itControlChangeEvent);
1624 schoenebeck 1041 }
1625 schoenebeck 1044 // to avoid other MIDI CC #6 messages to be misenterpreted as RPN controller data
1626     pEngineChannel->ResetMidiRpnController();
1627 schoenebeck 1041 break;
1628     }
1629 schoenebeck 424 case 7: { // volume
1630     //TODO: not sample accurate yet
1631 schoenebeck 947 pEngineChannel->MidiVolume = VolumeCurve[itControlChangeEvent->Param.CC.Value];
1632 schoenebeck 660 pEngineChannel->bStatusChanged = true; // engine channel status has changed, so set notify flag
1633 schoenebeck 424 break;
1634     }
1635     case 10: { // panpot
1636     //TODO: not sample accurate yet
1637 persson 831 pEngineChannel->GlobalPanLeft = PanCurve[128 - itControlChangeEvent->Param.CC.Value];
1638     pEngineChannel->GlobalPanRight = PanCurve[itControlChangeEvent->Param.CC.Value];
1639 schoenebeck 424 break;
1640     }
1641     case 64: { // sustain
1642 schoenebeck 769 if (itControlChangeEvent->Param.CC.Value >= 64 && !pEngineChannel->SustainPedal) {
1643 iliev 776 dmsg(4,("DAMPER (RIGHT) PEDAL DOWN\n"));
1644 schoenebeck 411 pEngineChannel->SustainPedal = true;
1645 schoenebeck 53
1646 iliev 716 #if !CONFIG_PROCESS_MUTED_CHANNELS
1647 schoenebeck 705 if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
1648 iliev 716 #endif
1649 schoenebeck 705
1650 schoenebeck 53 // cancel release process of voices if necessary
1651 schoenebeck 411 RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
1652 schoenebeck 473 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 schoenebeck 769 *itNewEvent = *itControlChangeEvent; // copy event to the key's own event list
1658 schoenebeck 473 itNewEvent->Type = Event::type_cancel_release; // transform event type
1659 schoenebeck 53 }
1660 schoenebeck 473 else dmsg(1,("Event pool emtpy!\n"));
1661 schoenebeck 53 }
1662     }
1663     }
1664 schoenebeck 769 if (itControlChangeEvent->Param.CC.Value < 64 && pEngineChannel->SustainPedal) {
1665 iliev 776 dmsg(4,("DAMPER (RIGHT) PEDAL UP\n"));
1666 schoenebeck 411 pEngineChannel->SustainPedal = false;
1667 schoenebeck 53
1668 iliev 716 #if !CONFIG_PROCESS_MUTED_CHANNELS
1669 schoenebeck 705 if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
1670 iliev 716 #endif
1671 schoenebeck 705
1672 schoenebeck 53 // release voices if their respective key is not pressed
1673 schoenebeck 411 RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
1674 schoenebeck 473 for (; iuiKey; ++iuiKey) {
1675     midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
1676 iliev 776 if (!pKey->KeyPressed && ShouldReleaseVoice(pEngineChannel, *iuiKey)) {
1677 schoenebeck 473 RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
1678     if (itNewEvent) {
1679 schoenebeck 769 *itNewEvent = *itControlChangeEvent; // copy event to the key's own event list
1680 schoenebeck 473 itNewEvent->Type = Event::type_release; // transform event type
1681 schoenebeck 53 }
1682 schoenebeck 473 else dmsg(1,("Event pool emtpy!\n"));
1683 schoenebeck 53 }
1684     }
1685     }
1686     break;
1687     }
1688 schoenebeck 829 case 65: { // portamento on / off
1689     KillAllVoices(pEngineChannel, itControlChangeEvent);
1690     pEngineChannel->PortamentoMode = itControlChangeEvent->Param.CC.Value >= 64;
1691     break;
1692     }
1693 iliev 776 case 66: { // sostenuto
1694     if (itControlChangeEvent->Param.CC.Value >= 64 && !pEngineChannel->SostenutoPedal) {
1695     dmsg(4,("SOSTENUTO (CENTER) PEDAL DOWN\n"));
1696     pEngineChannel->SostenutoPedal = true;
1697 schoenebeck 53
1698 iliev 776 #if !CONFIG_PROCESS_MUTED_CHANNELS
1699     if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
1700     #endif
1701 schoenebeck 53
1702 iliev 776 SostenutoKeyCount = 0;
1703     // Remeber the pressed keys
1704     RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
1705     for (; iuiKey; ++iuiKey) {
1706     midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
1707     if (pKey->KeyPressed && SostenutoKeyCount < 128) SostenutoKeys[SostenutoKeyCount++] = *iuiKey;
1708     }
1709     }
1710     if (itControlChangeEvent->Param.CC.Value < 64 && pEngineChannel->SostenutoPedal) {
1711     dmsg(4,("SOSTENUTO (CENTER) PEDAL UP\n"));
1712     pEngineChannel->SostenutoPedal = false;
1713    
1714     #if !CONFIG_PROCESS_MUTED_CHANNELS
1715     if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
1716     #endif
1717    
1718     // release voices if the damper pedal is up and their respective key is not pressed
1719     for (int i = 0; i < SostenutoKeyCount; i++) {
1720     midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[SostenutoKeys[i]];
1721     if (!pKey->KeyPressed && !pEngineChannel->SustainPedal) {
1722     RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
1723     if (itNewEvent) {
1724     *itNewEvent = *itControlChangeEvent; // copy event to the key's own event list
1725     itNewEvent->Type = Event::type_release; // transform event type
1726     }
1727     else dmsg(1,("Event pool emtpy!\n"));
1728     }
1729     }
1730     }
1731     break;
1732     }
1733 schoenebeck 1041 case 100: { // RPN controller LSB
1734     pEngineChannel->SetMidiRpnControllerLsb(itControlChangeEvent->Param.CC.Value);
1735     break;
1736     }
1737     case 101: { // RPN controller MSB
1738     pEngineChannel->SetMidiRpnControllerMsb(itControlChangeEvent->Param.CC.Value);
1739     break;
1740     }
1741 iliev 776
1742    
1743 schoenebeck 473 // Channel Mode Messages
1744    
1745     case 120: { // all sound off
1746 schoenebeck 769 KillAllVoices(pEngineChannel, itControlChangeEvent);
1747 schoenebeck 473 break;
1748     }
1749     case 121: { // reset all controllers
1750     pEngineChannel->ResetControllers();
1751     break;
1752     }
1753     case 123: { // all notes off
1754 schoenebeck 849 #if CONFIG_PROCESS_ALL_NOTES_OFF
1755 schoenebeck 769 ReleaseAllVoices(pEngineChannel, itControlChangeEvent);
1756 schoenebeck 849 #endif // CONFIG_PROCESS_ALL_NOTES_OFF
1757 schoenebeck 473 break;
1758     }
1759 schoenebeck 829 case 126: { // mono mode on
1760     KillAllVoices(pEngineChannel, itControlChangeEvent);
1761     pEngineChannel->SoloMode = true;
1762     break;
1763     }
1764     case 127: { // poly mode on
1765     KillAllVoices(pEngineChannel, itControlChangeEvent);
1766     pEngineChannel->SoloMode = false;
1767     break;
1768     }
1769 schoenebeck 473 }
1770 schoenebeck 1001
1771     // handle FX send controllers
1772     if (!pEngineChannel->fxSends.empty()) {
1773     for (int iFxSend = 0; iFxSend < pEngineChannel->GetFxSendCount(); iFxSend++) {
1774     FxSend* pFxSend = pEngineChannel->GetFxSend(iFxSend);
1775     if (pFxSend->MidiController() == itControlChangeEvent->Param.CC.Controller)
1776     pFxSend->SetLevel(itControlChangeEvent->Param.CC.Value);
1777 iliev 1108 pFxSend->SetInfoChanged(true);
1778 schoenebeck 1001 }
1779     }
1780 schoenebeck 53 }
1781    
1782     /**
1783 schoenebeck 244 * Reacts on MIDI system exclusive messages.
1784     *
1785 schoenebeck 271 * @param itSysexEvent - sysex data size and time stamp of the sysex event
1786 schoenebeck 244 */
1787 schoenebeck 271 void Engine::ProcessSysex(Pool<Event>::Iterator& itSysexEvent) {
1788 schoenebeck 970 RingBuffer<uint8_t,false>::NonVolatileReader reader = pSysexBuffer->get_non_volatile_reader();
1789 schoenebeck 244
1790     uint8_t exclusive_status, id;
1791     if (!reader.pop(&exclusive_status)) goto free_sysex_data;
1792     if (!reader.pop(&id)) goto free_sysex_data;
1793     if (exclusive_status != 0xF0) goto free_sysex_data;
1794    
1795     switch (id) {
1796     case 0x41: { // Roland
1797 schoenebeck 493 dmsg(3,("Roland Sysex\n"));
1798 schoenebeck 244 uint8_t device_id, model_id, cmd_id;
1799     if (!reader.pop(&device_id)) goto free_sysex_data;
1800     if (!reader.pop(&model_id)) goto free_sysex_data;
1801     if (!reader.pop(&cmd_id)) goto free_sysex_data;
1802     if (model_id != 0x42 /*GS*/) goto free_sysex_data;
1803     if (cmd_id != 0x12 /*DT1*/) goto free_sysex_data;
1804    
1805     // command address
1806     uint8_t addr[3]; // 2 byte addr MSB, followed by 1 byte addr LSB)
1807 schoenebeck 970 const RingBuffer<uint8_t,false>::NonVolatileReader checksum_reader = reader; // so we can calculate the check sum later
1808 schoenebeck 244 if (reader.read(&addr[0], 3) != 3) goto free_sysex_data;
1809     if (addr[0] == 0x40 && addr[1] == 0x00) { // System Parameters
1810 schoenebeck 493 dmsg(3,("\tSystem Parameter\n"));
1811 schoenebeck 244 }
1812     else if (addr[0] == 0x40 && addr[1] == 0x01) { // Common Parameters
1813 schoenebeck 493 dmsg(3,("\tCommon Parameter\n"));
1814 schoenebeck 244 }
1815     else if (addr[0] == 0x40 && (addr[1] & 0xf0) == 0x10) { // Part Parameters (1)
1816 schoenebeck 493 dmsg(3,("\tPart Parameter\n"));
1817     switch (addr[2]) {
1818 schoenebeck 244 case 0x40: { // scale tuning
1819 schoenebeck 493 dmsg(3,("\t\tScale Tuning\n"));
1820 schoenebeck 244 uint8_t scale_tunes[12]; // detuning of all 12 semitones of an octave
1821     if (reader.read(&scale_tunes[0], 12) != 12) goto free_sysex_data;
1822     uint8_t checksum;
1823 schoenebeck 493 if (!reader.pop(&checksum)) goto free_sysex_data;
1824 schoenebeck 563 #if CONFIG_ASSERT_GS_SYSEX_CHECKSUM
1825     if (GSCheckSum(checksum_reader, 12)) goto free_sysex_data;
1826     #endif // CONFIG_ASSERT_GS_SYSEX_CHECKSUM
1827 schoenebeck 244 for (int i = 0; i < 12; i++) scale_tunes[i] -= 64;
1828     AdjustScale((int8_t*) scale_tunes);
1829 schoenebeck 493 dmsg(3,("\t\t\tNew scale applied.\n"));
1830 schoenebeck 244 break;
1831     }
1832     }
1833     }
1834     else if (addr[0] == 0x40 && (addr[1] & 0xf0) == 0x20) { // Part Parameters (2)
1835     }
1836     else if (addr[0] == 0x41) { // Drum Setup Parameters
1837     }
1838     break;
1839     }
1840     }
1841    
1842     free_sysex_data: // finally free sysex data
1843 schoenebeck 271 pSysexBuffer->increment_read_ptr(itSysexEvent->Param.Sysex.Size);
1844 schoenebeck 244 }
1845    
1846     /**
1847     * Calculates the Roland GS sysex check sum.
1848     *
1849     * @param AddrReader - reader which currently points to the first GS
1850     * command address byte of the GS sysex message in
1851     * question
1852     * @param DataSize - size of the GS message data (in bytes)
1853     */
1854 schoenebeck 970 uint8_t Engine::GSCheckSum(const RingBuffer<uint8_t,false>::NonVolatileReader AddrReader, uint DataSize) {
1855     RingBuffer<uint8_t,false>::NonVolatileReader reader = AddrReader;
1856 schoenebeck 244 uint bytes = 3 /*addr*/ + DataSize;
1857     uint8_t addr_and_data[bytes];
1858     reader.read(&addr_and_data[0], bytes);
1859     uint8_t sum = 0;
1860     for (uint i = 0; i < bytes; i++) sum += addr_and_data[i];
1861     return 128 - sum % 128;
1862     }
1863    
1864     /**
1865     * Allows to tune each of the twelve semitones of an octave.
1866     *
1867     * @param ScaleTunes - detuning of all twelve semitones (in cents)
1868     */
1869     void Engine::AdjustScale(int8_t ScaleTunes[12]) {
1870     memcpy(&this->ScaleTuning[0], &ScaleTunes[0], 12); //TODO: currently not sample accurate
1871     }
1872    
1873     /**
1874 schoenebeck 473 * Releases all voices on an engine channel. All voices will go into
1875     * the release stage and thus it might take some time (e.g. dependant to
1876     * their envelope release time) until they actually die.
1877     *
1878     * @param pEngineChannel - engine channel on which all voices should be released
1879     * @param itReleaseEvent - event which caused this releasing of all voices
1880     */
1881     void Engine::ReleaseAllVoices(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itReleaseEvent) {
1882     RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
1883     while (iuiKey) {
1884     midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
1885     ++iuiKey;
1886     // append a 'release' event to the key's own event list
1887     RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
1888     if (itNewEvent) {
1889     *itNewEvent = *itReleaseEvent; // copy original event (to the key's event list)
1890     itNewEvent->Type = Event::type_release; // transform event type
1891     }
1892     else dmsg(1,("Event pool emtpy!\n"));
1893     }
1894     }
1895    
1896     /**
1897     * Kills all voices on an engine channel as soon as possible. Voices
1898     * won't get into release state, their volume level will be ramped down
1899     * as fast as possible.
1900     *
1901     * @param pEngineChannel - engine channel on which all voices should be killed
1902     * @param itKillEvent - event which caused this killing of all voices
1903     */
1904     void Engine::KillAllVoices(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itKillEvent) {
1905     RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
1906     RTList<uint>::Iterator end = pEngineChannel->pActiveKeys->end();
1907     while (iuiKey != end) { // iterate through all active keys
1908     midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
1909     ++iuiKey;
1910     RTList<Voice>::Iterator itVoice = pKey->pActiveVoices->first();
1911     RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();
1912     for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
1913     itVoice->Kill(itKillEvent);
1914 schoenebeck 663 --VoiceSpawnsLeft; //FIXME: just a temporary workaround, we should check the cause in StealVoice() instead
1915 schoenebeck 473 }
1916     }
1917     }
1918    
1919 iliev 776 /**
1920     * Determines whether the specified voice should be released.
1921     *
1922     * @param pEngineChannel - The engine channel on which the voice should be checked
1923     * @param Key - The key number
1924     * @returns true if the specified should be released, false otherwise.
1925     */
1926     bool Engine::ShouldReleaseVoice(EngineChannel* pEngineChannel, int Key) {
1927     if (pEngineChannel->SustainPedal) return false;
1928    
1929     if (pEngineChannel->SostenutoPedal) {
1930     for (int i = 0; i < SostenutoKeyCount; i++)
1931     if (Key == SostenutoKeys[i]) return false;
1932     }
1933    
1934     return true;
1935     }
1936    
1937 schoenebeck 53 uint Engine::VoiceCount() {
1938     return ActiveVoiceCount;
1939     }
1940    
1941     uint Engine::VoiceCountMax() {
1942     return ActiveVoiceCountMax;
1943     }
1944    
1945     bool Engine::DiskStreamSupported() {
1946     return true;
1947     }
1948    
1949     uint Engine::DiskStreamCount() {
1950     return (pDiskThread) ? pDiskThread->ActiveStreamCount : 0;
1951     }
1952    
1953     uint Engine::DiskStreamCountMax() {
1954     return (pDiskThread) ? pDiskThread->ActiveStreamCountMax : 0;
1955     }
1956    
1957     String Engine::DiskStreamBufferFillBytes() {
1958     return pDiskThread->GetBufferFillBytes();
1959     }
1960    
1961     String Engine::DiskStreamBufferFillPercentage() {
1962     return pDiskThread->GetBufferFillPercentage();
1963     }
1964    
1965 senkov 112 String Engine::EngineName() {
1966 schoenebeck 475 return LS_GIG_ENGINE_NAME;
1967 senkov 112 }
1968    
1969 schoenebeck 53 String Engine::Description() {
1970     return "Gigasampler Engine";
1971     }
1972    
1973     String Engine::Version() {
1974 schoenebeck 1321 String s = "$Revision: 1.80 $";
1975 schoenebeck 123 return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword
1976 schoenebeck 53 }
1977    
1978 schoenebeck 947 InstrumentManager* Engine::GetInstrumentManager() {
1979     return &instruments;
1980     }
1981    
1982 persson 831 // static constant initializers
1983     const float* Engine::VolumeCurve(InitVolumeCurve());
1984     const float* Engine::PanCurve(InitPanCurve());
1985 persson 832 const float* Engine::CrossfadeCurve(InitCrossfadeCurve());
1986 persson 831
1987     float* Engine::InitVolumeCurve() {
1988     // line-segment approximation
1989     const float segments[] = {
1990     0, 0, 2, 0.0046, 16, 0.016, 31, 0.051, 45, 0.115, 54.5, 0.2,
1991     64.5, 0.39, 74, 0.74, 92, 1.03, 114, 1.94, 119.2, 2.2, 127, 2.2
1992     };
1993     return InitCurve(segments);
1994     }
1995    
1996     float* Engine::InitPanCurve() {
1997     // line-segment approximation
1998     const float segments[] = {
1999     0, 0, 1, 0,
2000     2, 0.05, 31.5, 0.7, 51, 0.851, 74.5, 1.12,
2001     127, 1.41, 128, 1.41
2002     };
2003     return InitCurve(segments, 129);
2004     }
2005    
2006 persson 832 float* Engine::InitCrossfadeCurve() {
2007     // line-segment approximation
2008     const float segments[] = {
2009     0, 0, 1, 0.03, 10, 0.1, 51, 0.58, 127, 1
2010     };
2011     return InitCurve(segments);
2012     }
2013    
2014 persson 831 float* Engine::InitCurve(const float* segments, int size) {
2015     float* y = new float[size];
2016     for (int x = 0 ; x < size ; x++) {
2017     if (x > segments[2]) segments += 2;
2018     y[x] = segments[1] + (x - segments[0]) *
2019     (segments[3] - segments[1]) / (segments[2] - segments[0]);
2020     }
2021     return y;
2022     }
2023    
2024 persson 1038 /**
2025     * Changes the instrument for an engine channel.
2026     *
2027     * @param pEngineChannel - engine channel on which the instrument
2028     * should be changed
2029     * @param pInstrument - new instrument
2030     * @returns a list of dimension regions from the old instrument
2031     * that are still in use
2032     */
2033     ::gig::DimensionRegion** Engine::ChangeInstrument(EngineChannel* pEngineChannel, ::gig::Instrument* pInstrument) {
2034     instrument_change_command_t command;
2035     command.pEngineChannel = pEngineChannel;
2036     command.pInstrument = pInstrument;
2037     InstrumentChangeQueue->push(&command);
2038    
2039     // wait for the audio thread to confirm that the instrument
2040     // change has been done
2041     instrument_change_reply_t reply;
2042     while (InstrumentChangeReplyQueue->pop(&reply) == 0) {
2043     usleep(10000);
2044     }
2045     return pDimRegionsInUse;
2046     }
2047    
2048 schoenebeck 53 }} // namespace LinuxSampler::gig

  ViewVC Help
Powered by ViewVC