/[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 239 by schoenebeck, Sun Sep 12 14:48:19 2004 UTC revision 1762 by schoenebeck, Fri Aug 29 17:33:02 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;  
         InstrumentStat = -1;  
   
         AudioDeviceChannelLeft  = -1;  
         AudioDeviceChannelRight = -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 104  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 117  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;
         GlobalVolume        = 1.0;  
   
         // set all MIDI controller values to zero  
         memset(ControllerTable, 0x00, 128);  
296    
297          // reset key info          // reset voice stealing parameters
298          for (uint i = 0; i < 128; i++) {          pVoiceStealingQueue->clear();
299              pMIDIKeyInfo[i].pActiveVoices->clear();          itLastStolenVoice          = RTList<Voice>::Iterator();
300              pMIDIKeyInfo[i].pEvents->clear();          itLastStolenVoiceGlobally  = RTList<Voice>::Iterator();
301              pMIDIKeyInfo[i].KeyPressed = false;          iuiLastStolenKey           = RTList<uint>::Iterator();
302              pMIDIKeyInfo[i].Active     = false;          iuiLastStolenKeyGlobally   = RTList<uint>::Iterator();
303              pMIDIKeyInfo[i].pSelf      = NULL;          pLastStolenChannel         = NULL;
         }  
   
         // reset all key groups  
         map<uint,uint*>::iterator iter = ActiveKeyGroups.begin();  
         for (; iter != ActiveKeyGroups.end(); iter++) iter->second = 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);  
         }  
   
         InstrumentFile = FileName;  
         InstrumentIdx = Instrument;  
         InstrumentStat = 0;  
   
         // delete all key groups  
         ActiveKeyGroups.clear();  
   
         // request gig instrument from instrument manager  
         try {  
             instrument_id_t instrid;  
             instrid.FileName    = FileName;  
             instrid.iInstrument = Instrument;  
             pInstrument = Instruments.Borrow(instrid, this);  
             if (!pInstrument) {  
                 InstrumentStat = -1;  
                 dmsg(1,("no instrument loaded!!!\n"));  
                 exit(EXIT_FAILURE);  
             }  
         }  
         catch (RIFF::Exception e) {  
             InstrumentStat = -2;  
             String msg = "gig::Engine error: Failed to load instrument, cause: " + e.Message;  
             throw LinuxSamplerException(msg);  
         }  
         catch (InstrumentResourceManagerException e) {  
             InstrumentStat = -3;  
             String msg = "gig::Engine error: Failed to load instrument, cause: " + e.Message();  
             throw LinuxSamplerException(msg);  
         }  
         catch (...) {  
             InstrumentStat = -4;  
             throw LinuxSamplerException("gig::Engine error: Failed to load instrument, cause: Unknown exception while trying to parse gig file.");  
         }  
   
         // rebuild ActiveKeyGroups map with key groups of current instrument  
         for (::gig::Region* pRegion = pInstrument->GetFirstRegion(); pRegion; pRegion = pInstrument->GetNextRegion())  
             if (pRegion->KeyGroup) ActiveKeyGroups[pRegion->KeyGroup] = NULL;  
   
         InstrumentStat = 100;  
   
         // 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; //TODO: there are couple of engine parameters we should update here as well if the instrument was updated (see LoadInstrument())  
         Enable();  
     }  
   
344      void Engine::Connect(AudioOutputDevice* pAudioOut) {      void Engine::Connect(AudioOutputDevice* pAudioOut) {
345          pAudioOutputDevice = pAudioOut;          pAudioOutputDevice = pAudioOut;
346    
# Line 290  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->AudioDeviceChannelLeft  = 0;          this->MaxSamplesPerCycle = pAudioOutputDevice->MaxSamplesPerCycle();
359          this->AudioDeviceChannelRight = 1;          this->SampleRate         = pAudioOutputDevice->SampleRate();
360          this->pOutputLeft             = pAudioOutputDevice->Channel(0)->Buffer();  
361          this->pOutputRight            = pAudioOutputDevice->Channel(1)->Buffer();          MinFadeOutSamples = int(double(SampleRate) * CONFIG_EG_MIN_RELEASE_TIME) - 1;
362          this->MaxSamplesPerCycle      = pAudioOutputDevice->MaxSamplesPerCycle();          if (MaxSamplesPerCycle < MinFadeOutSamples) {
363          this->SampleRate              = pAudioOutputDevice->SampleRate();              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;
392              dmsg(3,("d"));              dmsg(3,("d"));
393          }          }
394          pVoicePool->clear();          pVoicePool->clear();
# Line 321  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              AudioDeviceChannelLeft  = -1;          // process request for suspending one region
418              AudioDeviceChannelRight = -1;          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       *  Let this engine proceed to render the given amount of sample points. The       * Called by the engine's (audio) thread once per cycle to check if
485       *  calculated audio data of all voices of this engine will be placed into       * streams of voices that were killed due to suspension request have
486       *  the engine's audio sum buffer which has to be copied and eventually be       * finally really been deleted by the disk thread.
487       *  converted to the appropriate value range by the audio output class (e.g.       */
488       *  AlsaIO or JackIO) right after.      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.
561         * The engine will iterate through all engine channels and render audio
562         * for each engine channel independently. The calculated audio data of
563         * all voices of each engine channel will be placed into the audio sum
564         * 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              return 0;              return 0;
577          }          }
578          if (!pInstrument) {  
579              dmsg(5,("gig::Engine: no instrument loaded\n"));          // process requests for suspending / resuming regions (i.e. to avoid
580              return 0;          // crashes while these regions are modified by an instrument editor)
581            ProcessSuspensionsChanges();
582    
583            // update time of start and end of this audio fragment (as events' time stamps relate to this)
584            pEventGenerator->UpdateFragmentTime(Samples);
585    
586            // We only allow a maximum of CONFIG_MAX_VOICES voices to be spawned
587            // in each audio fragment. All subsequent request for spawning new
588            // voices in the same audio fragment will be ignored.
589            VoiceSpawnsLeft = CONFIG_MAX_VOICES;
590    
591            // get all events from the engine's global input event queue which belong to the current fragment
592            // (these are usually just SysEx messages)
593            ImportEvents(Samples);
594    
595            // process engine global events (these are currently only MIDI System Exclusive messages)
596            {
597                RTList<Event>::Iterator itEvent = pGlobalEvents->first();
598                RTList<Event>::Iterator end     = pGlobalEvents->end();
599                for (; itEvent != end; ++itEvent) {
600                    switch (itEvent->Type) {
601                        case Event::type_sysex:
602                            dmsg(5,("Engine: Sysex received\n"));
603                            ProcessSysex(itEvent);
604                            break;
605                    }
606                }
607          }          }
608    
609            // reset internal voice counter (just for statistic of active voices)
610            ActiveVoiceCountTemp = 0;
611    
612          // empty the event lists for the new fragment          // handle instrument change commands
613          pEvents->clear();          bool instrumentChanged = false;
614          pCCEvents->clear();          for (int i = 0; i < engineChannels.size(); i++) {
615          for (uint i = 0; i < Event::destination_count; i++) {              EngineChannel* pEngineChannel = engineChannels[i];
616              pSynthesisEvents[i]->clear();  
617                // as we're going to (carefully) write some status to the
618                // synchronized struct, we cast away the const
619                EngineChannel::instrument_change_command_t& cmd =
620                    const_cast<EngineChannel::instrument_change_command_t&>(pEngineChannel->InstrumentChangeCommandReader.Lock());
621    
622                pEngineChannel->pDimRegionsInUse = cmd.pDimRegionsInUse;
623                pEngineChannel->pDimRegionsInUse->clear();
624    
625                if (cmd.bChangeInstrument) {
626                    // change instrument
627                    dmsg(5,("Engine: instrument change command received\n"));
628                    cmd.bChangeInstrument = false;
629                    pEngineChannel->pInstrument = cmd.pInstrument;
630                    instrumentChanged = true;
631    
632                    // Iterate through all active voices and mark them as
633                    // "orphans", which means that the dimension regions
634                    // and samples they use should be released to the
635                    // instrument resource manager when the voices die.
636                    int i = 0;
637                    RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
638                    RTList<uint>::Iterator end    = pEngineChannel->pActiveKeys->end();
639                    while (iuiKey != end) { // iterate through all active keys
640                        midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
641                        ++iuiKey;
642    
643                        RTList<Voice>::Iterator itVoice     = pKey->pActiveVoices->first();
644                        RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();
645                        for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
646                            itVoice->Orphan = true;
647                        }
648                    }
649                }
650            }
651            if (instrumentChanged) {
652                //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
653                ResetSuspendedRegions();
654          }          }
655    
656          // read and copy events from input queue          // handle events on all engine channels
657          Event event = pEventGenerator->CreateEvent();          for (int i = 0; i < engineChannels.size(); i++) {
658          while (true) {              ProcessEvents(engineChannels[i], Samples);
             if (!pEventQueue->pop(&event)) break;  
             pEvents->alloc_assign(event);  
659          }          }
660    
661            // render all 'normal', active voices on all engine channels
662            for (int i = 0; i < engineChannels.size(); i++) {
663                RenderActiveVoices(engineChannels[i], Samples);
664            }
665    
666          // 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
667          pEventGenerator->UpdateFragmentTime(Samples);          RenderStolenVoices(Samples);
668    
669            // handle audio routing for engine channels with FX sends
670            for (int i = 0; i < engineChannels.size(); i++) {
671                if (engineChannels[i]->fxSends.empty()) continue; // ignore if no FX sends
672                RouteAudio(engineChannels[i], Samples);
673            }
674    
675          // process events          // handle cleanup on all engine channels for the next audio fragment
676          Event* pNextEvent = pEvents->first();          for (int i = 0; i < engineChannels.size(); i++) {
677          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;  
             }  
678          }          }
679    
680    
681          // render audio from all active voices          // empty the engine's event list for the next audio fragment
682          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();  
683    
684                  // now render current voice          // reset voice stealing for the next audio fragment
685                  pVoice->Render(Samples);          pVoiceStealingQueue->clear();
686                  if (pVoice->IsActive()) active_voices++; // still active  
687                  else { // voice reached end, is now inactive          // just some statistics about this engine instance
688                      KillVoiceImmediately(pVoice); // remove voice from the list of active voices          ActiveVoiceCount = ActiveVoiceCountTemp;
689            if (ActiveVoiceCount > ActiveVoiceCountMax) ActiveVoiceCountMax = ActiveVoiceCount;
690    
691            // in case regions were previously suspended and we killed voices
692            // with disk streams due to that, check if those streams have finally
693            // been deleted by the disk thread
694            if (iPendingStreamDeletions) ProcessPendingStreamDeletions();
695    
696            for (int i = 0; i < engineChannels.size(); i++) {
697                engineChannels[i]->InstrumentChangeCommandReader.Unlock();
698            }
699            FrameTime += Samples;
700    
701            return 0;
702        }
703    
704        /**
705         * Dispatch and handle all events in this audio fragment for the given
706         * engine channel.
707         *
708         * @param pEngineChannel - engine channel on which events should be
709         *                         processed
710         * @param Samples        - amount of sample points to be processed in
711         *                         this audio fragment cycle
712         */
713        void Engine::ProcessEvents(EngineChannel* pEngineChannel, uint Samples) {
714            // get all events from the engine channels's input event queue which belong to the current fragment
715            // (these are the common events like NoteOn, NoteOff, ControlChange, etc.)
716            pEngineChannel->ImportEvents(Samples);
717    
718            // process events
719            {
720                RTList<Event>::Iterator itEvent = pEngineChannel->pEvents->first();
721                RTList<Event>::Iterator end     = pEngineChannel->pEvents->end();
722                for (; itEvent != end; ++itEvent) {
723                    switch (itEvent->Type) {
724                        case Event::type_note_on:
725                            dmsg(5,("Engine: Note on received\n"));
726                            ProcessNoteOn((EngineChannel*)itEvent->pEngineChannel, itEvent);
727                            break;
728                        case Event::type_note_off:
729                            dmsg(5,("Engine: Note off received\n"));
730                            ProcessNoteOff((EngineChannel*)itEvent->pEngineChannel, itEvent);
731                            break;
732                        case Event::type_control_change:
733                            dmsg(5,("Engine: MIDI CC received\n"));
734                            ProcessControlChange((EngineChannel*)itEvent->pEngineChannel, itEvent);
735                            break;
736                        case Event::type_pitchbend:
737                            dmsg(5,("Engine: Pitchbend received\n"));
738                            ProcessPitchbend((EngineChannel*)itEvent->pEngineChannel, itEvent);
739                            break;
740                  }                  }
741              }              }
             pKey->pEvents->clear(); // free all events on the key  
