/[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 392 by schoenebeck, Sat Feb 19 02:40:24 2005 UTC revision 1305 by iliev, Mon Aug 27 07:51:28 2007 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-2007 Christian Schoenebeck                        *
7   *                                                                         *   *                                                                         *
8   *   This program is free software; you can redistribute it and/or modify  *   *   This program is free software; you can redistribute it and/or modify  *
9   *   it under the terms of the GNU General Public License as published by  *   *   it under the terms of the GNU General Public License as published by  *
# Line 24  Line 25 
25  #include "DiskThread.h"  #include "DiskThread.h"
26  #include "Voice.h"  #include "Voice.h"
27  #include "EGADSR.h"  #include "EGADSR.h"
28    #include "../EngineFactory.h"
29    
30  #include "Engine.h"  #include "Engine.h"
31    
 #if defined(__APPLE__)  
 # include <stdlib.h>  
 #else  
 # include <malloc.h>  
 #endif  
   
32  namespace LinuxSampler { namespace gig {  namespace LinuxSampler { namespace gig {
33    
34      InstrumentResourceManager Engine::Instruments;      InstrumentResourceManager Engine::instruments;
35    
36        std::map<AudioOutputDevice*,Engine*> Engine::engines;
37    
38        /**
39         * Get a gig::Engine object for the given gig::EngineChannel and the
40         * given AudioOutputDevice. All engine channels which are connected to
41         * the same audio output device will use the same engine instance. This
42         * method will be called by a gig::EngineChannel whenever it's
43         * connecting to a audio output device.
44         *
45         * @param pChannel - engine channel which acquires an engine object
46         * @param pDevice  - the audio output device \a pChannel is connected to
47         */
48        Engine* Engine::AcquireEngine(LinuxSampler::gig::EngineChannel* pChannel, AudioOutputDevice* pDevice) {
49            Engine* pEngine = NULL;
50            // check if there's already an engine for the given audio output device
51            if (engines.count(pDevice)) {
52                dmsg(4,("Using existing gig::Engine.\n"));
53                pEngine = engines[pDevice];
54    
55                // Disable the engine while the new engine channel is
56                // added and initialized. The engine will be enabled again
57                // in EngineChannel::Connect.
58                pEngine->DisableAndLock();
59            } else { // create a new engine (and disk thread) instance for the given audio output device
60                dmsg(4,("Creating new gig::Engine.\n"));
61                pEngine = (Engine*) EngineFactory::Create("gig");
62                pEngine->Connect(pDevice);
63                engines[pDevice] = pEngine;
64            }
65            // register engine channel to the engine instance
66            pEngine->engineChannels.add(pChannel);
67            // remember index in the ArrayList
68            pChannel->iEngineIndexSelf = pEngine->engineChannels.size() - 1;
69            dmsg(4,("This gig::Engine has now %d EngineChannels.\n",pEngine->engineChannels.size()));
70            return pEngine;
71        }
72    
73        /**
74         * Once an engine channel is disconnected from an audio output device,
75         * it wil immediately call this method to unregister itself from the
76         * engine instance and if that engine instance is not used by any other
77         * engine channel anymore, then that engine instance will be destroyed.
78         *
79         * @param pChannel - engine channel which wants to disconnect from it's
80         *                   engine instance
81         * @param pDevice  - audio output device \a pChannel was connected to
82         */
83        void Engine::FreeEngine(LinuxSampler::gig::EngineChannel* pChannel, AudioOutputDevice* pDevice) {
84            dmsg(4,("Disconnecting EngineChannel from gig::Engine.\n"));
85            Engine* pEngine = engines[pDevice];
86            // unregister EngineChannel from the Engine instance
87            pEngine->engineChannels.remove(pChannel);
88            // if the used Engine instance is not used anymore, then destroy it
89            if (pEngine->engineChannels.empty()) {
90                pDevice->Disconnect(pEngine);
91                engines.erase(pDevice);
92                delete pEngine;
93                dmsg(4,("Destroying gig::Engine.\n"));
94            }
95            else dmsg(4,("This gig::Engine has now %d EngineChannels.\n",pEngine->engineChannels.size()));
96        }
97    
98        /**
99         * Constructor
100         */
101      Engine::Engine() {      Engine::Engine() {
         pRIFF              = NULL;  
         pGig               = NULL;  
         pInstrument        = NULL;  
102          pAudioOutputDevice = NULL;          pAudioOutputDevice = NULL;
103          pDiskThread        = NULL;          pDiskThread        = NULL;
104          pEventGenerator    = NULL;          pEventGenerator    = NULL;
105          pSysexBuffer       = new RingBuffer<uint8_t>(SYSEX_BUFFER_SIZE, 0);          pSysexBuffer       = new RingBuffer<uint8_t,false>(CONFIG_SYSEX_BUFFER_SIZE, 0);
106          pEventQueue        = new RingBuffer<Event>(MAX_EVENTS_PER_FRAGMENT, 0);          pEventQueue        = new RingBuffer<Event,false>(CONFIG_MAX_EVENTS_PER_FRAGMENT, 0);
107          pEventPool         = new Pool<Event>(MAX_EVENTS_PER_FRAGMENT);          pEventPool         = new Pool<Event>(CONFIG_MAX_EVENTS_PER_FRAGMENT);
108          pVoicePool         = new Pool<Voice>(MAX_AUDIO_VOICES);          pVoicePool         = new Pool<Voice>(CONFIG_MAX_VOICES);
109          pActiveKeys        = new Pool<uint>(128);          pDimRegionsInUse   = new ::gig::DimensionRegion*[CONFIG_MAX_VOICES + 1];
110          pVoiceStealingQueue = new RTList<Event>(pEventPool);          pVoiceStealingQueue = new RTList<Event>(pEventPool);
111          pEvents            = new RTList<Event>(pEventPool);          pGlobalEvents      = new RTList<Event>(pEventPool);
112          pCCEvents          = new RTList<Event>(pEventPool);          InstrumentChangeQueue      = new RingBuffer<instrument_change_command_t,false>(1, 0);
113          for (uint i = 0; i < Event::destination_count; i++) {          InstrumentChangeReplyQueue = new RingBuffer<instrument_change_reply_t,false>(1, 0);
114              pSynthesisEvents[i] = new RTList<Event>(pEventPool);  
         }  
         for (uint i = 0; i < 128; i++) {  
             pMIDIKeyInfo[i].pActiveVoices  = new RTList<Voice>(pVoicePool);  
             pMIDIKeyInfo[i].KeyPressed     = false;  
             pMIDIKeyInfo[i].Active         = false;  
             pMIDIKeyInfo[i].ReleaseTrigger = false;  
             pMIDIKeyInfo[i].pEvents        = new RTList<Event>(pEventPool);  
         }  
115          for (RTList<Voice>::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {          for (RTList<Voice>::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
116              iterVoice->SetEngine(this);              iterVoice->SetEngine(this);
117          }          }
118          pVoicePool->clear();          pVoicePool->clear();
119    
         pSynthesisParameters[0] = NULL; // we allocate when an audio device is connected  
         pBasicFilterParameters  = NULL;  
         pMainFilterParameters   = NULL;  
   
         InstrumentIdx = -1;  
         InstrumentStat = -1;  
   
         AudioDeviceChannelLeft  = -1;  
         AudioDeviceChannelRight = -1;  
   
120          ResetInternal();          ResetInternal();
121            ResetScaleTuning();
122      }      }
123    
124        /**
125         * Destructor
126         */
127      Engine::~Engine() {      Engine::~Engine() {
128            MidiInputPort::RemoveSysexListener(this);
129          if (pDiskThread) {          if (pDiskThread) {
130              dmsg(1,("Stopping disk thread..."));              dmsg(1,("Stopping disk thread..."));
131              pDiskThread->StopThread();              pDiskThread->StopThread();
132              delete pDiskThread;              delete pDiskThread;
133              dmsg(1,("OK\n"));              dmsg(1,("OK\n"));
134          }          }
   
         if (pInstrument) Instruments.HandBack(pInstrument, this);  
   
         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];  
         }  
         if (pEvents)     delete pEvents;  
         if (pCCEvents)   delete pCCEvents;  
135          if (pEventQueue) delete pEventQueue;          if (pEventQueue) delete pEventQueue;
136          if (pEventPool)  delete pEventPool;          if (pEventPool)  delete pEventPool;
137          if (pVoicePool) {          if (pVoicePool) {
138                  pVoicePool->clear();              pVoicePool->clear();
139                  delete pVoicePool;              delete pVoicePool;
140          }          }
         if (pActiveKeys) delete pActiveKeys;  
         if (pSysexBuffer) delete pSysexBuffer;  
141          if (pEventGenerator) delete pEventGenerator;          if (pEventGenerator) delete pEventGenerator;
         if (pMainFilterParameters) delete[] pMainFilterParameters;  
         if (pBasicFilterParameters) delete[] pBasicFilterParameters;  
         if (pSynthesisParameters[0]) free(pSynthesisParameters[0]);  
142          if (pVoiceStealingQueue) delete pVoiceStealingQueue;          if (pVoiceStealingQueue) delete pVoiceStealingQueue;
143            if (pSysexBuffer) delete pSysexBuffer;
144            if (pGlobalEvents) delete pGlobalEvents;
145            if (InstrumentChangeQueue) delete InstrumentChangeQueue;
146            if (InstrumentChangeReplyQueue) delete InstrumentChangeReplyQueue;
147            if (pDimRegionsInUse) delete[] pDimRegionsInUse;
148            Unregister();
149      }      }
150    
151      void Engine::Enable() {      void Engine::Enable() {
# Line 140  namespace LinuxSampler { namespace gig { Line 172  namespace LinuxSampler { namespace gig {
172       */       */
173      void Engine::Reset() {      void Engine::Reset() {
174          DisableAndLock();          DisableAndLock();
   
         //if (pAudioOutputDevice->IsPlaying()) { // if already running  
             /*  
             // signal audio thread not to enter render part anymore  
             SuspensionRequested = true;  
             // sleep until wakened by audio thread  
             pthread_mutex_lock(&__render_state_mutex);  
             pthread_cond_wait(&__render_exit_condition, &__render_state_mutex);  
             pthread_mutex_unlock(&__render_state_mutex);  
             */  
         //}  
   
         //if (wasplaying) pAudioOutputDevice->Stop();  
   
175          ResetInternal();          ResetInternal();
176            ResetScaleTuning();
         // signal audio thread to continue with rendering  
         //SuspensionRequested = false;  
177          Enable();          Enable();
178      }      }
179    
180      /**      /**
181       *  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
182       *  control and status variables. This method is not thread safe!       *  control and status variables. This method is protected by a mutex.
183       */       */
184      void Engine::ResetInternal() {      void Engine::ResetInternal() {
185          Pitch               = 0;          ResetInternalMutex.Lock();
186          SustainPedal        = false;  
187            // make sure that the engine does not get any sysex messages
188            // while it's reseting
189            bool sysexDisabled = MidiInputPort::RemoveSysexListener(this);
190          ActiveVoiceCount    = 0;          ActiveVoiceCount    = 0;
191          ActiveVoiceCountMax = 0;          ActiveVoiceCountMax = 0;
         GlobalVolume        = 1.0;  
         CurrentKeyDimension = 0;  
192    
193          // reset voice stealing parameters          // reset voice stealing parameters
         itLastStolenVoice = RTList<Voice>::Iterator();  
         iuiLastStolenKey  = RTList<uint>::Iterator();  
194          pVoiceStealingQueue->clear();          pVoiceStealingQueue->clear();
195            itLastStolenVoice          = RTList<Voice>::Iterator();
196          // reset to normal chromatic scale (means equal temper)          itLastStolenVoiceGlobally  = RTList<Voice>::Iterator();
197          memset(&ScaleTuning[0], 0x00, 12);          iuiLastStolenKey           = RTList<uint>::Iterator();
198            iuiLastStolenKeyGlobally   = RTList<uint>::Iterator();
199          // set all MIDI controller values to zero          pLastStolenChannel         = NULL;
         memset(ControllerTable, 0x00, 128);  
   
         // reset key info  
         for (uint i = 0; i < 128; i++) {  
             pMIDIKeyInfo[i].pActiveVoices->clear();  
             pMIDIKeyInfo[i].pEvents->clear();  
             pMIDIKeyInfo[i].KeyPressed     = false;  
             pMIDIKeyInfo[i].Active         = false;  
             pMIDIKeyInfo[i].ReleaseTrigger = false;  
             pMIDIKeyInfo[i].itSelf         = Pool<uint>::Iterator();  
         }  
   
         // reset all key groups  
         map<uint,uint*>::iterator iter = ActiveKeyGroups.begin();  
         for (; iter != ActiveKeyGroups.end(); iter++) iter->second = NULL;  
200    
201          // reset all voices          // reset all voices
202          for (RTList<Voice>::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {          for (RTList<Voice>::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
# Line 204  namespace LinuxSampler { namespace gig { Line 204  namespace LinuxSampler { namespace gig {
204          }          }
205          pVoicePool->clear();          pVoicePool->clear();
206    
         // free all active keys  
         pActiveKeys->clear();  
   
207          // reset disk thread          // reset disk thread
208          if (pDiskThread) pDiskThread->Reset();          if (pDiskThread) pDiskThread->Reset();
209    
210          // delete all input events          // delete all input events
211          pEventQueue->init();          pEventQueue->init();
212            pSysexBuffer->init();
213            if (sysexDisabled) MidiInputPort::AddSysexListener(this);
214            ResetInternalMutex.Unlock();
215      }      }
216    
217      /**      /**
218       * More or less a workaround to set the instrument name, index and load       * Reset to normal, chromatic scale (means equal tempered).
      * status variable to zero percent immediately, that is without blocking  
      * the calling thread. It might be used in future for other preparations  
      * as well though.  
      *  
      * @param FileName   - file name of the Gigasampler instrument file  
      * @param Instrument - index of the instrument in the .gig file  
      * @see LoadInstrument()  
219       */       */
220      void Engine::PrepareLoadInstrument(const char* FileName, uint Instrument) {      void Engine::ResetScaleTuning() {
221          InstrumentFile = FileName;          memset(&ScaleTuning[0], 0x00, 12);
         InstrumentIdx  = Instrument;  
         InstrumentStat = 0;  
222      }      }
223    
224      /**      /**
225       * Load an instrument from a .gig file. PrepareLoadInstrument() has to       * Connect this engine instance with the given audio output device.
226       * be called first to provide the information which instrument to load.       * This method will be called when an Engine instance is created.
227       * This method will then actually start to load the instrument and block       * All of the engine's data structures which are dependant to the used
228       * the calling thread until loading was completed.       * audio output device / driver will be (re)allocated and / or
229         * adjusted appropriately.
230       *       *
231       * @returns detailed description of the method call result       * @param pAudioOut - audio output device to connect to
      * @see PrepareLoadInstrument()  
      */  
     void Engine::LoadInstrument() {  
   
         DisableAndLock();  
   
         ResetInternal(); // reset engine  
   
         // free old instrument  
         if (pInstrument) {  
             // give old instrument back to instrument manager  
             Instruments.HandBack(pInstrument, this);  
         }  
   
         // delete all key groups  
         ActiveKeyGroups.clear();  
   
         // request gig instrument from instrument manager  
         try {  
             instrument_id_t instrid;  
             instrid.FileName    = InstrumentFile;  
             instrid.iInstrument = InstrumentIdx;  
             pInstrument = Instruments.Borrow(instrid, this);  
             if (!pInstrument) {  
                 InstrumentStat = -1;  
                 dmsg(1,("no instrument loaded!!!\n"));  
                 exit(EXIT_FAILURE);  
             }  
         }  
         catch (RIFF::Exception e) {  
             InstrumentStat = -2;  
             String msg = "gig::Engine error: Failed to load instrument, cause: " + e.Message;  
             throw LinuxSamplerException(msg);  
         }  
         catch (InstrumentResourceManagerException e) {  
             InstrumentStat = -3;  
             String msg = "gig::Engine error: Failed to load instrument, cause: " + e.Message();  
             throw LinuxSamplerException(msg);  
         }  
         catch (...) {  
             InstrumentStat = -4;  
             throw LinuxSamplerException("gig::Engine error: Failed to load instrument, cause: Unknown exception while trying to parse gig file.");  
         }  
   
         // rebuild ActiveKeyGroups map with key groups of current instrument  
         for (::gig::Region* pRegion = pInstrument->GetFirstRegion(); pRegion; pRegion = pInstrument->GetNextRegion())  
             if (pRegion->KeyGroup) ActiveKeyGroups[pRegion->KeyGroup] = NULL;  
   
         InstrumentIdxName = pInstrument->pInfo->Name;  
         InstrumentStat = 100;  
   
         // inform audio driver for the need of two channels  
         try {  
             if (pAudioOutputDevice) pAudioOutputDevice->AcquireChannels(2); // gig Engine only stereo  
         }  
         catch (AudioOutputException e) {  
             String msg = "Audio output device unable to provide 2 audio channels, cause: " + e.Message();  
             throw LinuxSamplerException(msg);  
         }  
   
         Enable();  
     }  
   
     /**  
      * Will be called by the InstrumentResourceManager when the instrument  
      * we are currently using in this engine is going to be updated, so we  
      * can stop playback before that happens.  
      */  
     void Engine::ResourceToBeUpdated(::gig::Instrument* pResource, void*& pUpdateArg) {  
         dmsg(3,("gig::Engine: Received instrument update message.\n"));  
         DisableAndLock();  
         ResetInternal();  
         this->pInstrument = NULL;  
     }  
   
     /**  
      * Will be called by the InstrumentResourceManager when the instrument  
      * update process was completed, so we can continue with playback.  
232       */       */
     void Engine::ResourceUpdated(::gig::Instrument* pOldResource, ::gig::Instrument* pNewResource, void* pUpdateArg) {  
         this->pInstrument = pNewResource; //TODO: there are couple of engine parameters we should update here as well if the instrument was updated (see LoadInstrument())  
         Enable();  
     }  
   
233      void Engine::Connect(AudioOutputDevice* pAudioOut) {      void Engine::Connect(AudioOutputDevice* pAudioOut) {
234          pAudioOutputDevice = pAudioOut;          pAudioOutputDevice = pAudioOut;
235    
# Line 332  namespace LinuxSampler { namespace gig { Line 241  namespace LinuxSampler { namespace gig {
241          }          }
242          catch (AudioOutputException e) {          catch (AudioOutputException e) {
243              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();
244              throw LinuxSamplerException(msg);              throw Exception(msg);
245          }          }
246    
247          this->AudioDeviceChannelLeft  = 0;          this->MaxSamplesPerCycle = pAudioOutputDevice->MaxSamplesPerCycle();
248          this->AudioDeviceChannelRight = 1;          this->SampleRate         = pAudioOutputDevice->SampleRate();
         this->pOutputLeft             = pAudioOutputDevice->Channel(0)->Buffer();  
         this->pOutputRight            = pAudioOutputDevice->Channel(1)->Buffer();  
         this->MaxSamplesPerCycle      = pAudioOutputDevice->MaxSamplesPerCycle();  
         this->SampleRate              = pAudioOutputDevice->SampleRate();  
249    
250          // FIXME: audio drivers with varying fragment sizes might be a problem here          // FIXME: audio drivers with varying fragment sizes might be a problem here
251          MaxFadeOutPos = MaxSamplesPerCycle - int(double(SampleRate) * EG_MIN_RELEASE_TIME) - 1;          MaxFadeOutPos = MaxSamplesPerCycle - int(double(SampleRate) * CONFIG_EG_MIN_RELEASE_TIME) - 1;
252          if (MaxFadeOutPos < 0)          if (MaxFadeOutPos < 0) {
253              throw LinuxSamplerException("EG_MIN_RELEASE_TIME in EGADSR.h to big for current audio fragment size / sampling rate!");              std::cerr << "gig::Engine: WARNING, CONFIG_EG_MIN_RELEASE_TIME "
254                          << "too big for current audio fragment size & sampling rate! "
255                          << "May lead to click sounds if voice stealing chimes in!\n" << std::flush;
256                // force volume ramp downs at the beginning of each fragment
257                MaxFadeOutPos = 0;
258                // lower minimum release time
259                const float minReleaseTime = (float) MaxSamplesPerCycle / (float) SampleRate;
260                for (RTList<Voice>::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
261                    iterVoice->EG1.CalculateFadeOutCoeff(minReleaseTime, SampleRate);
262                }
263                pVoicePool->clear();
264            }
265    
266          // (re)create disk thread          // (re)create disk thread
267          if (this->pDiskThread) {          if (this->pDiskThread) {
# Line 354  namespace LinuxSampler { namespace gig { Line 270  namespace LinuxSampler { namespace gig {
270              delete this->pDiskThread;              delete this->pDiskThread;
271              dmsg(1,("OK\n"));              dmsg(1,("OK\n"));
272          }          }
273          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
274                                               &instruments);
275          if (!pDiskThread) {          if (!pDiskThread) {
276              dmsg(0,("gig::Engine  new diskthread = NULL\n"));              dmsg(0,("gig::Engine  new diskthread = NULL\n"));
277              exit(EXIT_FAILURE);              exit(EXIT_FAILURE);
# Line 370  namespace LinuxSampler { namespace gig { Line 287  namespace LinuxSampler { namespace gig {
287          if (pEventGenerator) delete pEventGenerator;          if (pEventGenerator) delete pEventGenerator;
288          pEventGenerator = new EventGenerator(pAudioOut->SampleRate());          pEventGenerator = new EventGenerator(pAudioOut->SampleRate());
289    
         // (re)allocate synthesis parameter matrix  
         if (pSynthesisParameters[0]) free(pSynthesisParameters[0]);  
   
         #if defined(__APPLE__)  
         pSynthesisParameters[0] = (float *) malloc(Event::destination_count * sizeof(float) * pAudioOut->MaxSamplesPerCycle());  
         #else  
         pSynthesisParameters[0] = (float *) memalign(16,(Event::destination_count * sizeof(float) * pAudioOut->MaxSamplesPerCycle()));  
         #endif  
         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()];  
   
290          dmsg(1,("Starting disk thread..."));          dmsg(1,("Starting disk thread..."));
291          pDiskThread->StartThread();          pDiskThread->StartThread();
292          dmsg(1,("OK\n"));          dmsg(1,("OK\n"));
# Line 399  namespace LinuxSampler { namespace gig { Line 299  namespace LinuxSampler { namespace gig {
299          }          }
300      }      }
301    
302      void Engine::DisconnectAudioOutputDevice() {      /**
303          if (pAudioOutputDevice) { // if clause to prevent disconnect loops       * Clear all engine global event lists.
304              AudioOutputDevice* olddevice = pAudioOutputDevice;       */
305              pAudioOutputDevice = NULL;      void Engine::ClearEventLists() {
306              olddevice->Disconnect(this);          pGlobalEvents->clear();
307              AudioDeviceChannelLeft  = -1;      }
308              AudioDeviceChannelRight = -1;  
309        /**
310         * Copy all events from the engine's global input queue buffer to the
311         * engine's internal event list. This will be done at the beginning of
312         * each audio cycle (that is each RenderAudio() call) to distinguish
313         * all global events which have to be processed in the current audio
314         * cycle. These events are usually just SysEx messages. Every
315         * EngineChannel has it's own input event queue buffer and event list
316         * to handle common events like NoteOn, NoteOff and ControlChange
317         * events.
318         *
319         * @param Samples - number of sample points to be processed in the
320         *                  current audio cycle
321         */
322        void Engine::ImportEvents(uint Samples) {
323            RingBuffer<Event,false>::NonVolatileReader eventQueueReader = pEventQueue->get_non_volatile_reader();
324            Event* pEvent;
325            while (true) {
326                // get next event from input event queue
327                if (!(pEvent = eventQueueReader.pop())) break;
328                // if younger event reached, ignore that and all subsequent ones for now
329                if (pEvent->FragmentPos() >= Samples) {
330                    eventQueueReader--;
331                    dmsg(2,("Younger Event, pos=%d ,Samples=%d!\n",pEvent->FragmentPos(),Samples));
332                    pEvent->ResetFragmentPos();
333                    break;
334                }
335                // copy event to internal event list
336                if (pGlobalEvents->poolIsEmpty()) {
337                    dmsg(1,("Event pool emtpy!\n"));
338                    break;
339                }
340                *pGlobalEvents->allocAppend() = *pEvent;
341          }          }
342            eventQueueReader.free(); // free all copied events from input queue
343      }      }
344    
345      /**      /**
346       *  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.
347       *  calculated audio data of all voices of this engine will be placed into       * The engine will iterate through all engine channels and render audio
348       *  the engine's audio sum buffer which has to be copied and eventually be       * for each engine channel independently. The calculated audio data of
349       *  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
350       *  AlsaIO or JackIO) right after.       * buffers of the respective audio output device, connected to the
351         * respective engine channel.
352       *       *
353       *  @param Samples - number of sample points to be rendered       *  @param Samples - number of sample points to be rendered
354       *  @returns       0 on success       *  @returns       0 on success
355       */       */
356      int Engine::RenderAudio(uint Samples) {      int Engine::RenderAudio(uint Samples) {
357          dmsg(5,("RenderAudio(Samples=%d)\n", Samples));          dmsg(7,("RenderAudio(Samples=%d)\n", Samples));
358    
359          // return if no instrument loaded or engine disabled          // return if engine disabled
360          if (EngineDisabled.Pop()) {          if (EngineDisabled.Pop()) {
361              dmsg(5,("gig::Engine: engine disabled (val=%d)\n",EngineDisabled.GetUnsafe()));              dmsg(5,("gig::Engine: engine disabled (val=%d)\n",EngineDisabled.GetUnsafe()));
362              return 0;              return 0;
363          }          }
         if (!pInstrument) {  
             dmsg(5,("gig::Engine: no instrument loaded\n"));  
             return 0;  
         }  
   
364    
365          // update time of start and end of this audio fragment (as events' time stamps relate to this)          // update time of start and end of this audio fragment (as events' time stamps relate to this)
366          pEventGenerator->UpdateFragmentTime(Samples);          pEventGenerator->UpdateFragmentTime(Samples);
367    
368            // We only allow a maximum of CONFIG_MAX_VOICES voices to be spawned
369            // in each audio fragment. All subsequent request for spawning new
370            // voices in the same audio fragment will be ignored.
371            VoiceSpawnsLeft = CONFIG_MAX_VOICES;
372    
373            // get all events from the engine's global input event queue which belong to the current fragment
374            // (these are usually just SysEx messages)
375            ImportEvents(Samples);
376    
377          // empty the event lists for the new fragment          // process engine global events (these are currently only MIDI System Exclusive messages)
         pEvents->clear();  
         pCCEvents->clear();  
         for (uint i = 0; i < Event::destination_count; i++) {  
             pSynthesisEvents[i]->clear();  
         }  
378          {          {
379              RTList<uint>::Iterator iuiKey = pActiveKeys->first();              RTList<Event>::Iterator itEvent = pGlobalEvents->first();
380              RTList<uint>::Iterator end    = pActiveKeys->end();              RTList<Event>::Iterator end     = pGlobalEvents->end();
381              for(; iuiKey != end; ++iuiKey) {              for (; itEvent != end; ++itEvent) {
382                  pMIDIKeyInfo[*iuiKey].pEvents->clear(); // free all events on the key                  switch (itEvent->Type) {
383                        case Event::type_sysex:
384                            dmsg(5,("Engine: Sysex received\n"));
385                            ProcessSysex(itEvent);
386                            break;
387                    }
388              }              }
389          }          }
390    
391            // reset internal voice counter (just for statistic of active voices)
392            ActiveVoiceCountTemp = 0;
393    
394          // get all events from the input event queue which belong to the current fragment          // handle instrument change commands
395          {          instrument_change_command_t command;
396              RingBuffer<Event>::NonVolatileReader eventQueueReader = pEventQueue->get_non_volatile_reader();          if (InstrumentChangeQueue->pop(&command) > 0) {
397              Event* pEvent;              EngineChannel* pEngineChannel = command.pEngineChannel;
398              while (true) {              pEngineChannel->pInstrument = command.pInstrument;
399                  // get next event from input event queue  
400                  if (!(pEvent = eventQueueReader.pop())) break;              // iterate through all active voices and mark their
401                  // if younger event reached, ignore that and all subsequent ones for now              // dimension regions as "in use". The instrument resource
402                  if (pEvent->FragmentPos() >= Samples) {              // manager may delete all of the instrument except the
403                      eventQueueReader--;              // dimension regions and samples that are in use.
404                      dmsg(2,("Younger Event, pos=%d ,Samples=%d!\n",pEvent->FragmentPos(),Samples));              int i = 0;
405                      pEvent->ResetFragmentPos();              RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
406                      break;              RTList<uint>::Iterator end    = pEngineChannel->pActiveKeys->end();
407                  }              while (iuiKey != end) { // iterate through all active keys
408                  // copy event to internal event list                  midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
409                  if (pEvents->poolIsEmpty()) {                  ++iuiKey;
410                      dmsg(1,("Event pool emtpy!\n"));  
411                      break;                  RTList<Voice>::Iterator itVoice     = pKey->pActiveVoices->first();
412                    RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();
413                    for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
414                        if (!itVoice->Orphan) {
415                            itVoice->Orphan = true;
416                            pDimRegionsInUse[i++] = itVoice->pDimRgn;
417                        }
418                  }                  }
                 *pEvents->allocAppend() = *pEvent;  
419              }              }
420              eventQueueReader.free(); // free all copied events from input queue              pDimRegionsInUse[i] = 0; // end of list
421    
422                // send a reply to the calling thread, which is waiting
423                instrument_change_reply_t reply;
424                InstrumentChangeReplyQueue->push(&reply);
425            }
426    
427            // handle events on all engine channels
428            for (int i = 0; i < engineChannels.size(); i++) {
429                ProcessEvents(engineChannels[i], Samples);
430            }
431    
432            // render all 'normal', active voices on all engine channels
433            for (int i = 0; i < engineChannels.size(); i++) {
434                RenderActiveVoices(engineChannels[i], Samples);
435            }
436    
437            // now that all ordinary voices on ALL engine channels are rendered, render new stolen voices
438            RenderStolenVoices(Samples);
439    
440            // handle audio routing for engine channels with FX sends
441            for (int i = 0; i < engineChannels.size(); i++) {
442                if (engineChannels[i]->fxSends.empty()) continue; // ignore if no FX sends
443                RouteAudio(engineChannels[i], Samples);
444            }
445    
446            // handle cleanup on all engine channels for the next audio fragment
447            for (int i = 0; i < engineChannels.size(); i++) {
448                PostProcess(engineChannels[i]);
449          }          }
450    
451    
452            // empty the engine's event list for the next audio fragment
453            ClearEventLists();
454    
455            // reset voice stealing for the next audio fragment
456            pVoiceStealingQueue->clear();
457    
458            // just some statistics about this engine instance
459            ActiveVoiceCount = ActiveVoiceCountTemp;
460            if (ActiveVoiceCount > ActiveVoiceCountMax) ActiveVoiceCountMax = ActiveVoiceCount;
461    
462            FrameTime += Samples;
463    
464            return 0;
465        }
466    
467        /**
468         * Dispatch and handle all events in this audio fragment for the given
469         * engine channel.
470         *
471         * @param pEngineChannel - engine channel on which events should be
472         *                         processed
473         * @param Samples        - amount of sample points to be processed in
474         *                         this audio fragment cycle
475         */
476        void Engine::ProcessEvents(EngineChannel* pEngineChannel, uint Samples) {
477            // get all events from the engine channels's input event queue which belong to the current fragment
478            // (these are the common events like NoteOn, NoteOff, ControlChange, etc.)
479            pEngineChannel->ImportEvents(Samples);
480    
481          // process events          // process events
482          {          {
483              RTList<Event>::Iterator itEvent = pEvents->first();              RTList<Event>::Iterator itEvent = pEngineChannel->pEvents->first();
484              RTList<Event>::Iterator end     = pEvents->end();              RTList<Event>::Iterator end     = pEngineChannel->pEvents->end();
485              for (; itEvent != end; ++itEvent) {              for (; itEvent != end; ++itEvent) {
486                  switch (itEvent->Type) {                  switch (itEvent->Type) {
487                      case Event::type_note_on:                      case Event::type_note_on:
488                          dmsg(5,("Engine: Note on received\n"));                          dmsg(5,("Engine: Note on received\n"));
489                          ProcessNoteOn(itEvent);                          ProcessNoteOn((EngineChannel*)itEvent->pEngineChannel, itEvent);
490                          break;                          break;
491                      case Event::type_note_off:                      case Event::type_note_off:
492                          dmsg(5,("Engine: Note off received\n"));                          dmsg(5,("Engine: Note off received\n"));
493                          ProcessNoteOff(itEvent);                          ProcessNoteOff((EngineChannel*)itEvent->pEngineChannel, itEvent);
494                          break;                          break;
495                      case Event::type_control_change:                      case Event::type_control_change:
496                          dmsg(5,("Engine: MIDI CC received\n"));                          dmsg(5,("Engine: MIDI CC received\n"));
497                          ProcessControlChange(itEvent);                          ProcessControlChange((EngineChannel*)itEvent->pEngineChannel, itEvent);
498                          break;                          break;
499                      case Event::type_pitchbend:                      case Event::type_pitchbend:
500                          dmsg(5,("Engine: Pitchbend received\n"));                          dmsg(5,("Engine: Pitchbend received\n"));
501                          ProcessPitchbend(itEvent);                          ProcessPitchbend((EngineChannel*)itEvent->pEngineChannel, itEvent);
                         break;  
                     case Event::type_sysex:  
                         dmsg(5,("Engine: Sysex received\n"));  
                         ProcessSysex(itEvent);  
502                          break;                          break;
503                  }                  }
504              }              }
505          }          }
506    
507            // reset voice stealing for the next engine channel (or next audio fragment)
508            itLastStolenVoice         = RTList<Voice>::Iterator();
509            itLastStolenVoiceGlobally = RTList<Voice>::Iterator();
510            iuiLastStolenKey          = RTList<uint>::Iterator();
511            iuiLastStolenKeyGlobally  = RTList<uint>::Iterator();
512            pLastStolenChannel        = NULL;
513        }
514    
515          int active_voices = 0;      /**
516         * Render all 'normal' voices (that is voices which were not stolen in
517         * this fragment) on the given engine channel.
518         *
519         * @param pEngineChannel - engine channel on which audio should be
520         *                         rendered
521         * @param Samples        - amount of sample points to be rendered in
522         *                         this audio fragment cycle
523         */
524        void Engine::RenderActiveVoices(EngineChannel* pEngineChannel, uint Samples) {
525            #if !CONFIG_PROCESS_MUTED_CHANNELS
526            if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
527            #endif
528    
529          // render audio from all active voices          uint voiceCount = 0;
530          {          uint streamCount = 0;
531              RTList<uint>::Iterator iuiKey = pActiveKeys->first();          RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
532              RTList<uint>::Iterator end    = pActiveKeys->end();          RTList<uint>::Iterator end    = pEngineChannel->pActiveKeys->end();
533              while (iuiKey != end) { // iterate through all active keys          while (iuiKey != end) { // iterate through all active keys
534                  midi_key_info_t* pKey = &pMIDIKeyInfo[*iuiKey];              midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
535                  ++iuiKey;              ++iuiKey;
536    
537                RTList<Voice>::Iterator itVoice     = pKey->pActiveVoices->first();
538                RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();
539                for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
540                    // now render current voice
541                    itVoice->Render(Samples);
542                    if (itVoice->IsActive()) { // still active
543                        ActiveVoiceCountTemp++;
544                        voiceCount++;
545    
546                  RTList<Voice>::Iterator itVoice     = pKey->pActiveVoices->first();                      if (itVoice->PlaybackState == Voice::playback_state_disk) {
547                  RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();                          if ((itVoice->DiskStreamRef).State == Stream::state_active) streamCount++;
                 for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key  
                     // now render current voice  
                     itVoice->Render(Samples);  
                     if (itVoice->IsActive()) active_voices++; // still active  
                     else { // voice reached end, is now inactive  
                         FreeVoice(itVoice); // remove voice from the list of active voices  
548                      }                      }
549                    }  else { // voice reached end, is now inactive
550                        FreeVoice(pEngineChannel, itVoice); // remove voice from the list of active voices
551                  }                  }
552              }              }
553          }          }
554            
555            pEngineChannel->SetVoiceCount(voiceCount);
556            pEngineChannel->SetDiskStreamCount(streamCount);
557        }
558    
559        /**
560          // now render all postponed voices from voice stealing       * Render all stolen voices (only voices which were stolen in this
561          {       * fragment) on the given engine channel. Stolen voices are rendered
562              RTList<Event>::Iterator itVoiceStealEvent = pVoiceStealingQueue->first();       * after all normal voices have been rendered; this is needed to render
563              RTList<Event>::Iterator end               = pVoiceStealingQueue->end();       * audio of those voices which were selected for voice stealing until
564              for (; itVoiceStealEvent != end; ++itVoiceStealEvent) {       * the point were the stealing (that is the take over of the voice)
565                  Pool<Voice>::Iterator itNewVoice = LaunchVoice(itVoiceStealEvent, itVoiceStealEvent->Param.Note.Layer, itVoiceStealEvent->Param.Note.ReleaseTrigger, false);       * actually happened.
566                  if (itNewVoice) {       *
567                      for (; itNewVoice; itNewVoice = itNewVoice->itChildVoice) {       * @param pEngineChannel - engine channel on which audio should be
568                          itNewVoice->Render(Samples);       *                         rendered
569                          if (itNewVoice->IsActive()) active_voices++; // still active       * @param Samples        - amount of sample points to be rendered in
570                          else { // voice reached end, is now inactive       *                         this audio fragment cycle
571                              FreeVoice(itNewVoice); // remove voice from the list of active voices       */
572        void Engine::RenderStolenVoices(uint Samples) {
573            RTList<Event>::Iterator itVoiceStealEvent = pVoiceStealingQueue->first();
574            RTList<Event>::Iterator end               = pVoiceStealingQueue->end();
575            for (; itVoiceStealEvent != end; ++itVoiceStealEvent) {
576                EngineChannel* pEngineChannel = (EngineChannel*) itVoiceStealEvent->pEngineChannel;
577                if (!pEngineChannel->pInstrument) continue; // ignore if no instrument loaded
578                Pool<Voice>::Iterator itNewVoice =
579                    LaunchVoice(pEngineChannel, itVoiceStealEvent, itVoiceStealEvent->Param.Note.Layer, itVoiceStealEvent->Param.Note.ReleaseTrigger, false, false);
580                if (itNewVoice) {
581                    itNewVoice->Render(Samples);
582                    if (itNewVoice->IsActive()) { // still active
583                        ActiveVoiceCountTemp++;
584                        pEngineChannel->SetVoiceCount(pEngineChannel->GetVoiceCount() + 1);
585    
586                        if (itNewVoice->PlaybackState == Voice::playback_state_disk) {
587                            if (itNewVoice->DiskStreamRef.State == Stream::state_active) {
588                                pEngineChannel->SetDiskStreamCount(pEngineChannel->GetDiskStreamCount() + 1);
589                          }                          }
590                      }                      }
591                    } else { // voice reached end, is now inactive
592                        FreeVoice(pEngineChannel, itNewVoice); // remove voice from the list of active voices
593                  }                  }
                 else dmsg(1,("gig::Engine: ERROR, voice stealing didn't work out!\n"));  
