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

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

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

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

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

  ViewVC Help
Powered by ViewVC