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

Legend:
Removed from v.80  
changed lines
  Added in v.1893

  ViewVC Help
Powered by ViewVC