594              }              }
595                else dmsg(1,("gig::Engine: ERROR, voice stealing didn't work out!\n"));
596    
597                // we need to clear the key's event list explicitly here in case key was never active
598                midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[itVoiceStealEvent->Param.Note.Key];
599                pKey->VoiceTheftsQueued--;
600                if (!pKey->Active && !pKey->VoiceTheftsQueued) pKey->pEvents->clear();
601          }          }
602          // reset voice stealing for the new fragment      }
         pVoiceStealingQueue->clear();  
         itLastStolenVoice = RTList<Voice>::Iterator();  
         iuiLastStolenKey  = RTList<uint>::Iterator();  
603    
604        /**
605         * Will be called in case the respective engine channel sports FX send
606         * channels. In this particular case, engine channel local buffers are
607         * used to render and mix all voices to. This method is responsible for
608         * copying the audio data from those local buffers to the master audio
609         * output channels as well as to the FX send audio output channels with
610         * their respective FX send levels.
611         *
612         * @param pEngineChannel - engine channel from which audio should be
613         *                         routed
614         * @param Samples        - amount of sample points to be routed in
615         *                         this audio fragment cycle
616         */
617        void Engine::RouteAudio(EngineChannel* pEngineChannel, uint Samples) {
618            // route master signal
619            {
620                AudioChannel* pDstL = pAudioOutputDevice->Channel(pEngineChannel->AudioDeviceChannelLeft);
621                AudioChannel* pDstR = pAudioOutputDevice->Channel(pEngineChannel->AudioDeviceChannelRight);
622                pEngineChannel->pChannelLeft->MixTo(pDstL, Samples);
623                pEngineChannel->pChannelRight->MixTo(pDstR, Samples);
624            }
625            // route FX send signal
626            {
627                for (int iFxSend = 0; iFxSend < pEngineChannel->GetFxSendCount(); iFxSend++) {
628                    FxSend* pFxSend = pEngineChannel->GetFxSend(iFxSend);
629                    // left channel
630                    const int iDstL = pFxSend->DestinationChannel(0);
631                    if (iDstL < 0) {
632                        dmsg(1,("Engine::RouteAudio() Error: invalid FX send (L) destination channel"));
633                    } else {
634                        AudioChannel* pDstL = pAudioOutputDevice->Channel(iDstL);
635                        if (!pDstL) {
636                            dmsg(1,("Engine::RouteAudio() Error: invalid FX send (L) destination channel"));
637                        } else pEngineChannel->pChannelLeft->MixTo(pDstL, Samples, pFxSend->Level());
638                    }
639                    // right channel
640                    const int iDstR = pFxSend->DestinationChannel(1);
641                    if (iDstR < 0) {
642                        dmsg(1,("Engine::RouteAudio() Error: invalid FX send (R) destination channel"));
643                    } else {
644                        AudioChannel* pDstR = pAudioOutputDevice->Channel(iDstR);
645                        if (!pDstR) {
646                            dmsg(1,("Engine::RouteAudio() Error: invalid FX send (R) destination channel"));
647                        } else pEngineChannel->pChannelRight->MixTo(pDstR, Samples, pFxSend->Level());
648                    }
649                }
650            }
651            // reset buffers with silence (zero out) for the next audio cycle
652            pEngineChannel->pChannelLeft->Clear();
653            pEngineChannel->pChannelRight->Clear();
654        }
655    
656        /**
657         * Free all keys which have turned inactive in this audio fragment, from
658         * the list of active keys and clear all event lists on that engine
659         * channel.
660         *
661         * @param pEngineChannel - engine channel to cleanup
662         */
663        void Engine::PostProcess(EngineChannel* pEngineChannel) {
664          // free all keys which have no active voices left          // free all keys which have no active voices left
665          {          {
666              RTList<uint>::Iterator iuiKey = pActiveKeys->first();              RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
667              RTList<uint>::Iterator end    = pActiveKeys->end();              RTList<uint>::Iterator end    = pEngineChannel->pActiveKeys->end();
668              while (iuiKey != end) { // iterate through all active keys              while (iuiKey != end) { // iterate through all active keys
669                  midi_key_info_t* pKey = &pMIDIKeyInfo[*iuiKey];                  midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
670                  ++iuiKey;                  ++iuiKey;
671                  if (pKey->pActiveVoices->isEmpty()) FreeKey(pKey);                  if (pKey->pActiveVoices->isEmpty()) FreeKey(pEngineChannel, pKey);
672                  #if DEVMODE                  #if CONFIG_DEVMODE
673                  else { // FIXME: should be removed before the final release (purpose: just a sanity check for debugging)                  else { // just a sanity check for debugging
674                      RTList<Voice>::Iterator itVoice     = pKey->pActiveVoices->first();                      RTList<Voice>::Iterator itVoice     = pKey->pActiveVoices->first();
675                      RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();                      RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();
676                      for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key                      for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
# Line 574  namespace LinuxSampler { namespace gig { Line 679  namespace LinuxSampler { namespace gig {
679                          }                          }
680                      }                      }
681                  }                  }
682                  #endif // DEVMODE                  #endif // CONFIG_DEVMODE
683              }              }
684          }          }
685    
686            // empty the engine channel's own event lists
687          // write that to the disk thread class so that it can print it          pEngineChannel->ClearEventLists();
         // on the console for debugging purposes  
         ActiveVoiceCount = active_voices;  
         if (ActiveVoiceCount > ActiveVoiceCountMax) ActiveVoiceCountMax = ActiveVoiceCount;  
   
   
         return 0;  
     }  
   
     /**  
      *  Will be called by the MIDIIn Thread to let the audio thread trigger a new  
      *  voice for the given key.  
      *  
      *  @param Key      - MIDI key number of the triggered key  
      *  @param Velocity - MIDI velocity value of the triggered key  
      */  
     void Engine::SendNoteOn(uint8_t Key, uint8_t Velocity) {  
         Event event               = pEventGenerator->CreateEvent();  
         event.Type                = Event::type_note_on;  
         event.Param.Note.Key      = Key;  
         event.Param.Note.Velocity = Velocity;  
         if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);  
         else dmsg(1,("Engine: Input event queue full!"));  
     }  
   
     /**  
      *  Will be called by the MIDIIn Thread to signal the audio thread to release  
      *  voice(s) on the given key.  
      *  
      *  @param Key      - MIDI key number of the released key  
      *  @param Velocity - MIDI release velocity value of the released key  
      */  
     void Engine::SendNoteOff(uint8_t Key, uint8_t Velocity) {  
         Event event               = pEventGenerator->CreateEvent();  
         event.Type                = Event::type_note_off;  
         event.Param.Note.Key      = Key;  
         event.Param.Note.Velocity = Velocity;  
         if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);  
         else dmsg(1,("Engine: Input event queue full!"));  
     }  
   
     /**  
      *  Will be called by the MIDIIn Thread to signal the audio thread to change  
      *  the pitch value for all voices.  
      *  
      *  @param Pitch - MIDI pitch value (-8192 ... +8191)  
      */  
     void Engine::SendPitchbend(int Pitch) {  
         Event event             = pEventGenerator->CreateEvent();  
         event.Type              = Event::type_pitchbend;  
         event.Param.Pitch.Pitch = Pitch;  
         if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);  
         else dmsg(1,("Engine: Input event queue full!"));  
     }  
   
     /**  
      *  Will be called by the MIDIIn Thread to signal the audio thread that a  
      *  continuous controller value has changed.  
      *  
      *  @param Controller - MIDI controller number of the occured control change  
      *  @param Value      - value of the control change  
      */  
     void Engine::SendControlChange(uint8_t Controller, uint8_t Value) {  
         Event event               = pEventGenerator->CreateEvent();  
         event.Type                = Event::type_control_change;  
         event.Param.CC.Controller = Controller;  
         event.Param.CC.Value      = Value;  
         if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);  
         else dmsg(1,("Engine: Input event queue full!"));  
