/[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 1424 - (hide annotations) (download)
Sun Oct 14 22:00:17 2007 UTC (16 years, 5 months ago) by schoenebeck
File size: 99832 byte(s)
* code cleanup:
- global.h now only covers global definitions that are needed for the C++
  API header files, all implementation internal global definitions are now
  in global_private.h
- atomic.h is not exposed to the C++ API anymore (replaced the references
  in SynchronizedConfig.h for this with local definitions)
- no need to include config.h anymore for using LS's API header files
- DB instruments classes are not exposed to the C++ API
- POSIX callback functions of Thread.h are hidden
- the (optional) gig Engine benchmark compiles again
- updated Doxyfile.in
- fixed warnings in API doc generation
* preparations for release 0.5.0

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

  ViewVC Help
Powered by ViewVC