742          }          }
743    
744            // reset voice stealing for the next engine channel (or next audio fragment)
745            itLastStolenVoice         = RTList<Voice>::Iterator();
746            itLastStolenVoiceGlobally = RTList<Voice>::Iterator();
747            iuiLastStolenKey          = RTList<uint>::Iterator();
748            iuiLastStolenKeyGlobally  = RTList<uint>::Iterator();
749            pLastStolenChannel        = NULL;
750        }
751    
752          // write that to the disk thread class so that it can print it      /**
753          // on the console for debugging purposes       * Render all 'normal' voices (that is voices which were not stolen in
754          ActiveVoiceCount = active_voices;       * this fragment) on the given engine channel.
755          if (ActiveVoiceCount > ActiveVoiceCountMax) ActiveVoiceCountMax = ActiveVoiceCount;       *
756         * @param pEngineChannel - engine channel on which audio should be
757         *                         rendered
758         * @param Samples        - amount of sample points to be rendered in
759         *                         this audio fragment cycle
760         */
761        void Engine::RenderActiveVoices(EngineChannel* pEngineChannel, uint Samples) {
762            #if !CONFIG_PROCESS_MUTED_CHANNELS
763            if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
764            #endif
765    
766            uint voiceCount = 0;
767            uint streamCount = 0;
768            RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
769            RTList<uint>::Iterator end    = pEngineChannel->pActiveKeys->end();
770            while (iuiKey != end) { // iterate through all active keys
771                midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
772                ++iuiKey;
773    
774                RTList<Voice>::Iterator itVoice     = pKey->pActiveVoices->first();
775                RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();
776                for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
777                    // now render current voice
778                    itVoice->Render(Samples);
779                    if (itVoice->IsActive()) { // still active
780                        if (!itVoice->Orphan) {
781                            *(pEngineChannel->pDimRegionsInUse->allocAppend()) = itVoice->pDimRgn;
782                        }
783                        ActiveVoiceCountTemp++;
784                        voiceCount++;
785    
786                        if (itVoice->PlaybackState == Voice::playback_state_disk) {
787                            if ((itVoice->DiskStreamRef).State == Stream::state_active) streamCount++;
788                        }
789                    }  else { // voice reached end, is now inactive
790                        FreeVoice(pEngineChannel, itVoice); // remove voice from the list of active voices
791                    }
792                }
793            }
794    
795          return 0;          pEngineChannel->SetVoiceCount(voiceCount);
796            pEngineChannel->SetDiskStreamCount(streamCount);
797      }      }
798    
799      /**      /**
800       *  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
801       *  voice for the given key.       * fragment) on the given engine channel. Stolen voices are rendered
802         * after all normal voices have been rendered; this is needed to render
803         * audio of those voices which were selected for voice stealing until
804         * the point were the stealing (that is the take over of the voice)
805         * actually happened.
806       *       *
807       *  @param Key      - MIDI key number of the triggered key       * @param pEngineChannel - engine channel on which audio should be
808       *  @param Velocity - MIDI velocity value of the triggered key       *                         rendered
809         * @param Samples        - amount of sample points to be rendered in
810         *                         this audio fragment cycle
811       */       */
812      void Engine::SendNoteOn(uint8_t Key, uint8_t Velocity) {      void Engine::RenderStolenVoices(uint Samples) {
813          Event event    = pEventGenerator->CreateEvent();          RTList<Event>::Iterator itVoiceStealEvent = pVoiceStealingQueue->first();
814          event.Type     = Event::type_note_on;          RTList<Event>::Iterator end               = pVoiceStealingQueue->end();
815          event.Key      = Key;          for (; itVoiceStealEvent != end; ++itVoiceStealEvent) {
816          event.Velocity = Velocity;              EngineChannel* pEngineChannel = (EngineChannel*) itVoiceStealEvent->pEngineChannel;
817          if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);              if (!pEngineChannel->pInstrument) continue; // ignore if no instrument loaded
818          else dmsg(1,("Engine: Input event queue full!"));              Pool<Voice>::Iterator itNewVoice =
819                    LaunchVoice(pEngineChannel, itVoiceStealEvent, itVoiceStealEvent->Param.Note.Layer, itVoiceStealEvent->Param.Note.ReleaseTrigger, false, false);
820                if (itNewVoice) {
821                    itNewVoice->Render(Samples);
822                    if (itNewVoice->IsActive()) { // still active
823                        *(pEngineChannel->pDimRegionsInUse->allocAppend()) = itNewVoice->pDimRgn;
824                        ActiveVoiceCountTemp++;
825                        pEngineChannel->SetVoiceCount(pEngineChannel->GetVoiceCount() + 1);
826    
827                        if (itNewVoice->PlaybackState == Voice::playback_state_disk) {
828                            if (itNewVoice->DiskStreamRef.State == Stream::state_active) {
829                                pEngineChannel->SetDiskStreamCount(pEngineChannel->GetDiskStreamCount() + 1);
830                            }
831                        }
832                    } else { // voice reached end, is now inactive
833                        FreeVoice(pEngineChannel, itNewVoice); // remove voice from the list of active voices
834                    }
835                }
836                else dmsg(1,("gig::Engine: ERROR, voice stealing didn't work out!\n"));
837    
838                // we need to clear the key's event list explicitly here in case key was never active
839                midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[itVoiceStealEvent->Param.Note.Key];
840                pKey->VoiceTheftsQueued--;
841                if (!pKey->Active && !pKey->VoiceTheftsQueued) pKey->pEvents->clear();
842            }
843      }      }
844    
845      /**      /**
846       *  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
847       *  voice(s) on the given key.       * channels. In this particular case, engine channel local buffers are
848         * used to render and mix all voices to. This method is responsible for
849         * copying the audio data from those local buffers to the master audio
850         * output channels as well as to the FX send audio output channels with
851         * their respective FX send levels.
852       *       *
853       *  @param Key      - MIDI key number of the released key       * @param pEngineChannel - engine channel from which audio should be
854       *  @param Velocity - MIDI release velocity value of the released key       *                         routed
855         * @param Samples        - amount of sample points to be routed in
856         *                         this audio fragment cycle
857       */       */
858      void Engine::SendNoteOff(uint8_t Key, uint8_t Velocity) {      void Engine::RouteAudio(EngineChannel* pEngineChannel, uint Samples) {
859          Event event    = pEventGenerator->CreateEvent();          // route dry signal
860          event.Type     = Event::type_note_off;          {
861          event.Key      = Key;              AudioChannel* pDstL = pAudioOutputDevice->Channel(pEngineChannel->AudioDeviceChannelLeft);
862          event.Velocity = Velocity;              AudioChannel* pDstR = pAudioOutputDevice->Channel(pEngineChannel->AudioDeviceChannelRight);
863          if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);              pEngineChannel->pChannelLeft->MixTo(pDstL, Samples);
864          else dmsg(1,("Engine: Input event queue full!"));              pEngineChannel->pChannelRight->MixTo(pDstR, Samples);
865            }
866            // route FX send signal
867            {
868                for (int iFxSend = 0; iFxSend < pEngineChannel->GetFxSendCount(); iFxSend++) {
869                    FxSend* pFxSend = pEngineChannel->GetFxSend(iFxSend);
870                    for (int iChan = 0; iChan < 2; ++iChan) {
871                        AudioChannel* pSource =
872                            (iChan)
873                                ? pEngineChannel->pChannelRight
874                                : pEngineChannel->pChannelLeft;
875                        const int iDstChan = pFxSend->DestinationChannel(iChan);
876                        if (iDstChan < 0) {
877                            dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination channel (%d->%d)", ((iChan) ? "R" : "L"), iChan, iDstChan));
878                            goto channel_cleanup;
879                        }
880                        AudioChannel* pDstChan = NULL;
881                        if (pFxSend->DestinationMasterEffectChain() >= 0) { // fx send routed to an internal master effect
882                            EffectChain* pEffectChain =
883                                pAudioOutputDevice->MasterEffectChain(
884                                    pFxSend->DestinationMasterEffectChain()
885                                );
886                            if (!pEffectChain) {
887                                dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination effect chain %d", ((iChan) ? "R" : "L"), pFxSend->DestinationMasterEffectChain()));
888                                goto channel_cleanup;
889                            }
890                            Effect* pEffect =
891                                pEffectChain->GetEffect(
892                                    pFxSend->DestinationMasterEffect()
893                                );
894                            if (!pEffect) {
895                                dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination effect %d of effect chain %d", ((iChan) ? "R" : "L"), pFxSend->DestinationMasterEffect(), pFxSend->DestinationMasterEffectChain()));
896                                goto channel_cleanup;
897                            }
898                            pDstChan = pEffect->InputChannel(iDstChan);
899                        } else { // FX send routed directly to an audio output channel
900                            pDstChan = pAudioOutputDevice->Channel(iDstChan);
901                        }
902                        if (!pDstChan) {
903                            dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination channel (%d->%d)", ((iChan) ? "R" : "L"), iChan, iDstChan));
904                            goto channel_cleanup;
905                        }
906                        pSource->MixTo(pDstChan, Samples, pFxSend->Level());
907                    }
908                }
909            }
910            channel_cleanup:
911            // reset buffers with silence (zero out) for the next audio cycle
912            pEngineChannel->pChannelLeft->Clear();
913            pEngineChannel->pChannelRight->Clear();
914      }      }
915    
916      /**      /**
917       *  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
918       *  the pitch value for all voices.       * the list of active keys and clear all event lists on that engine
919         * channel.
920       *       *
921       *  @param Pitch - MIDI pitch value (-8192 ... +8191)       * @param pEngineChannel - engine channel to cleanup
922       */       */
923      void Engine::SendPitchbend(int Pitch) {      void Engine::PostProcess(EngineChannel* pEngineChannel) {
924          Event event = pEventGenerator->CreateEvent();          // free all keys which have no active voices left
925          event.Type  = Event::type_pitchbend;          {
926          event.Pitch = Pitch;              RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
927          if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);              RTList<uint>::Iterator end    = pEngineChannel->pActiveKeys->end();
928          else dmsg(1,("Engine: Input event queue full!"));              while (iuiKey != end) { // iterate through all active keys
929                    midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
930                    ++iuiKey;
931                    if (pKey->pActiveVoices->isEmpty()) FreeKey(pEngineChannel, pKey);
932                    #if CONFIG_DEVMODE
933                    else { // just a sanity check for debugging
934                        RTList<Voice>::Iterator itVoice     = pKey->pActiveVoices->first();
935                        RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();
936                        for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
937                            if (itVoice->itKillEvent) {
938                                dmsg(1,("gig::Engine: ERROR, killed voice survived !!!\n"));
939                            }
940                        }
941                    }
942                    #endif // CONFIG_DEVMODE
943                }
944            }
945    
946            // empty the engine channel's own event lists
947            pEngineChannel->ClearEventLists();
948      }      }
949    
950      /**      /**
951       *  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
952       *  continuous controller value has changed.       *  exclusive message has arrived.
953       *       *
954       *  @param Controller - MIDI controller number of the occured control change       *  @param pData - pointer to sysex data
955       *  @param Value      - value of the control change       *  @param Size  - lenght of sysex data (in bytes)
956         *  @param pSender - the MIDI input port on which the SysEx message was
957         *                   received
958       */       */
959      void Engine::SendControlChange(uint8_t Controller, uint8_t Value) {      void Engine::SendSysex(void* pData, uint Size, MidiInputPort* pSender) {
960          Event event      = pEventGenerator->CreateEvent();          Event event             = pEventGenerator->CreateEvent();
961          event.Type       = Event::type_control_change;          event.Type              = Event::type_sysex;
962          event.Controller = Controller;          event.Param.Sysex.Size  = Size;
963          event.Value      = Value;          event.pEngineChannel    = NULL; // as Engine global event
964          if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);          event.pMidiInputPort    = pSender;
965            if (pEventQueue->write_space() > 0) {
966                if (pSysexBuffer->write_space() >= Size) {
967                    // copy sysex data to input buffer
968                    uint toWrite = Size;
969                    uint8_t* pPos = (uint8_t*) pData;
970                    while (toWrite) {
971                        const uint writeNow = RTMath::Min(toWrite, pSysexBuffer->write_space_to_end());
972                        pSysexBuffer->write(pPos, writeNow);
973                        toWrite -= writeNow;
974                        pPos    += writeNow;
975    
976                    }
977                    // finally place sysex event into input event queue
978                    pEventQueue->push(&event);
979                }
980                else dmsg(1,("Engine: Sysex message too large (%d byte) for input buffer (%d byte)!",Size,CONFIG_SYSEX_BUFFER_SIZE));
981            }
982          else dmsg(1,("Engine: Input event queue full!"));          else dmsg(1,("Engine: Input event queue full!"));
983      }      }
984    
985      /**      /**
986       *  Assigns and triggers a new voice for the respective MIDI key.       *  Assigns and triggers a new voice for the respective MIDI key.
987       *       *
988       *  @param pNoteOnEvent - key, velocity and time stamp of the event       *  @param pEngineChannel - engine channel on which this event occured on
989         *  @param itNoteOnEvent - key, velocity and time stamp of the event
990       */       */
991      void Engine::ProcessNoteOn(Event* pNoteOnEvent) {      void Engine::ProcessNoteOn(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent) {
992          midi_key_info_t* pKey = &pMIDIKeyInfo[pNoteOnEvent->Key];          #if !CONFIG_PROCESS_MUTED_CHANNELS
993            if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
994            #endif
995    
996            if (!pEngineChannel->pInstrument) return; // ignore if no instrument loaded
997    
998            //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
999            itNoteOnEvent->Param.Note.Key += pEngineChannel->GlobalTranspose;
1000    
1001            const int key = itNoteOnEvent->Param.Note.Key;
1002            midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[key];
1003    
1004            // move note on event to the key's own event list
1005            RTList<Event>::Iterator itNoteOnEventOnKeyList = itNoteOnEvent.moveToEndOf(pKey->pEvents);
1006    
1007            // if Solo Mode then kill all already active voices
1008            if (pEngineChannel->SoloMode) {
1009                Pool<uint>::Iterator itYoungestKey = pEngineChannel->pActiveKeys->last();
1010                if (itYoungestKey) {
1011                    const int iYoungestKey = *itYoungestKey;
1012                    const midi_key_info_t* pOtherKey = &pEngineChannel->pMIDIKeyInfo[iYoungestKey];
1013                    if (pOtherKey->Active) {
1014                        // get final portamento position of currently active voice
1015                        if (pEngineChannel->PortamentoMode) {
1016                            RTList<Voice>::Iterator itVoice = pOtherKey->pActiveVoices->last();
1017                            if (itVoice) itVoice->UpdatePortamentoPos(itNoteOnEventOnKeyList);
1018                        }
1019                        // kill all voices on the (other) key
1020                        RTList<Voice>::Iterator itVoiceToBeKilled = pOtherKey->pActiveVoices->first();
1021                        RTList<Voice>::Iterator end               = pOtherKey->pActiveVoices->end();
1022                        for (; itVoiceToBeKilled != end; ++itVoiceToBeKilled) {
1023                            if (itVoiceToBeKilled->Type != Voice::type_release_trigger)
1024                                itVoiceToBeKilled->Kill(itNoteOnEventOnKeyList);
1025                        }
1026                    }
1027                }
1028                // set this key as 'currently active solo key'
1029                pEngineChannel->SoloKey = key;
1030            }
1031    
1032            // Change key dimension value if key is in keyswitching area
1033            {
1034                const ::gig::Instrument* pInstrument = pEngineChannel->pInstrument;
1035                if (key >= pInstrument->DimensionKeyRange.low && key <= pInstrument->DimensionKeyRange.high)
1036                    pEngineChannel->CurrentKeyDimension = float(key - pInstrument->DimensionKeyRange.low) /
1037                        (pInstrument->DimensionKeyRange.high - pInstrument->DimensionKeyRange.low + 1);
1038            }
1039    
1040          pKey->KeyPressed = true; // the MIDI key was now pressed down          pKey->KeyPressed = true; // the MIDI key was now pressed down
1041            pKey->Velocity   = itNoteOnEventOnKeyList->Param.Note.Velocity;
1042            pKey->NoteOnTime = FrameTime + itNoteOnEventOnKeyList->FragmentPos(); // will be used to calculate note length
1043    
1044          // cancel release process of voices on this key if needed          // cancel release process of voices on this key if needed
1045          if (pKey->Active && !SustainPedal) {          if (pKey->Active && !pEngineChannel->SustainPedal) {
1046              Event* pCancelReleaseEvent = pKey->pEvents->alloc();              RTList<Event>::Iterator itCancelReleaseEvent = pKey->pEvents->allocAppend();
1047              if (pCancelReleaseEvent) {              if (itCancelReleaseEvent) {
1048                  *pCancelReleaseEvent = *pNoteOnEvent;                  *itCancelReleaseEvent = *itNoteOnEventOnKeyList;         // copy event
1049                  pCancelReleaseEvent->Type = Event::type_cancel_release; // transform event type                  itCancelReleaseEvent->Type = Event::type_cancel_release; // transform event type
1050              }              }
1051              else dmsg(1,("Event pool emtpy!\n"));              else dmsg(1,("Event pool emtpy!\n"));
1052          }          }
1053    
1054          // allocate and trigger a new voice for the key          // allocate and trigger new voice(s) for the key
1055          LaunchVoice(pNoteOnEvent);          {
1056                // first, get total amount of required voices (dependant on amount of layers)
1057                ::gig::Region* pRegion = pEngineChannel->pInstrument->GetRegion(itNoteOnEventOnKeyList->Param.Note.Key);
1058                if (pRegion && !RegionSuspended(pRegion)) {
1059                    int voicesRequired = pRegion->Layers;
1060                    // now launch the required amount of voices
1061                    for (int i = 0; i < voicesRequired; i++)
1062                        LaunchVoice(pEngineChannel, itNoteOnEventOnKeyList, i, false, true, true);
1063                }
1064            }
1065    
1066          // finally move note on event to the key's own event list          // if neither a voice was spawned or postponed then remove note on event from key again
1067          pEvents->move(pNoteOnEvent, pKey->pEvents);          if (!pKey->Active && !pKey->VoiceTheftsQueued)
1068                pKey->pEvents->free(itNoteOnEventOnKeyList);
1069    
1070            if (!pEngineChannel->SoloMode || pEngineChannel->PortamentoPos < 0.0f) pEngineChannel->PortamentoPos = (float) key;
1071            pKey->RoundRobinIndex++;
1072      }      }
1073    
1074      /**      /**
# Line 555  namespace LinuxSampler { namespace gig { Line 1077  namespace LinuxSampler { namespace gig {
1077       *  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.
1078       *  due to completion of sample playback).       *  due to completion of sample playback).
1079       *       *
1080       *  @param pNoteOffEvent - key, velocity and time stamp of the event       *  @param pEngineChannel - engine channel on which this event occured on
1081         *  @param itNoteOffEvent - key, velocity and time stamp of the event
1082       */       */
1083      void Engine::ProcessNoteOff(Event* pNoteOffEvent) {      void Engine::ProcessNoteOff(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOffEvent) {
1084          midi_key_info_t* pKey = &pMIDIKeyInfo[pNoteOffEvent->Key];          #if !CONFIG_PROCESS_MUTED_CHANNELS
1085            if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
1086            #endif
1087    
1088            //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
1089            itNoteOffEvent->Param.Note.Key += pEngineChannel->GlobalTranspose;
1090    
1091            const int iKey = itNoteOffEvent->Param.Note.Key;
1092            midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[iKey];
1093          pKey->KeyPressed = false; // the MIDI key was now released          pKey->KeyPressed = false; // the MIDI key was now released
1094    
1095          // release voices on this key if needed          // move event to the key's own event list
1096          if (pKey->Active && !SustainPedal) {          RTList<Event>::Iterator itNoteOffEventOnKeyList = itNoteOffEvent.moveToEndOf(pKey->pEvents);
1097              pNoteOffEvent->Type = Event::type_release; // transform event type  
1098              pEvents->move(pNoteOffEvent, pKey->pEvents); // move event to the key's own event list          bool bShouldRelease = pKey->Active && ShouldReleaseVoice(pEngineChannel, itNoteOffEventOnKeyList->Param.Note.Key);
1099    
1100            // in case Solo Mode is enabled, kill all voices on this key and respawn a voice on the highest pressed key (if any)
1101            if (pEngineChannel->SoloMode && pEngineChannel->pInstrument) { //TODO: this feels like too much code just for handling solo mode :P
1102                bool bOtherKeysPressed = false;
1103                if (iKey == pEngineChannel->SoloKey) {
1104                    pEngineChannel->SoloKey = -1;
1105                    // if there's still a key pressed down, respawn a voice (group) on the highest key
1106                    for (int i = 127; i > 0; i--) {
1107                        midi_key_info_t* pOtherKey = &pEngineChannel->pMIDIKeyInfo[i];
1108                        if (pOtherKey->KeyPressed) {
1109                            bOtherKeysPressed = true;
1110                            // make the other key the new 'currently active solo key'
1111                            pEngineChannel->SoloKey = i;
1112                            // get final portamento position of currently active voice
1113                            if (pEngineChannel->PortamentoMode) {
1114                                RTList<Voice>::Iterator itVoice = pKey->pActiveVoices->first();
1115                                if (itVoice) itVoice->UpdatePortamentoPos(itNoteOffEventOnKeyList);
1116                            }
1117                            // create a pseudo note on event
1118                            RTList<Event>::Iterator itPseudoNoteOnEvent = pOtherKey->pEvents->allocAppend();
1119                            if (itPseudoNoteOnEvent) {
1120                                // copy event
1121                                *itPseudoNoteOnEvent = *itNoteOffEventOnKeyList;
1122                                // transform event to a note on event
1123                                itPseudoNoteOnEvent->Type                = Event::type_note_on;
1124                                itPseudoNoteOnEvent->Param.Note.Key      = i;
1125                                itPseudoNoteOnEvent->Param.Note.Velocity = pOtherKey->Velocity;
1126                                // allocate and trigger new voice(s) for the other key
1127                                {
1128                                    // first, get total amount of required voices (dependant on amount of layers)
1129                                    ::gig::Region* pRegion = pEngineChannel->pInstrument->GetRegion(i);
1130                                    if (pRegion) {
1131                                        int voicesRequired = pRegion->Layers;
1132                                        // now launch the required amount of voices
1133                                        for (int iLayer = 0; iLayer < voicesRequired; iLayer++)
1134                                            LaunchVoice(pEngineChannel, itPseudoNoteOnEvent, iLayer, false, true, false);
1135                                    }
1136                                }
1137                                // if neither a voice was spawned or postponed then remove note on event from key again
1138                                if (!pOtherKey->Active && !pOtherKey->VoiceTheftsQueued)
1139                                    pOtherKey->pEvents->free(itPseudoNoteOnEvent);
1140    
1141                            } else dmsg(1,("Could not respawn voice, no free event left\n"));
1142                            break; // done
1143                        }
1144                    }
1145                }
1146                if (bOtherKeysPressed) {
1147                    if (pKey->Active) { // kill all voices on this key
1148                        bShouldRelease = false; // no need to release, as we kill it here
1149                        RTList<Voice>::Iterator itVoiceToBeKilled = pKey->pActiveVoices->first();
1150                        RTList<Voice>::Iterator end               = pKey->pActiveVoices->end();
1151                        for (; itVoiceToBeKilled != end; ++itVoiceToBeKilled) {
1152                            if (itVoiceToBeKilled->Type != Voice::type_release_trigger)
1153                                itVoiceToBeKilled->Kill(itNoteOffEventOnKeyList);
1154                        }
1155                    }
1156                } else pEngineChannel->PortamentoPos = -1.0f;
1157          }          }
1158    
1159            // if no solo mode (the usual case) or if solo mode and no other key pressed, then release voices on this key if needed
1160            if (bShouldRelease) {
1161                itNoteOffEventOnKeyList->Type = Event::type_release; // transform event type
1162    
1163                // spawn release triggered voice(s) if needed
1164                if (pKey->ReleaseTrigger && pEngineChannel->pInstrument) {
1165                    // first, get total amount of required voices (dependant on amount of layers)
1166                    ::gig::Region* pRegion = pEngineChannel->pInstrument->GetRegion(itNoteOffEventOnKeyList->Param.Note.Key);
1167                    if (pRegion) {
1168                        int voicesRequired = pRegion->Layers;
1169    
1170                        // MIDI note-on velocity is used instead of note-off velocity
1171                        itNoteOffEventOnKeyList->Param.Note.Velocity = pKey->Velocity;
1172    
1173                        // now launch the required amount of voices
1174                        for (int i = 0; i < voicesRequired; i++)
1175                            LaunchVoice(pEngineChannel, itNoteOffEventOnKeyList, i, true, false, false); //FIXME: for the moment we don't perform voice stealing for release triggered samples
1176                    }
1177                    pKey->ReleaseTrigger = false;
1178                }
1179            }
1180    
1181            // if neither a voice was spawned or postponed on this key then remove note off event from key again
1182            if (!pKey->Active && !pKey->VoiceTheftsQueued)
1183                pKey->pEvents->free(itNoteOffEventOnKeyList);
1184      }      }
1185    
1186      /**      /**
1187       *  Moves pitchbend event from the general (input) event list to the pitch       *  Moves pitchbend event from the general (input) event list to the engine
1188       *  event list.       *  channel's event list. It will actually processed later by the
1189         *  respective voice.
1190       *       *
1191       *  @param pPitchbendEvent - absolute pitch value and time stamp of the event       *  @param pEngineChannel - engine channel on which this event occured on
1192         *  @param itPitchbendEvent - absolute pitch value and time stamp of the event
1193       */       */
1194      void Engine::ProcessPitchbend(Event* pPitchbendEvent) {      void Engine::ProcessPitchbend(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itPitchbendEvent) {
1195          this->Pitch = pPitchbendEvent->Pitch; // store current pitch value          pEngineChannel->Pitch = itPitchbendEvent->Param.Pitch.Pitch; // store current pitch value
         pEvents->move(pPitchbendEvent, pSynthesisEvents[Event::destination_vco]);  
1196      }      }
1197    
1198      /**      /**
# Line 585  namespace LinuxSampler { namespace gig { Line 1200  namespace LinuxSampler { namespace gig {
1200       *  called by the ProcessNoteOn() method and by the voices itself       *  called by the ProcessNoteOn() method and by the voices itself
1201       *  (e.g. to spawn further voices on the same key for layered sounds).       *  (e.g. to spawn further voices on the same key for layered sounds).
1202       *       *
1203       *  @param pNoteOnEvent - key, velocity and time stamp of the event       *  @param pEngineChannel      - engine channel on which this event occured on
1204       *  @param iLayer       - layer index for the new voice (optional - only       *  @param itNoteOnEvent       - key, velocity and time stamp of the event
1205       *                        in case of layered sounds of course)       *  @param iLayer              - layer index for the new voice (optional - only
1206         *                               in case of layered sounds of course)
1207         *  @param ReleaseTriggerVoice - if new voice is a release triggered voice
1208         *                               (optional, default = false)
1209         *  @param VoiceStealing       - if voice stealing should be performed
1210         *                               when there is no free voice
1211         *                               (optional, default = true)
1212         *  @param HandleKeyGroupConflicts - if voices should be killed due to a
1213         *                                   key group conflict
1214         *  @returns pointer to new voice or NULL if there was no free voice or
1215         *           if the voice wasn't triggered (for example when no region is
1216         *           defined for the given key).
1217       */       */
1218      void Engine::LaunchVoice(Event* pNoteOnEvent, int iLayer) {      Pool<Voice>::Iterator Engine::LaunchVoice(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent, int iLayer, bool ReleaseTriggerVoice, bool VoiceStealing, bool HandleKeyGroupConflicts) {
1219          midi_key_info_t* pKey = &pMIDIKeyInfo[pNoteOnEvent->Key];          int MIDIKey            = itNoteOnEvent->Param.Note.Key;
1220            midi_key_info_t* pKey  = &pEngineChannel->pMIDIKeyInfo[MIDIKey];
1221            ::gig::Region* pRegion = pEngineChannel->pInstrument->GetRegion(MIDIKey);
1222    
1223            // if nothing defined for this key
1224            if (!pRegion) return Pool<Voice>::Iterator(); // nothing to do
1225    
1226            // only mark the first voice of a layered voice (group) to be in a
1227            // key group, so the layered voices won't kill each other
1228            int iKeyGroup = (iLayer == 0 && !ReleaseTriggerVoice) ? pRegion->KeyGroup : 0;
1229    
1230            // handle key group (a.k.a. exclusive group) conflicts
1231            if (HandleKeyGroupConflicts) {
1232                if (iKeyGroup) { // if this voice / key belongs to a key group
1233                    uint** ppKeyGroup = &pEngineChannel->ActiveKeyGroups[iKeyGroup];
1234                    if (*ppKeyGroup) { // if there's already an active key in that key group
1235                        midi_key_info_t* pOtherKey = &pEngineChannel->pMIDIKeyInfo[**ppKeyGroup];
1236                        // kill all voices on the (other) key
1237                        RTList<Voice>::Iterator itVoiceToBeKilled = pOtherKey->pActiveVoices->first();
1238                        RTList<Voice>::Iterator end               = pOtherKey->pActiveVoices->end();
1239                        for (; itVoiceToBeKilled != end; ++itVoiceToBeKilled) {
1240                            if (itVoiceToBeKilled->Type != Voice::type_release_trigger) {
1241                                itVoiceToBeKilled->Kill(itNoteOnEvent);
1242                                --VoiceSpawnsLeft; //FIXME: just a hack, we should better check in StealVoice() if the voice was killed due to key conflict
1243                            }
1244                        }
1245                    }
1246                }
1247            }
1248    
1249            Voice::type_t VoiceType = Voice::type_normal;
1250    
1251            // get current dimension values to select the right dimension region
1252            //TODO: for stolen voices this dimension region selection block is processed twice, this should be changed
1253            //FIXME: controller values for selecting the dimension region here are currently not sample accurate
1254            uint DimValues[8] = { 0 };
1255            for (int i = pRegion->Dimensions - 1; i >= 0; i--) {
1256                switch (pRegion->pDimensionDefinitions[i].dimension) {
1257                    case ::gig::dimension_samplechannel:
1258                        DimValues[i] = 0; //TODO: we currently ignore this dimension
1259                        break;
1260                    case ::gig::dimension_layer:
1261                        DimValues[i] = iLayer;
1262                        break;
1263                    case ::gig::dimension_velocity:
1264                        DimValues[i] = itNoteOnEvent->Param.Note.Velocity;
1265                        break;
1266                    case ::gig::dimension_channelaftertouch:
1267                        DimValues[i] = pEngineChannel->ControllerTable[128];
1268                        break;
1269                    case ::gig::dimension_releasetrigger:
1270                        VoiceType = (ReleaseTriggerVoice) ? Voice::type_release_trigger : (!iLayer) ? Voice::type_release_trigger_required : Voice::type_normal;
1271                        DimValues[i] = (uint) ReleaseTriggerVoice;
1272                        break;
1273                    case ::gig::dimension_keyboard:
1274                        DimValues[i] = (uint) (pEngineChannel->CurrentKeyDimension * pRegion->pDimensionDefinitions[i].zones);
1275                        break;
1276                    case ::gig::dimension_roundrobin:
1277                        DimValues[i] = (uint) pEngineChannel->pMIDIKeyInfo[MIDIKey].RoundRobinIndex; // incremented for each note on
1278                        break;
1279                    case ::gig::dimension_random:
1280                        RandomSeed   = RandomSeed * 1103515245 + 12345; // classic pseudo random number generator
1281                        DimValues[i] = (uint) RandomSeed >> (32 - pRegion->pDimensionDefinitions[i].bits); // highest bits are most random
1282                        break;
1283                    case ::gig::dimension_modwheel:
1284                        DimValues[i] = pEngineChannel->ControllerTable[1];
1285                        break;
1286                    case ::gig::dimension_breath:
1287                        DimValues[i] = pEngineChannel->ControllerTable[2];
1288                        break;
1289                    case ::gig::dimension_foot:
1290                        DimValues[i] = pEngineChannel->ControllerTable[4];
1291                        break;
1292                    case ::gig::dimension_portamentotime:
1293                        DimValues[i] = pEngineChannel->ControllerTable[5];
1294                        break;
1295                    case ::gig::dimension_effect1:
1296                        DimValues[i] = pEngineChannel->ControllerTable[12];
1297                        break;
1298                    case ::gig::dimension_effect2:
1299                        DimValues[i] = pEngineChannel->ControllerTable[13];
1300                        break;
1301                    case ::gig::dimension_genpurpose1:
1302                        DimValues[i] = pEngineChannel->ControllerTable[16];
1303                        break;
1304                    case ::gig::dimension_genpurpose2:
1305                        DimValues[i] = pEngineChannel->ControllerTable[17];
1306                        break;
1307                    case ::gig::dimension_genpurpose3:
1308                        DimValues[i] = pEngineChannel->ControllerTable[18];
1309                        break;
1310                    case ::gig::dimension_genpurpose4:
1311                        DimValues[i] = pEngineChannel->ControllerTable[19];
1312                        break;
1313                    case ::gig::dimension_sustainpedal:
1314                        DimValues[i] = pEngineChannel->ControllerTable[64];
1315                        break;
1316                    case ::gig::dimension_portamento:
1317                        DimValues[i] = pEngineChannel->ControllerTable[65];
1318                        break;
1319                    case ::gig::dimension_sostenutopedal:
1320                        DimValues[i] = pEngineChannel->ControllerTable[66];
1321                        break;
1322                    case ::gig::dimension_softpedal:
1323                        DimValues[i] = pEngineChannel->ControllerTable[67];
1324                        break;
1325                    case ::gig::dimension_genpurpose5:
1326                        DimValues[i] = pEngineChannel->ControllerTable[80];
1327                        break;
1328                    case ::gig::dimension_genpurpose6:
1329                        DimValues[i] = pEngineChannel->ControllerTable[81];
1330                        break;
1331                    case ::gig::dimension_genpurpose7:
1332                        DimValues[i] = pEngineChannel->ControllerTable[82];
1333                        break;
1334                    case ::gig::dimension_genpurpose8:
1335                        DimValues[i] = pEngineChannel->ControllerTable[83];
1336                        break;
1337                    case ::gig::dimension_effect1depth:
1338                        DimValues[i] = pEngineChannel->ControllerTable[91];
1339                        break;
1340                    case ::gig::dimension_effect2depth:
1341                        DimValues[i] = pEngineChannel->ControllerTable[92];
1342                        break;
1343                    case ::gig::dimension_effect3depth:
1344                        DimValues[i] = pEngineChannel->ControllerTable[93];
1345                        break;
1346                    case ::gig::dimension_effect4depth:
1347                        DimValues[i] = pEngineChannel->ControllerTable[94];
1348                        break;
1349                    case ::gig::dimension_effect5depth:
1350                        DimValues[i] = pEngineChannel->ControllerTable[95];
1351                        break;
1352                    case ::gig::dimension_none:
1353                        std::cerr << "gig::Engine::LaunchVoice() Error: dimension=none\n" << std::flush;
1354                        break;
1355                    default:
1356                        std::cerr << "gig::Engine::LaunchVoice() Error: Unknown dimension\n" << std::flush;
1357                }
1358            }
1359    
1360            // return if this is a release triggered voice and there is no
1361            // releasetrigger dimension (could happen if an instrument
1362            // change has occured between note on and off)
1363            if (ReleaseTriggerVoice && VoiceType != Voice::type_release_trigger) return Pool<Voice>::Iterator();
1364    
1365            ::gig::DimensionRegion* pDimRgn = pRegion->GetDimensionRegionByValue(DimValues);
1366    
1367            // no need to continue if sample is silent
1368            if (!pDimRgn->pSample || !pDimRgn->pSample->SamplesTotal) return Pool<Voice>::Iterator();
1369    
1370          // allocate a new voice for the key          // allocate a new voice for the key
1371          Voice* pNewVoice = pKey->pActiveVoices->alloc();          Pool<Voice>::Iterator itNewVoice = pKey->pActiveVoices->allocAppend();
1372          if (pNewVoice) {          if (itNewVoice) {
1373              // launch the new voice              // launch the new voice
1374              if (pNewVoice->Trigger(pNoteOnEvent, this->Pitch, this->pInstrument, iLayer) < 0) {              if (itNewVoice->Trigger(pEngineChannel, itNoteOnEvent, pEngineChannel->Pitch, pDimRgn, VoiceType, iKeyGroup) < 0) {
1375                  dmsg(1,("Triggering new voice failed!\n"));                  dmsg(4,("Voice not triggered\n"));
1376                  pKey->pActiveVoices->free(pNewVoice);                  pKey->pActiveVoices->free(itNewVoice);
1377              }              }
1378              else { // on success              else { // on success
1379                  uint** ppKeyGroup = NULL;                  --VoiceSpawnsLeft;
                 if (pNewVoice->KeyGroup) { // if this voice / key belongs to a key group  
                     ppKeyGroup = &ActiveKeyGroups[pNewVoice->KeyGroup];  
                     if (*ppKeyGroup) { // if there's already an active key in that key group  
                         midi_key_info_t* pOtherKey = &pMIDIKeyInfo[**ppKeyGroup];  
                         // kill all voices on the (other) key  
                         Voice* pVoiceToBeKilled = pOtherKey->pActiveVoices->first();  
                         for (; pVoiceToBeKilled; pVoiceToBeKilled = pOtherKey->pActiveVoices->next())  
                             if (pVoiceToBeKilled != pNewVoice) pVoiceToBeKilled->Kill(pNoteOnEvent);  
                     }  
                 }  
1380                  if (!pKey->Active) { // mark as active key                  if (!pKey->Active) { // mark as active key
1381                      pKey->Active = true;                      pKey->Active = true;
1382                      pKey->pSelf  = pActiveKeys->alloc();                      pKey->itSelf = pEngineChannel->pActiveKeys->allocAppend();
1383                      *pKey->pSelf = pNoteOnEvent->Key;                      *pKey->itSelf = itNoteOnEvent->Param.Note.Key;
1384                  }                  }
1385                  if (pNewVoice->KeyGroup) {                  if (itNewVoice->KeyGroup) {
1386                      *ppKeyGroup = pKey->pSelf; // put key as the (new) active key to its key group                      uint** ppKeyGroup = &pEngineChannel->ActiveKeyGroups[itNewVoice->KeyGroup];
1387                        *ppKeyGroup = &*pKey->itSelf; // put key as the (new) active key to its key group
1388                  }                  }
1389                    if (itNewVoice->Type == Voice::type_release_trigger_required) pKey->ReleaseTrigger = true; // mark key for the need of release triggered voice(s)
1390                    return itNewVoice; // success
1391              }              }
1392          }          }
1393          else std::cerr << "No free voice!" << std::endl << std::flush;          else if (VoiceStealing) {
1394                // try to steal one voice
1395                int result = StealVoice(pEngineChannel, itNoteOnEvent);
1396                if (!result) { // voice stolen successfully
1397                    // put note-on event into voice-stealing queue, so it will be reprocessed after killed voice died
1398                    RTList<Event>::Iterator itStealEvent = pVoiceStealingQueue->allocAppend();
1399                    if (itStealEvent) {
1400                        *itStealEvent = *itNoteOnEvent; // copy event
1401                        itStealEvent->Param.Note.Layer = iLayer;
1402                        itStealEvent->Param.Note.ReleaseTrigger = ReleaseTriggerVoice;
1403                        pKey->VoiceTheftsQueued++;
1404                    }
1405                    else dmsg(1,("Voice stealing queue full!\n"));
1406                }
1407            }
1408    
1409            return Pool<Voice>::Iterator(); // no free voice or error
1410      }      }
1411    
1412      /**      /**
1413       *  Immediately kills the voice given with pVoice (no matter if sustain is       *  Will be called by LaunchVoice() method in case there are no free
1414       *  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
1415       *  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
1416         *  voice actually died.
1417       *       *
1418       *  @param pVoice - points to the voice to be killed       *  @param pEngineChannel - engine channel on which this event occured on
1419         *  @param itNoteOnEvent - key, velocity and time stamp of the event
1420         *  @returns 0 on success, a value < 0 if no active voice could be picked for voice stealing
1421       */       */
1422      void Engine::KillVoiceImmediately(Voice* pVoice) {      int Engine::StealVoice(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent) {
1423          if (pVoice) {          if (VoiceSpawnsLeft <= 0) {
1424              if (pVoice->IsActive()) pVoice->KillImmediately();              dmsg(1,("Max. voice thefts per audio fragment reached (you may raise CONFIG_MAX_VOICES).\n"));
1425                return -1;
1426            }
1427            if (!pEventPool->poolIsEmpty()) {
1428    
1429                RTList<Voice>::Iterator itSelectedVoice;
1430    
1431                // Select one voice for voice stealing
1432                switch (CONFIG_VOICE_STEAL_ALGO) {
1433    
1434                    // try to pick the oldest voice on the key where the new
1435                    // voice should be spawned, if there is no voice on that
1436                    // key, or no voice left to kill, then procceed with
1437                    // 'oldestkey' algorithm
1438                    case voice_steal_algo_oldestvoiceonkey: {
1439                        midi_key_info_t* pSelectedKey = &pEngineChannel->pMIDIKeyInfo[itNoteOnEvent->Param.Note.Key];
1440                        itSelectedVoice = pSelectedKey->pActiveVoices->first();
1441                        // proceed iterating if voice was created in this fragment cycle
1442                        while (itSelectedVoice && !itSelectedVoice->IsStealable()) ++itSelectedVoice;
1443                        // if we haven't found a voice then proceed with algorithm 'oldestkey'
1444                        if (itSelectedVoice && itSelectedVoice->IsStealable()) break;
1445                    } // no break - intentional !
1446    
1447                    // try to pick the oldest voice on the oldest active key
1448                    // from the same engine channel
1449                    // (caution: must stay after 'oldestvoiceonkey' algorithm !)
1450                    case voice_steal_algo_oldestkey: {
1451                        // if we already stole in this fragment, try to proceed on same key
1452                        if (this->itLastStolenVoice) {
1453                            itSelectedVoice = this->itLastStolenVoice;
1454                            do {
1455                                ++itSelectedVoice;
1456                            } while (itSelectedVoice && !itSelectedVoice->IsStealable()); // proceed iterating if voice was created in this fragment cycle
1457                            // found a "stealable" voice ?
1458                            if (itSelectedVoice && itSelectedVoice->IsStealable()) {
1459                                // remember which voice we stole, so we can simply proceed on next voice stealing
1460                                this->itLastStolenVoice = itSelectedVoice;
1461                                break; // selection succeeded
1462                            }
1463                        }
1464                        // get (next) oldest key
1465                        RTList<uint>::Iterator iuiSelectedKey = (this->iuiLastStolenKey) ? ++this->iuiLastStolenKey : pEngineChannel->pActiveKeys->first();
1466                        while (iuiSelectedKey) {
1467                            midi_key_info_t* pSelectedKey = &pEngineChannel->pMIDIKeyInfo[*iuiSelectedKey];
1468                            itSelectedVoice = pSelectedKey->pActiveVoices->first();
1469                            // proceed iterating if voice was created in this fragment cycle
1470                            while (itSelectedVoice && !itSelectedVoice->IsStealable()) ++itSelectedVoice;
1471                            // found a "stealable" voice ?
1472                            if (itSelectedVoice && itSelectedVoice->IsStealable()) {
1473                                // remember which voice on which key we stole, so we can simply proceed on next voice stealing
1474                                this->iuiLastStolenKey  = iuiSelectedKey;
1475                                this->itLastStolenVoice = itSelectedVoice;
1476                                break; // selection succeeded
1477                            }
1478                            ++iuiSelectedKey; // get next oldest key
1479                        }
1480                        break;
1481                    }
1482    
1483              midi_key_info_t* pKey = &pMIDIKeyInfo[pVoice->MIDIKey];                  // don't steal anything
1484                    case voice_steal_algo_none:
1485                    default: {
1486                        dmsg(1,("No free voice (voice stealing disabled)!\n"));
1487                        return -1;
1488                    }
1489                }
1490    
1491              // free the voice object              // if we couldn't steal a voice from the same engine channel then
1492              pVoicePool->free(pVoice);              // steal oldest voice on the oldest key from any other engine channel
1493                // (the smaller engine channel number, the higher priority)
1494                if (!itSelectedVoice || !itSelectedVoice->IsStealable()) {
1495                    EngineChannel* pSelectedChannel;
1496                    int            iChannelIndex;
1497                    // select engine channel
1498                    if (pLastStolenChannel) {
1499                        pSelectedChannel = pLastStolenChannel;
1500                        iChannelIndex    = pSelectedChannel->iEngineIndexSelf;
1501                    } else { // pick the engine channel followed by this engine channel
1502                        iChannelIndex    = (pEngineChannel->iEngineIndexSelf + 1) % engineChannels.size();
1503                        pSelectedChannel = engineChannels[iChannelIndex];
1504                    }
1505    
1506              // check if there are no voices left on the MIDI key and update the key info if so                  // if we already stole in this fragment, try to proceed on same key
1507              if (pKey->pActiveVoices->is_empty()) {                  if (this->itLastStolenVoiceGlobally) {
1508                  if (pVoice->KeyGroup) { // if voice / key belongs to a key group                      itSelectedVoice = this->itLastStolenVoiceGlobally;
1509                      uint** ppKeyGroup = &ActiveKeyGroups[pVoice->KeyGroup];                      do {
1510                      if (*ppKeyGroup == pKey->pSelf) *ppKeyGroup = NULL; // remove key from key group                          ++itSelectedVoice;
1511                        } while (itSelectedVoice && !itSelectedVoice->IsStealable()); // proceed iterating if voice was created in this fragment cycle
1512                  }                  }
1513                  pKey->Active = false;  
1514                  pActiveKeys->free(pKey->pSelf); // remove key from list of active keys                  #if CONFIG_DEVMODE
1515                  pKey->pSelf = NULL;                  EngineChannel* pBegin = pSelectedChannel; // to detect endless loop
1516                  dmsg(3,("Key has no more voices now\n"));                  #endif // CONFIG_DEVMODE
1517    
1518                    // did we find a 'stealable' voice?
1519                    if (itSelectedVoice && itSelectedVoice->IsStealable()) {
1520                        // remember which voice we stole, so we can simply proceed on next voice stealing
1521                        this->itLastStolenVoiceGlobally = itSelectedVoice;
1522                    } else while (true) { // iterate through engine channels
1523                        // get (next) oldest key
1524                        RTList<uint>::Iterator iuiSelectedKey = (this->iuiLastStolenKeyGlobally) ? ++this->iuiLastStolenKeyGlobally : pSelectedChannel->pActiveKeys->first();
1525                        this->iuiLastStolenKeyGlobally = RTList<uint>::Iterator(); // to prevent endless loop (see line above)
1526                        while (iuiSelectedKey) {
1527                            midi_key_info_t* pSelectedKey = &pSelectedChannel->pMIDIKeyInfo[*iuiSelectedKey];
1528                            itSelectedVoice = pSelectedKey->pActiveVoices->first();
1529                            // proceed iterating if voice was created in this fragment cycle
1530                            while (itSelectedVoice && !itSelectedVoice->IsStealable()) ++itSelectedVoice;
1531                            // found a "stealable" voice ?
1532                            if (itSelectedVoice && itSelectedVoice->IsStealable()) {
1533                                // remember which voice on which key on which engine channel we stole, so we can simply proceed on next voice stealing
1534                                this->iuiLastStolenKeyGlobally  = iuiSelectedKey;
1535                                this->itLastStolenVoiceGlobally = itSelectedVoice;
1536                                this->pLastStolenChannel        = pSelectedChannel;
1537                                goto stealable_voice_found; // selection succeeded
1538                            }
1539                            ++iuiSelectedKey; // get next key on current engine channel
1540                        }
1541                        // get next engine channel
1542                        iChannelIndex    = (iChannelIndex + 1) % engineChannels.size();
1543                        pSelectedChannel = engineChannels[iChannelIndex];
1544    
1545                        #if CONFIG_DEVMODE
1546                        if (pSelectedChannel == pBegin) {
1547                            dmsg(1,("FATAL ERROR: voice stealing endless loop!\n"));
1548                            dmsg(1,("VoiceSpawnsLeft=%d.\n", VoiceSpawnsLeft));
1549                            dmsg(1,("Exiting.\n"));
1550                            exit(-1);
1551                        }
1552                        #endif // CONFIG_DEVMODE
1553                    }
1554                }
1555    
1556                // jump point if a 'stealable' voice was found
1557                stealable_voice_found:
1558    
1559                #if CONFIG_DEVMODE
1560                if (!itSelectedVoice->IsActive()) {
1561                    dmsg(1,("gig::Engine: ERROR, tried to steal a voice which was not active !!!\n"));
1562                    return -1;
1563                }
1564                #endif // CONFIG_DEVMODE
1565    
1566                // now kill the selected voice
1567                itSelectedVoice->Kill(itNoteOnEvent);
1568    
1569                --VoiceSpawnsLeft;
1570    
1571                return 0; // success
1572            }
1573            else {
1574                dmsg(1,("Event pool emtpy!\n"));
1575                return -1;
1576            }
1577        }
1578    
1579        /**
1580         *  Removes the given voice from the MIDI key's list of active voices.
1581         *  This method will be called when a voice went inactive, e.g. because
1582         *  it finished to playback its sample, finished its release stage or
1583         *  just was killed.
1584         *
1585         *  @param pEngineChannel - engine channel on which this event occured on
1586         *  @param itVoice - points to the voice to be freed
1587         */
1588        void Engine::FreeVoice(EngineChannel* pEngineChannel, Pool<Voice>::Iterator& itVoice) {
1589            if (itVoice) {
1590                midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[itVoice->MIDIKey];
1591    
1592                uint keygroup = itVoice->KeyGroup;
1593    
1594                // if the sample and dimension region belong to an
1595                // instrument that is unloaded, tell the disk thread to
1596                // release them
1597                if (itVoice->Orphan) {
1598                    pDiskThread->OrderDeletionOfDimreg(itVoice->pDimRgn);
1599                }
1600    
1601                // free the voice object
1602                pVoicePool->free(itVoice);
1603    
1604                // if no other voices left and member of a key group, remove from key group
1605                if (pKey->pActiveVoices->isEmpty() && keygroup) {
1606                    uint** ppKeyGroup = &pEngineChannel->ActiveKeyGroups[keygroup];
1607                    if (*ppKeyGroup == &*pKey->itSelf) *ppKeyGroup = NULL; // remove key from key group
1608              }              }
1609          }          }
1610          else std::cerr << "Couldn't release voice! (pVoice == NULL)\n" << std::flush;          else std::cerr << "Couldn't release voice! (!itVoice)\n" << std::flush;
1611        }
1612    
1613        /**
1614         *  Called when there's no more voice left on a key, this call will
1615         *  update the key info respectively.
1616         *
1617         *  @param pEngineChannel - engine channel on which this event occured on
1618         *  @param pKey - key which is now inactive
1619         */
1620        void Engine::FreeKey(EngineChannel* pEngineChannel, midi_key_info_t* pKey) {
1621            if (pKey->pActiveVoices->isEmpty()) {
1622                pKey->Active = false;
1623                pEngineChannel->pActiveKeys->free(pKey->itSelf); // remove key from list of active keys
1624                pKey->itSelf = RTList<uint>::Iterator();
1625                pKey->ReleaseTrigger = false;
1626                pKey->pEvents->clear();
1627                dmsg(3,("Key has no more voices now\n"));
1628            }
1629            else dmsg(1,("gig::Engine: Oops, tried to free a key which contains voices.\n"));
1630      }      }
1631    
1632      /**      /**
1633       *  Reacts on supported control change commands (e.g. pitch bend wheel,       *  Reacts on supported control change commands (e.g. pitch bend wheel,
1634       *  modulation wheel, aftertouch).       *  modulation wheel, aftertouch).
1635       *       *
1636       *  @param pControlChangeEvent - controller, value and time stamp of the event       *  @param pEngineChannel - engine channel on which this event occured on
1637         *  @param itControlChangeEvent - controller, value and time stamp of the event
1638       */       */
1639      void Engine::ProcessControlChange(Event* pControlChangeEvent) {      void Engine::ProcessControlChange(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itControlChangeEvent) {
1640          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));
1641    
1642            // handle the "control triggered" MIDI rule: a control change
1643            // event can trigger a new note on or note off event
1644            if (pEngineChannel->pInstrument) {
1645    
1646                ::gig::MidiRule* rule;
1647                for (int i = 0 ; (rule = pEngineChannel->pInstrument->GetMidiRule(i)) ; i++) {
1648    
1649                    if (::gig::MidiRuleCtrlTrigger* ctrlTrigger =
1650                        dynamic_cast< ::gig::MidiRuleCtrlTrigger*>(rule)) {
1651                        if (itControlChangeEvent->Param.CC.Controller ==
1652                            ctrlTrigger->ControllerNumber) {
1653    
1654                            uint8_t oldCCValue = pEngineChannel->ControllerTable[
1655                                itControlChangeEvent->Param.CC.Controller];
1656                            uint8_t newCCValue = itControlChangeEvent->Param.CC.Value;
1657    
1658                            for (int i = 0 ; i < ctrlTrigger->Triggers ; i++) {
1659                                ::gig::MidiRuleCtrlTrigger::trigger_t* pTrigger =
1660                                      &ctrlTrigger->pTriggers[i];
1661    
1662                                // check if the controller has passed the
1663                                // trigger point in the right direction
1664                                if ((pTrigger->Descending &&
1665                                     oldCCValue > pTrigger->TriggerPoint &&
1666                                     newCCValue <= pTrigger->TriggerPoint) ||
1667                                    (!pTrigger->Descending &&
1668                                     oldCCValue < pTrigger->TriggerPoint &&
1669                                     newCCValue >= pTrigger->TriggerPoint)) {
1670    
1671                                    RTList<Event>::Iterator itNewEvent = pGlobalEvents->allocAppend();
1672                                    if (itNewEvent) {
1673                                        *itNewEvent = *itControlChangeEvent;
1674                                        itNewEvent->Param.Note.Key = pTrigger->Key;
1675    
1676                                        if (pTrigger->NoteOff || pTrigger->Velocity == 0) {
1677                                            itNewEvent->Type = Event::type_note_off;
1678                                            itNewEvent->Param.Note.Velocity = 100;
1679    
1680                                            ProcessNoteOff(pEngineChannel, itNewEvent);
1681                                        } else {
1682                                            itNewEvent->Type = Event::type_note_on;
1683                                            //TODO: if Velocity is 255, the triggered velocity should
1684                                            // depend on how fast the controller is moving
1685                                            itNewEvent->Param.Note.Velocity =
1686                                                pTrigger->Velocity == 255 ? 100 :
1687                                                pTrigger->Velocity;
1688    
1689                                            ProcessNoteOn(pEngineChannel, itNewEvent);
1690                                        }
1691                                    }
1692                                    else dmsg(1,("Event pool emtpy!\n"));
1693                                }
1694                            }
1695                        }
1696                    }
1697                }
1698            }
1699    
1700          switch (pControlChangeEvent->Controller) {          // update controller value in the engine channel's controller table
1701              case 64: {          pEngineChannel->ControllerTable[itControlChangeEvent->Param.CC.Controller] = itControlChangeEvent->Param.CC.Value;
1702                  if (pControlChangeEvent->Value >= 64 && !SustainPedal) {  
1703                      dmsg(4,("PEDAL DOWN\n"));          // handle hard coded MIDI controllers
1704                      SustainPedal = true;          switch (itControlChangeEvent->Param.CC.Controller) {
1705                case 5: { // portamento time
1706                    pEngineChannel->PortamentoTime = (float) itControlChangeEvent->Param.CC.Value / 127.0f * (float) CONFIG_PORTAMENTO_TIME_MAX + (float) CONFIG_PORTAMENTO_TIME_MIN;
1707                    break;
1708                }
1709                case 6: { // data entry (currently only used for RPN controllers)
1710                    if (pEngineChannel->GetMidiRpnController() == 2) { // coarse tuning in half tones
1711                        int transpose = (int) itControlChangeEvent->Param.CC.Value - 64;
1712                        // limit to +- two octaves for now
1713                        transpose = RTMath::Min(transpose,  24);
1714                        transpose = RTMath::Max(transpose, -24);
1715                        pEngineChannel->GlobalTranspose = transpose;
1716                        // workaround, so we won't have hanging notes
1717                        ReleaseAllVoices(pEngineChannel, itControlChangeEvent);
1718                    }
1719                    // to avoid other MIDI CC #6 messages to be misenterpreted as RPN controller data
1720                    pEngineChannel->ResetMidiRpnController();
1721                    break;
1722                }
1723                case 7: { // volume
1724                    //TODO: not sample accurate yet
1725                    pEngineChannel->MidiVolume = VolumeCurve[itControlChangeEvent->Param.CC.Value];
1726                    pEngineChannel->bStatusChanged = true; // engine channel status has changed, so set notify flag
1727                    break;
1728                }
1729                case 10: { // panpot
1730                    //TODO: not sample accurate yet
1731                    pEngineChannel->GlobalPanLeft  = PanCurve[128 - itControlChangeEvent->Param.CC.Value];
1732                    pEngineChannel->GlobalPanRight = PanCurve[itControlChangeEvent->Param.CC.Value];
1733                    pEngineChannel->iLastPanRequest = itControlChangeEvent->Param.CC.Value;
1734                    break;
1735                }
1736                case 64: { // sustain
1737                    if (itControlChangeEvent->Param.CC.Value >= 64 && !pEngineChannel->SustainPedal) {
1738                        dmsg(4,("DAMPER (RIGHT) PEDAL DOWN\n"));
1739                        pEngineChannel->SustainPedal = true;
1740    
1741                        #if !CONFIG_PROCESS_MUTED_CHANNELS
1742                        if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
1743                        #endif
1744    
1745                      // cancel release process of voices if necessary                      // cancel release process of voices if necessary
1746                      uint* piKey = pActiveKeys->first();                      RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
1747                      if (piKey) {                      for (; iuiKey; ++iuiKey) {
1748                          pControlChangeEvent->Type = Event::type_cancel_release; // transform event type                          midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
1749                          while (piKey) {                          if (!pKey->KeyPressed) {
1750                              midi_key_info_t* pKey = &pMIDIKeyInfo[*piKey];                              RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
1751                              pActiveKeys->set_current(piKey);                              if (itNewEvent) {
1752                              piKey = pActiveKeys->next();                                  *itNewEvent = *itControlChangeEvent; // copy event to the key's own event list
1753                              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"));  
1754                              }                              }
1755                                else dmsg(1,("Event pool emtpy!\n"));
1756                          }                          }
1757                      }                      }
1758                  }                  }
1759                  if (pControlChangeEvent->Value < 64 && SustainPedal) {                  if (itControlChangeEvent->Param.CC.Value < 64 && pEngineChannel->SustainPedal) {
1760                      dmsg(4,("PEDAL UP\n"));                      dmsg(4,("DAMPER (RIGHT) PEDAL UP\n"));
1761                      SustainPedal = false;                      pEngineChannel->SustainPedal = false;
1762    
1763                        #if !CONFIG_PROCESS_MUTED_CHANNELS
1764                        if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
1765                        #endif
1766    
1767                      // release voices if their respective key is not pressed                      // release voices if their respective key is not pressed
1768                      uint* piKey = pActiveKeys->first();                      RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
1769                      if (piKey) {                      for (; iuiKey; ++iuiKey) {
1770                          pControlChangeEvent->Type = Event::type_release; // transform event type                          midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
1771                          while (piKey) {                          if (!pKey->KeyPressed && ShouldReleaseVoice(pEngineChannel, *iuiKey)) {
1772                              midi_key_info_t* pKey = &pMIDIKeyInfo[*piKey];                              RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
1773                              pActiveKeys->set_current(piKey);                              if (itNewEvent) {
1774                              piKey = pActiveKeys->next();                                  *itNewEvent = *itControlChangeEvent; // copy event to the key's own event list
1775                              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"));  
1776                              }                              }
1777                                else dmsg(1,("Event pool emtpy!\n"));
1778                          }                          }
1779                      }                      }
1780                  }                  }
1781                  break;                  break;
1782              }              }
1783          }              case 65: { // portamento on / off
1784                    const bool bPortamento = itControlChangeEvent->Param.CC.Value >= 64;
1785                    if (bPortamento != pEngineChannel->PortamentoMode)
1786                        KillAllVoices(pEngineChannel, itControlChangeEvent);
1787                    pEngineChannel->PortamentoMode = bPortamento;
1788                    break;
1789                }
1790                case 66: { // sostenuto
1791                    if (itControlChangeEvent->Param.CC.Value >= 64 && !pEngineChannel->SostenutoPedal) {
1792                        dmsg(4,("SOSTENUTO (CENTER) PEDAL DOWN\n"));
1793                        pEngineChannel->SostenutoPedal = true;
1794    
1795                        #if !CONFIG_PROCESS_MUTED_CHANNELS
1796                        if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
1797                        #endif
1798    
1799                        SostenutoKeyCount = 0;
1800                        // Remeber the pressed keys
1801                        RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
1802                        for (; iuiKey; ++iuiKey) {
1803                            midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
1804                            if (pKey->KeyPressed && SostenutoKeyCount < 128) SostenutoKeys[SostenutoKeyCount++] = *iuiKey;
1805                        }
1806                    }
1807                    if (itControlChangeEvent->Param.CC.Value < 64 && pEngineChannel->SostenutoPedal) {
1808                        dmsg(4,("SOSTENUTO (CENTER) PEDAL UP\n"));
1809                        pEngineChannel->SostenutoPedal = false;
1810    
1811                        #if !CONFIG_PROCESS_MUTED_CHANNELS
1812                        if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
1813                        #endif
1814    
1815                        // release voices if the damper pedal is up and their respective key is not pressed
1816                        for (int i = 0; i < SostenutoKeyCount; i++) {
1817                            midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[SostenutoKeys[i]];
1818                            if (!pKey->KeyPressed && !pEngineChannel->SustainPedal) {
1819                                RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
1820                                if (itNewEvent) {
1821                                    *itNewEvent = *itControlChangeEvent; // copy event to the key's own event list
1822                                    itNewEvent->Type = Event::type_release; // transform event type
1823                                }
1824                                else dmsg(1,("Event pool emtpy!\n"));
1825                            }
1826                        }
1827                    }
1828                    break;
1829                }
1830                case 100: { // RPN controller LSB
1831                    pEngineChannel->SetMidiRpnControllerLsb(itControlChangeEvent->Param.CC.Value);
1832                    break;
1833                }
1834                case 101: { // RPN controller MSB
1835                    pEngineChannel->SetMidiRpnControllerMsb(itControlChangeEvent->Param.CC.Value);
1836                    break;
1837                }
1838    
         // update controller value in the engine's controller table  
         ControllerTable[pControlChangeEvent->Controller] = pControlChangeEvent->Value;  