688      }      }
689    
690      /**      /**
# Line 661  namespace LinuxSampler { namespace gig { Line 698  namespace LinuxSampler { namespace gig {
698          Event event             = pEventGenerator->CreateEvent();          Event event             = pEventGenerator->CreateEvent();
699          event.Type              = Event::type_sysex;          event.Type              = Event::type_sysex;
700          event.Param.Sysex.Size  = Size;          event.Param.Sysex.Size  = Size;
701            event.pEngineChannel    = NULL; // as Engine global event
702          if (pEventQueue->write_space() > 0) {          if (pEventQueue->write_space() > 0) {
703              if (pSysexBuffer->write_space() >= Size) {              if (pSysexBuffer->write_space() >= Size) {
704                  // copy sysex data to input buffer                  // copy sysex data to input buffer
# Line 676  namespace LinuxSampler { namespace gig { Line 714  namespace LinuxSampler { namespace gig {
714                  // finally place sysex event into input event queue                  // finally place sysex event into input event queue
715                  pEventQueue->push(&event);                  pEventQueue->push(&event);
716              }              }
717              else dmsg(1,("Engine: Sysex message too large (%d byte) for input buffer (%d byte)!",Size,SYSEX_BUFFER_SIZE));              else dmsg(1,("Engine: Sysex message too large (%d byte) for input buffer (%d byte)!",Size,CONFIG_SYSEX_BUFFER_SIZE));
718          }          }
719          else dmsg(1,("Engine: Input event queue full!"));          else dmsg(1,("Engine: Input event queue full!"));
720      }      }
# Line 684  namespace LinuxSampler { namespace gig { Line 722  namespace LinuxSampler { namespace gig {
722      /**      /**
723       *  Assigns and triggers a new voice for the respective MIDI key.       *  Assigns and triggers a new voice for the respective MIDI key.
724       *       *
725         *  @param pEngineChannel - engine channel on which this event occured on
726       *  @param itNoteOnEvent - key, velocity and time stamp of the event       *  @param itNoteOnEvent - key, velocity and time stamp of the event
727       */       */
728      void Engine::ProcessNoteOn(Pool<Event>::Iterator& itNoteOnEvent) {      void Engine::ProcessNoteOn(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent) {
729            #if !CONFIG_PROCESS_MUTED_CHANNELS
730            if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
731            #endif
732    
733            if (!pEngineChannel->pInstrument) return; // ignore if no instrument loaded
734    
735            //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
736            itNoteOnEvent->Param.Note.Key += pEngineChannel->GlobalTranspose;
737    
738          const int key = itNoteOnEvent->Param.Note.Key;          const int key = itNoteOnEvent->Param.Note.Key;
739            midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[key];
740    
741          // Change key dimension value if key is in keyswitching area          // move note on event to the key's own event list
742          if (key >= pInstrument->DimensionKeyRange.low && key <= pInstrument->DimensionKeyRange.high)          RTList<Event>::Iterator itNoteOnEventOnKeyList = itNoteOnEvent.moveToEndOf(pKey->pEvents);
             CurrentKeyDimension = ((key - pInstrument->DimensionKeyRange.low) * 128) /  
                 (pInstrument->DimensionKeyRange.high - pInstrument->DimensionKeyRange.low + 1);  
743    
744          midi_key_info_t* pKey = &pMIDIKeyInfo[key];          // if Solo Mode then kill all already active voices
745            if (pEngineChannel->SoloMode) {
746                Pool<uint>::Iterator itYoungestKey = pEngineChannel->pActiveKeys->last();
747                if (itYoungestKey) {
748                    const int iYoungestKey = *itYoungestKey;
749                    const midi_key_info_t* pOtherKey = &pEngineChannel->pMIDIKeyInfo[iYoungestKey];
750                    if (pOtherKey->Active) {
751                        // get final portamento position of currently active voice
752                        if (pEngineChannel->PortamentoMode) {
753                            RTList<Voice>::Iterator itVoice = pOtherKey->pActiveVoices->last();
754                            if (itVoice) itVoice->UpdatePortamentoPos(itNoteOnEventOnKeyList);
755                        }
756                        // kill all voices on the (other) key
757                        RTList<Voice>::Iterator itVoiceToBeKilled = pOtherKey->pActiveVoices->first();
758                        RTList<Voice>::Iterator end               = pOtherKey->pActiveVoices->end();
759                        for (; itVoiceToBeKilled != end; ++itVoiceToBeKilled) {
760                            if (itVoiceToBeKilled->Type != Voice::type_release_trigger)
761                                itVoiceToBeKilled->Kill(itNoteOnEventOnKeyList);
762                        }
763                    }
764                }
765                // set this key as 'currently active solo key'
766                pEngineChannel->SoloKey = key;
767            }
768    
769            // Change key dimension value if key is in keyswitching area
770            {
771                const ::gig::Instrument* pInstrument = pEngineChannel->pInstrument;
772                if (key >= pInstrument->DimensionKeyRange.low && key <= pInstrument->DimensionKeyRange.high)
773                    pEngineChannel->CurrentKeyDimension = float(key - pInstrument->DimensionKeyRange.low) /
774                        (pInstrument->DimensionKeyRange.high - pInstrument->DimensionKeyRange.low + 1);
775            }
776    
777          pKey->KeyPressed = true; // the MIDI key was now pressed down          pKey->KeyPressed = true; // the MIDI key was now pressed down
778            pKey->Velocity   = itNoteOnEventOnKeyList->Param.Note.Velocity;
779            pKey->NoteOnTime = FrameTime + itNoteOnEventOnKeyList->FragmentPos(); // will be used to calculate note length
780    
781          // cancel release process of voices on this key if needed          // cancel release process of voices on this key if needed
782          if (pKey->Active && !SustainPedal) {          if (pKey->Active && !pEngineChannel->SustainPedal) {
783              RTList<Event>::Iterator itCancelReleaseEvent = pKey->pEvents->allocAppend();              RTList<Event>::Iterator itCancelReleaseEvent = pKey->pEvents->allocAppend();
784              if (itCancelReleaseEvent) {              if (itCancelReleaseEvent) {
785                  *itCancelReleaseEvent = *itNoteOnEvent;                  // copy event                  *itCancelReleaseEvent = *itNoteOnEventOnKeyList;         // copy event
786                  itCancelReleaseEvent->Type = Event::type_cancel_release; // transform event type                  itCancelReleaseEvent->Type = Event::type_cancel_release; // transform event type
787              }              }
788              else dmsg(1,("Event pool emtpy!\n"));              else dmsg(1,("Event pool emtpy!\n"));
789          }          }
790    
791          // move note on event to the key's own event list          // allocate and trigger new voice(s) for the key
792          RTList<Event>::Iterator itNoteOnEventOnKeyList = itNoteOnEvent.moveToEndOf(pKey->pEvents);          {
793                // first, get total amount of required voices (dependant on amount of layers)
794                ::gig::Region* pRegion = pEngineChannel->pInstrument->GetRegion(itNoteOnEventOnKeyList->Param.Note.Key);
795                if (pRegion) {
796                    int voicesRequired = pRegion->Layers;
797                    // now launch the required amount of voices
798                    for (int i = 0; i < voicesRequired; i++)
799                        LaunchVoice(pEngineChannel, itNoteOnEventOnKeyList, i, false, true, true);
800                }
801            }
802    
803          // allocate and trigger a new voice for the key          // if neither a voice was spawned or postponed then remove note on event from key again
804          LaunchVoice(itNoteOnEventOnKeyList, 0, false, true);          if (!pKey->Active && !pKey->VoiceTheftsQueued)
805                pKey->pEvents->free(itNoteOnEventOnKeyList);
806    
807            if (!pEngineChannel->SoloMode || pEngineChannel->PortamentoPos < 0.0f) pEngineChannel->PortamentoPos = (float) key;
808            pKey->RoundRobinIndex++;
809      }      }
810    
811      /**      /**
# Line 722  namespace LinuxSampler { namespace gig { Line 814  namespace LinuxSampler { namespace gig {
814       *  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.
815       *  due to completion of sample playback).       *  due to completion of sample playback).
816       *       *
817         *  @param pEngineChannel - engine channel on which this event occured on
818       *  @param itNoteOffEvent - key, velocity and time stamp of the event       *  @param itNoteOffEvent - key, velocity and time stamp of the event
819       */       */
820      void Engine::ProcessNoteOff(Pool<Event>::Iterator& itNoteOffEvent) {      void Engine::ProcessNoteOff(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOffEvent) {
821          midi_key_info_t* pKey = &pMIDIKeyInfo[itNoteOffEvent->Param.Note.Key];          #if !CONFIG_PROCESS_MUTED_CHANNELS
822            if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
823            #endif
824    
825          pKey->KeyPressed = false; // the MIDI key was now released          //HACK: we should better add the transpose value only to the most mandatory places (like for retrieving the region and calculating the tuning), because otherwise voices will unintendedly survive when changing transpose while playing
826            itNoteOffEvent->Param.Note.Key += pEngineChannel->GlobalTranspose;
827    
828          // release voices on this key if needed          const int iKey = itNoteOffEvent->Param.Note.Key;
829          if (pKey->Active && !SustainPedal) {          midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[iKey];
830              itNoteOffEvent->Type = Event::type_release; // transform event type          pKey->KeyPressed = false; // the MIDI key was now released
         }  
831    
832          // move event to the key's own event list          // move event to the key's own event list
833          RTList<Event>::Iterator itNoteOffEventOnKeyList = itNoteOffEvent.moveToEndOf(pKey->pEvents);          RTList<Event>::Iterator itNoteOffEventOnKeyList = itNoteOffEvent.moveToEndOf(pKey->pEvents);
834    
835          // spawn release triggered voice(s) if needed          bool bShouldRelease = pKey->Active && ShouldReleaseVoice(pEngineChannel, itNoteOffEventOnKeyList->Param.Note.Key);
836          if (pKey->ReleaseTrigger) {  
837              LaunchVoice(itNoteOffEventOnKeyList, 0, true, false); //FIXME: for the moment we don't perform voice stealing for release triggered samples          // in case Solo Mode is enabled, kill all voices on this key and respawn a voice on the highest pressed key (if any)
838              pKey->ReleaseTrigger = false;          if (pEngineChannel->SoloMode && pEngineChannel->pInstrument) { //TODO: this feels like too much code just for handling solo mode :P
839                bool bOtherKeysPressed = false;
840                if (iKey == pEngineChannel->SoloKey) {
841                    pEngineChannel->SoloKey = -1;
842                    // if there's still a key pressed down, respawn a voice (group) on the highest key
843                    for (int i = 127; i > 0; i--) {
844                        midi_key_info_t* pOtherKey = &pEngineChannel->pMIDIKeyInfo[i];
845                        if (pOtherKey->KeyPressed) {
846                            bOtherKeysPressed = true;
847                            // make the other key the new 'currently active solo key'
848                            pEngineChannel->SoloKey = i;
849                            // get final portamento position of currently active voice
850                            if (pEngineChannel->PortamentoMode) {
851                                RTList<Voice>::Iterator itVoice = pKey->pActiveVoices->first();
852                                if (itVoice) itVoice->UpdatePortamentoPos(itNoteOffEventOnKeyList);
853                            }
854                            // create a pseudo note on event
855                            RTList<Event>::Iterator itPseudoNoteOnEvent = pOtherKey->pEvents->allocAppend();
856                            if (itPseudoNoteOnEvent) {
857                                // copy event
858                                *itPseudoNoteOnEvent = *itNoteOffEventOnKeyList;
859                                // transform event to a note on event
860                                itPseudoNoteOnEvent->Type                = Event::type_note_on;
861                                itPseudoNoteOnEvent->Param.Note.Key      = i;
862                                itPseudoNoteOnEvent->Param.Note.Velocity = pOtherKey->Velocity;
863                                // allocate and trigger new voice(s) for the other key
864                                {
865                                    // first, get total amount of required voices (dependant on amount of layers)
866                                    ::gig::Region* pRegion = pEngineChannel->pInstrument->GetRegion(i);
867                                    if (pRegion) {
868                                        int voicesRequired = pRegion->Layers;
869                                        // now launch the required amount of voices
870                                        for (int iLayer = 0; iLayer < voicesRequired; iLayer++)
871                                            LaunchVoice(pEngineChannel, itPseudoNoteOnEvent, iLayer, false, true, false);
872                                    }
873                                }
874                                // if neither a voice was spawned or postponed then remove note on event from key again
875                                if (!pOtherKey->Active && !pOtherKey->VoiceTheftsQueued)
876                                    pOtherKey->pEvents->free(itPseudoNoteOnEvent);
877    
878                            } else dmsg(1,("Could not respawn voice, no free event left\n"));
879                            break; // done
880                        }
881                    }
882                }
883                if (bOtherKeysPressed) {
884                    if (pKey->Active) { // kill all voices on this key
885                        bShouldRelease = false; // no need to release, as we kill it here
886                        RTList<Voice>::Iterator itVoiceToBeKilled = pKey->pActiveVoices->first();
887                        RTList<Voice>::Iterator end               = pKey->pActiveVoices->end();
888                        for (; itVoiceToBeKilled != end; ++itVoiceToBeKilled) {
889                            if (itVoiceToBeKilled->Type != Voice::type_release_trigger)
890                                itVoiceToBeKilled->Kill(itNoteOffEventOnKeyList);
891                        }
892                    }
893                } else pEngineChannel->PortamentoPos = -1.0f;
894            }
895    
896            // if no solo mode (the usual case) or if solo mode and no other key pressed, then release voices on this key if needed
897            if (bShouldRelease) {
898                itNoteOffEventOnKeyList->Type = Event::type_release; // transform event type
899    
900                // spawn release triggered voice(s) if needed
901                if (pKey->ReleaseTrigger && pEngineChannel->pInstrument) {
902                    // first, get total amount of required voices (dependant on amount of layers)
903                    ::gig::Region* pRegion = pEngineChannel->pInstrument->GetRegion(itNoteOffEventOnKeyList->Param.Note.Key);
904                    if (pRegion) {
905                        int voicesRequired = pRegion->Layers;
906    
907                        // MIDI note-on velocity is used instead of note-off velocity
908                        itNoteOffEventOnKeyList->Param.Note.Velocity = pKey->Velocity;
909    
910                        // now launch the required amount of voices
911                        for (int i = 0; i < voicesRequired; i++)
912                            LaunchVoice(pEngineChannel, itNoteOffEventOnKeyList, i, true, false, false); //FIXME: for the moment we don't perform voice stealing for release triggered samples
913                    }
914                    pKey->ReleaseTrigger = false;
915                }
916          }          }
917    
918            // if neither a voice was spawned or postponed on this key then remove note off event from key again
919            if (!pKey->Active && !pKey->VoiceTheftsQueued)
920                pKey->pEvents->free(itNoteOffEventOnKeyList);
921      }      }
922    
923      /**      /**
924       *  Moves pitchbend event from the general (input) event list to the pitch       *  Moves pitchbend event from the general (input) event list to the engine
925       *  event list.       *  channel's event list. It will actually processed later by the
926         *  respective voice.
927       *       *
928         *  @param pEngineChannel - engine channel on which this event occured on
929       *  @param itPitchbendEvent - absolute pitch value and time stamp of the event       *  @param itPitchbendEvent - absolute pitch value and time stamp of the event
930       */       */
931      void Engine::ProcessPitchbend(Pool<Event>::Iterator& itPitchbendEvent) {      void Engine::ProcessPitchbend(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itPitchbendEvent) {
932          this->Pitch = itPitchbendEvent->Param.Pitch.Pitch; // store current pitch value          pEngineChannel->Pitch = itPitchbendEvent->Param.Pitch.Pitch; // store current pitch value
         itPitchbendEvent.moveToEndOf(pSynthesisEvents[Event::destination_vco]);  
933      }      }
934    
935      /**      /**
# Line 760  namespace LinuxSampler { namespace gig { Line 937  namespace LinuxSampler { namespace gig {
937       *  called by the ProcessNoteOn() method and by the voices itself       *  called by the ProcessNoteOn() method and by the voices itself
938       *  (e.g. to spawn further voices on the same key for layered sounds).       *  (e.g. to spawn further voices on the same key for layered sounds).
939       *       *
940         *  @param pEngineChannel      - engine channel on which this event occured on
941       *  @param itNoteOnEvent       - key, velocity and time stamp of the event       *  @param itNoteOnEvent       - key, velocity and time stamp of the event
942       *  @param iLayer              - layer index for the new voice (optional - only       *  @param iLayer              - layer index for the new voice (optional - only
943       *                               in case of layered sounds of course)       *                               in case of layered sounds of course)
# Line 768  namespace LinuxSampler { namespace gig { Line 946  namespace LinuxSampler { namespace gig {
946       *  @param VoiceStealing       - if voice stealing should be performed       *  @param VoiceStealing       - if voice stealing should be performed
947       *                               when there is no free voice       *                               when there is no free voice
948       *                               (optional, default = true)       *                               (optional, default = true)
949         *  @param HandleKeyGroupConflicts - if voices should be killed due to a
950         *                                   key group conflict
951       *  @returns pointer to new voice or NULL if there was no free voice or       *  @returns pointer to new voice or NULL if there was no free voice or
952       *           if the voice wasn't triggered (for example when no region is       *           if the voice wasn't triggered (for example when no region is
953       *           defined for the given key).       *           defined for the given key).
954       */       */
955      Pool<Voice>::Iterator Engine::LaunchVoice(Pool<Event>::Iterator& itNoteOnEvent, int iLayer, bool ReleaseTriggerVoice, bool VoiceStealing) {      Pool<Voice>::Iterator Engine::LaunchVoice(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent, int iLayer, bool ReleaseTriggerVoice, bool VoiceStealing, bool HandleKeyGroupConflicts) {
956          midi_key_info_t* pKey = &pMIDIKeyInfo[itNoteOnEvent->Param.Note.Key];          int MIDIKey            = itNoteOnEvent->Param.Note.Key;
957            midi_key_info_t* pKey  = &pEngineChannel->pMIDIKeyInfo[MIDIKey];
958            ::gig::Region* pRegion = pEngineChannel->pInstrument->GetRegion(MIDIKey);
959    
960            // if nothing defined for this key
961            if (!pRegion) return Pool<Voice>::Iterator(); // nothing to do
962    
963            // only mark the first voice of a layered voice (group) to be in a
964            // key group, so the layered voices won't kill each other
965            int iKeyGroup = (iLayer == 0 && !ReleaseTriggerVoice) ? pRegion->KeyGroup : 0;
966    
967            // handle key group (a.k.a. exclusive group) conflicts
968            if (HandleKeyGroupConflicts) {
969                if (iKeyGroup) { // if this voice / key belongs to a key group
970                    uint** ppKeyGroup = &pEngineChannel->ActiveKeyGroups[iKeyGroup];
971                    if (*ppKeyGroup) { // if there's already an active key in that key group
972                        midi_key_info_t* pOtherKey = &pEngineChannel->pMIDIKeyInfo[**ppKeyGroup];
973                        // kill all voices on the (other) key
974                        RTList<Voice>::Iterator itVoiceToBeKilled = pOtherKey->pActiveVoices->first();
975                        RTList<Voice>::Iterator end               = pOtherKey->pActiveVoices->end();
976                        for (; itVoiceToBeKilled != end; ++itVoiceToBeKilled) {
977                            if (itVoiceToBeKilled->Type != Voice::type_release_trigger) {
978                                itVoiceToBeKilled->Kill(itNoteOnEvent);
979                                --VoiceSpawnsLeft; //FIXME: just a hack, we should better check in StealVoice() if the voice was killed due to key conflict
980                            }
981                        }
982                    }
983                }
984            }
985    
986            Voice::type_t VoiceType = Voice::type_normal;
987    
988            // get current dimension values to select the right dimension region
989            //TODO: for stolen voices this dimension region selection block is processed twice, this should be changed
990            //FIXME: controller values for selecting the dimension region here are currently not sample accurate
991            uint DimValues[8] = { 0 };
992            for (int i = pRegion->Dimensions - 1; i >= 0; i--) {
993                switch (pRegion->pDimensionDefinitions[i].dimension) {
994                    case ::gig::dimension_samplechannel:
995                        DimValues[i] = 0; //TODO: we currently ignore this dimension
996                        break;
997                    case ::gig::dimension_layer:
998                        DimValues[i] = iLayer;
999                        break;
1000                    case ::gig::dimension_velocity:
1001                        DimValues[i] = itNoteOnEvent->Param.Note.Velocity;
1002                        break;
1003                    case ::gig::dimension_channelaftertouch:
1004                        DimValues[i] = pEngineChannel->ControllerTable[128];
1005                        break;
1006                    case ::gig::dimension_releasetrigger:
1007                        VoiceType = (ReleaseTriggerVoice) ? Voice::type_release_trigger : (!iLayer) ? Voice::type_release_trigger_required : Voice::type_normal;
1008                        DimValues[i] = (uint) ReleaseTriggerVoice;
1009                        break;
1010                    case ::gig::dimension_keyboard:
1011                        DimValues[i] = (uint) (pEngineChannel->CurrentKeyDimension * pRegion->pDimensionDefinitions[i].zones);
1012                        break;
1013                    case ::gig::dimension_roundrobin:
1014                        DimValues[i] = (uint) pEngineChannel->pMIDIKeyInfo[MIDIKey].RoundRobinIndex; // incremented for each note on
1015                        break;
1016                    case ::gig::dimension_random:
1017                        RandomSeed   = RandomSeed * 1103515245 + 12345; // classic pseudo random number generator
1018                        DimValues[i] = (uint) RandomSeed >> (32 - pRegion->pDimensionDefinitions[i].bits); // highest bits are most random
1019                        break;
1020                    case ::gig::dimension_modwheel:
1021                        DimValues[i] = pEngineChannel->ControllerTable[1];
1022                        break;
1023                    case ::gig::dimension_breath:
1024                        DimValues[i] = pEngineChannel->ControllerTable[2];
1025                        break;
1026                    case ::gig::dimension_foot:
1027                        DimValues[i] = pEngineChannel->ControllerTable[4];
1028                        break;
1029                    case ::gig::dimension_portamentotime:
1030                        DimValues[i] = pEngineChannel->ControllerTable[5];
1031                        break;
1032                    case ::gig::dimension_effect1:
1033                        DimValues[i] = pEngineChannel->ControllerTable[12];
1034                        break;
1035                    case ::gig::dimension_effect2:
1036                        DimValues[i] = pEngineChannel->ControllerTable[13];
1037                        break;
1038                    case ::gig::dimension_genpurpose1:
1039                        DimValues[i] = pEngineChannel->ControllerTable[16];
1040                        break;
1041                    case ::gig::dimension_genpurpose2:
1042                        DimValues[i] = pEngineChannel->ControllerTable[17];
1043                        break;
1044                    case ::gig::dimension_genpurpose3:
1045                        DimValues[i] = pEngineChannel->ControllerTable[18];
1046                        break;
1047                    case ::gig::dimension_genpurpose4:
1048                        DimValues[i] = pEngineChannel->ControllerTable[19];
1049                        break;
1050                    case ::gig::dimension_sustainpedal:
1051                        DimValues[i] = pEngineChannel->ControllerTable[64];
1052                        break;
1053                    case ::gig::dimension_portamento:
1054                        DimValues[i] = pEngineChannel->ControllerTable[65];
1055                        break;
1056                    case ::gig::dimension_sostenutopedal:
1057                        DimValues[i] = pEngineChannel->ControllerTable[66];
1058                        break;
1059                    case ::gig::dimension_softpedal:
1060                        DimValues[i] = pEngineChannel->ControllerTable[67];
1061                        break;
1062                    case ::gig::dimension_genpurpose5:
1063                        DimValues[i] = pEngineChannel->ControllerTable[80];
1064                        break;
1065                    case ::gig::dimension_genpurpose6:
1066                        DimValues[i] = pEngineChannel->ControllerTable[81];
1067                        break;
1068                    case ::gig::dimension_genpurpose7:
1069                        DimValues[i] = pEngineChannel->ControllerTable[82];
1070                        break;
1071                    case ::gig::dimension_genpurpose8:
1072                        DimValues[i] = pEngineChannel->ControllerTable[83];
1073                        break;
1074                    case ::gig::dimension_effect1depth:
1075                        DimValues[i] = pEngineChannel->ControllerTable[91];
1076                        break;
1077                    case ::gig::dimension_effect2depth:
1078                        DimValues[i] = pEngineChannel->ControllerTable[92];
1079                        break;
1080                    case ::gig::dimension_effect3depth:
1081                        DimValues[i] = pEngineChannel->ControllerTable[93];
1082                        break;
1083                    case ::gig::dimension_effect4depth:
1084                        DimValues[i] = pEngineChannel->ControllerTable[94];
1085                        break;
1086                    case ::gig::dimension_effect5depth:
1087                        DimValues[i] = pEngineChannel->ControllerTable[95];
1088                        break;
1089                    case ::gig::dimension_none:
1090                        std::cerr << "gig::Engine::LaunchVoice() Error: dimension=none\n" << std::flush;
1091                        break;
1092                    default:
1093                        std::cerr << "gig::Engine::LaunchVoice() Error: Unknown dimension\n" << std::flush;
1094                }
1095            }
1096    
1097            // return if this is a release triggered voice and there is no
1098            // releasetrigger dimension (could happen if an instrument
1099            // change has occured between note on and off)
1100            if (ReleaseTriggerVoice && VoiceType != Voice::type_release_trigger) return Pool<Voice>::Iterator();
1101    
1102            ::gig::DimensionRegion* pDimRgn = pRegion->GetDimensionRegionByValue(DimValues);
1103    
1104            // no need to continue if sample is silent
1105            if (!pDimRgn->pSample || !pDimRgn->pSample->SamplesTotal) return Pool<Voice>::Iterator();
1106    
1107          // allocate a new voice for the key          // allocate a new voice for the key
1108          Pool<Voice>::Iterator itNewVoice = pKey->pActiveVoices->allocAppend();          Pool<Voice>::Iterator itNewVoice = pKey->pActiveVoices->allocAppend();
1109          if (itNewVoice) {          if (itNewVoice) {
1110              // launch the new voice              // launch the new voice
1111              if (itNewVoice->Trigger(itNoteOnEvent, this->Pitch, this->pInstrument, iLayer, ReleaseTriggerVoice, VoiceStealing) < 0) {              if (itNewVoice->Trigger(pEngineChannel, itNoteOnEvent, pEngineChannel->Pitch, pDimRgn, VoiceType, iKeyGroup) < 0) {
1112                  dmsg(4,("Voice not triggered\n"));                  dmsg(4,("Voice not triggered\n"));
1113                  pKey->pActiveVoices->free(itNewVoice);                  pKey->pActiveVoices->free(itNewVoice);
1114              }              }
1115              else { // on success              else { // on success
1116                  uint** ppKeyGroup = NULL;                  --VoiceSpawnsLeft;
                 if (itNewVoice->KeyGroup) { // if this voice / key belongs to a key group  
                     ppKeyGroup = &ActiveKeyGroups[itNewVoice->KeyGroup];  
                     if (*ppKeyGroup) { // if there's already an active key in that key group  
                         midi_key_info_t* pOtherKey = &pMIDIKeyInfo[**ppKeyGroup];  
                         // kill all voices on the (other) key  
                         RTList<Voice>::Iterator itVoiceToBeKilled = pOtherKey->pActiveVoices->first();  
                         RTList<Voice>::Iterator end               = pOtherKey->pActiveVoices->end();  
                         for (; itVoiceToBeKilled != end; ++itVoiceToBeKilled) {  
                             if (itVoiceToBeKilled->Type != Voice::type_release_trigger) itVoiceToBeKilled->Kill(itNoteOnEvent);  
                         }  
                     }  
                 }  
1117                  if (!pKey->Active) { // mark as active key                  if (!pKey->Active) { // mark as active key
1118                      pKey->Active = true;                      pKey->Active = true;
1119                      pKey->itSelf = pActiveKeys->allocAppend();                      pKey->itSelf = pEngineChannel->pActiveKeys->allocAppend();
1120                      *pKey->itSelf = itNoteOnEvent->Param.Note.Key;                      *pKey->itSelf = itNoteOnEvent->Param.Note.Key;
1121                  }                  }
1122                  if (itNewVoice->KeyGroup) {                  if (itNewVoice->KeyGroup) {
1123                        uint** ppKeyGroup = &pEngineChannel->ActiveKeyGroups[itNewVoice->KeyGroup];
1124                      *ppKeyGroup = &*pKey->itSelf; // put key as the (new) active key to its key group                      *ppKeyGroup = &*pKey->itSelf; // put key as the (new) active key to its key group
1125                  }                  }
1126                  if (itNewVoice->Type == Voice::type_release_trigger_required) pKey->ReleaseTrigger = true; // mark key for the need of release triggered voice(s)                  if (itNewVoice->Type == Voice::type_release_trigger_required) pKey->ReleaseTrigger = true; // mark key for the need of release triggered voice(s)
# Line 810  namespace LinuxSampler { namespace gig { Line 1128  namespace LinuxSampler { namespace gig {
1128              }              }
1129          }          }
1130          else if (VoiceStealing) {          else if (VoiceStealing) {
1131              // first, get total amount of required voices (dependant on amount of layers)              // try to steal one voice
1132              ::gig::Region* pRegion = pInstrument->GetRegion(itNoteOnEvent->Param.Note.Key);              int result = StealVoice(pEngineChannel, itNoteOnEvent);
1133              if (!pRegion) return Pool<Voice>::Iterator(); // nothing defined for this MIDI key, so no voice needed              if (!result) { // voice stolen successfully
1134              int voicesRequired = pRegion->Layers;                  // put note-on event into voice-stealing queue, so it will be reprocessed after killed voice died
1135                    RTList<Event>::Iterator itStealEvent = pVoiceStealingQueue->allocAppend();
1136              // now steal the (remaining) amount of voices                  if (itStealEvent) {
1137              for (int i = iLayer; i < voicesRequired; i++)                      *itStealEvent = *itNoteOnEvent; // copy event
1138                  StealVoice(itNoteOnEvent);                      itStealEvent->Param.Note.Layer = iLayer;
1139                        itStealEvent->Param.Note.ReleaseTrigger = ReleaseTriggerVoice;
1140              // put note-on event into voice-stealing queue, so it will be reprocessed after killed voice died                      pKey->VoiceTheftsQueued++;
1141              RTList<Event>::Iterator itStealEvent = pVoiceStealingQueue->allocAppend();                  }
1142              if (itStealEvent) {                  else dmsg(1,("Voice stealing queue full!\n"));
                 *itStealEvent = *itNoteOnEvent; // copy event  
                 itStealEvent->Param.Note.Layer = iLayer;  
                 itStealEvent->Param.Note.ReleaseTrigger = ReleaseTriggerVoice;  
1143              }              }
             else dmsg(1,("Voice stealing queue full!\n"));  
