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

Legend:
Removed from v.285  
changed lines
  Added in v.1041

  ViewVC Help
Powered by ViewVC