1839    
1840          // move event from the unsorted event list to the control change event list              // Channel Mode Messages
1841          pEvents->move(pControlChangeEvent, pCCEvents);  
1842                case 120: { // all sound off
1843                    KillAllVoices(pEngineChannel, itControlChangeEvent);
1844                    break;
1845                }
1846                case 121: { // reset all controllers
1847                    pEngineChannel->ResetControllers();
1848                    break;
1849                }
1850                case 123: { // all notes off
1851                    #if CONFIG_PROCESS_ALL_NOTES_OFF
1852                    ReleaseAllVoices(pEngineChannel, itControlChangeEvent);
1853                    #endif // CONFIG_PROCESS_ALL_NOTES_OFF
1854                    break;
1855                }
1856                case 126: { // mono mode on
1857                    if (!pEngineChannel->SoloMode)
1858                        KillAllVoices(pEngineChannel, itControlChangeEvent);
1859                    pEngineChannel->SoloMode = true;
1860                    break;
1861                }
1862                case 127: { // poly mode on
1863                    if (pEngineChannel->SoloMode)
1864                        KillAllVoices(pEngineChannel, itControlChangeEvent);
1865                    pEngineChannel->SoloMode = false;
1866                    break;
1867                }
1868            }
1869    
1870            // handle FX send controllers
1871            if (!pEngineChannel->fxSends.empty()) {
1872                for (int iFxSend = 0; iFxSend < pEngineChannel->GetFxSendCount(); iFxSend++) {
1873                    FxSend* pFxSend = pEngineChannel->GetFxSend(iFxSend);
1874                    if (pFxSend->MidiController() == itControlChangeEvent->Param.CC.Controller) {
1875                        pFxSend->SetLevel(itControlChangeEvent->Param.CC.Value);
1876                        pFxSend->SetInfoChanged(true);
1877                    }
1878                }
1879            }
1880      }      }
1881    
1882      /**      /**
1883       * Initialize the parameter sequence for the modulation destination given by       *  Reacts on MIDI system exclusive messages.
1884       * by 'dst' with the constant value given by val.       *
1885         *  @param itSysexEvent - sysex data size and time stamp of the sysex event
1886       */       */
1887      void Engine::ResetSynthesisParameters(Event::destination_t dst, float val) {      void Engine::ProcessSysex(Pool<Event>::Iterator& itSysexEvent) {
1888          int maxsamples = pAudioOutputDevice->MaxSamplesPerCycle();          RingBuffer<uint8_t,false>::NonVolatileReader reader = pSysexBuffer->get_non_volatile_reader();
1889          float* m = &pSynthesisParameters[dst][0];  
1890          for (int i = 0; i < maxsamples; i += 4) {          uint8_t exclusive_status, id;
1891             m[i]   = val;          if (!reader.pop(&exclusive_status)) goto free_sysex_data;
1892             m[i+1] = val;          if (!reader.pop(&id))               goto free_sysex_data;
1893             m[i+2] = val;          if (exclusive_status != 0xF0)       goto free_sysex_data;
1894             m[i+3] = val;  
1895            switch (id) {
1896                case 0x7f: { // (Realtime) Universal Sysex (GM Standard)
1897                    uint8_t sysex_channel, sub_id1, sub_id2, val_msb, val_lsb;;
1898                    if (!reader.pop(&sysex_channel)) goto free_sysex_data;
1899                    if (!reader.pop(&sub_id1)) goto free_sysex_data;
1900                    if (!reader.pop(&sub_id2)) goto free_sysex_data;
1901                    if (!reader.pop(&val_lsb)) goto free_sysex_data;
1902                    if (!reader.pop(&val_msb)) goto free_sysex_data;
1903                    //TODO: for now we simply ignore the sysex channel, seldom used anyway
1904                    switch (sub_id1) {
1905                        case 0x04: // Device Control
1906                            switch (sub_id2) {
1907                                case 0x01: { // Master Volume
1908                                    const double volume =
1909                                        double((uint(val_msb)<<7) | uint(val_lsb)) / 16383.0;
1910                                    #if CONFIG_MASTER_VOLUME_SYSEX_BY_PORT
1911                                    // apply volume to all sampler channels that
1912                                    // are connected to the same MIDI input port
1913                                    // this sysex message arrived on
1914                                    for (int i = 0; i < engineChannels.size(); ++i) {
1915                                        EngineChannel* pEngineChannel = engineChannels[i];
1916                                        if (pEngineChannel->GetMidiInputPort() ==
1917                                            itSysexEvent->pMidiInputPort)
1918                                        {
1919                                            pEngineChannel->Volume(volume);
1920                                        }
1921                                    }
1922                                    #else
1923                                    // apply volume globally to the whole sampler
1924                                    GLOBAL_VOLUME = volume;
1925                                    #endif // CONFIG_MASTER_VOLUME_SYSEX_BY_PORT
1926                                    break;
1927                                }
1928                            }
1929                            break;
1930                    }
1931                    break;
1932                }
1933                case 0x41: { // Roland
1934                    dmsg(3,("Roland Sysex\n"));
1935                    uint8_t device_id, model_id, cmd_id;
1936                    if (!reader.pop(&device_id)) goto free_sysex_data;
1937                    if (!reader.pop(&model_id))  goto free_sysex_data;
1938                    if (!reader.pop(&cmd_id))    goto free_sysex_data;
1939                    if (model_id != 0x42 /*GS*/) goto free_sysex_data;
1940                    if (cmd_id != 0x12 /*DT1*/)  goto free_sysex_data;
1941    
1942                    // command address
1943                    uint8_t addr[3]; // 2 byte addr MSB, followed by 1 byte addr LSB)
1944                    const RingBuffer<uint8_t,false>::NonVolatileReader checksum_reader = reader; // so we can calculate the check sum later
1945                    if (reader.read(&addr[0], 3) != 3) goto free_sysex_data;
1946                    if (addr[0] == 0x40 && addr[1] == 0x00) { // System Parameters
1947                        dmsg(3,("\tSystem Parameter\n"));
1948                    }
1949                    else if (addr[0] == 0x40 && addr[1] == 0x01) { // Common Parameters
1950                        dmsg(3,("\tCommon Parameter\n"));
1951                    }
1952                    else if (addr[0] == 0x40 && (addr[1] & 0xf0) == 0x10) { // Part Parameters (1)
1953                        dmsg(3,("\tPart Parameter\n"));
1954                        switch (addr[2]) {
1955                            case 0x40: { // scale tuning
1956                                dmsg(3,("\t\tScale Tuning\n"));
1957                                uint8_t scale_tunes[12]; // detuning of all 12 semitones of an octave
1958                                if (reader.read(&scale_tunes[0], 12) != 12) goto free_sysex_data;
1959                                uint8_t checksum;
1960                                if (!reader.pop(&checksum)) goto free_sysex_data;
1961                                #if CONFIG_ASSERT_GS_SYSEX_CHECKSUM
1962                                if (GSCheckSum(checksum_reader, 12)) goto free_sysex_data;
1963                                #endif // CONFIG_ASSERT_GS_SYSEX_CHECKSUM
1964                                for (int i = 0; i < 12; i++) scale_tunes[i] -= 64;
1965                                AdjustScale((int8_t*) scale_tunes);
1966                                dmsg(3,("\t\t\tNew scale applied.\n"));
1967                                break;
1968                            }
1969                            case 0x15: { // chromatic / drumkit mode
1970                                dmsg(3,("\t\tMIDI Instrument Map Switch\n"));
1971                                uint8_t part = addr[1] & 0x0f;
1972                                uint8_t map;
1973                                if (!reader.pop(&map)) goto free_sysex_data;
1974                                for (int i = 0; i < engineChannels.size(); ++i) {
1975                                    EngineChannel* pEngineChannel = engineChannels[i];
1976                                    if (
1977                                        (pEngineChannel->midiChannel == part ||
1978                                         pEngineChannel->midiChannel == midi_chan_all) &&
1979                                         pEngineChannel->GetMidiInputPort() == itSysexEvent->pMidiInputPort
1980                                    ) {
1981                                        try {
1982                                            pEngineChannel->SetMidiInstrumentMap(map);
1983                                        } catch (Exception e) {
1984                                            dmsg(2,("\t\t\tCould not apply MIDI instrument map %d to part %d: %s\n", map, part, e.Message().c_str()));
1985                                            goto free_sysex_data;
1986                                        } catch (...) {
1987                                            dmsg(2,("\t\t\tCould not apply MIDI instrument map %d to part %d (unknown exception)\n", map, part));
1988                                            goto free_sysex_data;
1989                                        }
1990                                    }
1991                                }
1992                                dmsg(3,("\t\t\tApplied MIDI instrument map %d to part %d.\n", map, part));
1993                                break;
1994                            }
1995                        }
1996                    }
1997                    else if (addr[0] == 0x40 && (addr[1] & 0xf0) == 0x20) { // Part Parameters (2)
1998                    }
1999                    else if (addr[0] == 0x41) { // Drum Setup Parameters
2000                    }
2001                    break;
2002                }
2003          }          }
2004    
2005            free_sysex_data: // finally free sysex data
2006            pSysexBuffer->increment_read_ptr(itSysexEvent->Param.Sysex.Size);
2007      }      }
2008    
2009      float Engine::Volume() {      /**
2010          return GlobalVolume;       * Calculates the Roland GS sysex check sum.
2011         *
2012         * @param AddrReader - reader which currently points to the first GS
2013         *                     command address byte of the GS sysex message in
2014         *                     question
2015         * @param DataSize   - size of the GS message data (in bytes)
2016         */
2017        uint8_t Engine::GSCheckSum(const RingBuffer<uint8_t,false>::NonVolatileReader AddrReader, uint DataSize) {
2018            RingBuffer<uint8_t,false>::NonVolatileReader reader = AddrReader;
2019            uint bytes = 3 /*addr*/ + DataSize;
2020            uint8_t addr_and_data[bytes];
2021            reader.read(&addr_and_data[0], bytes);
2022            uint8_t sum = 0;
2023            for (uint i = 0; i < bytes; i++) sum += addr_and_data[i];
2024            return 128 - sum % 128;
2025      }      }
2026    
2027      void Engine::Volume(float f) {      /**
2028          GlobalVolume = f;       * Allows to tune each of the twelve semitones of an octave.
2029         *
2030         * @param ScaleTunes - detuning of all twelve semitones (in cents)
2031         */
2032        void Engine::AdjustScale(int8_t ScaleTunes[12]) {
2033            memcpy(&this->ScaleTuning[0], &ScaleTunes[0], 12); //TODO: currently not sample accurate
2034      }      }
2035    
2036      uint Engine::Channels() {      /**
2037          return 2;       * Releases all voices on an engine channel. All voices will go into
2038         * the release stage and thus it might take some time (e.g. dependant to
2039         * their envelope release time) until they actually die.
2040         *
2041         * @param pEngineChannel - engine channel on which all voices should be released
2042         * @param itReleaseEvent - event which caused this releasing of all voices
2043         */
2044        void Engine::ReleaseAllVoices(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itReleaseEvent) {
2045            RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
2046            while (iuiKey) {
2047                midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
2048                ++iuiKey;
2049                // append a 'release' event to the key's own event list
2050                RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
2051                if (itNewEvent) {
2052                    *itNewEvent = *itReleaseEvent; // copy original event (to the key's event list)
2053                    itNewEvent->Type = Event::type_release; // transform event type
2054                }
2055                else dmsg(1,("Event pool emtpy!\n"));
2056            }
2057      }      }
2058    
2059      void Engine::SetOutputChannel(uint EngineAudioChannel, uint AudioDeviceChannel) {      /**
2060          AudioChannel* pChannel = pAudioOutputDevice->Channel(AudioDeviceChannel);       * Kills all voices on an engine channel as soon as possible. Voices
2061          if (!pChannel) throw AudioOutputException("Invalid audio output device channel " + ToString(AudioDeviceChannel));       * won't get into release state, their volume level will be ramped down
2062          switch (EngineAudioChannel) {       * as fast as possible.
2063              case 0: // left output channel       *
2064                  pOutputLeft = pChannel->Buffer();       * @param pEngineChannel - engine channel on which all voices should be killed
2065                  AudioDeviceChannelLeft = AudioDeviceChannel;       * @param itKillEvent    - event which caused this killing of all voices
2066                  break;       */
2067              case 1: // right output channel      void Engine::KillAllVoices(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itKillEvent) {
2068                  pOutputRight = pChannel->Buffer();          RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
2069                  AudioDeviceChannelRight = AudioDeviceChannel;          RTList<uint>::Iterator end    = pEngineChannel->pActiveKeys->end();
2070                  break;          while (iuiKey != end) { // iterate through all active keys
2071              default:              midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
2072                  throw AudioOutputException("Invalid engine audio channel " + ToString(EngineAudioChannel));              ++iuiKey;
2073                RTList<Voice>::Iterator itVoice     = pKey->pActiveVoices->first();
2074                RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();
2075                for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
2076                    itVoice->Kill(itKillEvent);
2077                    --VoiceSpawnsLeft; //FIXME: just a temporary workaround, we should check the cause in StealVoice() instead
2078                }
2079          }          }
2080      }      }
2081    
2082      int Engine::OutputChannel(uint EngineAudioChannel) {      /**
2083          switch (EngineAudioChannel) {       * Determines whether the specified voice should be released.
2084              case 0: // left channel       *
2085                  return AudioDeviceChannelLeft;       * @param pEngineChannel - The engine channel on which the voice should be checked
2086              case 1: // right channel       * @param Key - The key number
2087                  return AudioDeviceChannelRight;       * @returns true if the specified should be released, false otherwise.
2088              default:       */
2089                  throw AudioOutputException("Invalid engine audio channel " + ToString(EngineAudioChannel));      bool Engine::ShouldReleaseVoice(EngineChannel* pEngineChannel, int Key) {
2090            if (pEngineChannel->SustainPedal) return false;
2091    
2092            if (pEngineChannel->SostenutoPedal) {
2093                for (int i = 0; i < SostenutoKeyCount; i++)
2094                    if (Key == SostenutoKeys[i]) return false;
2095          }          }
2096    
2097            return true;
2098      }      }
2099    
2100      uint Engine::VoiceCount() {      uint Engine::VoiceCount() {
# Line 802  namespace LinuxSampler { namespace gig { Line 2126  namespace LinuxSampler { namespace gig {
2126      }      }
2127    
2128      String Engine::EngineName() {      String Engine::EngineName() {
2129          return "GigEngine";          return LS_GIG_ENGINE_NAME;
2130      }      }
2131    
2132      String Engine::InstrumentFileName() {      String Engine::Description() {
2133          return InstrumentFile;          return "Gigasampler Format Engine";
     }  
   
     int Engine::InstrumentIndex() {  
         return InstrumentIdx;  
2134      }      }
2135    
2136      int Engine::InstrumentStatus() {      String Engine::Version() {
2137          return InstrumentStat;          String s = "$Revision: 1.96 $";
2138            return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword
2139      }      }
2140    
2141      String Engine::Description() {      InstrumentManager* Engine::GetInstrumentManager() {
2142          return "Gigasampler Engine";          return &instruments;
2143      }      }
2144    
2145      String Engine::Version() {      // static constant initializers
2146          String s = "$Revision: 1.10 $";      const Engine::FloatTable Engine::VolumeCurve(InitVolumeCurve());
2147          return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword      const Engine::FloatTable Engine::PanCurve(InitPanCurve());
2148        const Engine::FloatTable Engine::CrossfadeCurve(InitCrossfadeCurve());
2149    
2150        float* Engine::InitVolumeCurve() {
2151            // line-segment approximation
2152            const float segments[] = {
2153                0, 0, 2, 0.0046, 16, 0.016, 31, 0.051, 45, 0.115, 54.5, 0.2,
2154                64.5, 0.39, 74, 0.74, 92, 1.03, 114, 1.94, 119.2, 2.2, 127, 2.2
2155            };
2156            return InitCurve(segments);
2157        }
2158    
2159        float* Engine::InitPanCurve() {
2160            // line-segment approximation
2161            const float segments[] = {
2162                0, 0, 1, 0,
2163                2, 0.05, 31.5, 0.7, 51, 0.851, 74.5, 1.12,
2164                127, 1.41, 128, 1.41
2165            };
2166            return InitCurve(segments, 129);
2167        }
2168    
2169        float* Engine::InitCrossfadeCurve() {
2170            // line-segment approximation
2171            const float segments[] = {
2172                0, 0, 1, 0.03, 10, 0.1, 51, 0.58, 127, 1
2173            };
2174            return InitCurve(segments);
2175        }
2176    
2177        float* Engine::InitCurve(const float* segments, int size) {
2178            float* y = new float[size];
2179            for (int x = 0 ; x < size ; x++) {
2180                if (x > segments[2]) segments += 2;
2181                y[x] = segments[1] + (x - segments[0]) *
2182                    (segments[3] - segments[1]) / (segments[2] - segments[0]);
2183            }
2184            return y;
2185      }      }
2186    
2187  }} // namespace LinuxSampler::gig  }} // namespace LinuxSampler::gig

Legend:
Removed from v.239  
changed lines
  Added in v.1762

  ViewVC Help
Powered by ViewVC