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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.56  
changed lines
  Added in v.1321

  ViewVC Help
Powered by ViewVC