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

Legend:
Removed from v.123  
changed lines
  Added in v.1764

  ViewVC Help
Powered by ViewVC