/[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 287 by schoenebeck, Sat Oct 16 17:38:03 2004 UTC revision 1750 by schoenebeck, Thu Jul 10 15:00:38 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 24  Line 25 
25  #include "DiskThread.h"  #include "DiskThread.h"
26  #include "Voice.h"  #include "Voice.h"
27  #include "EGADSR.h"  #include "EGADSR.h"
28    #include "../EngineFactory.h"
29    
30  #include "Engine.h"  #include "Engine.h"
31    
32    #include "../../common/global_private.h"
33    
34  namespace LinuxSampler { namespace gig {  namespace LinuxSampler { namespace gig {
35    
36      InstrumentResourceManager Engine::Instruments;      InstrumentResourceManager Engine::instruments;
37    
38        std::map<AudioOutputDevice*,Engine*> Engine::engines;
39    
40        /**
41         * Get a gig::Engine object for the given gig::EngineChannel and the
42         * given AudioOutputDevice. All engine channels which are connected to
43         * the same audio output device will use the same engine instance. This
44         * method will be called by a gig::EngineChannel whenever it's
45         * connecting to a audio output device.
46         *
47         * @param pChannel - engine channel which acquires an engine object
48         * @param pDevice  - the audio output device \a pChannel is connected to
49         */
50        Engine* Engine::AcquireEngine(LinuxSampler::gig::EngineChannel* pChannel, AudioOutputDevice* pDevice) {
51            Engine* pEngine = NULL;
52            // check if there's already an engine for the given audio output device
53            if (engines.count(pDevice)) {
54                dmsg(4,("Using existing gig::Engine.\n"));
55                pEngine = engines[pDevice];
56    
57                // Disable the engine while the new engine channel is
58                // added and initialized. The engine will be enabled again
59                // in EngineChannel::Connect.
60                pEngine->DisableAndLock();
61            } else { // create a new engine (and disk thread) instance for the given audio output device
62                dmsg(4,("Creating new gig::Engine.\n"));
63                pEngine = (Engine*) EngineFactory::Create("gig");
64                pEngine->Connect(pDevice);
65                engines[pDevice] = pEngine;
66            }
67            // register engine channel to the engine instance
68            pEngine->engineChannels.add(pChannel);
69            // remember index in the ArrayList
70            pChannel->iEngineIndexSelf = pEngine->engineChannels.size() - 1;
71            dmsg(4,("This gig::Engine has now %d EngineChannels.\n",pEngine->engineChannels.size()));
72            return pEngine;
73        }
74    
75      Engine::Engine() {      /**
76          pRIFF              = NULL;       * Once an engine channel is disconnected from an audio output device,
77          pGig               = NULL;       * it will immediately call this method to unregister itself from the
78          pInstrument        = NULL;       * engine instance and if that engine instance is not used by any other
79         * engine channel anymore, then that engine instance will be destroyed.
80         *
81         * @param pChannel - engine channel which wants to disconnect from it's
82         *                   engine instance
83         * @param pDevice  - audio output device \a pChannel was connected to
84         */
85        void Engine::FreeEngine(LinuxSampler::gig::EngineChannel* pChannel, AudioOutputDevice* pDevice) {
86            dmsg(4,("Disconnecting EngineChannel from gig::Engine.\n"));
87            Engine* pEngine = engines[pDevice];
88            // unregister EngineChannel from the Engine instance
89            pEngine->engineChannels.remove(pChannel);
90            // if the used Engine instance is not used anymore, then destroy it
91            if (pEngine->engineChannels.empty()) {
92                pDevice->Disconnect(pEngine);
93                engines.erase(pDevice);
94                delete pEngine;
95                dmsg(4,("Destroying gig::Engine.\n"));
96            }
97            else dmsg(4,("This gig::Engine has now %d EngineChannels.\n",pEngine->engineChannels.size()));
98        }
99    
100        /**
101         * Constructor
102         */
103        Engine::Engine() : SuspendedRegions(128) {
104          pAudioOutputDevice = NULL;          pAudioOutputDevice = NULL;
105          pDiskThread        = NULL;          pDiskThread        = NULL;
106          pEventGenerator    = NULL;          pEventGenerator    = NULL;
107          pSysexBuffer       = new RingBuffer<uint8_t>(SYSEX_BUFFER_SIZE, 0);          pSysexBuffer       = new RingBuffer<uint8_t,false>(CONFIG_SYSEX_BUFFER_SIZE, 0);
108          pEventQueue        = new RingBuffer<Event>(MAX_EVENTS_PER_FRAGMENT, 0);          pEventQueue        = new RingBuffer<Event,false>(CONFIG_MAX_EVENTS_PER_FRAGMENT, 0);
109          pEventPool         = new Pool<Event>(MAX_EVENTS_PER_FRAGMENT);          pEventPool         = new Pool<Event>(CONFIG_MAX_EVENTS_PER_FRAGMENT);
110          pVoicePool         = new Pool<Voice>(MAX_AUDIO_VOICES);          pVoicePool         = new Pool<Voice>(CONFIG_MAX_VOICES);
111          pActiveKeys        = new Pool<uint>(128);          pDimRegionPool[0]  = new Pool< ::gig::DimensionRegion*>(CONFIG_MAX_VOICES);
112            pDimRegionPool[1]  = new Pool< ::gig::DimensionRegion*>(CONFIG_MAX_VOICES);
113          pVoiceStealingQueue = new RTList<Event>(pEventPool);          pVoiceStealingQueue = new RTList<Event>(pEventPool);
114          pEvents            = new RTList<Event>(pEventPool);          pGlobalEvents      = new RTList<Event>(pEventPool);
115          pCCEvents          = new RTList<Event>(pEventPool);  
         for (uint i = 0; i < Event::destination_count; i++) {  
             pSynthesisEvents[i] = new RTList<Event>(pEventPool);  
         }  
         for (uint i = 0; i < 128; i++) {  
             pMIDIKeyInfo[i].pActiveVoices  = new RTList<Voice>(pVoicePool);  
             pMIDIKeyInfo[i].KeyPressed     = false;  
             pMIDIKeyInfo[i].Active         = false;  
             pMIDIKeyInfo[i].ReleaseTrigger = false;  
             pMIDIKeyInfo[i].pEvents        = new RTList<Event>(pEventPool);  
         }  
116          for (RTList<Voice>::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {          for (RTList<Voice>::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
117              iterVoice->SetEngine(this);              iterVoice->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          if (pSysexBuffer) delete pSysexBuffer;              delete pVoicePool;
142            }
143          if (pEventGenerator) delete pEventGenerator;          if (pEventGenerator) delete pEventGenerator;
         if (pMainFilterParameters) delete[] pMainFilterParameters;  
         if (pBasicFilterParameters) delete[] pBasicFilterParameters;  
         if (pSynthesisParameters[0]) delete[] pSynthesisParameters[0];  
144          if (pVoiceStealingQueue) delete pVoiceStealingQueue;          if (pVoiceStealingQueue) delete pVoiceStealingQueue;
145            if (pSysexBuffer) delete pSysexBuffer;
146            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 109  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 122  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;  
296    
297          // reset voice stealing parameters          // reset voice stealing parameters
         itLastStolenVoice = RTList<Voice>::Iterator();  
         iuiLastStolenKey  = RTList<uint>::Iterator();  
298          pVoiceStealingQueue->clear();          pVoiceStealingQueue->clear();
299            itLastStolenVoice          = RTList<Voice>::Iterator();
300          // reset to normal chromatic scale (means equal temper)          itLastStolenVoiceGlobally  = RTList<Voice>::Iterator();
301          memset(&ScaleTuning[0], 0x00, 12);          iuiLastStolenKey           = RTList<uint>::Iterator();
302            iuiLastStolenKeyGlobally   = RTList<uint>::Iterator();
303          // set all MIDI controller values to zero          pLastStolenChannel         = NULL;
         memset(ControllerTable, 0x00, 128);  
   
         // reset key info  
         for (uint i = 0; i < 128; i++) {  
             pMIDIKeyInfo[i].pActiveVoices->clear();  
             pMIDIKeyInfo[i].pEvents->clear();  
             pMIDIKeyInfo[i].KeyPressed     = false;  
             pMIDIKeyInfo[i].Active         = false;  
             pMIDIKeyInfo[i].ReleaseTrigger = false;  
             pMIDIKeyInfo[i].itSelf         = Pool<uint>::Iterator();  
         }  
   
         // 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 (RTList<Voice>::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {          for (RTList<Voice>::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
# Line 190  namespace LinuxSampler { namespace gig { Line 308  namespace LinuxSampler { namespace gig {
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 304  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          // FIXME: audio drivers with varying fragment sizes might be a problem here                        << "May lead to click sounds if voice stealing chimes in!\n" << std::flush;
366          MaxFadeOutPos = MaxSamplesPerCycle - int(double(SampleRate) * EG_MIN_RELEASE_TIME) - 1;              // force volume ramp downs at the beginning of each fragment
367          if (MaxFadeOutPos < 0)              MinFadeOutSamples = MaxSamplesPerCycle;
368              throw LinuxSamplerException("EG_MIN_RELEASE_TIME in EGADSR.h to big for current audio fragment size / sampling rate!");              // 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);
# Line 340  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"));
# Line 364  namespace LinuxSampler { namespace gig { Line 409  namespace LinuxSampler { namespace gig {
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          }          }
         if (!pInstrument) {  
             dmsg(5,("gig::Engine: no instrument loaded\n"));  
             return 0;  
         }  
578    
579            // process requests for suspending / resuming regions (i.e. to avoid
580            // crashes while these regions are modified by an instrument editor)
581            ProcessSuspensionsChanges();
582    
583          // empty the event lists for the new fragment          // update time of start and end of this audio fragment (as events' time stamps relate to this)
584          pEvents->clear();          pEventGenerator->UpdateFragmentTime(Samples);
585          pCCEvents->clear();  
586          for (uint i = 0; i < Event::destination_count; i++) {          // We only allow a maximum of CONFIG_MAX_VOICES voices to be spawned
587              pSynthesisEvents[i]->clear();          // 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<uint>::Iterator iuiKey = pActiveKeys->first();              RTList<Event>::Iterator itEvent = pGlobalEvents->first();
598              RTList<uint>::Iterator end    = pActiveKeys->end();              RTList<Event>::Iterator end     = pGlobalEvents->end();
599              for(; iuiKey != end; ++iuiKey) {              for (; itEvent != end; ++itEvent) {
600                  pMIDIKeyInfo[*iuiKey].pEvents->clear(); // free all events on the key                  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          // read and copy events from input queue          // reset internal voice counter (just for statistic of active voices)
610          Event event = pEventGenerator->CreateEvent();          ActiveVoiceCountTemp = 0;
611          while (true) {  
612              if (!pEventQueue->pop(&event) || pEvents->poolIsEmpty()) break;          // handle instrument change commands
613              *pEvents->allocAppend() = event;          bool instrumentChanged = false;
614            for (int i = 0; i < engineChannels.size(); i++) {
615                EngineChannel* pEngineChannel = engineChannels[i];
616    
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            // handle events on all engine channels
657            for (int i = 0; i < engineChannels.size(); i++) {
658                ProcessEvents(engineChannels[i], Samples);
659            }
660    
661          // update time of start and end of this audio fragment (as events' time stamps relate to this)          // render all 'normal', active voices on all engine channels
662          pEventGenerator->UpdateFragmentTime(Samples);          for (int i = 0; i < engineChannels.size(); i++) {
663                RenderActiveVoices(engineChannels[i], Samples);
664            }
665    
666            // now that all ordinary voices on ALL engine channels are rendered, render new stolen voices
667            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            // handle cleanup on all engine channels for the next audio fragment
676            for (int i = 0; i < engineChannels.size(); i++) {
677                PostProcess(engineChannels[i]);
678            }
679    
680    
681            // empty the engine's event list for the next audio fragment
682            ClearEventLists();
683    
684            // reset voice stealing for the next audio fragment
685            pVoiceStealingQueue->clear();
686    
687            // just some statistics about this engine instance
688            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          // process events
719          {          {
720              RTList<Event>::Iterator itEvent = pEvents->first();              RTList<Event>::Iterator itEvent = pEngineChannel->pEvents->first();
721              RTList<Event>::Iterator end     = pEvents->end();              RTList<Event>::Iterator end     = pEngineChannel->pEvents->end();
722              for (; itEvent != end; ++itEvent) {              for (; itEvent != end; ++itEvent) {
723                  switch (itEvent->Type) {                  switch (itEvent->Type) {
724                      case Event::type_note_on:                      case Event::type_note_on:
725                          dmsg(5,("Engine: Note on received\n"));                          dmsg(5,("Engine: Note on received\n"));
726                          ProcessNoteOn(itEvent);                          ProcessNoteOn((EngineChannel*)itEvent->pEngineChannel, itEvent);
727                          break;                          break;
728                      case Event::type_note_off:                      case Event::type_note_off:
729                          dmsg(5,("Engine: Note off received\n"));                          dmsg(5,("Engine: Note off received\n"));
730                          ProcessNoteOff(itEvent);                          ProcessNoteOff((EngineChannel*)itEvent->pEngineChannel, itEvent);
731                          break;                          break;
732                      case Event::type_control_change:                      case Event::type_control_change:
733                          dmsg(5,("Engine: MIDI CC received\n"));                          dmsg(5,("Engine: MIDI CC received\n"));
734                          ProcessControlChange(itEvent);                          ProcessControlChange((EngineChannel*)itEvent->pEngineChannel, itEvent);
735                          break;                          break;
736                      case Event::type_pitchbend:                      case Event::type_pitchbend:
737                          dmsg(5,("Engine: Pitchbend received\n"));                          dmsg(5,("Engine: Pitchbend received\n"));
738                          ProcessPitchbend(itEvent);                          ProcessPitchbend((EngineChannel*)itEvent->pEngineChannel, itEvent);
                         break;  
                     case Event::type_sysex:  
                         dmsg(5,("Engine: Sysex received\n"));  
                         ProcessSysex(itEvent);  
739                          break;                          break;
740                  }                  }
741              }              }
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          int active_voices = 0;      /**
753         * Render all 'normal' voices (that is voices which were not stolen in
754          // render audio from all active voices       * this fragment) on the given engine channel.
755          {       *
756              RTList<uint>::Iterator iuiKey = pActiveKeys->first();       * @param pEngineChannel - engine channel on which audio should be
757              RTList<uint>::Iterator end    = pActiveKeys->end();       *                         rendered
758              while (iuiKey != end) { // iterate through all active keys       * @param Samples        - amount of sample points to be rendered in
759                  midi_key_info_t* pKey = &pMIDIKeyInfo[*iuiKey];       *                         this audio fragment cycle
760                  ++iuiKey;       */
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                  RTList<Voice>::Iterator itVoice     = pKey->pActiveVoices->first();                      if (itVoice->PlaybackState == Voice::playback_state_disk) {
787                  RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();                          if ((itVoice->DiskStreamRef).State == Stream::state_active) streamCount++;
                 for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key  
                     // now render current voice  
                     itVoice->Render(Samples);  
                     if (itVoice->IsActive()) active_voices++; // still active  
                     else { // voice reached end, is now inactive  
                         FreeVoice(itVoice); // remove voice from the list of active voices  
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            pEngineChannel->SetVoiceCount(voiceCount);
796            pEngineChannel->SetDiskStreamCount(streamCount);
797        }
798    
799          // now render all postponed voices from voice stealing      /**
800          {       * Render all stolen voices (only voices which were stolen in this
801              RTList<Event>::Iterator itVoiceStealEvent = pVoiceStealingQueue->first();       * fragment) on the given engine channel. Stolen voices are rendered
802              RTList<Event>::Iterator end               = pVoiceStealingQueue->end();       * after all normal voices have been rendered; this is needed to render
803              for (; itVoiceStealEvent != end; ++itVoiceStealEvent) {       * audio of those voices which were selected for voice stealing until
804                  Pool<Voice>::Iterator itNewVoice = LaunchVoice(itVoiceStealEvent, itVoiceStealEvent->Param.Note.Layer, itVoiceStealEvent->Param.Note.ReleaseTrigger, false);       * the point were the stealing (that is the take over of the voice)
805                  if (itNewVoice) {       * actually happened.
806                      for (; itNewVoice; itNewVoice = itNewVoice->itChildVoice) {       *
807                          itNewVoice->Render(Samples);       * @param pEngineChannel - engine channel on which audio should be
808                          if (itNewVoice->IsActive()) active_voices++; // still active       *                         rendered
809                          else { // voice reached end, is now inactive       * @param Samples        - amount of sample points to be rendered in
810                              FreeVoice(itNewVoice); // remove voice from the list of active voices       *                         this audio fragment cycle
811         */
812        void Engine::RenderStolenVoices(uint Samples) {
813            RTList<Event>::Iterator itVoiceStealEvent = pVoiceStealingQueue->first();
814            RTList<Event>::Iterator end               = pVoiceStealingQueue->end();
815            for (; itVoiceStealEvent != end; ++itVoiceStealEvent) {
816                EngineChannel* pEngineChannel = (EngineChannel*) itVoiceStealEvent->pEngineChannel;
817                if (!pEngineChannel->pInstrument) continue; // ignore if no instrument loaded
818                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                  }                  }
                 else dmsg(1,("gig::Engine: ERROR, voice stealing didn't work out!\n"));  
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          // reset voice stealing for the new fragment      }
         pVoiceStealingQueue->clear();  
         itLastStolenVoice = RTList<Voice>::Iterator();  
         iuiLastStolenKey  = RTList<uint>::Iterator();  
844    
845        /**
846         * Will be called in case the respective engine channel sports FX send
847         * 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 pEngineChannel - engine channel from which audio should be
854         *                         routed
855         * @param Samples        - amount of sample points to be routed in
856         *                         this audio fragment cycle
857         */
858        void Engine::RouteAudio(EngineChannel* pEngineChannel, uint Samples) {
859            // route dry signal
860            {
861                AudioChannel* pDstL = pAudioOutputDevice->Channel(pEngineChannel->AudioDeviceChannelLeft);
862                AudioChannel* pDstR = pAudioOutputDevice->Channel(pEngineChannel->AudioDeviceChannelRight);
863                pEngineChannel->pChannelLeft->MixTo(pDstL, Samples);
864                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         * Free all keys which have turned inactive in this audio fragment, from
918         * the list of active keys and clear all event lists on that engine
919         * channel.
920         *
921         * @param pEngineChannel - engine channel to cleanup
922         */
923        void Engine::PostProcess(EngineChannel* pEngineChannel) {
924          // free all keys which have no active voices left          // free all keys which have no active voices left
925          {          {
926              RTList<uint>::Iterator iuiKey = pActiveKeys->first();              RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
927              RTList<uint>::Iterator end    = pActiveKeys->end();              RTList<uint>::Iterator end    = pEngineChannel->pActiveKeys->end();
928              while (iuiKey != end) { // iterate through all active keys              while (iuiKey != end) { // iterate through all active keys
929                  midi_key_info_t* pKey = &pMIDIKeyInfo[*iuiKey];                  midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
930                  ++iuiKey;                  ++iuiKey;
931                  if (pKey->pActiveVoices->isEmpty()) FreeKey(pKey);                  if (pKey->pActiveVoices->isEmpty()) FreeKey(pEngineChannel, pKey);
932                  #if DEVMODE                  #if CONFIG_DEVMODE
933                  else { // FIXME: should be removed before the final release (purpose: just a sanity check for debugging)                  else { // just a sanity check for debugging
934                      RTList<Voice>::Iterator itVoice     = pKey->pActiveVoices->first();                      RTList<Voice>::Iterator itVoice     = pKey->pActiveVoices->first();
935                      RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();                      RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();
936                      for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key                      for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
# Line 521  namespace LinuxSampler { namespace gig { Line 939  namespace LinuxSampler { namespace gig {
939                          }                          }
940                      }                      }
941                  }                  }
942                  #endif // DEVMODE                  #endif // CONFIG_DEVMODE
943              }              }
944          }          }
945    
946            // empty the engine channel's own event lists
947          // write that to the disk thread class so that it can print it          pEngineChannel->ClearEventLists();
         // on the console for debugging purposes  
         ActiveVoiceCount = active_voices;  
         if (ActiveVoiceCount > ActiveVoiceCountMax) ActiveVoiceCountMax = ActiveVoiceCount;  
   
   
         return 0;  
     }  
   
     /**  
      *  Will be called by the MIDIIn Thread to let the audio thread trigger a new  
      *  voice for the given key.  
      *  
      *  @param Key      - MIDI key number of the triggered key  
      *  @param Velocity - MIDI velocity value of the triggered key  
      */  
     void Engine::SendNoteOn(uint8_t Key, uint8_t Velocity) {  
         Event event               = pEventGenerator->CreateEvent();  
         event.Type                = Event::type_note_on;  
         event.Param.Note.Key      = Key;  
         event.Param.Note.Velocity = Velocity;  
         if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);  
         else dmsg(1,("Engine: Input event queue full!"));  
     }  
   
     /**  
      *  Will be called by the MIDIIn Thread to signal the audio thread to release  
      *  voice(s) on the given key.  
      *  
      *  @param Key      - MIDI key number of the released key  
      *  @param Velocity - MIDI release velocity value of the released key  
      */  
     void Engine::SendNoteOff(uint8_t Key, uint8_t Velocity) {  
         Event event               = pEventGenerator->CreateEvent();  
         event.Type                = Event::type_note_off;  
         event.Param.Note.Key      = Key;  
         event.Param.Note.Velocity = Velocity;  
         if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);  
         else dmsg(1,("Engine: Input event queue full!"));  
     }  
   
     /**  
      *  Will be called by the MIDIIn Thread to signal the audio thread to change  
      *  the pitch value for all voices.  
      *  
      *  @param Pitch - MIDI pitch value (-8192 ... +8191)  
      */  
     void Engine::SendPitchbend(int Pitch) {  
         Event event             = pEventGenerator->CreateEvent();  
         event.Type              = Event::type_pitchbend;  
         event.Param.Pitch.Pitch = Pitch;  
         if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);  
         else dmsg(1,("Engine: Input event queue full!"));  
     }  
   
     /**  
      *  Will be called by the MIDIIn Thread to signal the audio thread that a  
      *  continuous controller value has changed.  
      *  
      *  @param Controller - MIDI controller number of the occured control change  
      *  @param Value      - value of the control change  
      */  
     void Engine::SendControlChange(uint8_t Controller, uint8_t Value) {  
         Event event               = pEventGenerator->CreateEvent();  
         event.Type                = Event::type_control_change;  
         event.Param.CC.Controller = Controller;  
         event.Param.CC.Value      = Value;  
         if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);  
         else dmsg(1,("Engine: Input event queue full!"));  
948      }      }
949    
950      /**      /**
# Line 608  namespace LinuxSampler { namespace gig { Line 958  namespace LinuxSampler { namespace gig {
958          Event event             = pEventGenerator->CreateEvent();          Event event             = pEventGenerator->CreateEvent();
959          event.Type              = Event::type_sysex;          event.Type              = Event::type_sysex;
960          event.Param.Sysex.Size  = Size;          event.Param.Sysex.Size  = Size;
961            event.pEngineChannel    = NULL; // as Engine global event
962          if (pEventQueue->write_space() > 0) {          if (pEventQueue->write_space() > 0) {
963              if (pSysexBuffer->write_space() >= Size) {              if (pSysexBuffer->write_space() >= Size) {
964                  // copy sysex data to input buffer                  // copy sysex data to input buffer
# Line 623  namespace LinuxSampler { namespace gig { Line 974  namespace LinuxSampler { namespace gig {
974                  // finally place sysex event into input event queue                  // finally place sysex event into input event queue
975                  pEventQueue->push(&event);                  pEventQueue->push(&event);
976              }              }
977              else dmsg(1,("Engine: Sysex message too large (%d byte) for input buffer (%d byte)!",Size,SYSEX_BUFFER_SIZE));              else dmsg(1,("Engine: Sysex message too large (%d byte) for input buffer (%d byte)!",Size,CONFIG_SYSEX_BUFFER_SIZE));
978          }          }
979          else dmsg(1,("Engine: Input event queue full!"));          else dmsg(1,("Engine: Input event queue full!"));
980      }      }
# Line 631  namespace LinuxSampler { namespace gig { Line 982  namespace LinuxSampler { namespace gig {
982      /**      /**
983       *  Assigns and triggers a new voice for the respective MIDI key.       *  Assigns and triggers a new voice for the respective MIDI key.
984       *       *
985         *  @param pEngineChannel - engine channel on which this event occured on
986       *  @param itNoteOnEvent - key, velocity and time stamp of the event       *  @param itNoteOnEvent - key, velocity and time stamp of the event
987       */       */
988      void Engine::ProcessNoteOn(Pool<Event>::Iterator& itNoteOnEvent) {      void Engine::ProcessNoteOn(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent) {
989          midi_key_info_t* pKey = &pMIDIKeyInfo[itNoteOnEvent->Param.Note.Key];          #if !CONFIG_PROCESS_MUTED_CHANNELS
990            if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
991            #endif
992    
993            if (!pEngineChannel->pInstrument) return; // ignore if no instrument loaded
994    
995            //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
996            itNoteOnEvent->Param.Note.Key += pEngineChannel->GlobalTranspose;
997    
998            const int key = itNoteOnEvent->Param.Note.Key;
999            midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[key];
1000    
1001            // move note on event to the key's own event list
1002            RTList<Event>::Iterator itNoteOnEventOnKeyList = itNoteOnEvent.moveToEndOf(pKey->pEvents);
1003    
1004            // if Solo Mode then kill all already active voices
1005            if (pEngineChannel->SoloMode) {
1006                Pool<uint>::Iterator itYoungestKey = pEngineChannel->pActiveKeys->last();
1007                if (itYoungestKey) {
1008                    const int iYoungestKey = *itYoungestKey;
1009                    const midi_key_info_t* pOtherKey = &pEngineChannel->pMIDIKeyInfo[iYoungestKey];
1010                    if (pOtherKey->Active) {
1011                        // get final portamento position of currently active voice
1012                        if (pEngineChannel->PortamentoMode) {
1013                            RTList<Voice>::Iterator itVoice = pOtherKey->pActiveVoices->last();
1014                            if (itVoice) itVoice->UpdatePortamentoPos(itNoteOnEventOnKeyList);
1015                        }
1016                        // kill all voices on the (other) key
1017                        RTList<Voice>::Iterator itVoiceToBeKilled = pOtherKey->pActiveVoices->first();
1018                        RTList<Voice>::Iterator end               = pOtherKey->pActiveVoices->end();
1019                        for (; itVoiceToBeKilled != end; ++itVoiceToBeKilled) {
1020                            if (itVoiceToBeKilled->Type != Voice::type_release_trigger)
1021                                itVoiceToBeKilled->Kill(itNoteOnEventOnKeyList);
1022                        }
1023                    }
1024                }
1025                // set this key as 'currently active solo key'
1026                pEngineChannel->SoloKey = key;
1027            }
1028    
1029            // Change key dimension value if key is in keyswitching area
1030            {
1031                const ::gig::Instrument* pInstrument = pEngineChannel->pInstrument;
1032                if (key >= pInstrument->DimensionKeyRange.low && key <= pInstrument->DimensionKeyRange.high)
1033                    pEngineChannel->CurrentKeyDimension = float(key - pInstrument->DimensionKeyRange.low) /
1034                        (pInstrument->DimensionKeyRange.high - pInstrument->DimensionKeyRange.low + 1);
1035            }
1036    
1037          pKey->KeyPressed = true; // the MIDI key was now pressed down          pKey->KeyPressed = true; // the MIDI key was now pressed down
1038            pKey->Velocity   = itNoteOnEventOnKeyList->Param.Note.Velocity;
1039            pKey->NoteOnTime = FrameTime + itNoteOnEventOnKeyList->FragmentPos(); // will be used to calculate note length
1040    
1041          // cancel release process of voices on this key if needed          // cancel release process of voices on this key if needed
1042          if (pKey->Active && !SustainPedal) {          if (pKey->Active && !pEngineChannel->SustainPedal) {
1043              RTList<Event>::Iterator itCancelReleaseEvent = pKey->pEvents->allocAppend();              RTList<Event>::Iterator itCancelReleaseEvent = pKey->pEvents->allocAppend();
1044              if (itCancelReleaseEvent) {              if (itCancelReleaseEvent) {
1045                  *itCancelReleaseEvent = *itNoteOnEvent;                  // copy event                  *itCancelReleaseEvent = *itNoteOnEventOnKeyList;         // copy event
1046                  itCancelReleaseEvent->Type = Event::type_cancel_release; // transform event type                  itCancelReleaseEvent->Type = Event::type_cancel_release; // transform event type
1047              }              }
1048              else dmsg(1,("Event pool emtpy!\n"));              else dmsg(1,("Event pool emtpy!\n"));
1049          }          }
1050    
1051          // move note on event to the key's own event list          // allocate and trigger new voice(s) for the key
1052          RTList<Event>::Iterator itNoteOnEventOnKeyList = itNoteOnEvent.moveToEndOf(pKey->pEvents);          {
1053                // first, get total amount of required voices (dependant on amount of layers)
1054                ::gig::Region* pRegion = pEngineChannel->pInstrument->GetRegion(itNoteOnEventOnKeyList->Param.Note.Key);
1055                if (pRegion && !RegionSuspended(pRegion)) {
1056                    int voicesRequired = pRegion->Layers;
1057                    // now launch the required amount of voices
1058                    for (int i = 0; i < voicesRequired; i++)
1059                        LaunchVoice(pEngineChannel, itNoteOnEventOnKeyList, i, false, true, true);
1060                }
1061            }
1062    
1063          // allocate and trigger a new voice for the key          // if neither a voice was spawned or postponed then remove note on event from key again
1064          LaunchVoice(itNoteOnEventOnKeyList, 0, false, true);          if (!pKey->Active && !pKey->VoiceTheftsQueued)
1065                pKey->pEvents->free(itNoteOnEventOnKeyList);
1066    
1067            if (!pEngineChannel->SoloMode || pEngineChannel->PortamentoPos < 0.0f) pEngineChannel->PortamentoPos = (float) key;
1068            pKey->RoundRobinIndex++;
1069      }      }
1070    
1071      /**      /**
# Line 661  namespace LinuxSampler { namespace gig { Line 1074  namespace LinuxSampler { namespace gig {
1074       *  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.
1075       *  due to completion of sample playback).       *  due to completion of sample playback).
1076       *       *
1077         *  @param pEngineChannel - engine channel on which this event occured on
1078       *  @param itNoteOffEvent - key, velocity and time stamp of the event       *  @param itNoteOffEvent - key, velocity and time stamp of the event
1079       */       */
1080      void Engine::ProcessNoteOff(Pool<Event>::Iterator& itNoteOffEvent) {      void Engine::ProcessNoteOff(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOffEvent) {
1081          midi_key_info_t* pKey = &pMIDIKeyInfo[itNoteOffEvent->Param.Note.Key];          #if !CONFIG_PROCESS_MUTED_CHANNELS
1082            if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
1083            #endif
1084    
1085          pKey->KeyPressed = false; // the MIDI key was now released          //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
1086            itNoteOffEvent->Param.Note.Key += pEngineChannel->GlobalTranspose;
1087    
1088          // release voices on this key if needed          const int iKey = itNoteOffEvent->Param.Note.Key;
1089          if (pKey->Active && !SustainPedal) {          midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[iKey];
1090              itNoteOffEvent->Type = Event::type_release; // transform event type          pKey->KeyPressed = false; // the MIDI key was now released
         }  
1091    
1092          // move event to the key's own event list          // move event to the key's own event list
1093          RTList<Event>::Iterator itNoteOffEventOnKeyList = itNoteOffEvent.moveToEndOf(pKey->pEvents);          RTList<Event>::Iterator itNoteOffEventOnKeyList = itNoteOffEvent.moveToEndOf(pKey->pEvents);
1094    
1095          // spawn release triggered voice(s) if needed          bool bShouldRelease = pKey->Active && ShouldReleaseVoice(pEngineChannel, itNoteOffEventOnKeyList->Param.Note.Key);
1096          if (pKey->ReleaseTrigger) {  
1097              LaunchVoice(itNoteOffEventOnKeyList, 0, true, false); //FIXME: for the moment we don't perform voice stealing for release triggered samples          // in case Solo Mode is enabled, kill all voices on this key and respawn a voice on the highest pressed key (if any)
1098              pKey->ReleaseTrigger = false;          if (pEngineChannel->SoloMode && pEngineChannel->pInstrument) { //TODO: this feels like too much code just for handling solo mode :P
1099                bool bOtherKeysPressed = false;
1100                if (iKey == pEngineChannel->SoloKey) {
1101                    pEngineChannel->SoloKey = -1;
1102                    // if there's still a key pressed down, respawn a voice (group) on the highest key
1103                    for (int i = 127; i > 0; i--) {
1104                        midi_key_info_t* pOtherKey = &pEngineChannel->pMIDIKeyInfo[i];
1105                        if (pOtherKey->KeyPressed) {
1106                            bOtherKeysPressed = true;
1107                            // make the other key the new 'currently active solo key'
1108                            pEngineChannel->SoloKey = i;
1109                            // get final portamento position of currently active voice
1110                            if (pEngineChannel->PortamentoMode) {
1111                                RTList<Voice>::Iterator itVoice = pKey->pActiveVoices->first();
1112                                if (itVoice) itVoice->UpdatePortamentoPos(itNoteOffEventOnKeyList);
1113                            }
1114                            // create a pseudo note on event
1115                            RTList<Event>::Iterator itPseudoNoteOnEvent = pOtherKey->pEvents->allocAppend();
1116                            if (itPseudoNoteOnEvent) {
1117                                // copy event
1118                                *itPseudoNoteOnEvent = *itNoteOffEventOnKeyList;
1119                                // transform event to a note on event
1120                                itPseudoNoteOnEvent->Type                = Event::type_note_on;
1121                                itPseudoNoteOnEvent->Param.Note.Key      = i;
1122                                itPseudoNoteOnEvent->Param.Note.Velocity = pOtherKey->Velocity;
1123                                // allocate and trigger new voice(s) for the other key
1124                                {
1125                                    // first, get total amount of required voices (dependant on amount of layers)
1126                                    ::gig::Region* pRegion = pEngineChannel->pInstrument->GetRegion(i);
1127                                    if (pRegion) {
1128                                        int voicesRequired = pRegion->Layers;
1129                                        // now launch the required amount of voices
1130                                        for (int iLayer = 0; iLayer < voicesRequired; iLayer++)
1131                                            LaunchVoice(pEngineChannel, itPseudoNoteOnEvent, iLayer, false, true, false);
1132                                    }
1133                                }
1134                                // if neither a voice was spawned or postponed then remove note on event from key again
1135                                if (!pOtherKey->Active && !pOtherKey->VoiceTheftsQueued)
1136                                    pOtherKey->pEvents->free(itPseudoNoteOnEvent);
1137    
1138                            } else dmsg(1,("Could not respawn voice, no free event left\n"));
1139                            break; // done
1140                        }
1141                    }
1142                }
1143                if (bOtherKeysPressed) {
1144                    if (pKey->Active) { // kill all voices on this key
1145                        bShouldRelease = false; // no need to release, as we kill it here
1146                        RTList<Voice>::Iterator itVoiceToBeKilled = pKey->pActiveVoices->first();
1147                        RTList<Voice>::Iterator end               = pKey->pActiveVoices->end();
1148                        for (; itVoiceToBeKilled != end; ++itVoiceToBeKilled) {
1149                            if (itVoiceToBeKilled->Type != Voice::type_release_trigger)
1150                                itVoiceToBeKilled->Kill(itNoteOffEventOnKeyList);
1151                        }
1152                    }
1153                } else pEngineChannel->PortamentoPos = -1.0f;
1154          }          }
1155    
1156            // if no solo mode (the usual case) or if solo mode and no other key pressed, then release voices on this key if needed
1157            if (bShouldRelease) {
1158                itNoteOffEventOnKeyList->Type = Event::type_release; // transform event type
1159    
1160                // spawn release triggered voice(s) if needed
1161                if (pKey->ReleaseTrigger && pEngineChannel->pInstrument) {
1162                    // first, get total amount of required voices (dependant on amount of layers)
1163                    ::gig::Region* pRegion = pEngineChannel->pInstrument->GetRegion(itNoteOffEventOnKeyList->Param.Note.Key);
1164                    if (pRegion) {
1165                        int voicesRequired = pRegion->Layers;
1166    
1167                        // MIDI note-on velocity is used instead of note-off velocity
1168                        itNoteOffEventOnKeyList->Param.Note.Velocity = pKey->Velocity;
1169    
1170                        // now launch the required amount of voices
1171                        for (int i = 0; i < voicesRequired; i++)
1172                            LaunchVoice(pEngineChannel, itNoteOffEventOnKeyList, i, true, false, false); //FIXME: for the moment we don't perform voice stealing for release triggered samples
1173                    }
1174                    pKey->ReleaseTrigger = false;
1175                }
1176            }
1177    
1178            // if neither a voice was spawned or postponed on this key then remove note off event from key again
1179            if (!pKey->Active && !pKey->VoiceTheftsQueued)
1180                pKey->pEvents->free(itNoteOffEventOnKeyList);
1181      }      }
1182    
1183      /**      /**
1184       *  Moves pitchbend event from the general (input) event list to the pitch       *  Moves pitchbend event from the general (input) event list to the engine
1185       *  event list.       *  channel's event list. It will actually processed later by the
1186         *  respective voice.
1187       *       *
1188         *  @param pEngineChannel - engine channel on which this event occured on
1189       *  @param itPitchbendEvent - absolute pitch value and time stamp of the event       *  @param itPitchbendEvent - absolute pitch value and time stamp of the event
1190       */       */
1191      void Engine::ProcessPitchbend(Pool<Event>::Iterator& itPitchbendEvent) {      void Engine::ProcessPitchbend(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itPitchbendEvent) {
1192          this->Pitch = itPitchbendEvent->Param.Pitch.Pitch; // store current pitch value          pEngineChannel->Pitch = itPitchbendEvent->Param.Pitch.Pitch; // store current pitch value
         itPitchbendEvent.moveToEndOf(pSynthesisEvents[Event::destination_vco]);  
1193      }      }
1194    
1195      /**      /**
# Line 699  namespace LinuxSampler { namespace gig { Line 1197  namespace LinuxSampler { namespace gig {
1197       *  called by the ProcessNoteOn() method and by the voices itself       *  called by the ProcessNoteOn() method and by the voices itself
1198       *  (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).
1199       *       *
1200         *  @param pEngineChannel      - engine channel on which this event occured on
1201       *  @param itNoteOnEvent       - key, velocity and time stamp of the event       *  @param itNoteOnEvent       - key, velocity and time stamp of the event
1202       *  @param iLayer              - layer index for the new voice (optional - only       *  @param iLayer              - layer index for the new voice (optional - only
1203       *                               in case of layered sounds of course)       *                               in case of layered sounds of course)
# Line 707  namespace LinuxSampler { namespace gig { Line 1206  namespace LinuxSampler { namespace gig {
1206       *  @param VoiceStealing       - if voice stealing should be performed       *  @param VoiceStealing       - if voice stealing should be performed
1207       *                               when there is no free voice       *                               when there is no free voice
1208       *                               (optional, default = true)       *                               (optional, default = true)
1209         *  @param HandleKeyGroupConflicts - if voices should be killed due to a
1210         *                                   key group conflict
1211       *  @returns pointer to new voice or NULL if there was no free voice or       *  @returns pointer to new voice or NULL if there was no free voice or
1212       *           if an error occured while trying to trigger the new voice       *           if the voice wasn't triggered (for example when no region is
1213         *           defined for the given key).
1214       */       */
1215      Pool<Voice>::Iterator Engine::LaunchVoice(Pool<Event>::Iterator& itNoteOnEvent, int iLayer, bool ReleaseTriggerVoice, bool VoiceStealing) {      Pool<Voice>::Iterator Engine::LaunchVoice(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent, int iLayer, bool ReleaseTriggerVoice, bool VoiceStealing, bool HandleKeyGroupConflicts) {
1216          midi_key_info_t* pKey = &pMIDIKeyInfo[itNoteOnEvent->Param.Note.Key];          int MIDIKey            = itNoteOnEvent->Param.Note.Key;
1217            midi_key_info_t* pKey  = &pEngineChannel->pMIDIKeyInfo[MIDIKey];
1218            ::gig::Region* pRegion = pEngineChannel->pInstrument->GetRegion(MIDIKey);
1219    
1220            // if nothing defined for this key
1221            if (!pRegion) return Pool<Voice>::Iterator(); // nothing to do
1222    
1223            // only mark the first voice of a layered voice (group) to be in a
1224            // key group, so the layered voices won't kill each other
1225            int iKeyGroup = (iLayer == 0 && !ReleaseTriggerVoice) ? pRegion->KeyGroup : 0;
1226    
1227            // handle key group (a.k.a. exclusive group) conflicts
1228            if (HandleKeyGroupConflicts) {
1229                if (iKeyGroup) { // if this voice / key belongs to a key group
1230                    uint** ppKeyGroup = &pEngineChannel->ActiveKeyGroups[iKeyGroup];
1231                    if (*ppKeyGroup) { // if there's already an active key in that key group
1232                        midi_key_info_t* pOtherKey = &pEngineChannel->pMIDIKeyInfo[**ppKeyGroup];
1233                        // kill all voices on the (other) key
1234                        RTList<Voice>::Iterator itVoiceToBeKilled = pOtherKey->pActiveVoices->first();
1235                        RTList<Voice>::Iterator end               = pOtherKey->pActiveVoices->end();
1236                        for (; itVoiceToBeKilled != end; ++itVoiceToBeKilled) {
1237                            if (itVoiceToBeKilled->Type != Voice::type_release_trigger) {
1238                                itVoiceToBeKilled->Kill(itNoteOnEvent);
1239                                --VoiceSpawnsLeft; //FIXME: just a hack, we should better check in StealVoice() if the voice was killed due to key conflict
1240                            }
1241                        }
1242                    }
1243                }
1244            }
1245    
1246            Voice::type_t VoiceType = Voice::type_normal;
1247    
1248            // get current dimension values to select the right dimension region
1249            //TODO: for stolen voices this dimension region selection block is processed twice, this should be changed
1250            //FIXME: controller values for selecting the dimension region here are currently not sample accurate
1251            uint DimValues[8] = { 0 };
1252            for (int i = pRegion->Dimensions - 1; i >= 0; i--) {
1253                switch (pRegion->pDimensionDefinitions[i].dimension) {
1254                    case ::gig::dimension_samplechannel:
1255                        DimValues[i] = 0; //TODO: we currently ignore this dimension
1256                        break;
1257                    case ::gig::dimension_layer:
1258                        DimValues[i] = iLayer;
1259                        break;
1260                    case ::gig::dimension_velocity:
1261                        DimValues[i] = itNoteOnEvent->Param.Note.Velocity;
1262                        break;
1263                    case ::gig::dimension_channelaftertouch:
1264                        DimValues[i] = pEngineChannel->ControllerTable[128];
1265                        break;
1266                    case ::gig::dimension_releasetrigger:
1267                        VoiceType = (ReleaseTriggerVoice) ? Voice::type_release_trigger : (!iLayer) ? Voice::type_release_trigger_required : Voice::type_normal;
1268                        DimValues[i] = (uint) ReleaseTriggerVoice;
1269                        break;
1270                    case ::gig::dimension_keyboard:
1271                        DimValues[i] = (uint) (pEngineChannel->CurrentKeyDimension * pRegion->pDimensionDefinitions[i].zones);
1272                        break;
1273                    case ::gig::dimension_roundrobin:
1274                        DimValues[i] = (uint) pEngineChannel->pMIDIKeyInfo[MIDIKey].RoundRobinIndex; // incremented for each note on
1275                        break;
1276                    case ::gig::dimension_random:
1277                        RandomSeed   = RandomSeed * 1103515245 + 12345; // classic pseudo random number generator
1278                        DimValues[i] = (uint) RandomSeed >> (32 - pRegion->pDimensionDefinitions[i].bits); // highest bits are most random
1279                        break;
1280                    case ::gig::dimension_modwheel:
1281                        DimValues[i] = pEngineChannel->ControllerTable[1];
1282                        break;
1283                    case ::gig::dimension_breath:
1284                        DimValues[i] = pEngineChannel->ControllerTable[2];
1285                        break;
1286                    case ::gig::dimension_foot:
1287                        DimValues[i] = pEngineChannel->ControllerTable[4];
1288                        break;
1289                    case ::gig::dimension_portamentotime:
1290                        DimValues[i] = pEngineChannel->ControllerTable[5];
1291                        break;
1292                    case ::gig::dimension_effect1:
1293                        DimValues[i] = pEngineChannel->ControllerTable[12];
1294                        break;
1295                    case ::gig::dimension_effect2:
1296                        DimValues[i] = pEngineChannel->ControllerTable[13];
1297                        break;
1298                    case ::gig::dimension_genpurpose1:
1299                        DimValues[i] = pEngineChannel->ControllerTable[16];
1300                        break;
1301                    case ::gig::dimension_genpurpose2:
1302                        DimValues[i] = pEngineChannel->ControllerTable[17];
1303                        break;
1304                    case ::gig::dimension_genpurpose3:
1305                        DimValues[i] = pEngineChannel->ControllerTable[18];
1306                        break;
1307                    case ::gig::dimension_genpurpose4:
1308                        DimValues[i] = pEngineChannel->ControllerTable[19];
1309                        break;
1310                    case ::gig::dimension_sustainpedal:
1311                        DimValues[i] = pEngineChannel->ControllerTable[64];
1312                        break;
1313                    case ::gig::dimension_portamento:
1314                        DimValues[i] = pEngineChannel->ControllerTable[65];
1315                        break;
1316                    case ::gig::dimension_sostenutopedal:
1317                        DimValues[i] = pEngineChannel->ControllerTable[66];
1318                        break;
1319                    case ::gig::dimension_softpedal:
1320                        DimValues[i] = pEngineChannel->ControllerTable[67];
1321                        break;
1322                    case ::gig::dimension_genpurpose5:
1323                        DimValues[i] = pEngineChannel->ControllerTable[80];
1324                        break;
1325                    case ::gig::dimension_genpurpose6:
1326                        DimValues[i] = pEngineChannel->ControllerTable[81];
1327                        break;
1328                    case ::gig::dimension_genpurpose7:
1329                        DimValues[i] = pEngineChannel->ControllerTable[82];
1330                        break;
1331                    case ::gig::dimension_genpurpose8:
1332                        DimValues[i] = pEngineChannel->ControllerTable[83];
1333                        break;
1334                    case ::gig::dimension_effect1depth:
1335                        DimValues[i] = pEngineChannel->ControllerTable[91];
1336                        break;
1337                    case ::gig::dimension_effect2depth:
1338                        DimValues[i] = pEngineChannel->ControllerTable[92];
1339                        break;
1340                    case ::gig::dimension_effect3depth:
1341                        DimValues[i] = pEngineChannel->ControllerTable[93];
1342                        break;
1343                    case ::gig::dimension_effect4depth:
1344                        DimValues[i] = pEngineChannel->ControllerTable[94];
1345                        break;
1346                    case ::gig::dimension_effect5depth:
1347                        DimValues[i] = pEngineChannel->ControllerTable[95];
1348                        break;
1349                    case ::gig::dimension_none:
1350                        std::cerr << "gig::Engine::LaunchVoice() Error: dimension=none\n" << std::flush;
1351                        break;
1352                    default:
1353                        std::cerr << "gig::Engine::LaunchVoice() Error: Unknown dimension\n" << std::flush;
1354                }
1355            }
1356    
1357            // return if this is a release triggered voice and there is no
1358            // releasetrigger dimension (could happen if an instrument
1359            // change has occured between note on and off)
1360            if (ReleaseTriggerVoice && VoiceType != Voice::type_release_trigger) return Pool<Voice>::Iterator();
1361    
1362            ::gig::DimensionRegion* pDimRgn = pRegion->GetDimensionRegionByValue(DimValues);
1363    
1364            // no need to continue if sample is silent
1365            if (!pDimRgn->pSample || !pDimRgn->pSample->SamplesTotal) return Pool<Voice>::Iterator();
1366    
1367          // allocate a new voice for the key          // allocate a new voice for the key
1368          Pool<Voice>::Iterator itNewVoice = pKey->pActiveVoices->allocAppend();          Pool<Voice>::Iterator itNewVoice = pKey->pActiveVoices->allocAppend();
1369          if (itNewVoice) {          if (itNewVoice) {
1370              // launch the new voice              // launch the new voice
1371              if (itNewVoice->Trigger(itNoteOnEvent, this->Pitch, this->pInstrument, iLayer, ReleaseTriggerVoice, VoiceStealing) < 0) {              if (itNewVoice->Trigger(pEngineChannel, itNoteOnEvent, pEngineChannel->Pitch, pDimRgn, VoiceType, iKeyGroup) < 0) {
1372                  dmsg(1,("Triggering new voice failed!\n"));                  dmsg(4,("Voice not triggered\n"));
1373                  pKey->pActiveVoices->free(itNewVoice);                  pKey->pActiveVoices->free(itNewVoice);
1374              }              }
1375              else { // on success              else { // on success
1376                  uint** ppKeyGroup = NULL;                  --VoiceSpawnsLeft;
                 if (itNewVoice->KeyGroup) { // if this voice / key belongs to a key group  
                     ppKeyGroup = &ActiveKeyGroups[itNewVoice->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  
                         RTList<Voice>::Iterator itVoiceToBeKilled = pOtherKey->pActiveVoices->first();  
                         RTList<Voice>::Iterator end               = pOtherKey->pActiveVoices->end();  
                         for (; itVoiceToBeKilled != end; ++itVoiceToBeKilled) {  
                             if (itVoiceToBeKilled->Type != Voice::type_release_trigger) itVoiceToBeKilled->Kill(itNoteOnEvent);  
                         }  
                     }  
                 }  
1377                  if (!pKey->Active) { // mark as active key                  if (!pKey->Active) { // mark as active key
1378                      pKey->Active = true;                      pKey->Active = true;
1379                      pKey->itSelf = pActiveKeys->allocAppend();                      pKey->itSelf = pEngineChannel->pActiveKeys->allocAppend();
1380                      *pKey->itSelf = itNoteOnEvent->Param.Note.Key;                      *pKey->itSelf = itNoteOnEvent->Param.Note.Key;
1381                  }                  }
1382                  if (itNewVoice->KeyGroup) {                  if (itNewVoice->KeyGroup) {
1383                        uint** ppKeyGroup = &pEngineChannel->ActiveKeyGroups[itNewVoice->KeyGroup];
1384                      *ppKeyGroup = &*pKey->itSelf; // put key as the (new) active key to its key group                      *ppKeyGroup = &*pKey->itSelf; // put key as the (new) active key to its key group
1385                  }                  }
1386                  if (itNewVoice->Type == Voice::type_release_trigger_required) pKey->ReleaseTrigger = true; // mark key for the need of release triggered voice(s)                  if (itNewVoice->Type == Voice::type_release_trigger_required) pKey->ReleaseTrigger = true; // mark key for the need of release triggered voice(s)
# Line 748  namespace LinuxSampler { namespace gig { Line 1388  namespace LinuxSampler { namespace gig {
1388              }              }
1389          }          }
1390          else if (VoiceStealing) {          else if (VoiceStealing) {
1391              // first, get total amount of required voices (dependant on amount of layers)              // try to steal one voice
1392              ::gig::Region* pRegion = pInstrument->GetRegion(itNoteOnEvent->Param.Note.Key);              int result = StealVoice(pEngineChannel, itNoteOnEvent);
1393              if (!pRegion) return Pool<Voice>::Iterator(); // nothing defined for this MIDI key, so no voice needed              if (!result) { // voice stolen successfully
1394              int voicesRequired = pRegion->Layers;                  // put note-on event into voice-stealing queue, so it will be reprocessed after killed voice died
1395                    RTList<Event>::Iterator itStealEvent = pVoiceStealingQueue->allocAppend();
1396              // now steal the (remaining) amount of voices                  if (itStealEvent) {
1397              for (int i = iLayer; i < voicesRequired; i++)                      *itStealEvent = *itNoteOnEvent; // copy event
1398                  StealVoice(itNoteOnEvent);                      itStealEvent->Param.Note.Layer = iLayer;
1399                        itStealEvent->Param.Note.ReleaseTrigger = ReleaseTriggerVoice;
1400              // put note-on event into voice-stealing queue, so it will be reprocessed after killed voice died                      pKey->VoiceTheftsQueued++;
1401              RTList<Event>::Iterator itStealEvent = pVoiceStealingQueue->allocAppend();                  }
1402              if (itStealEvent) {                  else dmsg(1,("Voice stealing queue full!\n"));
                 *itStealEvent = *itNoteOnEvent; // copy event  
                 itStealEvent->Param.Note.Layer = iLayer;  
                 itStealEvent->Param.Note.ReleaseTrigger = ReleaseTriggerVoice;  
1403              }              }
             else dmsg(1,("Voice stealing queue full!\n"));  
1404          }          }
1405    
1406          return Pool<Voice>::Iterator(); // no free voice or error          return Pool<Voice>::Iterator(); // no free voice or error
# Line 776  namespace LinuxSampler { namespace gig { Line 1412  namespace LinuxSampler { namespace gig {
1412       *  voice stealing and postpone the note-on event until the selected       *  voice stealing and postpone the note-on event until the selected
1413       *  voice actually died.       *  voice actually died.
1414       *       *
1415         *  @param pEngineChannel - engine channel on which this event occured on
1416       *  @param itNoteOnEvent - key, velocity and time stamp of the event       *  @param itNoteOnEvent - key, velocity and time stamp of the event
1417         *  @returns 0 on success, a value < 0 if no active voice could be picked for voice stealing
1418       */       */
1419      void Engine::StealVoice(Pool<Event>::Iterator& itNoteOnEvent) {      int Engine::StealVoice(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent) {
1420            if (VoiceSpawnsLeft <= 0) {
1421                dmsg(1,("Max. voice thefts per audio fragment reached (you may raise CONFIG_MAX_VOICES).\n"));
1422                return -1;
1423            }
1424          if (!pEventPool->poolIsEmpty()) {          if (!pEventPool->poolIsEmpty()) {
1425    
1426              RTList<uint>::Iterator  iuiOldestKey;              RTList<Voice>::Iterator itSelectedVoice;
             RTList<Voice>::Iterator itOldestVoice;  
1427    
1428              // Select one voice for voice stealing              // Select one voice for voice stealing
1429              switch (VOICE_STEAL_ALGORITHM) {              switch (CONFIG_VOICE_STEAL_ALGO) {
1430    
1431                  // try to pick the oldest voice on the key where the new                  // try to pick the oldest voice on the key where the new
1432                  // voice should be spawned, if there is no voice on that                  // voice should be spawned, if there is no voice on that
1433                  // key, or no voice left to kill there, then procceed with                  // key, or no voice left to kill, then procceed with
1434                  // 'oldestkey' algorithm                  // 'oldestkey' algorithm
1435                  case voice_steal_algo_keymask: {                  case voice_steal_algo_oldestvoiceonkey: {
1436                      midi_key_info_t* pOldestKey = &pMIDIKeyInfo[itNoteOnEvent->Param.Note.Key];                      midi_key_info_t* pSelectedKey = &pEngineChannel->pMIDIKeyInfo[itNoteOnEvent->Param.Note.Key];
1437                      if (itLastStolenVoice) {                      itSelectedVoice = pSelectedKey->pActiveVoices->first();
1438                          itOldestVoice = itLastStolenVoice;                      // proceed iterating if voice was created in this fragment cycle
1439                          ++itOldestVoice;                      while (itSelectedVoice && !itSelectedVoice->IsStealable()) ++itSelectedVoice;
1440                      }                      // if we haven't found a voice then proceed with algorithm 'oldestkey'
1441                      else { // no voice stolen in this audio fragment cycle yet                      if (itSelectedVoice && itSelectedVoice->IsStealable()) break;
                         itOldestVoice = pOldestKey->pActiveVoices->first();  
                     }  
                     if (itOldestVoice) {  
                         iuiOldestKey = pOldestKey->itSelf;  
                         break; // selection succeeded  
                     }  
1442                  } // no break - intentional !                  } // no break - intentional !
1443    
1444                  // try to pick the oldest voice on the oldest active key                  // try to pick the oldest voice on the oldest active key
1445                  // (caution: must stay after 'keymask' algorithm !)                  // from the same engine channel
1446                    // (caution: must stay after 'oldestvoiceonkey' algorithm !)
1447                  case voice_steal_algo_oldestkey: {                  case voice_steal_algo_oldestkey: {
1448                      if (itLastStolenVoice) {                      // if we already stole in this fragment, try to proceed on same key
1449                          midi_key_info_t* pOldestKey = &pMIDIKeyInfo[*iuiLastStolenKey];                      if (this->itLastStolenVoice) {
1450                          itOldestVoice = itLastStolenVoice;                          itSelectedVoice = this->itLastStolenVoice;
1451                          ++itOldestVoice;                          do {
1452                          if (!itOldestVoice) {                              ++itSelectedVoice;
1453                              iuiOldestKey = iuiLastStolenKey;                          } while (itSelectedVoice && !itSelectedVoice->IsStealable()); // proceed iterating if voice was created in this fragment cycle
1454                              ++iuiOldestKey;                          // found a "stealable" voice ?
1455                              if (iuiOldestKey) {                          if (itSelectedVoice && itSelectedVoice->IsStealable()) {
1456                                  midi_key_info_t* pOldestKey = &pMIDIKeyInfo[*iuiOldestKey];                              // remember which voice we stole, so we can simply proceed on next voice stealing
1457                                  itOldestVoice = pOldestKey->pActiveVoices->first();                              this->itLastStolenVoice = itSelectedVoice;
1458                              }                              break; // selection succeeded
                             else {  
                                 dmsg(1,("gig::Engine: Warning, too less voices, even for voice stealing! - Better recompile with higher MAX_AUDIO_VOICES.\n"));  
                                 return;  
                             }  
1459                          }                          }
                         else iuiOldestKey = iuiLastStolenKey;  
1460                      }                      }
1461                      else { // no voice stolen in this audio fragment cycle yet                      // get (next) oldest key
1462                          iuiOldestKey = pActiveKeys->first();                      RTList<uint>::Iterator iuiSelectedKey = (this->iuiLastStolenKey) ? ++this->iuiLastStolenKey : pEngineChannel->pActiveKeys->first();
1463                          midi_key_info_t* pOldestKey = &pMIDIKeyInfo[*iuiOldestKey];                      while (iuiSelectedKey) {
1464                          itOldestVoice = pOldestKey->pActiveVoices->first();                          midi_key_info_t* pSelectedKey = &pEngineChannel->pMIDIKeyInfo[*iuiSelectedKey];
1465                            itSelectedVoice = pSelectedKey->pActiveVoices->first();
1466                            // proceed iterating if voice was created in this fragment cycle
1467                            while (itSelectedVoice && !itSelectedVoice->IsStealable()) ++itSelectedVoice;
1468                            // found a "stealable" voice ?
1469                            if (itSelectedVoice && itSelectedVoice->IsStealable()) {
1470                                // remember which voice on which key we stole, so we can simply proceed on next voice stealing
1471                                this->iuiLastStolenKey  = iuiSelectedKey;
1472                                this->itLastStolenVoice = itSelectedVoice;
1473                                break; // selection succeeded
1474                            }
1475                            ++iuiSelectedKey; // get next oldest key
1476                      }                      }
1477                      break;                      break;
1478                  }                  }
# Line 839  namespace LinuxSampler { namespace gig { Line 1481  namespace LinuxSampler { namespace gig {
1481                  case voice_steal_algo_none:                  case voice_steal_algo_none:
1482                  default: {                  default: {
1483                      dmsg(1,("No free voice (voice stealing disabled)!\n"));                      dmsg(1,("No free voice (voice stealing disabled)!\n"));
1484                      return;                      return -1;
1485                  }                  }
1486              }              }
1487    
1488              //FIXME: can be removed, just a sanity check for debugging              // if we couldn't steal a voice from the same engine channel then
1489              if (!itOldestVoice->IsActive()) dmsg(1,("gig::Engine: ERROR, tried to steal a voice which was not active !!!\n"));              // steal oldest voice on the oldest key from any other engine channel
1490                // (the smaller engine channel number, the higher priority)
1491                if (!itSelectedVoice || !itSelectedVoice->IsStealable()) {
1492                    EngineChannel* pSelectedChannel;
1493                    int            iChannelIndex;
1494                    // select engine channel
1495                    if (pLastStolenChannel) {
1496                        pSelectedChannel = pLastStolenChannel;
1497                        iChannelIndex    = pSelectedChannel->iEngineIndexSelf;
1498                    } else { // pick the engine channel followed by this engine channel
1499                        iChannelIndex    = (pEngineChannel->iEngineIndexSelf + 1) % engineChannels.size();
1500                        pSelectedChannel = engineChannels[iChannelIndex];
1501                    }
1502    
1503                    // if we already stole in this fragment, try to proceed on same key
1504                    if (this->itLastStolenVoiceGlobally) {
1505                        itSelectedVoice = this->itLastStolenVoiceGlobally;
1506                        do {
1507                            ++itSelectedVoice;
1508                        } while (itSelectedVoice && !itSelectedVoice->IsStealable()); // proceed iterating if voice was created in this fragment cycle
1509                    }
1510    
1511                    #if CONFIG_DEVMODE
1512                    EngineChannel* pBegin = pSelectedChannel; // to detect endless loop
1513                    #endif // CONFIG_DEVMODE
1514    
1515                    // did we find a 'stealable' voice?
1516                    if (itSelectedVoice && itSelectedVoice->IsStealable()) {
1517                        // remember which voice we stole, so we can simply proceed on next voice stealing
1518                        this->itLastStolenVoiceGlobally = itSelectedVoice;
1519                    } else while (true) { // iterate through engine channels
1520                        // get (next) oldest key
1521                        RTList<uint>::Iterator iuiSelectedKey = (this->iuiLastStolenKeyGlobally) ? ++this->iuiLastStolenKeyGlobally : pSelectedChannel->pActiveKeys->first();
1522                        this->iuiLastStolenKeyGlobally = RTList<uint>::Iterator(); // to prevent endless loop (see line above)
1523                        while (iuiSelectedKey) {
1524                            midi_key_info_t* pSelectedKey = &pSelectedChannel->pMIDIKeyInfo[*iuiSelectedKey];
1525                            itSelectedVoice = pSelectedKey->pActiveVoices->first();
1526                            // proceed iterating if voice was created in this fragment cycle
1527                            while (itSelectedVoice && !itSelectedVoice->IsStealable()) ++itSelectedVoice;
1528                            // found a "stealable" voice ?
1529                            if (itSelectedVoice && itSelectedVoice->IsStealable()) {
1530                                // remember which voice on which key on which engine channel we stole, so we can simply proceed on next voice stealing
1531                                this->iuiLastStolenKeyGlobally  = iuiSelectedKey;
1532                                this->itLastStolenVoiceGlobally = itSelectedVoice;
1533                                this->pLastStolenChannel        = pSelectedChannel;
1534                                goto stealable_voice_found; // selection succeeded
1535                            }
1536                            ++iuiSelectedKey; // get next key on current engine channel
1537                        }
1538                        // get next engine channel
1539                        iChannelIndex    = (iChannelIndex + 1) % engineChannels.size();
1540                        pSelectedChannel = engineChannels[iChannelIndex];
1541    
1542                        #if CONFIG_DEVMODE
1543                        if (pSelectedChannel == pBegin) {
1544                            dmsg(1,("FATAL ERROR: voice stealing endless loop!\n"));
1545                            dmsg(1,("VoiceSpawnsLeft=%d.\n", VoiceSpawnsLeft));
1546                            dmsg(1,("Exiting.\n"));
1547                            exit(-1);
1548                        }
1549                        #endif // CONFIG_DEVMODE
1550                    }
1551                }
1552    
1553                // jump point if a 'stealable' voice was found
1554                stealable_voice_found:
1555    
1556                #if CONFIG_DEVMODE
1557                if (!itSelectedVoice->IsActive()) {
1558                    dmsg(1,("gig::Engine: ERROR, tried to steal a voice which was not active !!!\n"));
1559                    return -1;
1560                }
1561                #endif // CONFIG_DEVMODE
1562    
1563              // now kill the selected voice              // now kill the selected voice
1564              itOldestVoice->Kill(itNoteOnEvent);              itSelectedVoice->Kill(itNoteOnEvent);
1565              // remember which voice on which key we stole, so we can simply proceed for the next voice stealing  
1566              this->itLastStolenVoice = itOldestVoice;              --VoiceSpawnsLeft;
1567              this->iuiLastStolenKey = iuiOldestKey;  
1568                return 0; // success
1569            }
1570            else {
1571                dmsg(1,("Event pool emtpy!\n"));
1572                return -1;
1573          }          }
         else dmsg(1,("Event pool emtpy!\n"));  
1574      }      }
1575    
1576      /**      /**
# Line 861  namespace LinuxSampler { namespace gig { Line 1579  namespace LinuxSampler { namespace gig {
1579       *  it finished to playback its sample, finished its release stage or       *  it finished to playback its sample, finished its release stage or
1580       *  just was killed.       *  just was killed.
1581       *       *
1582         *  @param pEngineChannel - engine channel on which this event occured on
1583       *  @param itVoice - points to the voice to be freed       *  @param itVoice - points to the voice to be freed
1584       */       */
1585      void Engine::FreeVoice(Pool<Voice>::Iterator& itVoice) {      void Engine::FreeVoice(EngineChannel* pEngineChannel, Pool<Voice>::Iterator& itVoice) {
1586          if (itVoice) {          if (itVoice) {
1587              midi_key_info_t* pKey = &pMIDIKeyInfo[itVoice->MIDIKey];              midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[itVoice->MIDIKey];
1588    
1589              uint keygroup = itVoice->KeyGroup;              uint keygroup = itVoice->KeyGroup;
1590    
1591                // if the sample and dimension region belong to an
1592                // instrument that is unloaded, tell the disk thread to
1593                // release them
1594                if (itVoice->Orphan) {
1595                    pDiskThread->OrderDeletionOfDimreg(itVoice->pDimRgn);
1596                }
1597    
1598              // free the voice object              // free the voice object
1599              pVoicePool->free(itVoice);              pVoicePool->free(itVoice);
1600    
1601              // if no other voices left and member of a key group, remove from key group              // if no other voices left and member of a key group, remove from key group
1602              if (pKey->pActiveVoices->isEmpty() && keygroup) {              if (pKey->pActiveVoices->isEmpty() && keygroup) {
1603                  uint** ppKeyGroup = &ActiveKeyGroups[keygroup];                  uint** ppKeyGroup = &pEngineChannel->ActiveKeyGroups[keygroup];
1604                  if (*ppKeyGroup == &*pKey->itSelf) *ppKeyGroup = NULL; // remove key from key group                  if (*ppKeyGroup == &*pKey->itSelf) *ppKeyGroup = NULL; // remove key from key group
1605              }              }
1606          }          }
# Line 885  namespace LinuxSampler { namespace gig { Line 1611  namespace LinuxSampler { namespace gig {
1611       *  Called when there's no more voice left on a key, this call will       *  Called when there's no more voice left on a key, this call will
1612       *  update the key info respectively.       *  update the key info respectively.
1613       *       *
1614         *  @param pEngineChannel - engine channel on which this event occured on
1615       *  @param pKey - key which is now inactive       *  @param pKey - key which is now inactive
1616       */       */
1617      void Engine::FreeKey(midi_key_info_t* pKey) {      void Engine::FreeKey(EngineChannel* pEngineChannel, midi_key_info_t* pKey) {
1618          if (pKey->pActiveVoices->isEmpty()) {          if (pKey->pActiveVoices->isEmpty()) {
1619              pKey->Active = false;              pKey->Active = false;
1620              pActiveKeys->free(pKey->itSelf); // remove key from list of active keys              pEngineChannel->pActiveKeys->free(pKey->itSelf); // remove key from list of active keys
1621              pKey->itSelf = RTList<uint>::Iterator();              pKey->itSelf = RTList<uint>::Iterator();
1622              pKey->ReleaseTrigger = false;              pKey->ReleaseTrigger = false;
1623              pKey->pEvents->clear();              pKey->pEvents->clear();
# Line 903  namespace LinuxSampler { namespace gig { Line 1630  namespace LinuxSampler { namespace gig {
1630       *  Reacts on supported control change commands (e.g. pitch bend wheel,       *  Reacts on supported control change commands (e.g. pitch bend wheel,
1631       *  modulation wheel, aftertouch).       *  modulation wheel, aftertouch).
1632       *       *
1633         *  @param pEngineChannel - engine channel on which this event occured on
1634       *  @param itControlChangeEvent - controller, value and time stamp of the event       *  @param itControlChangeEvent - controller, value and time stamp of the event
1635       */       */
1636      void Engine::ProcessControlChange(Pool<Event>::Iterator& itControlChangeEvent) {      void Engine::ProcessControlChange(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itControlChangeEvent) {
1637          dmsg(4,("Engine::ContinuousController cc=%d v=%d\n", itControlChangeEvent->Param.CC.Controller, itControlChangeEvent->Param.CC.Value));          dmsg(4,("Engine::ContinuousController cc=%d v=%d\n", itControlChangeEvent->Param.CC.Controller, itControlChangeEvent->Param.CC.Value));
1638    
1639            // handle the "control triggered" MIDI rule: a control change
1640            // event can trigger a new note on or note off event
1641            if (pEngineChannel->pInstrument) {
1642    
1643                ::gig::MidiRule* rule;
1644                for (int i = 0 ; (rule = pEngineChannel->pInstrument->GetMidiRule(i)) ; i++) {
1645    
1646                    if (::gig::MidiRuleCtrlTrigger* ctrlTrigger =
1647                        dynamic_cast< ::gig::MidiRuleCtrlTrigger*>(rule)) {
1648                        if (itControlChangeEvent->Param.CC.Controller ==
1649                            ctrlTrigger->ControllerNumber) {
1650    
1651                            uint8_t oldCCValue = pEngineChannel->ControllerTable[
1652                                itControlChangeEvent->Param.CC.Controller];
1653                            uint8_t newCCValue = itControlChangeEvent->Param.CC.Value;
1654    
1655                            for (int i = 0 ; i < ctrlTrigger->Triggers ; i++) {
1656                                ::gig::MidiRuleCtrlTrigger::trigger_t* pTrigger =
1657                                      &ctrlTrigger->pTriggers[i];
1658    
1659                                // check if the controller has passed the
1660                                // trigger point in the right direction
1661                                if ((pTrigger->Descending &&
1662                                     oldCCValue > pTrigger->TriggerPoint &&
1663                                     newCCValue <= pTrigger->TriggerPoint) ||
1664                                    (!pTrigger->Descending &&
1665                                     oldCCValue < pTrigger->TriggerPoint &&
1666                                     newCCValue >= pTrigger->TriggerPoint)) {
1667    
1668                                    RTList<Event>::Iterator itNewEvent = pGlobalEvents->allocAppend();
1669                                    if (itNewEvent) {
1670                                        *itNewEvent = *itControlChangeEvent;
1671                                        itNewEvent->Param.Note.Key = pTrigger->Key;
1672    
1673                                        if (pTrigger->NoteOff || pTrigger->Velocity == 0) {
1674                                            itNewEvent->Type = Event::type_note_off;
1675                                            itNewEvent->Param.Note.Velocity = 100;
1676    
1677                                            ProcessNoteOff(pEngineChannel, itNewEvent);
1678                                        } else {
1679                                            itNewEvent->Type = Event::type_note_on;
1680                                            //TODO: if Velocity is 255, the triggered velocity should
1681                                            // depend on how fast the controller is moving
1682                                            itNewEvent->Param.Note.Velocity =
1683                                                pTrigger->Velocity == 255 ? 100 :
1684                                                pTrigger->Velocity;
1685    
1686                                            ProcessNoteOn(pEngineChannel, itNewEvent);
1687                                        }
1688                                    }
1689                                    else dmsg(1,("Event pool emtpy!\n"));
1690                                }
1691                            }
1692                        }
1693                    }
1694                }
1695            }
1696    
1697            // update controller value in the engine channel's controller table
1698            pEngineChannel->ControllerTable[itControlChangeEvent->Param.CC.Controller] = itControlChangeEvent->Param.CC.Value;
1699    
1700            // handle hard coded MIDI controllers
1701          switch (itControlChangeEvent->Param.CC.Controller) {          switch (itControlChangeEvent->Param.CC.Controller) {
1702              case 64: {              case 5: { // portamento time
1703                  if (itControlChangeEvent->Param.CC.Value >= 64 && !SustainPedal) {                  pEngineChannel->PortamentoTime = (float) itControlChangeEvent->Param.CC.Value / 127.0f * (float) CONFIG_PORTAMENTO_TIME_MAX + (float) CONFIG_PORTAMENTO_TIME_MIN;
1704                      dmsg(4,("PEDAL DOWN\n"));                  break;
1705                      SustainPedal = true;              }
1706                case 6: { // data entry (currently only used for RPN controllers)
1707                    if (pEngineChannel->GetMidiRpnController() == 2) { // coarse tuning in half tones
1708                        int transpose = (int) itControlChangeEvent->Param.CC.Value - 64;
1709                        // limit to +- two octaves for now
1710                        transpose = RTMath::Min(transpose,  24);
1711                        transpose = RTMath::Max(transpose, -24);
1712                        pEngineChannel->GlobalTranspose = transpose;
1713                        // workaround, so we won't have hanging notes
1714                        ReleaseAllVoices(pEngineChannel, itControlChangeEvent);
1715                    }
1716                    // to avoid other MIDI CC #6 messages to be misenterpreted as RPN controller data
1717                    pEngineChannel->ResetMidiRpnController();
1718                    break;
1719                }
1720                case 7: { // volume
1721                    //TODO: not sample accurate yet
1722                    pEngineChannel->MidiVolume = VolumeCurve[itControlChangeEvent->Param.CC.Value];
1723                    pEngineChannel->bStatusChanged = true; // engine channel status has changed, so set notify flag
1724                    break;
1725                }
1726                case 10: { // panpot
1727                    //TODO: not sample accurate yet
1728                    pEngineChannel->GlobalPanLeft  = PanCurve[128 - itControlChangeEvent->Param.CC.Value];
1729                    pEngineChannel->GlobalPanRight = PanCurve[itControlChangeEvent->Param.CC.Value];
1730                    pEngineChannel->iLastPanRequest = itControlChangeEvent->Param.CC.Value;
1731                    break;
1732                }
1733                case 64: { // sustain
1734                    if (itControlChangeEvent->Param.CC.Value >= 64 && !pEngineChannel->SustainPedal) {
1735                        dmsg(4,("DAMPER (RIGHT) PEDAL DOWN\n"));
1736                        pEngineChannel->SustainPedal = true;
1737    
1738                        #if !CONFIG_PROCESS_MUTED_CHANNELS
1739                        if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
1740                        #endif
1741    
1742                      // cancel release process of voices if necessary                      // cancel release process of voices if necessary
1743                      RTList<uint>::Iterator iuiKey = pActiveKeys->first();                      RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
1744                      if (iuiKey) {                      for (; iuiKey; ++iuiKey) {
1745                          itControlChangeEvent->Type = Event::type_cancel_release; // transform event type                          midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
1746                          while (iuiKey) {                          if (!pKey->KeyPressed) {
1747                              midi_key_info_t* pKey = &pMIDIKeyInfo[*iuiKey];                              RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
1748                              ++iuiKey;                              if (itNewEvent) {
1749                              if (!pKey->KeyPressed) {                                  *itNewEvent = *itControlChangeEvent; // copy event to the key's own event list
1750                                  RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();                                  itNewEvent->Type = Event::type_cancel_release; // transform event type
                                 if (itNewEvent) *itNewEvent = *itControlChangeEvent; // copy event to the key's own event list  
                                 else dmsg(1,("Event pool emtpy!\n"));  
1751                              }                              }
1752                                else dmsg(1,("Event pool emtpy!\n"));
1753                          }                          }
1754                      }                      }
1755                  }                  }
1756                  if (itControlChangeEvent->Param.CC.Value < 64 && SustainPedal) {                  if (itControlChangeEvent->Param.CC.Value < 64 && pEngineChannel->SustainPedal) {
1757                      dmsg(4,("PEDAL UP\n"));                      dmsg(4,("DAMPER (RIGHT) PEDAL UP\n"));
1758                      SustainPedal = false;                      pEngineChannel->SustainPedal = false;
1759    
1760                        #if !CONFIG_PROCESS_MUTED_CHANNELS
1761                        if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
1762                        #endif
1763    
1764                      // release voices if their respective key is not pressed                      // release voices if their respective key is not pressed
1765                      RTList<uint>::Iterator iuiKey = pActiveKeys->first();                      RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
1766                      if (iuiKey) {                      for (; iuiKey; ++iuiKey) {
1767                          itControlChangeEvent->Type = Event::type_release; // transform event type                          midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
1768                          while (iuiKey) {                          if (!pKey->KeyPressed && ShouldReleaseVoice(pEngineChannel, *iuiKey)) {
1769                              midi_key_info_t* pKey = &pMIDIKeyInfo[*iuiKey];                              RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
1770                              ++iuiKey;                              if (itNewEvent) {
1771                              if (!pKey->KeyPressed) {                                  *itNewEvent = *itControlChangeEvent; // copy event to the key's own event list
1772                                  RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();                                  itNewEvent->Type = Event::type_release; // transform event type
                                 if (itNewEvent) *itNewEvent = *itControlChangeEvent; // copy event to the key's own event list  
                                 else dmsg(1,("Event pool emtpy!\n"));  
1773                              }                              }
1774                                else dmsg(1,("Event pool emtpy!\n"));
1775                          }                          }
1776                      }                      }
1777                  }                  }
1778                  break;                  break;
1779              }              }
1780          }              case 65: { // portamento on / off
1781                    const bool bPortamento = itControlChangeEvent->Param.CC.Value >= 64;
1782                    if (bPortamento != pEngineChannel->PortamentoMode)
1783                        KillAllVoices(pEngineChannel, itControlChangeEvent);
1784                    pEngineChannel->PortamentoMode = bPortamento;
1785                    break;
1786                }
1787                case 66: { // sostenuto
1788                    if (itControlChangeEvent->Param.CC.Value >= 64 && !pEngineChannel->SostenutoPedal) {
1789                        dmsg(4,("SOSTENUTO (CENTER) PEDAL DOWN\n"));
1790                        pEngineChannel->SostenutoPedal = true;
1791    
1792                        #if !CONFIG_PROCESS_MUTED_CHANNELS
1793                        if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
1794                        #endif
1795    
1796                        SostenutoKeyCount = 0;
1797                        // Remeber the pressed keys
1798                        RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
1799                        for (; iuiKey; ++iuiKey) {
1800                            midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
1801                            if (pKey->KeyPressed && SostenutoKeyCount < 128) SostenutoKeys[SostenutoKeyCount++] = *iuiKey;
1802                        }
1803                    }
1804                    if (itControlChangeEvent->Param.CC.Value < 64 && pEngineChannel->SostenutoPedal) {
1805                        dmsg(4,("SOSTENUTO (CENTER) PEDAL UP\n"));
1806                        pEngineChannel->SostenutoPedal = false;
1807    
1808                        #if !CONFIG_PROCESS_MUTED_CHANNELS
1809                        if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
1810                        #endif
1811    
1812                        // release voices if the damper pedal is up and their respective key is not pressed
1813                        for (int i = 0; i < SostenutoKeyCount; i++) {
1814                            midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[SostenutoKeys[i]];
1815                            if (!pKey->KeyPressed && !pEngineChannel->SustainPedal) {
1816                                RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
1817                                if (itNewEvent) {
1818                                    *itNewEvent = *itControlChangeEvent; // copy event to the key's own event list
1819                                    itNewEvent->Type = Event::type_release; // transform event type
1820                                }
1821                                else dmsg(1,("Event pool emtpy!\n"));
1822                            }
1823                        }
1824                    }
1825                    break;
1826                }
1827                case 100: { // RPN controller LSB
1828                    pEngineChannel->SetMidiRpnControllerLsb(itControlChangeEvent->Param.CC.Value);
1829                    break;
1830                }
1831                case 101: { // RPN controller MSB
1832                    pEngineChannel->SetMidiRpnControllerMsb(itControlChangeEvent->Param.CC.Value);
1833                    break;
1834                }
1835    
         // update controller value in the engine's controller table  
         ControllerTable[itControlChangeEvent->Param.CC.Controller] = itControlChangeEvent->Param.CC.Value;  
1836    
1837          // move event from the unsorted event list to the control change event list              // Channel Mode Messages
1838          itControlChangeEvent.moveToEndOf(pCCEvents);  
1839                case 120: { // all sound off
1840                    KillAllVoices(pEngineChannel, itControlChangeEvent);
1841                    break;
1842                }
1843                case 121: { // reset all controllers
1844                    pEngineChannel->ResetControllers();
1845                    break;
1846                }
1847                case 123: { // all notes off
1848                    #if CONFIG_PROCESS_ALL_NOTES_OFF
1849                    ReleaseAllVoices(pEngineChannel, itControlChangeEvent);
1850                    #endif // CONFIG_PROCESS_ALL_NOTES_OFF
1851                    break;
1852                }
1853                case 126: { // mono mode on
1854                    if (!pEngineChannel->SoloMode)
1855                        KillAllVoices(pEngineChannel, itControlChangeEvent);
1856                    pEngineChannel->SoloMode = true;
1857                    break;
1858                }
1859                case 127: { // poly mode on
1860                    if (pEngineChannel->SoloMode)
1861                        KillAllVoices(pEngineChannel, itControlChangeEvent);
1862                    pEngineChannel->SoloMode = false;
1863                    break;
1864                }
1865            }
1866    
1867            // handle FX send controllers
1868            if (!pEngineChannel->fxSends.empty()) {
1869                for (int iFxSend = 0; iFxSend < pEngineChannel->GetFxSendCount(); iFxSend++) {
1870                    FxSend* pFxSend = pEngineChannel->GetFxSend(iFxSend);
1871                    if (pFxSend->MidiController() == itControlChangeEvent->Param.CC.Controller) {
1872                        pFxSend->SetLevel(itControlChangeEvent->Param.CC.Value);
1873                        pFxSend->SetInfoChanged(true);
1874                    }
1875                }
1876            }
1877      }      }
1878    
1879      /**      /**
# Line 965  namespace LinuxSampler { namespace gig { Line 1882  namespace LinuxSampler { namespace gig {
1882       *  @param itSysexEvent - sysex data size and time stamp of the sysex event       *  @param itSysexEvent - sysex data size and time stamp of the sysex event
1883       */       */
1884      void Engine::ProcessSysex(Pool<Event>::Iterator& itSysexEvent) {      void Engine::ProcessSysex(Pool<Event>::Iterator& itSysexEvent) {
1885          RingBuffer<uint8_t>::NonVolatileReader reader = pSysexBuffer->get_non_volatile_reader();          RingBuffer<uint8_t,false>::NonVolatileReader reader = pSysexBuffer->get_non_volatile_reader();
1886    
1887          uint8_t exclusive_status, id;          uint8_t exclusive_status, id;
1888          if (!reader.pop(&exclusive_status)) goto free_sysex_data;          if (!reader.pop(&exclusive_status)) goto free_sysex_data;
# Line 973  namespace LinuxSampler { namespace gig { Line 1890  namespace LinuxSampler { namespace gig {
1890          if (exclusive_status != 0xF0)       goto free_sysex_data;          if (exclusive_status != 0xF0)       goto free_sysex_data;
1891    
1892          switch (id) {          switch (id) {
1893                case 0x7f: { // (Realtime) Universal Sysex (GM Standard)
1894                    uint8_t sysex_channel, sub_id1, sub_id2, val_msb, val_lsb;;
1895                    if (!reader.pop(&sysex_channel)) goto free_sysex_data;
1896                    if (!reader.pop(&sub_id1)) goto free_sysex_data;
1897                    if (!reader.pop(&sub_id2)) goto free_sysex_data;
1898                    if (!reader.pop(&val_lsb)) goto free_sysex_data;
1899                    if (!reader.pop(&val_msb)) goto free_sysex_data;
1900                    //TODO: for now we simply ignore the sysex channel, seldom used anyway
1901                    switch (sub_id1) {
1902                        case 0x04: // Device Control
1903                            switch (sub_id2) {
1904                                case 0x01: // Master Volume
1905                                    GLOBAL_VOLUME =
1906                                        double((uint(val_msb)<<7) | uint(val_lsb)) / 16383.0;
1907                                    break;
1908                            }
1909                            break;
1910                    }
1911                    break;
1912                }
1913              case 0x41: { // Roland              case 0x41: { // Roland
1914                    dmsg(3,("Roland Sysex\n"));
1915                  uint8_t device_id, model_id, cmd_id;                  uint8_t device_id, model_id, cmd_id;
1916                  if (!reader.pop(&device_id)) goto free_sysex_data;                  if (!reader.pop(&device_id)) goto free_sysex_data;
1917                  if (!reader.pop(&model_id))  goto free_sysex_data;                  if (!reader.pop(&model_id))  goto free_sysex_data;
# Line 983  namespace LinuxSampler { namespace gig { Line 1921  namespace LinuxSampler { namespace gig {
1921    
1922                  // command address                  // command address
1923                  uint8_t addr[3]; // 2 byte addr MSB, followed by 1 byte addr LSB)                  uint8_t addr[3]; // 2 byte addr MSB, followed by 1 byte addr LSB)
1924                  const RingBuffer<uint8_t>::NonVolatileReader checksum_reader = reader; // so we can calculate the check sum later                  const RingBuffer<uint8_t,false>::NonVolatileReader checksum_reader = reader; // so we can calculate the check sum later
1925                  if (reader.read(&addr[0], 3) != 3) goto free_sysex_data;                  if (reader.read(&addr[0], 3) != 3) goto free_sysex_data;
1926                  if (addr[0] == 0x40 && addr[1] == 0x00) { // System Parameters                  if (addr[0] == 0x40 && addr[1] == 0x00) { // System Parameters
1927                        dmsg(3,("\tSystem Parameter\n"));
1928                  }                  }
1929                  else if (addr[0] == 0x40 && addr[1] == 0x01) { // Common Parameters                  else if (addr[0] == 0x40 && addr[1] == 0x01) { // Common Parameters
1930                        dmsg(3,("\tCommon Parameter\n"));
1931                  }                  }
1932                  else if (addr[0] == 0x40 && (addr[1] & 0xf0) == 0x10) { // Part Parameters (1)                  else if (addr[0] == 0x40 && (addr[1] & 0xf0) == 0x10) { // Part Parameters (1)
1933                      switch (addr[3]) {                      dmsg(3,("\tPart Parameter\n"));
1934                        switch (addr[2]) {
1935                          case 0x40: { // scale tuning                          case 0x40: { // scale tuning
1936                                dmsg(3,("\t\tScale Tuning\n"));
1937                              uint8_t scale_tunes[12]; // detuning of all 12 semitones of an octave                              uint8_t scale_tunes[12]; // detuning of all 12 semitones of an octave
1938                              if (reader.read(&scale_tunes[0], 12) != 12) goto free_sysex_data;                              if (reader.read(&scale_tunes[0], 12) != 12) goto free_sysex_data;
1939                              uint8_t checksum;                              uint8_t checksum;
1940                              if (!reader.pop(&checksum))                      goto free_sysex_data;                              if (!reader.pop(&checksum)) goto free_sysex_data;
1941                              if (GSCheckSum(checksum_reader, 12) != checksum) goto free_sysex_data;                              #if CONFIG_ASSERT_GS_SYSEX_CHECKSUM
1942                                if (GSCheckSum(checksum_reader, 12)) goto free_sysex_data;
1943                                #endif // CONFIG_ASSERT_GS_SYSEX_CHECKSUM
1944                              for (int i = 0; i < 12; i++) scale_tunes[i] -= 64;                              for (int i = 0; i < 12; i++) scale_tunes[i] -= 64;
1945                              AdjustScale((int8_t*) scale_tunes);                              AdjustScale((int8_t*) scale_tunes);
1946                                dmsg(3,("\t\t\tNew scale applied.\n"));
1947                                break;
1948                            }
1949                            case 0x15: { // chromatic / drumkit mode
1950                                dmsg(3,("\t\tMIDI Instrument Map Switch\n"));
1951                                uint8_t part = addr[1] & 0x0f;
1952                                uint8_t map;
1953                                if (!reader.pop(&map)) goto free_sysex_data;
1954                                for (int i = 0; i < engineChannels.size(); ++i) {
1955                                    EngineChannel* pEngineChannel = engineChannels[i];
1956                                    if (pEngineChannel->midiChannel == part ||
1957                                        pEngineChannel->midiChannel == midi_chan_all
1958                                    ) {
1959                                        try {
1960                                            pEngineChannel->SetMidiInstrumentMap(map);
1961                                        } catch (Exception e) {
1962                                            dmsg(2,("\t\t\tCould not apply MIDI instrument map %d to part %d: %s\n", map, part, e.Message().c_str()));
1963                                            goto free_sysex_data;
1964                                        } catch (...) {
1965                                            dmsg(2,("\t\t\tCould not apply MIDI instrument map %d to part %d (unknown exception)\n", map, part));
1966                                            goto free_sysex_data;
1967                                        }
1968                                    }
1969                                }
1970                                dmsg(3,("\t\t\tApplied MIDI instrument map %d to part %d.\n", map, part));
1971                              break;                              break;
1972                          }                          }
1973                      }                      }
# Line 1023  namespace LinuxSampler { namespace gig { Line 1992  namespace LinuxSampler { namespace gig {
1992       *                     question       *                     question
1993       * @param DataSize   - size of the GS message data (in bytes)       * @param DataSize   - size of the GS message data (in bytes)
1994       */       */
1995      uint8_t Engine::GSCheckSum(const RingBuffer<uint8_t>::NonVolatileReader AddrReader, uint DataSize) {      uint8_t Engine::GSCheckSum(const RingBuffer<uint8_t,false>::NonVolatileReader AddrReader, uint DataSize) {
1996          RingBuffer<uint8_t>::NonVolatileReader reader = AddrReader;          RingBuffer<uint8_t,false>::NonVolatileReader reader = AddrReader;
1997          uint bytes = 3 /*addr*/ + DataSize;          uint bytes = 3 /*addr*/ + DataSize;
1998          uint8_t addr_and_data[bytes];          uint8_t addr_and_data[bytes];
1999          reader.read(&addr_and_data[0], bytes);          reader.read(&addr_and_data[0], bytes);
# Line 1043  namespace LinuxSampler { namespace gig { Line 2012  namespace LinuxSampler { namespace gig {
2012      }      }
2013    
2014      /**      /**
2015       * Initialize the parameter sequence for the modulation destination given by       * Releases all voices on an engine channel. All voices will go into
2016       * by 'dst' with the constant value given by val.       * the release stage and thus it might take some time (e.g. dependant to
2017         * their envelope release time) until they actually die.
2018         *
2019         * @param pEngineChannel - engine channel on which all voices should be released
2020         * @param itReleaseEvent - event which caused this releasing of all voices
2021       */       */
2022      void Engine::ResetSynthesisParameters(Event::destination_t dst, float val) {      void Engine::ReleaseAllVoices(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itReleaseEvent) {
2023          int maxsamples = pAudioOutputDevice->MaxSamplesPerCycle();          RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
2024          float* m = &pSynthesisParameters[dst][0];          while (iuiKey) {
2025          for (int i = 0; i < maxsamples; i += 4) {              midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
2026             m[i]   = val;              ++iuiKey;
2027             m[i+1] = val;              // append a 'release' event to the key's own event list
2028             m[i+2] = val;              RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
2029             m[i+3] = val;              if (itNewEvent) {
2030                    *itNewEvent = *itReleaseEvent; // copy original event (to the key's event list)
2031                    itNewEvent->Type = Event::type_release; // transform event type
2032                }
2033                else dmsg(1,("Event pool emtpy!\n"));
2034          }          }
2035      }      }
2036    
2037      float Engine::Volume() {      /**
2038          return GlobalVolume;       * Kills all voices on an engine channel as soon as possible. Voices
2039      }       * won't get into release state, their volume level will be ramped down
2040         * as fast as possible.
2041      void Engine::Volume(float f) {       *
2042          GlobalVolume = f;       * @param pEngineChannel - engine channel on which all voices should be killed
2043      }       * @param itKillEvent    - event which caused this killing of all voices
2044         */
2045      uint Engine::Channels() {      void Engine::KillAllVoices(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itKillEvent) {
2046          return 2;          RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
2047      }          RTList<uint>::Iterator end    = pEngineChannel->pActiveKeys->end();
2048            while (iuiKey != end) { // iterate through all active keys
2049      void Engine::SetOutputChannel(uint EngineAudioChannel, uint AudioDeviceChannel) {              midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
2050          AudioChannel* pChannel = pAudioOutputDevice->Channel(AudioDeviceChannel);              ++iuiKey;
2051          if (!pChannel) throw AudioOutputException("Invalid audio output device channel " + ToString(AudioDeviceChannel));              RTList<Voice>::Iterator itVoice     = pKey->pActiveVoices->first();
2052          switch (EngineAudioChannel) {              RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();
2053              case 0: // left output channel              for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
2054                  pOutputLeft = pChannel->Buffer();                  itVoice->Kill(itKillEvent);
2055                  AudioDeviceChannelLeft = AudioDeviceChannel;                  --VoiceSpawnsLeft; //FIXME: just a temporary workaround, we should check the cause in StealVoice() instead
2056                  break;              }
             case 1: // right output channel  
                 pOutputRight = pChannel->Buffer();  
                 AudioDeviceChannelRight = AudioDeviceChannel;  
                 break;  
             default:  
                 throw AudioOutputException("Invalid engine audio channel " + ToString(EngineAudioChannel));  
2057          }          }
2058      }      }
2059    
2060      int Engine::OutputChannel(uint EngineAudioChannel) {      /**
2061          switch (EngineAudioChannel) {       * Determines whether the specified voice should be released.
2062              case 0: // left channel       *
2063                  return AudioDeviceChannelLeft;       * @param pEngineChannel - The engine channel on which the voice should be checked
2064              case 1: // right channel       * @param Key - The key number
2065                  return AudioDeviceChannelRight;       * @returns true if the specified should be released, false otherwise.
2066              default:       */
2067                  throw AudioOutputException("Invalid engine audio channel " + ToString(EngineAudioChannel));      bool Engine::ShouldReleaseVoice(EngineChannel* pEngineChannel, int Key) {
2068            if (pEngineChannel->SustainPedal) return false;
2069    
2070            if (pEngineChannel->SostenutoPedal) {
2071                for (int i = 0; i < SostenutoKeyCount; i++)
2072                    if (Key == SostenutoKeys[i]) return false;
2073          }          }
2074    
2075            return true;
2076      }      }
2077    
2078      uint Engine::VoiceCount() {      uint Engine::VoiceCount() {
# Line 1126  namespace LinuxSampler { namespace gig { Line 2104  namespace LinuxSampler { namespace gig {
2104      }      }
2105    
2106      String Engine::EngineName() {      String Engine::EngineName() {
2107          return "GigEngine";          return LS_GIG_ENGINE_NAME;
     }  
   
     String Engine::InstrumentFileName() {  
         return InstrumentFile;  
2108      }      }
2109    
2110      int Engine::InstrumentIndex() {      String Engine::Description() {
2111          return InstrumentIdx;          return "Gigasampler Format Engine";
2112      }      }
2113    
2114      int Engine::InstrumentStatus() {      String Engine::Version() {
2115          return InstrumentStat;          String s = "$Revision: 1.94 $";
2116            return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword
2117      }      }
2118    
2119      String Engine::Description() {      InstrumentManager* Engine::GetInstrumentManager() {
2120          return "Gigasampler Engine";          return &instruments;
2121      }      }
2122    
2123      String Engine::Version() {      // static constant initializers
2124          String s = "$Revision: 1.17 $";      const Engine::FloatTable Engine::VolumeCurve(InitVolumeCurve());
2125          return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword      const Engine::FloatTable Engine::PanCurve(InitPanCurve());
2126        const Engine::FloatTable Engine::CrossfadeCurve(InitCrossfadeCurve());
2127    
2128        float* Engine::InitVolumeCurve() {
2129            // line-segment approximation
2130            const float segments[] = {
2131                0, 0, 2, 0.0046, 16, 0.016, 31, 0.051, 45, 0.115, 54.5, 0.2,
2132                64.5, 0.39, 74, 0.74, 92, 1.03, 114, 1.94, 119.2, 2.2, 127, 2.2
2133            };
2134            return InitCurve(segments);
2135        }
2136    
2137        float* Engine::InitPanCurve() {
2138            // line-segment approximation
2139            const float segments[] = {
2140                0, 0, 1, 0,
2141                2, 0.05, 31.5, 0.7, 51, 0.851, 74.5, 1.12,
2142                127, 1.41, 128, 1.41
2143            };
2144            return InitCurve(segments, 129);
2145        }
2146    
2147        float* Engine::InitCrossfadeCurve() {
2148            // line-segment approximation
2149            const float segments[] = {
2150                0, 0, 1, 0.03, 10, 0.1, 51, 0.58, 127, 1
2151            };
2152            return InitCurve(segments);
2153        }
2154    
2155        float* Engine::InitCurve(const float* segments, int size) {
2156            float* y = new float[size];
2157            for (int x = 0 ; x < size ; x++) {
2158                if (x > segments[2]) segments += 2;
2159                y[x] = segments[1] + (x - segments[0]) *
2160                    (segments[3] - segments[1]) / (segments[2] - segments[0]);
2161            }
2162            return y;
2163      }      }
2164    
2165  }} // namespace LinuxSampler::gig  }} // namespace LinuxSampler::gig

Legend:
Removed from v.287  
changed lines
  Added in v.1750

  ViewVC Help
Powered by ViewVC