1144          }          }
1145    
1146          return Pool<Voice>::Iterator(); // no free voice or error          return Pool<Voice>::Iterator(); // no free voice or error
# Line 838  namespace LinuxSampler { namespace gig { Line 1152  namespace LinuxSampler { namespace gig {
1152       *  voice stealing and postpone the note-on event until the selected       *  voice stealing and postpone the note-on event until the selected
1153       *  voice actually died.       *  voice actually died.
1154       *       *
1155         *  @param pEngineChannel - engine channel on which this event occured on
1156       *  @param itNoteOnEvent - key, velocity and time stamp of the event       *  @param itNoteOnEvent - key, velocity and time stamp of the event
1157         *  @returns 0 on success, a value < 0 if no active voice could be picked for voice stealing
1158       */       */
1159      void Engine::StealVoice(Pool<Event>::Iterator& itNoteOnEvent) {      int Engine::StealVoice(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent) {
1160            if (VoiceSpawnsLeft <= 0) {
1161                dmsg(1,("Max. voice thefts per audio fragment reached (you may raise CONFIG_MAX_VOICES).\n"));
1162                return -1;
1163            }
1164          if (!pEventPool->poolIsEmpty()) {          if (!pEventPool->poolIsEmpty()) {
1165    
1166              RTList<uint>::Iterator  iuiOldestKey;              RTList<Voice>::Iterator itSelectedVoice;
             RTList<Voice>::Iterator itOldestVoice;  
1167    
1168              // Select one voice for voice stealing              // Select one voice for voice stealing
1169              switch (VOICE_STEAL_ALGORITHM) {              switch (CONFIG_VOICE_STEAL_ALGO) {
1170    
1171                  // try to pick the oldest voice on the key where the new                  // try to pick the oldest voice on the key where the new
1172                  // voice should be spawned, if there is no voice on that                  // voice should be spawned, if there is no voice on that
1173                  // key, or no voice left to kill there, then procceed with                  // key, or no voice left to kill, then procceed with
1174                  // 'oldestkey' algorithm                  // 'oldestkey' algorithm
1175                  case voice_steal_algo_keymask: {                  case voice_steal_algo_oldestvoiceonkey: {
1176                      midi_key_info_t* pOldestKey = &pMIDIKeyInfo[itNoteOnEvent->Param.Note.Key];                      midi_key_info_t* pSelectedKey = &pEngineChannel->pMIDIKeyInfo[itNoteOnEvent->Param.Note.Key];
1177                      if (itLastStolenVoice) {                      itSelectedVoice = pSelectedKey->pActiveVoices->first();
1178                          itOldestVoice = itLastStolenVoice;                      // proceed iterating if voice was created in this fragment cycle
1179                          ++itOldestVoice;                      while (itSelectedVoice && !itSelectedVoice->IsStealable()) ++itSelectedVoice;
1180                      }                      // if we haven't found a voice then proceed with algorithm 'oldestkey'
1181                      else { // no voice stolen in this audio fragment cycle yet                      if (itSelectedVoice && itSelectedVoice->IsStealable()) break;
                         itOldestVoice = pOldestKey->pActiveVoices->first();  
                     }  
                     if (itOldestVoice) {  
                         iuiOldestKey = pOldestKey->itSelf;  
                         break; // selection succeeded  
                     }  
1182                  } // no break - intentional !                  } // no break - intentional !
1183    
1184                  // try to pick the oldest voice on the oldest active key                  // try to pick the oldest voice on the oldest active key
1185                  // (caution: must stay after 'keymask' algorithm !)                  // from the same engine channel
1186                    // (caution: must stay after 'oldestvoiceonkey' algorithm !)
1187                  case voice_steal_algo_oldestkey: {                  case voice_steal_algo_oldestkey: {
1188                      if (itLastStolenVoice) {                      // if we already stole in this fragment, try to proceed on same key
1189                          midi_key_info_t* pOldestKey = &pMIDIKeyInfo[*iuiLastStolenKey];                      if (this->itLastStolenVoice) {
1190                          itOldestVoice = itLastStolenVoice;                          itSelectedVoice = this->itLastStolenVoice;
1191                          ++itOldestVoice;                          do {
1192                          if (!itOldestVoice) {                              ++itSelectedVoice;
1193                              iuiOldestKey = iuiLastStolenKey;                          } while (itSelectedVoice && !itSelectedVoice->IsStealable()); // proceed iterating if voice was created in this fragment cycle
1194                              ++iuiOldestKey;                          // found a "stealable" voice ?
1195                              if (iuiOldestKey) {                          if (itSelectedVoice && itSelectedVoice->IsStealable()) {
1196                                  midi_key_info_t* pOldestKey = &pMIDIKeyInfo[*iuiOldestKey];                              // remember which voice we stole, so we can simply proceed on next voice stealing
1197                                  itOldestVoice = pOldestKey->pActiveVoices->first();                              this->itLastStolenVoice = itSelectedVoice;
1198                              }                              break; // selection succeeded
                             else {  
                                 dmsg(1,("gig::Engine: Warning, too less voices, even for voice stealing! - Better recompile with higher MAX_AUDIO_VOICES.\n"));  
                                 return;  
                             }  
1199                          }                          }
                         else iuiOldestKey = iuiLastStolenKey;  
1200                      }                      }
1201                      else { // no voice stolen in this audio fragment cycle yet                      // get (next) oldest key
1202                          iuiOldestKey = pActiveKeys->first();                      RTList<uint>::Iterator iuiSelectedKey = (this->iuiLastStolenKey) ? ++this->iuiLastStolenKey : pEngineChannel->pActiveKeys->first();
1203                          midi_key_info_t* pOldestKey = &pMIDIKeyInfo[*iuiOldestKey];                      while (iuiSelectedKey) {
1204                          itOldestVoice = pOldestKey->pActiveVoices->first();                          midi_key_info_t* pSelectedKey = &pEngineChannel->pMIDIKeyInfo[*iuiSelectedKey];
1205                            itSelectedVoice = pSelectedKey->pActiveVoices->first();
1206                            // proceed iterating if voice was created in this fragment cycle
1207                            while (itSelectedVoice && !itSelectedVoice->IsStealable()) ++itSelectedVoice;
1208                            // found a "stealable" voice ?
1209                            if (itSelectedVoice && itSelectedVoice->IsStealable()) {
1210                                // remember which voice on which key we stole, so we can simply proceed on next voice stealing
1211                                this->iuiLastStolenKey  = iuiSelectedKey;
1212                                this->itLastStolenVoice = itSelectedVoice;
1213                                break; // selection succeeded
1214                            }
1215                            ++iuiSelectedKey; // get next oldest key
1216                      }                      }
1217                      break;                      break;
1218                  }                  }
# Line 901  namespace LinuxSampler { namespace gig { Line 1221  namespace LinuxSampler { namespace gig {
1221                  case voice_steal_algo_none:                  case voice_steal_algo_none:
1222                  default: {                  default: {
1223                      dmsg(1,("No free voice (voice stealing disabled)!\n"));                      dmsg(1,("No free voice (voice stealing disabled)!\n"));
1224                      return;                      return -1;
1225                  }                  }
1226              }              }
1227    
1228              //FIXME: can be removed, just a sanity check for debugging              // if we couldn't steal a voice from the same engine channel then
1229              if (!itOldestVoice->IsActive()) dmsg(1,("gig::Engine: ERROR, tried to steal a voice which was not active !!!\n"));              // steal oldest voice on the oldest key from any other engine channel
1230                // (the smaller engine channel number, the higher priority)
1231                if (!itSelectedVoice || !itSelectedVoice->IsStealable()) {
1232                    EngineChannel* pSelectedChannel;
1233                    int            iChannelIndex;
1234                    // select engine channel
1235                    if (pLastStolenChannel) {
1236                        pSelectedChannel = pLastStolenChannel;
1237                        iChannelIndex    = pSelectedChannel->iEngineIndexSelf;
1238                    } else { // pick the engine channel followed by this engine channel
1239                        iChannelIndex    = (pEngineChannel->iEngineIndexSelf + 1) % engineChannels.size();
1240                        pSelectedChannel = engineChannels[iChannelIndex];
1241                    }
1242    
1243                    // if we already stole in this fragment, try to proceed on same key
1244                    if (this->itLastStolenVoiceGlobally) {
1245                        itSelectedVoice = this->itLastStolenVoiceGlobally;
1246                        do {
1247                            ++itSelectedVoice;
1248                        } while (itSelectedVoice && !itSelectedVoice->IsStealable()); // proceed iterating if voice was created in this fragment cycle
1249                    }
1250    
1251                    #if CONFIG_DEVMODE
1252                    EngineChannel* pBegin = pSelectedChannel; // to detect endless loop
1253                    #endif // CONFIG_DEVMODE
1254    
1255                    // did we find a 'stealable' voice?
1256                    if (itSelectedVoice && itSelectedVoice->IsStealable()) {
1257                        // remember which voice we stole, so we can simply proceed on next voice stealing
1258                        this->itLastStolenVoiceGlobally = itSelectedVoice;
1259                    } else while (true) { // iterate through engine channels
1260                        // get (next) oldest key
1261                        RTList<uint>::Iterator iuiSelectedKey = (this->iuiLastStolenKeyGlobally) ? ++this->iuiLastStolenKeyGlobally : pSelectedChannel->pActiveKeys->first();
1262                        this->iuiLastStolenKeyGlobally = RTList<uint>::Iterator(); // to prevent endless loop (see line above)
1263                        while (iuiSelectedKey) {
1264                            midi_key_info_t* pSelectedKey = &pSelectedChannel->pMIDIKeyInfo[*iuiSelectedKey];
1265                            itSelectedVoice = pSelectedKey->pActiveVoices->first();
1266                            // proceed iterating if voice was created in this fragment cycle
1267                            while (itSelectedVoice && !itSelectedVoice->IsStealable()) ++itSelectedVoice;
1268                            // found a "stealable" voice ?
1269                            if (itSelectedVoice && itSelectedVoice->IsStealable()) {
1270                                // remember which voice on which key on which engine channel we stole, so we can simply proceed on next voice stealing
1271                                this->iuiLastStolenKeyGlobally  = iuiSelectedKey;
1272                                this->itLastStolenVoiceGlobally = itSelectedVoice;
1273                                this->pLastStolenChannel        = pSelectedChannel;
1274                                goto stealable_voice_found; // selection succeeded
1275                            }
1276                            ++iuiSelectedKey; // get next key on current engine channel
1277                        }
1278                        // get next engine channel
1279                        iChannelIndex    = (iChannelIndex + 1) % engineChannels.size();
1280                        pSelectedChannel = engineChannels[iChannelIndex];
1281    
1282                        #if CONFIG_DEVMODE
1283                        if (pSelectedChannel == pBegin) {
1284                            dmsg(1,("FATAL ERROR: voice stealing endless loop!\n"));
1285                            dmsg(1,("VoiceSpawnsLeft=%d.\n", VoiceSpawnsLeft));
1286                            dmsg(1,("Exiting.\n"));
1287                            exit(-1);
1288                        }
1289                        #endif // CONFIG_DEVMODE
1290                    }
1291                }
1292    
1293                // jump point if a 'stealable' voice was found
1294                stealable_voice_found:
1295    
1296                #if CONFIG_DEVMODE
1297                if (!itSelectedVoice->IsActive()) {
1298                    dmsg(1,("gig::Engine: ERROR, tried to steal a voice which was not active !!!\n"));
1299                    return -1;
1300                }
1301                #endif // CONFIG_DEVMODE
1302    
1303              // now kill the selected voice              // now kill the selected voice
1304              itOldestVoice->Kill(itNoteOnEvent);              itSelectedVoice->Kill(itNoteOnEvent);
1305              // remember which voice on which key we stole, so we can simply proceed for the next voice stealing  
1306              this->itLastStolenVoice = itOldestVoice;              --VoiceSpawnsLeft;
1307              this->iuiLastStolenKey = iuiOldestKey;  
1308                return 0; // success
1309            }
1310            else {
1311                dmsg(1,("Event pool emtpy!\n"));
1312                return -1;
1313          }          }
         else dmsg(1,("Event pool emtpy!\n"));  
1314      }      }
1315    
1316      /**      /**
# Line 923  namespace LinuxSampler { namespace gig { Line 1319  namespace LinuxSampler { namespace gig {
1319       *  it finished to playback its sample, finished its release stage or       *  it finished to playback its sample, finished its release stage or
1320       *  just was killed.       *  just was killed.
1321       *       *
1322         *  @param pEngineChannel - engine channel on which this event occured on
1323       *  @param itVoice - points to the voice to be freed       *  @param itVoice - points to the voice to be freed
1324       */       */
1325      void Engine::FreeVoice(Pool<Voice>::Iterator& itVoice) {      void Engine::FreeVoice(EngineChannel* pEngineChannel, Pool<Voice>::Iterator& itVoice) {
1326          if (itVoice) {          if (itVoice) {
1327              midi_key_info_t* pKey = &pMIDIKeyInfo[itVoice->MIDIKey];              midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[itVoice->MIDIKey];
1328    
1329              uint keygroup = itVoice->KeyGroup;              uint keygroup = itVoice->KeyGroup;
1330    
1331                // if the sample and dimension region belong to an
1332                // instrument that is unloaded, tell the disk thread to
1333                // release them
1334                if (itVoice->Orphan) {
1335                    pDiskThread->OrderDeletionOfDimreg(itVoice->pDimRgn);
1336                }
1337    
1338              // free the voice object              // free the voice object
1339              pVoicePool->free(itVoice);              pVoicePool->free(itVoice);
1340    
1341              // if no other voices left and member of a key group, remove from key group              // if no other voices left and member of a key group, remove from key group
1342              if (pKey->pActiveVoices->isEmpty() && keygroup) {              if (pKey->pActiveVoices->isEmpty() && keygroup) {
1343                  uint** ppKeyGroup = &ActiveKeyGroups[keygroup];                  uint** ppKeyGroup = &pEngineChannel->ActiveKeyGroups[keygroup];
1344                  if (*ppKeyGroup == &*pKey->itSelf) *ppKeyGroup = NULL; // remove key from key group                  if (*ppKeyGroup == &*pKey->itSelf) *ppKeyGroup = NULL; // remove key from key group
1345              }              }
1346          }          }
# Line 947  namespace LinuxSampler { namespace gig { Line 1351  namespace LinuxSampler { namespace gig {
1351       *  Called when there's no more voice left on a key, this call will       *  Called when there's no more voice left on a key, this call will
1352       *  update the key info respectively.       *  update the key info respectively.
1353       *       *
1354         *  @param pEngineChannel - engine channel on which this event occured on
1355       *  @param pKey - key which is now inactive       *  @param pKey - key which is now inactive
1356       */       */
1357      void Engine::FreeKey(midi_key_info_t* pKey) {      void Engine::FreeKey(EngineChannel* pEngineChannel, midi_key_info_t* pKey) {
1358          if (pKey->pActiveVoices->isEmpty()) {          if (pKey->pActiveVoices->isEmpty()) {
1359              pKey->Active = false;              pKey->Active = false;
1360              pActiveKeys->free(pKey->itSelf); // remove key from list of active keys              pEngineChannel->pActiveKeys->free(pKey->itSelf); // remove key from list of active keys
1361              pKey->itSelf = RTList<uint>::Iterator();              pKey->itSelf = RTList<uint>::Iterator();
1362              pKey->ReleaseTrigger = false;              pKey->ReleaseTrigger = false;
1363              pKey->pEvents->clear();              pKey->pEvents->clear();
# Line 965  namespace LinuxSampler { namespace gig { Line 1370  namespace LinuxSampler { namespace gig {
1370       *  Reacts on supported control change commands (e.g. pitch bend wheel,       *  Reacts on supported control change commands (e.g. pitch bend wheel,
1371       *  modulation wheel, aftertouch).       *  modulation wheel, aftertouch).
1372       *       *
1373         *  @param pEngineChannel - engine channel on which this event occured on
1374       *  @param itControlChangeEvent - controller, value and time stamp of the event       *  @param itControlChangeEvent - controller, value and time stamp of the event
1375       */       */
1376      void Engine::ProcessControlChange(Pool<Event>::Iterator& itControlChangeEvent) {      void Engine::ProcessControlChange(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itControlChangeEvent) {
1377          dmsg(4,("Engine::ContinuousController cc=%d v=%d\n", itControlChangeEvent->Param.CC.Controller, itControlChangeEvent->Param.CC.Value));          dmsg(4,("Engine::ContinuousController cc=%d v=%d\n", itControlChangeEvent->Param.CC.Controller, itControlChangeEvent->Param.CC.Value));
1378    
1379            // update controller value in the engine channel's controller table
1380            pEngineChannel->ControllerTable[itControlChangeEvent->Param.CC.Controller] = itControlChangeEvent->Param.CC.Value;
1381    
1382            // handle hard coded MIDI controllers
1383          switch (itControlChangeEvent->Param.CC.Controller) {          switch (itControlChangeEvent->Param.CC.Controller) {
1384              case 64: {              case 5: { // portamento time
1385                  if (itControlChangeEvent->Param.CC.Value >= 64 && !SustainPedal) {                  pEngineChannel->PortamentoTime = (float) itControlChangeEvent->Param.CC.Value / 127.0f * (float) CONFIG_PORTAMENTO_TIME_MAX + (float) CONFIG_PORTAMENTO_TIME_MIN;
1386                      dmsg(4,("PEDAL DOWN\n"));                  break;
1387                      SustainPedal = true;              }
1388                case 6: { // data entry (currently only used for RPN controllers)
1389                    if (pEngineChannel->GetMidiRpnController() == 2) { // coarse tuning in half tones
1390                        int transpose = (int) itControlChangeEvent->Param.CC.Value - 64;
1391                        // limit to +- two octaves for now
1392                        transpose = RTMath::Min(transpose,  24);
1393                        transpose = RTMath::Max(transpose, -24);
1394                        pEngineChannel->GlobalTranspose = transpose;
1395                        // workaround, so we won't have hanging notes
1396                        ReleaseAllVoices(pEngineChannel, itControlChangeEvent);
1397                    }
1398                    // to avoid other MIDI CC #6 messages to be misenterpreted as RPN controller data
1399                    pEngineChannel->ResetMidiRpnController();
1400                    break;
1401                }
1402                case 7: { // volume
1403                    //TODO: not sample accurate yet
1404                    pEngineChannel->MidiVolume = VolumeCurve[itControlChangeEvent->Param.CC.Value];
1405                    pEngineChannel->bStatusChanged = true; // engine channel status has changed, so set notify flag
1406                    break;
1407                }
1408                case 10: { // panpot
1409                    //TODO: not sample accurate yet
1410                    pEngineChannel->GlobalPanLeft  = PanCurve[128 - itControlChangeEvent->Param.CC.Value];
1411                    pEngineChannel->GlobalPanRight = PanCurve[itControlChangeEvent->Param.CC.Value];
1412                    break;
1413                }
1414                case 64: { // sustain
1415                    if (itControlChangeEvent->Param.CC.Value >= 64 && !pEngineChannel->SustainPedal) {
1416                        dmsg(4,("DAMPER (RIGHT) PEDAL DOWN\n"));
1417                        pEngineChannel->SustainPedal = true;
1418    
1419                        #if !CONFIG_PROCESS_MUTED_CHANNELS
1420                        if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
1421                        #endif
1422    
1423                      // cancel release process of voices if necessary                      // cancel release process of voices if necessary
1424                      RTList<uint>::Iterator iuiKey = pActiveKeys->first();                      RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
1425                      if (iuiKey) {                      for (; iuiKey; ++iuiKey) {
1426                          itControlChangeEvent->Type = Event::type_cancel_release; // transform event type                          midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
1427                          while (iuiKey) {                          if (!pKey->KeyPressed) {
1428                              midi_key_info_t* pKey = &pMIDIKeyInfo[*iuiKey];                              RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
1429                              ++iuiKey;                              if (itNewEvent) {
1430                              if (!pKey->KeyPressed) {                                  *itNewEvent = *itControlChangeEvent; // copy event to the key's own event list
1431                                  RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();                                  itNewEvent->Type = Event::type_cancel_release; // transform event type
                                 if (itNewEvent) *itNewEvent = *itControlChangeEvent; // copy event to the key's own event list  
                                 else dmsg(1,("Event pool emtpy!\n"));  
1432                              }                              }
1433                                else dmsg(1,("Event pool emtpy!\n"));
1434                          }                          }
1435                      }                      }
1436                  }                  }
1437                  if (itControlChangeEvent->Param.CC.Value < 64 && SustainPedal) {                  if (itControlChangeEvent->Param.CC.Value < 64 && pEngineChannel->SustainPedal) {
1438                      dmsg(4,("PEDAL UP\n"));                      dmsg(4,("DAMPER (RIGHT) PEDAL UP\n"));
1439                      SustainPedal = false;                      pEngineChannel->SustainPedal = false;
1440    
1441                        #if !CONFIG_PROCESS_MUTED_CHANNELS
1442                        if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
1443                        #endif
1444    
1445                      // release voices if their respective key is not pressed                      // release voices if their respective key is not pressed
1446                      RTList<uint>::Iterator iuiKey = pActiveKeys->first();                      RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
1447                      if (iuiKey) {                      for (; iuiKey; ++iuiKey) {
1448                          itControlChangeEvent->Type = Event::type_release; // transform event type                          midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
1449                          while (iuiKey) {                          if (!pKey->KeyPressed && ShouldReleaseVoice(pEngineChannel, *iuiKey)) {
1450                              midi_key_info_t* pKey = &pMIDIKeyInfo[*iuiKey];                              RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
1451                              ++iuiKey;                              if (itNewEvent) {
1452                              if (!pKey->KeyPressed) {                                  *itNewEvent = *itControlChangeEvent; // copy event to the key's own event list
1453                                  RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();                                  itNewEvent->Type = Event::type_release; // transform event type
                                 if (itNewEvent) *itNewEvent = *itControlChangeEvent; // copy event to the key's own event list  
                                 else dmsg(1,("Event pool emtpy!\n"));  
1454                              }                              }
1455                                else dmsg(1,("Event pool emtpy!\n"));
1456                          }                          }
1457                      }                      }
1458                  }                  }
1459                  break;                  break;
1460              }              }
1461          }              case 65: { // portamento on / off
1462                    KillAllVoices(pEngineChannel, itControlChangeEvent);
1463                    pEngineChannel->PortamentoMode = itControlChangeEvent->Param.CC.Value >= 64;
1464                    break;
1465                }
1466                case 66: { // sostenuto
1467                    if (itControlChangeEvent->Param.CC.Value >= 64 && !pEngineChannel->SostenutoPedal) {
1468                        dmsg(4,("SOSTENUTO (CENTER) PEDAL DOWN\n"));
1469                        pEngineChannel->SostenutoPedal = true;
1470    
1471                        #if !CONFIG_PROCESS_MUTED_CHANNELS
1472                        if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
1473                        #endif
1474    
1475                        SostenutoKeyCount = 0;
1476                        // Remeber the pressed keys
1477                        RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
1478                        for (; iuiKey; ++iuiKey) {
1479                            midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
1480                            if (pKey->KeyPressed && SostenutoKeyCount < 128) SostenutoKeys[SostenutoKeyCount++] = *iuiKey;
1481                        }
1482                    }
1483                    if (itControlChangeEvent->Param.CC.Value < 64 && pEngineChannel->SostenutoPedal) {
1484                        dmsg(4,("SOSTENUTO (CENTER) PEDAL UP\n"));
1485                        pEngineChannel->SostenutoPedal = false;
1486    
1487                        #if !CONFIG_PROCESS_MUTED_CHANNELS
1488                        if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
1489                        #endif
1490    
1491                        // release voices if the damper pedal is up and their respective key is not pressed
1492                        for (int i = 0; i < SostenutoKeyCount; i++) {
1493                            midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[SostenutoKeys[i]];
1494                            if (!pKey->KeyPressed && !pEngineChannel->SustainPedal) {
1495                                RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
1496                                if (itNewEvent) {
1497                                    *itNewEvent = *itControlChangeEvent; // copy event to the key's own event list
1498                                    itNewEvent->Type = Event::type_release; // transform event type
1499                                }
1500                                else dmsg(1,("Event pool emtpy!\n"));
1501                            }
1502                        }
1503                    }
1504                    break;
1505                }
1506                case 100: { // RPN controller LSB
1507                    pEngineChannel->SetMidiRpnControllerLsb(itControlChangeEvent->Param.CC.Value);
1508                    break;
1509                }
1510                case 101: { // RPN controller MSB
1511                    pEngineChannel->SetMidiRpnControllerMsb(itControlChangeEvent->Param.CC.Value);
1512                    break;
1513                }
1514    
         // update controller value in the engine's controller table  
         ControllerTable[itControlChangeEvent->Param.CC.Controller] = itControlChangeEvent->Param.CC.Value;  
1515    
1516          // move event from the unsorted event list to the control change event list              // Channel Mode Messages
1517          itControlChangeEvent.moveToEndOf(pCCEvents);  
1518                case 120: { // all sound off
1519                    KillAllVoices(pEngineChannel, itControlChangeEvent);
1520                    break;
1521                }
1522                case 121: { // reset all controllers
1523                    pEngineChannel->ResetControllers();
1524                    break;
1525                }
1526                case 123: { // all notes off
1527                    #if CONFIG_PROCESS_ALL_NOTES_OFF
1528                    ReleaseAllVoices(pEngineChannel, itControlChangeEvent);
1529                    #endif // CONFIG_PROCESS_ALL_NOTES_OFF
1530                    break;
1531                }
1532                case 126: { // mono mode on
1533                    KillAllVoices(pEngineChannel, itControlChangeEvent);
1534                    pEngineChannel->SoloMode = true;
1535                    break;
1536                }
1537                case 127: { // poly mode on
1538                    KillAllVoices(pEngineChannel, itControlChangeEvent);
1539                    pEngineChannel->SoloMode = false;
1540                    break;
1541                }
1542            }
1543    
1544            // handle FX send controllers
1545            if (!pEngineChannel->fxSends.empty()) {
1546                for (int iFxSend = 0; iFxSend < pEngineChannel->GetFxSendCount(); iFxSend++) {
1547                    FxSend* pFxSend = pEngineChannel->GetFxSend(iFxSend);
1548                    if (pFxSend->MidiController() == itControlChangeEvent->Param.CC.Controller)
1549                        pFxSend->SetLevel(itControlChangeEvent->Param.CC.Value);
1550                        pFxSend->SetInfoChanged(true);
1551                }
1552            }
1553      }      }
1554    
1555      /**      /**
# Line 1027  namespace LinuxSampler { namespace gig { Line 1558  namespace LinuxSampler { namespace gig {
1558       *  @param itSysexEvent - sysex data size and time stamp of the sysex event       *  @param itSysexEvent - sysex data size and time stamp of the sysex event
1559       */       */
1560      void Engine::ProcessSysex(Pool<Event>::Iterator& itSysexEvent) {      void Engine::ProcessSysex(Pool<Event>::Iterator& itSysexEvent) {
1561          RingBuffer<uint8_t>::NonVolatileReader reader = pSysexBuffer->get_non_volatile_reader();          RingBuffer<uint8_t,false>::NonVolatileReader reader = pSysexBuffer->get_non_volatile_reader();
1562    
1563          uint8_t exclusive_status, id;          uint8_t exclusive_status, id;
1564          if (!reader.pop(&exclusive_status)) goto free_sysex_data;          if (!reader.pop(&exclusive_status)) goto free_sysex_data;
# Line 1036  namespace LinuxSampler { namespace gig { Line 1567  namespace LinuxSampler { namespace gig {
1567    
1568          switch (id) {          switch (id) {
1569              case 0x41: { // Roland              case 0x41: { // Roland
1570                    dmsg(3,("Roland Sysex\n"));
1571                  uint8_t device_id, model_id, cmd_id;                  uint8_t device_id, model_id, cmd_id;
1572                  if (!reader.pop(&device_id)) goto free_sysex_data;                  if (!reader.pop(&device_id)) goto free_sysex_data;
1573                  if (!reader.pop(&model_id))  goto free_sysex_data;                  if (!reader.pop(&model_id))  goto free_sysex_data;
# Line 1045  namespace LinuxSampler { namespace gig { Line 1577  namespace LinuxSampler { namespace gig {
1577    
1578                  // command address                  // command address
1579                  uint8_t addr[3]; // 2 byte addr MSB, followed by 1 byte addr LSB)                  uint8_t addr[3]; // 2 byte addr MSB, followed by 1 byte addr LSB)
1580                  const RingBuffer<uint8_t>::NonVolatileReader checksum_reader = reader; // so we can calculate the check sum later                  const RingBuffer<uint8_t,false>::NonVolatileReader checksum_reader = reader; // so we can calculate the check sum later
1581                  if (reader.read(&addr[0], 3) != 3) goto free_sysex_data;                  if (reader.read(&addr[0], 3) != 3) goto free_sysex_data;
1582                  if (addr[0] == 0x40 && addr[1] == 0x00) { // System Parameters                  if (addr[0] == 0x40 && addr[1] == 0x00) { // System Parameters
1583                        dmsg(3,("\tSystem Parameter\n"));
1584                  }                  }
1585                  else if (addr[0] == 0x40 && addr[1] == 0x01) { // Common Parameters                  else if (addr[0] == 0x40 && addr[1] == 0x01) { // Common Parameters
1586                        dmsg(3,("\tCommon Parameter\n"));
1587                  }                  }
1588                  else if (addr[0] == 0x40 && (addr[1] & 0xf0) == 0x10) { // Part Parameters (1)                  else if (addr[0] == 0x40 && (addr[1] & 0xf0) == 0x10) { // Part Parameters (1)
1589                      switch (addr[3]) {                      dmsg(3,("\tPart Parameter\n"));
1590                        switch (addr[2]) {
1591                          case 0x40: { // scale tuning                          case 0x40: { // scale tuning
1592                                dmsg(3,("\t\tScale Tuning\n"));
1593                              uint8_t scale_tunes[12]; // detuning of all 12 semitones of an octave                              uint8_t scale_tunes[12]; // detuning of all 12 semitones of an octave
1594                              if (reader.read(&scale_tunes[0], 12) != 12) goto free_sysex_data;                              if (reader.read(&scale_tunes[0], 12) != 12) goto free_sysex_data;
1595                              uint8_t checksum;                              uint8_t checksum;
1596                              if (!reader.pop(&checksum))                      goto free_sysex_data;                              if (!reader.pop(&checksum)) goto free_sysex_data;
1597                              if (GSCheckSum(checksum_reader, 12) != checksum) goto free_sysex_data;                              #if CONFIG_ASSERT_GS_SYSEX_CHECKSUM
1598                                if (GSCheckSum(checksum_reader, 12)) goto free_sysex_data;
1599                                #endif // CONFIG_ASSERT_GS_SYSEX_CHECKSUM
1600                              for (int i = 0; i < 12; i++) scale_tunes[i] -= 64;                              for (int i = 0; i < 12; i++) scale_tunes[i] -= 64;
1601                              AdjustScale((int8_t*) scale_tunes);                              AdjustScale((int8_t*) scale_tunes);
1602                                dmsg(3,("\t\t\tNew scale applied.\n"));
1603                              break;                              break;
1604                          }                          }
1605                      }                      }
# Line 1085  namespace LinuxSampler { namespace gig { Line 1624  namespace LinuxSampler { namespace gig {
1624       *                     question       *                     question
1625       * @param DataSize   - size of the GS message data (in bytes)       * @param DataSize   - size of the GS message data (in bytes)
1626       */       */
1627      uint8_t Engine::GSCheckSum(const RingBuffer<uint8_t>::NonVolatileReader AddrReader, uint DataSize) {      uint8_t Engine::GSCheckSum(const RingBuffer<uint8_t,false>::NonVolatileReader AddrReader, uint DataSize) {
1628          RingBuffer<uint8_t>::NonVolatileReader reader = AddrReader;          RingBuffer<uint8_t,false>::NonVolatileReader reader = AddrReader;
1629          uint bytes = 3 /*addr*/ + DataSize;          uint bytes = 3 /*addr*/ + DataSize;
1630          uint8_t addr_and_data[bytes];          uint8_t addr_and_data[bytes];
1631          reader.read(&addr_and_data[0], bytes);          reader.read(&addr_and_data[0], bytes);
# Line 1105  namespace LinuxSampler { namespace gig { Line 1644  namespace LinuxSampler { namespace gig {
1644      }      }
1645    
1646      /**      /**
1647       * Initialize the parameter sequence for the modulation destination given by       * Releases all voices on an engine channel. All voices will go into
1648       * by 'dst' with the constant value given by val.       * the release stage and thus it might take some time (e.g. dependant to
1649         * their envelope release time) until they actually die.
1650         *
1651         * @param pEngineChannel - engine channel on which all voices should be released
1652         * @param itReleaseEvent - event which caused this releasing of all voices
1653       */       */
1654      void Engine::ResetSynthesisParameters(Event::destination_t dst, float val) {      void Engine::ReleaseAllVoices(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itReleaseEvent) {
1655          int maxsamples = pAudioOutputDevice->MaxSamplesPerCycle();          RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
1656          float* m = &pSynthesisParameters[dst][0];          while (iuiKey) {
1657          for (int i = 0; i < maxsamples; i += 4) {              midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
1658             m[i]   = val;              ++iuiKey;
1659             m[i+1] = val;              // append a 'release' event to the key's own event list
1660             m[i+2] = val;              RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
1661             m[i+3] = val;              if (itNewEvent) {
1662                    *itNewEvent = *itReleaseEvent; // copy original event (to the key's event list)
1663                    itNewEvent->Type = Event::type_release; // transform event type
1664                }
1665                else dmsg(1,("Event pool emtpy!\n"));
1666          }          }
1667      }      }
1668    
1669      float Engine::Volume() {      /**
1670          return GlobalVolume;       * Kills all voices on an engine channel as soon as possible. Voices
1671      }       * won't get into release state, their volume level will be ramped down
1672         * as fast as possible.
1673      void Engine::Volume(float f) {       *
1674          GlobalVolume = f;       * @param pEngineChannel - engine channel on which all voices should be killed
1675      }       * @param itKillEvent    - event which caused this killing of all voices
1676         */
1677      uint Engine::Channels() {      void Engine::KillAllVoices(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itKillEvent) {
1678          return 2;          RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
1679      }          RTList<uint>::Iterator end    = pEngineChannel->pActiveKeys->end();
1680            while (iuiKey != end) { // iterate through all active keys
1681      void Engine::SetOutputChannel(uint EngineAudioChannel, uint AudioDeviceChannel) {              midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
1682          AudioChannel* pChannel = pAudioOutputDevice->Channel(AudioDeviceChannel);              ++iuiKey;
1683          if (!pChannel) throw AudioOutputException("Invalid audio output device channel " + ToString(AudioDeviceChannel));              RTList<Voice>::Iterator itVoice     = pKey->pActiveVoices->first();
1684          switch (EngineAudioChannel) {              RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();
1685              case 0: // left output channel              for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
1686                  pOutputLeft = pChannel->Buffer();                  itVoice->Kill(itKillEvent);
1687                  AudioDeviceChannelLeft = AudioDeviceChannel;                  --VoiceSpawnsLeft; //FIXME: just a temporary workaround, we should check the cause in StealVoice() instead
1688                  break;              }
             case 1: // right output channel  
                 pOutputRight = pChannel->Buffer();  
                 AudioDeviceChannelRight = AudioDeviceChannel;  
                 break;  
             default:  
                 throw AudioOutputException("Invalid engine audio channel " + ToString(EngineAudioChannel));  
1689          }          }
1690      }      }
1691    
1692      int Engine::OutputChannel(uint EngineAudioChannel) {      /**
1693          switch (EngineAudioChannel) {       * Determines whether the specified voice should be released.
1694              case 0: // left channel       *
1695                  return AudioDeviceChannelLeft;       * @param pEngineChannel - The engine channel on which the voice should be checked
1696              case 1: // right channel       * @param Key - The key number
1697                  return AudioDeviceChannelRight;       * @returns true if the specified should be released, false otherwise.
1698              default:       */
1699                  throw AudioOutputException("Invalid engine audio channel " + ToString(EngineAudioChannel));      bool Engine::ShouldReleaseVoice(EngineChannel* pEngineChannel, int Key) {
1700            if (pEngineChannel->SustainPedal) return false;
1701    
1702            if (pEngineChannel->SostenutoPedal) {
1703                for (int i = 0; i < SostenutoKeyCount; i++)
1704                    if (Key == SostenutoKeys[i]) return false;
1705          }          }
1706    
1707            return true;
1708      }      }
1709    
1710      uint Engine::VoiceCount() {      uint Engine::VoiceCount() {
# Line 1188  namespace LinuxSampler { namespace gig { Line 1736  namespace LinuxSampler { namespace gig {
1736      }      }
1737    
1738      String Engine::EngineName() {      String Engine::EngineName() {
1739          return "GigEngine";          return LS_GIG_ENGINE_NAME;
1740        }
1741    
1742        String Engine::Description() {
1743            return "Gigasampler Engine";
1744        }
1745    
1746        String Engine::Version() {
1747            String s = "$Revision: 1.79 $";
1748            return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword
1749      }      }
1750    
1751      String Engine::InstrumentFileName() {      InstrumentManager* Engine::GetInstrumentManager() {
1752          return InstrumentFile;          return &instruments;
1753      }      }
1754    
1755      String Engine::InstrumentName() {      // static constant initializers
1756          return InstrumentIdxName;      const float* Engine::VolumeCurve(InitVolumeCurve());
1757        const float* Engine::PanCurve(InitPanCurve());
1758        const float* Engine::CrossfadeCurve(InitCrossfadeCurve());
1759    
1760        float* Engine::InitVolumeCurve() {
1761            // line-segment approximation
1762            const float segments[] = {
1763                0, 0, 2, 0.0046, 16, 0.016, 31, 0.051, 45, 0.115, 54.5, 0.2,
1764                64.5, 0.39, 74, 0.74, 92, 1.03, 114, 1.94, 119.2, 2.2, 127, 2.2
1765            };
1766            return InitCurve(segments);
1767      }      }
1768    
1769      int Engine::InstrumentIndex() {      float* Engine::InitPanCurve() {
1770          return InstrumentIdx;          // line-segment approximation
1771            const float segments[] = {
1772                0, 0, 1, 0,
1773                2, 0.05, 31.5, 0.7, 51, 0.851, 74.5, 1.12,
1774                127, 1.41, 128, 1.41
1775            };
1776            return InitCurve(segments, 129);
1777      }      }
1778    
1779      int Engine::InstrumentStatus() {      float* Engine::InitCrossfadeCurve() {
1780          return InstrumentStat;          // line-segment approximation
1781            const float segments[] = {
1782                0, 0, 1, 0.03, 10, 0.1, 51, 0.58, 127, 1
1783            };
1784            return InitCurve(segments);
1785      }      }
1786    
1787      String Engine::Description() {      float* Engine::InitCurve(const float* segments, int size) {
1788          return "Gigasampler Engine";          float* y = new float[size];
1789            for (int x = 0 ; x < size ; x++) {
1790                if (x > segments[2]) segments += 2;
1791                y[x] = segments[1] + (x - segments[0]) *
1792                    (segments[3] - segments[1]) / (segments[2] - segments[0]);
1793            }
1794            return y;
1795      }      }
1796    
1797      String Engine::Version() {      /**
1798          String s = "$Revision: 1.25 $";       * Changes the instrument for an engine channel.
1799          return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword       *
1800         * @param pEngineChannel - engine channel on which the instrument
1801         *                         should be changed
1802         * @param pInstrument - new instrument
1803         * @returns a list of dimension regions from the old instrument
1804         *          that are still in use
1805         */
1806        ::gig::DimensionRegion** Engine::ChangeInstrument(EngineChannel* pEngineChannel, ::gig::Instrument* pInstrument) {
1807            instrument_change_command_t command;
1808            command.pEngineChannel = pEngineChannel;
1809            command.pInstrument = pInstrument;
1810            InstrumentChangeQueue->push(&command);
1811    
1812            // wait for the audio thread to confirm that the instrument
1813            // change has been done
1814            instrument_change_reply_t reply;
1815            while (InstrumentChangeReplyQueue->pop(&reply) == 0) {
1816                usleep(10000);
1817            }
1818            return pDimRegionsInUse;
1819      }      }
1820    
1821  }} // namespace LinuxSampler::gig  }} // namespace LinuxSampler::gig

Legend:
Removed from v.392  
changed lines
  Added in v.1305

  ViewVC Help
Powered by ViewVC