/[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 424 by schoenebeck, Fri Mar 4 22:54:11 2005 UTC revision 1044 by schoenebeck, Wed Feb 7 21:51: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 Christian Schoenebeck                              *   *   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 29  Line 29 
29    
30  #include "Engine.h"  #include "Engine.h"
31    
 #if defined(__APPLE__)  
 # include <stdlib.h>  
 #else  
 # include <malloc.h>  
 #endif  
   
32  namespace LinuxSampler { namespace gig {  namespace LinuxSampler { namespace gig {
33    
34      InstrumentResourceManager Engine::instruments;      InstrumentResourceManager Engine::instruments;
# Line 56  namespace LinuxSampler { namespace gig { Line 50  namespace LinuxSampler { namespace gig {
50          // check if there's already an engine for the given audio output device          // check if there's already an engine for the given audio output device
51          if (engines.count(pDevice)) {          if (engines.count(pDevice)) {
52              dmsg(4,("Using existing gig::Engine.\n"));              dmsg(4,("Using existing gig::Engine.\n"));
53              pEngine = engines[pDevice];                          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          } else { // create a new engine (and disk thread) instance for the given audio output device
60              dmsg(4,("Creating new gig::Engine.\n"));              dmsg(4,("Creating new gig::Engine.\n"));
61              pEngine = (Engine*) EngineFactory::Create("gig");              pEngine = (Engine*) EngineFactory::Create("gig");
62              pEngine->Connect(pDevice);              pEngine->Connect(pDevice);
63              engines[pDevice] = pEngine;                          engines[pDevice] = pEngine;
64          }          }
65          // register engine channel to the engine instance          // register engine channel to the engine instance
66          pEngine->engineChannels.push_back(pChannel);          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()));          dmsg(4,("This gig::Engine has now %d EngineChannels.\n",pEngine->engineChannels.size()));
70          return pEngine;          return pEngine;
71      }      }
# Line 94  namespace LinuxSampler { namespace gig { Line 95  namespace LinuxSampler { namespace gig {
95          else dmsg(4,("This gig::Engine has now %d EngineChannels.\n",pEngine->engineChannels.size()));          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() {
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            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                    InstrumentChangeReplyQueue = new RingBuffer<instrument_change_reply_t,false>(1, 0);
114          for (uint i = 0; i < Event::destination_count; i++) {  
             pSynthesisEvents[i] = 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;  
   
120          ResetInternal();          ResetInternal();
121            ResetScaleTuning();
122      }      }
123    
124        /**
125         * Destructor
126         */
127      Engine::~Engine() {      Engine::~Engine() {
128            MidiInputPort::RemoveSysexListener(this);
129          if (pDiskThread) {          if (pDiskThread) {
130              dmsg(1,("Stopping disk thread..."));              dmsg(1,("Stopping disk thread..."));
131              pDiskThread->StopThread();              pDiskThread->StopThread();
132              delete pDiskThread;              delete pDiskThread;
133              dmsg(1,("OK\n"));              dmsg(1,("OK\n"));
134          }          }
         for (uint i = 0; i < Event::destination_count; i++) {  
             if (pSynthesisEvents[i]) delete pSynthesisEvents[i];  
         }  
         if (pEvents)     delete pEvents;  
         if (pCCEvents)   delete pCCEvents;  
135          if (pEventQueue) delete pEventQueue;          if (pEventQueue) delete pEventQueue;
136          if (pEventPool)  delete pEventPool;          if (pEventPool)  delete pEventPool;
137          if (pVoicePool) {          if (pVoicePool) {
# Line 140  namespace LinuxSampler { namespace gig { Line 139  namespace LinuxSampler { namespace gig {
139              delete pVoicePool;              delete pVoicePool;
140          }          }
141          if (pEventGenerator) delete pEventGenerator;          if (pEventGenerator) delete pEventGenerator;
         if (pMainFilterParameters) delete[] pMainFilterParameters;  
         if (pBasicFilterParameters) delete[] pBasicFilterParameters;  
         if (pSynthesisParameters[0]) free(pSynthesisParameters[0]);  
142          if (pVoiceStealingQueue) delete pVoiceStealingQueue;          if (pVoiceStealingQueue) delete pVoiceStealingQueue;
143          if (pSysexBuffer) delete pSysexBuffer;          if (pSysexBuffer) delete pSysexBuffer;
144          EngineFactory::Destroy(this);          Unregister();
145      }      }
146    
147      void Engine::Enable() {      void Engine::Enable() {
# Line 173  namespace LinuxSampler { namespace gig { Line 169  namespace LinuxSampler { namespace gig {
169      void Engine::Reset() {      void Engine::Reset() {
170          DisableAndLock();          DisableAndLock();
171          ResetInternal();          ResetInternal();
172            ResetScaleTuning();
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            ResetInternalMutex.Lock();
182    
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;
188    
189          // reset voice stealing parameters          // reset voice stealing parameters
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            pLastStolenChannel         = 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 201  namespace LinuxSampler { namespace gig { Line 205  namespace LinuxSampler { namespace gig {
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         * Reset to normal, chromatic scale (means equal tempered).
215         */
216        void Engine::ResetScaleTuning() {
217            memset(&ScaleTuning[0], 0x00, 12);
218        }
219    
220        /**
221         * Connect this engine instance with the given audio output device.
222         * 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         */
229      void Engine::Connect(AudioOutputDevice* pAudioOut) {      void Engine::Connect(AudioOutputDevice* pAudioOut) {
230          pAudioOutputDevice = pAudioOut;          pAudioOutputDevice = pAudioOut;
231    
# Line 214  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->MaxSamplesPerCycle      = pAudioOutputDevice->MaxSamplesPerCycle();          this->MaxSamplesPerCycle = pAudioOutputDevice->MaxSamplesPerCycle();
244          this->SampleRate              = pAudioOutputDevice->SampleRate();          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 too 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) {
# Line 232  namespace LinuxSampler { namespace gig { Line 266  namespace LinuxSampler { namespace gig {
266              delete this->pDiskThread;              delete this->pDiskThread;
267              dmsg(1,("OK\n"));              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 248  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]) free(pSynthesisParameters[0]);  
   
         #if defined(__APPLE__)  
         pSynthesisParameters[0] = (float *) malloc(Event::destination_count * sizeof(float) * pAudioOut->MaxSamplesPerCycle());  
         #else  
         pSynthesisParameters[0] = (float *) memalign(16,(Event::destination_count * sizeof(float) * pAudioOut->MaxSamplesPerCycle()));  
         #endif  
         for (int dst = 1; dst < Event::destination_count; dst++)  
             pSynthesisParameters[dst] = pSynthesisParameters[dst - 1] + pAudioOut->MaxSamplesPerCycle();  
   
         // (re)allocate biquad filter parameter sequence  
         if (pBasicFilterParameters) delete[] pBasicFilterParameters;  
         if (pMainFilterParameters)  delete[] pMainFilterParameters;  
         pBasicFilterParameters = new biquad_param_t[pAudioOut->MaxSamplesPerCycle()];  
         pMainFilterParameters  = new biquad_param_t[pAudioOut->MaxSamplesPerCycle()];  
   
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 277  namespace LinuxSampler { namespace gig { Line 295  namespace LinuxSampler { namespace gig {
295          }          }
296      }      }
297    
298        /**
299         * Clear all engine global event lists.
300         */
301      void Engine::ClearEventLists() {      void Engine::ClearEventLists() {
302          pEvents->clear();          pGlobalEvents->clear();
         pCCEvents->clear();  
         for (uint i = 0; i < Event::destination_count; i++) {  
             pSynthesisEvents[i]->clear();  
         }  
303      }      }
304    
305      /**      /**
306       * Copy all events from the given input queue buffer to the engine's       * Copy all events from the engine's global input queue buffer to the
307       * internal event list. This will be done at the beginning of each audio       * engine's internal event list. This will be done at the beginning of
308       * cycle (that is each RenderAudio() call) to get all events which have       * each audio cycle (that is each RenderAudio() call) to distinguish
309       * to be processed in the current audio cycle. Each EngineChannel has       * all global events which have to be processed in the current audio
310       * it's own input event queue for the common channel specific events       * cycle. These events are usually just SysEx messages. Every
311       * (like NoteOn, NoteOff and ControlChange events). Beside that, the       * EngineChannel has it's own input event queue buffer and event list
312       * engine also has a input event queue for global events (usually SysEx       * to handle common events like NoteOn, NoteOff and ControlChange
313       * message).       * events.
314       *       *
315       * @param pEventQueue - input event buffer to read from       * @param Samples - number of sample points to be processed in the
316       * @param Samples     - number of sample points to be processed in the       *                  current audio cycle
      *                      current audio cycle  
317       */       */
318      void Engine::ImportEvents(RingBuffer<Event>* pEventQueue, uint Samples) {      void Engine::ImportEvents(uint Samples) {
319          RingBuffer<Event>::NonVolatileReader eventQueueReader = pEventQueue->get_non_volatile_reader();          RingBuffer<Event,false>::NonVolatileReader eventQueueReader = pEventQueue->get_non_volatile_reader();
320          Event* pEvent;          Event* pEvent;
321          while (true) {          while (true) {
322              // get next event from input event queue              // get next event from input event queue
# Line 313  namespace LinuxSampler { namespace gig { Line 329  namespace LinuxSampler { namespace gig {
329                  break;                  break;
330              }              }
331              // copy event to internal event list              // copy event to internal event list
332              if (pEvents->poolIsEmpty()) {              if (pGlobalEvents->poolIsEmpty()) {
333                  dmsg(1,("Event pool emtpy!\n"));                  dmsg(1,("Event pool emtpy!\n"));
334                  break;                  break;
335              }              }
336              *pEvents->allocAppend() = *pEvent;              *pGlobalEvents->allocAppend() = *pEvent;
337          }          }
338          eventQueueReader.free(); // free all copied events from input queue          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 engine disabled          // return if engine disabled
356          if (EngineDisabled.Pop()) {          if (EngineDisabled.Pop()) {
# Line 344  namespace LinuxSampler { namespace gig { Line 361  namespace LinuxSampler { namespace gig {
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          // empty the engine's event lists for the new fragment          // We only allow a maximum of CONFIG_MAX_VOICES voices to be spawned
365          ClearEventLists();          // 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          // get all events from the engine's global input event queue which belong to the current fragment
370          // (these are usually just SysEx messages)          // (these are usually just SysEx messages)
371          ImportEvents(this->pEventQueue, Samples);          ImportEvents(Samples);
372    
373          // process engine global events (these are currently only MIDI System Exclusive messages)          // 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) {
379                      case Event::type_sysex:                      case Event::type_sysex:
# Line 368  namespace LinuxSampler { namespace gig { Line 387  namespace LinuxSampler { namespace gig {
387          // reset internal voice counter (just for statistic of active voices)          // reset internal voice counter (just for statistic of active voices)
388          ActiveVoiceCountTemp = 0;          ActiveVoiceCountTemp = 0;
389    
390          // render audio for all engine channels          // handle instrument change commands
391          // TODO: should we make voice stealing engine globally? unfortunately this would mean other disadvantages so I left voice stealing in the engine channel space for now          instrument_change_command_t command;
392          {          if (InstrumentChangeQueue->pop(&command) > 0) {
393              std::list<EngineChannel*>::iterator itChannel = engineChannels.begin();              EngineChannel* pEngineChannel = command.pEngineChannel;
394              std::list<EngineChannel*>::iterator end       = engineChannels.end();              pEngineChannel->pInstrument = command.pInstrument;
395              for (; itChannel != end; itChannel++) {  
396                  if (!(*itChannel)->pInstrument) continue; // ignore if no instrument loaded              // iterate through all active voices and mark their
397                  RenderAudio(*itChannel, Samples);              // 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
404                    midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
405                    ++iuiKey;
406    
407                    RTList<Voice>::Iterator itVoice     = pKey->pActiveVoices->first();
408                    RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();
409                    for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
410                        if (!itVoice->Orphan) {
411                            itVoice->Orphan = true;
412                            pDimRegionsInUse[i++] = itVoice->pDimRgn;
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            // render all 'normal', active voices on all engine channels
429            for (int i = 0; i < engineChannels.size(); i++) {
430                RenderActiveVoices(engineChannels[i], Samples);
431            }
432    
433            // now that all ordinary voices on ALL engine channels are rendered, render new stolen voices
434            RenderStolenVoices(Samples);
435    
436            // handle audio routing for engine channels with FX sends
437            for (int i = 0; i < engineChannels.size(); i++) {
438                if (engineChannels[i]->fxSends.empty()) continue; // ignore if no FX sends
439                RouteAudio(engineChannels[i], Samples);
440            }
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            // reset voice stealing for the next audio fragment
452            pVoiceStealingQueue->clear();
453    
454          // just some statistics about this engine instance          // just some statistics about this engine instance
455          ActiveVoiceCount = ActiveVoiceCountTemp;          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      void Engine::RenderAudio(EngineChannel* pEngineChannel, uint Samples) {      /**
464          // empty the engine's event lists for the new fragment       * Dispatch and handle all events in this audio fragment for the given
465          ClearEventLists();       * engine channel.
466          // empty the engine channel's, MIDI key specific event lists       *
467          {       * @param pEngineChannel - engine channel on which events should be
468              RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();       *                         processed
469              RTList<uint>::Iterator end    = pEngineChannel->pActiveKeys->end();       * @param Samples        - amount of sample points to be processed in
470              for(; iuiKey != end; ++iuiKey) {       *                         this audio fragment cycle
471                  pEngineChannel->pMIDIKeyInfo[*iuiKey].pEvents->clear(); // free all events on the key       */
472              }      void Engine::ProcessEvents(EngineChannel* pEngineChannel, uint Samples) {
         }  
   
   
473          // get all events from the engine channels's input event queue which belong to the current fragment          // get all events from the engine channels's input event queue which belong to the current fragment
474          // (these are the common events like NoteOn, NoteOff, ControlChange, etc.)          // (these are the common events like NoteOn, NoteOff, ControlChange, etc.)
475          ImportEvents(pEngineChannel->pEventQueue, Samples);                pEngineChannel->ImportEvents(Samples);
   
476    
477          // process events          // process events
478          {          {
479              RTList<Event>::Iterator itEvent = pEvents->first();              RTList<Event>::Iterator itEvent = pEngineChannel->pEvents->first();
480              RTList<Event>::Iterator end     = pEvents->end();              RTList<Event>::Iterator end     = pEngineChannel->pEvents->end();
481              for (; itEvent != end; ++itEvent) {              for (; itEvent != end; ++itEvent) {
482                  switch (itEvent->Type) {                  switch (itEvent->Type) {
483                      case Event::type_note_on:                      case Event::type_note_on:
# Line 430  namespace LinuxSampler { namespace gig { Line 500  namespace LinuxSampler { namespace gig {
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         * Render all 'normal' voices (that is voices which were not stolen in
513         * this fragment) on the given engine channel.
514         *
515         * @param pEngineChannel - engine channel on which audio should be
516         *                         rendered
517         * @param Samples        - amount of sample points to be rendered in
518         *                         this audio fragment cycle
519         */
520        void Engine::RenderActiveVoices(EngineChannel* pEngineChannel, uint Samples) {
521            #if !CONFIG_PROCESS_MUTED_CHANNELS
522            if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
523            #endif
524    
525          // render audio from all active voices          RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
526          {          RTList<uint>::Iterator end    = pEngineChannel->pActiveKeys->end();
527              RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();          while (iuiKey != end) { // iterate through all active keys
528              RTList<uint>::Iterator end    = pEngineChannel->pActiveKeys->end();              midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
529              while (iuiKey != end) { // iterate through all active keys              ++iuiKey;
530                  midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];  
531                  ++iuiKey;              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                  RTList<Voice>::Iterator itVoice     = pKey->pActiveVoices->first();      /**
545                  RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();       * Render all stolen voices (only voices which were stolen in this
546                  for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key       * fragment) on the given engine channel. Stolen voices are rendered
547                      // now render current voice       * after all normal voices have been rendered; this is needed to render
548                      itVoice->Render(Samples);       * audio of those voices which were selected for voice stealing until
549                      if (itVoice->IsActive()) ActiveVoiceCountTemp++; // still active       * the point were the stealing (that is the take over of the voice)
550                      else { // voice reached end, is now inactive       * actually happened.
551                          FreeVoice(pEngineChannel, itVoice); // remove voice from the list of active voices       *
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          // now render all postponed voices from voice stealing       * Will be called in case the respective engine channel sports FX send
583         * 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 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::RouteAudio(EngineChannel* pEngineChannel, uint Samples) {
595            // route master signal
596          {          {
597              RTList<Event>::Iterator itVoiceStealEvent = pVoiceStealingQueue->first();              AudioChannel* pDstL = pAudioOutputDevice->Channel(pEngineChannel->AudioDeviceChannelLeft);
598              RTList<Event>::Iterator end               = pVoiceStealingQueue->end();              AudioChannel* pDstR = pAudioOutputDevice->Channel(pEngineChannel->AudioDeviceChannelRight);
599              for (; itVoiceStealEvent != end; ++itVoiceStealEvent) {              pEngineChannel->pChannelLeft->MixTo(pDstL, Samples);
600                  Pool<Voice>::Iterator itNewVoice =              pEngineChannel->pChannelRight->MixTo(pDstR, Samples);
601                      LaunchVoice(pEngineChannel, itVoiceStealEvent, itVoiceStealEvent->Param.Note.Layer, itVoiceStealEvent->Param.Note.ReleaseTrigger, false);          }
602                  if (itNewVoice) {          // route FX send signal
603                      for (; itNewVoice; itNewVoice = itNewVoice->itChildVoice) {          {
604                          itNewVoice->Render(Samples);              for (int iFxSend = 0; iFxSend < pEngineChannel->GetFxSendCount(); iFxSend++) {
605                          if (itNewVoice->IsActive()) ActiveVoiceCountTemp++; // still active                  FxSend* pFxSend = pEngineChannel->GetFxSend(iFxSend);
606                          else { // voice reached end, is now inactive                  // left channel
607                              FreeVoice(pEngineChannel, itNewVoice); // remove voice from the list of active voices                  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                  }                  }
                 else dmsg(1,("gig::Engine: ERROR, voice stealing didn't work out!\n"));  
626              }              }
627          }          }
628          // reset voice stealing for the new fragment          // reset buffers with silence (zero out) for the next audio cycle
629          pVoiceStealingQueue->clear();          pEngineChannel->pChannelLeft->Clear();
630          pEngineChannel->itLastStolenVoice = RTList<Voice>::Iterator();          pEngineChannel->pChannelRight->Clear();
631          pEngineChannel->iuiLastStolenKey  = RTList<uint>::Iterator();      }
           
632    
633        /**
634         * Free all keys which have turned inactive in this audio fragment, from
635         * the list of active keys and clear all event lists on that engine
636         * channel.
637         *
638         * @param pEngineChannel - engine channel to cleanup
639         */
640        void Engine::PostProcess(EngineChannel* pEngineChannel) {
641          // free all keys which have no active voices left          // free all keys which have no active voices left
642          {          {
643              RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();              RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
# Line 486  namespace LinuxSampler { namespace gig { Line 646  namespace LinuxSampler { namespace gig {
646                  midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];                  midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
647                  ++iuiKey;                  ++iuiKey;
648                  if (pKey->pActiveVoices->isEmpty()) FreeKey(pEngineChannel, pKey);                  if (pKey->pActiveVoices->isEmpty()) FreeKey(pEngineChannel, pKey);
649                  #if DEVMODE                  #if CONFIG_DEVMODE
650                  else { // FIXME: should be removed before the final release (purpose: just a sanity check for debugging)                  else { // just a sanity check for debugging
651                      RTList<Voice>::Iterator itVoice     = pKey->pActiveVoices->first();                      RTList<Voice>::Iterator itVoice     = pKey->pActiveVoices->first();
652                      RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();                      RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();
653                      for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key                      for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
# Line 496  namespace LinuxSampler { namespace gig { Line 656  namespace LinuxSampler { namespace gig {
656                          }                          }
657                      }                      }
658                  }                  }
659                  #endif // DEVMODE                  #endif // CONFIG_DEVMODE
660              }              }
661          }          }
662    
663            // empty the engine channel's own event lists
664            pEngineChannel->ClearEventLists();
665      }      }
666    
667      /**      /**
# Line 528  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 540  namespace LinuxSampler { namespace gig { Line 703  namespace LinuxSampler { namespace gig {
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(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent) {      void Engine::ProcessNoteOn(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent) {
706                    #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;          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          // Change key dimension value if key is in keyswitching area
747          {          {
748              const ::gig::Instrument* pInstrument = pEngineChannel->pInstrument;              const ::gig::Instrument* pInstrument = pEngineChannel->pInstrument;
749              if (key >= pInstrument->DimensionKeyRange.low && key <= pInstrument->DimensionKeyRange.high)              if (key >= pInstrument->DimensionKeyRange.low && key <= pInstrument->DimensionKeyRange.high)
750                  pEngineChannel->CurrentKeyDimension = ((key - pInstrument->DimensionKeyRange.low) * 128) /                  pEngineChannel->CurrentKeyDimension = float(key - pInstrument->DimensionKeyRange.low) /
751                      (pInstrument->DimensionKeyRange.high - pInstrument->DimensionKeyRange.low + 1);                      (pInstrument->DimensionKeyRange.high - pInstrument->DimensionKeyRange.low + 1);
752          }          }
753    
         midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[key];  
   
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 && !pEngineChannel->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          // allocate and trigger a new voice for the key          // if neither a voice was spawned or postponed then remove note on event from key again
781          LaunchVoice(pEngineChannel, itNoteOnEventOnKeyList, 0, false, true);          if (!pKey->Active && !pKey->VoiceTheftsQueued)
782                pKey->pEvents->free(itNoteOnEventOnKeyList);
783    
784            if (!pEngineChannel->SoloMode || pEngineChannel->PortamentoPos < 0.0f) pEngineChannel->PortamentoPos = (float) key;
785            pKey->RoundRobinIndex++;
786      }      }
787    
788      /**      /**
# Line 582  namespace LinuxSampler { namespace gig { Line 795  namespace LinuxSampler { namespace gig {
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(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOffEvent) {      void Engine::ProcessNoteOff(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOffEvent) {
798          midi_key_info_t* pKey = &pEngineChannel->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 && !pEngineChannel->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(pEngineChannel, itNoteOffEventOnKeyList, 0, true, false); //FIXME: for the moment we don't perform voice stealing for release triggered samples          // in case Solo Mode is enabled, kill all voices on this key and respawn a voice on the highest pressed key (if any)
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       *  @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(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itPitchbendEvent) {      void Engine::ProcessPitchbend(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itPitchbendEvent) {
909          pEngineChannel->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 627  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 the voice wasn't triggered (for example when no region is       *           if the voice wasn't triggered (for example when no region is
930       *           defined for the given key).       *           defined for the given key).
931       */       */
932      Pool<Voice>::Iterator Engine::LaunchVoice(EngineChannel* pEngineChannel, 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 = &pEngineChannel->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(pEngineChannel, itNoteOnEvent, pEngineChannel->Pitch, pEngineChannel->pInstrument, iLayer, ReleaseTriggerVoice, VoiceStealing) < 0) {              if (itNewVoice->Trigger(pEngineChannel, itNoteOnEvent, pEngineChannel->Pitch, pDimRgn, VoiceType, iKeyGroup) < 0) {
1089                  dmsg(4,("Voice not triggered\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 = &pEngineChannel->ActiveKeyGroups[itNewVoice->KeyGroup];  
                     if (*ppKeyGroup) { // if there's already an active key in that key group  
                         midi_key_info_t* pOtherKey = &pEngineChannel->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 = pEngineChannel->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 669  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 = pEngineChannel->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(pEngineChannel, 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 699  namespace LinuxSampler { namespace gig { Line 1131  namespace LinuxSampler { namespace gig {
1131       *       *
1132       *  @param pEngineChannel - engine channel on which this event occured on       *  @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(EngineChannel* pEngineChannel, 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 = &pEngineChannel->pMIDIKeyInfo[itNoteOnEvent->Param.Note.Key];                      midi_key_info_t* pSelectedKey = &pEngineChannel->pMIDIKeyInfo[itNoteOnEvent->Param.Note.Key];
1154                      if (pEngineChannel->itLastStolenVoice) {                      itSelectedVoice = pSelectedKey->pActiveVoices->first();
1155                          itOldestVoice = pEngineChannel->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 (pEngineChannel->itLastStolenVoice) {                      // if we already stole in this fragment, try to proceed on same key
1166                          midi_key_info_t* pOldestKey = &pEngineChannel->pMIDIKeyInfo[*pEngineChannel->iuiLastStolenKey];                      if (this->itLastStolenVoice) {
1167                          itOldestVoice = pEngineChannel->itLastStolenVoice;                          itSelectedVoice = this->itLastStolenVoice;
1168                          ++itOldestVoice;                          do {
1169                          if (!itOldestVoice) {                              ++itSelectedVoice;
1170                              iuiOldestKey = pEngineChannel->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 = &pEngineChannel->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 = pEngineChannel->iuiLastStolenKey;  
1177                      }                      }
1178                      else { // no voice stolen in this audio fragment cycle yet                      // get (next) oldest key
1179                          iuiOldestKey = pEngineChannel->pActiveKeys->first();                      RTList<uint>::Iterator iuiSelectedKey = (this->iuiLastStolenKey) ? ++this->iuiLastStolenKey : pEngineChannel->pActiveKeys->first();
1180                          midi_key_info_t* pOldestKey = &pEngineChannel->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 761  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              //FIXME: can be removed, just a sanity check for debugging              // if we couldn't steal a voice from the same engine channel then
1206              if (!itOldestVoice->IsActive()) dmsg(1,("gig::Engine: ERROR, tried to steal a voice which was not active !!!\n"));              // steal oldest voice on the oldest key from any other engine channel
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              pEngineChannel->itLastStolenVoice = itOldestVoice;              --VoiceSpawnsLeft;
1284              pEngineChannel->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 792  namespace LinuxSampler { namespace gig { Line 1305  namespace LinuxSampler { namespace gig {
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    
# Line 833  namespace LinuxSampler { namespace gig { Line 1353  namespace LinuxSampler { namespace gig {
1353      void Engine::ProcessControlChange(EngineChannel* pEngineChannel, 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 5: { // portamento time
1362                    pEngineChannel->PortamentoTime = (float) itControlChangeEvent->Param.CC.Value / 127.0f * (float) CONFIG_PORTAMENTO_TIME_MAX + (float) CONFIG_PORTAMENTO_TIME_MIN;
1363                    break;
1364                }
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                        // workaround, so we won't have hanging notes
1373                        ReleaseAllVoices(pEngineChannel, itControlChangeEvent);
1374                    }
1375                    // to avoid other MIDI CC #6 messages to be misenterpreted as RPN controller data
1376                    pEngineChannel->ResetMidiRpnController();
1377                    break;
1378                }
1379              case 7: { // volume              case 7: { // volume
1380                  //TODO: not sample accurate yet                  //TODO: not sample accurate yet
1381                  pEngineChannel->GlobalVolume = (float) itControlChangeEvent->Param.CC.Value / 127.0f;                  pEngineChannel->MidiVolume = VolumeCurve[itControlChangeEvent->Param.CC.Value];
1382                    pEngineChannel->bStatusChanged = true; // engine channel status has changed, so set notify flag
1383                  break;                  break;
1384              }              }
1385              case 10: { // panpot              case 10: { // panpot
1386                  //TODO: not sample accurate yet                  //TODO: not sample accurate yet
1387                  const int pan = (int) itControlChangeEvent->Param.CC.Value - 64;                  pEngineChannel->GlobalPanLeft  = PanCurve[128 - itControlChangeEvent->Param.CC.Value];
1388                  pEngineChannel->GlobalPanLeft  = 1.0f - float(RTMath::Max(pan, 0)) /  63.0f;                  pEngineChannel->GlobalPanRight = PanCurve[itControlChangeEvent->Param.CC.Value];
                 pEngineChannel->GlobalPanRight = 1.0f - float(RTMath::Min(pan, 0)) / -64.0f;  
1389                  break;                  break;
1390              }              }
1391              case 64: { // sustain              case 64: { // sustain
1392                  if (itControlChangeEvent->Param.CC.Value >= 64 && !pEngineChannel->SustainPedal) {                  if (itControlChangeEvent->Param.CC.Value >= 64 && !pEngineChannel->SustainPedal) {
1393                      dmsg(4,("PEDAL DOWN\n"));                      dmsg(4,("DAMPER (RIGHT) PEDAL DOWN\n"));
1394                      pEngineChannel->SustainPedal = true;                      pEngineChannel->SustainPedal = true;
1395    
1396                        #if !CONFIG_PROCESS_MUTED_CHANNELS
1397                        if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
1398                        #endif
1399    
1400                      // cancel release process of voices if necessary                      // cancel release process of voices if necessary
1401                      RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();                      RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
1402                      if (iuiKey) {                      for (; iuiKey; ++iuiKey) {
1403                          itControlChangeEvent->Type = Event::type_cancel_release; // transform event type                          midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
1404                          while (iuiKey) {                          if (!pKey->KeyPressed) {
1405                              midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];                              RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
1406                              ++iuiKey;                              if (itNewEvent) {
1407                              if (!pKey->KeyPressed) {                                  *itNewEvent = *itControlChangeEvent; // copy event to the key's own event list
1408                                  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"));  
1409                              }                              }
1410                                else dmsg(1,("Event pool emtpy!\n"));
1411                          }                          }
1412                      }                      }
1413                  }                  }
1414                  if (itControlChangeEvent->Param.CC.Value < 64 && pEngineChannel->SustainPedal) {                  if (itControlChangeEvent->Param.CC.Value < 64 && pEngineChannel->SustainPedal) {
1415                      dmsg(4,("PEDAL UP\n"));                      dmsg(4,("DAMPER (RIGHT) PEDAL UP\n"));
1416                      pEngineChannel->SustainPedal = false;                      pEngineChannel->SustainPedal = false;
1417    
1418                        #if !CONFIG_PROCESS_MUTED_CHANNELS
1419                        if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
1420                        #endif
1421    
1422                      // release voices if their respective key is not pressed                      // release voices if their respective key is not pressed
1423                      RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();                      RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
1424                      if (iuiKey) {                      for (; iuiKey; ++iuiKey) {
1425                          itControlChangeEvent->Type = Event::type_release; // transform event type                          midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
1426                          while (iuiKey) {                          if (!pKey->KeyPressed && ShouldReleaseVoice(pEngineChannel, *iuiKey)) {
1427                              midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];                              RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
1428                              ++iuiKey;                              if (itNewEvent) {
1429                              if (!pKey->KeyPressed) {                                  *itNewEvent = *itControlChangeEvent; // copy event to the key's own event list
1430                                  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"));  
1431                              }                              }
1432                                else dmsg(1,("Event pool emtpy!\n"));
1433                          }                          }
1434                      }                      }
1435                  }                  }
1436                  break;                  break;
1437              }              }
1438          }              case 65: { // portamento on / off
1439                    KillAllVoices(pEngineChannel, itControlChangeEvent);
1440                    pEngineChannel->PortamentoMode = itControlChangeEvent->Param.CC.Value >= 64;
1441                    break;
1442                }
1443                case 66: { // sostenuto
1444                    if (itControlChangeEvent->Param.CC.Value >= 64 && !pEngineChannel->SostenutoPedal) {
1445                        dmsg(4,("SOSTENUTO (CENTER) PEDAL DOWN\n"));
1446                        pEngineChannel->SostenutoPedal = true;
1447    
1448                        #if !CONFIG_PROCESS_MUTED_CHANNELS
1449                        if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
1450                        #endif
1451    
1452                        SostenutoKeyCount = 0;
1453                        // Remeber the pressed keys
1454                        RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
1455                        for (; iuiKey; ++iuiKey) {
1456                            midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
1457                            if (pKey->KeyPressed && SostenutoKeyCount < 128) SostenutoKeys[SostenutoKeyCount++] = *iuiKey;
1458                        }
1459                    }
1460                    if (itControlChangeEvent->Param.CC.Value < 64 && pEngineChannel->SostenutoPedal) {
1461                        dmsg(4,("SOSTENUTO (CENTER) PEDAL UP\n"));
1462                        pEngineChannel->SostenutoPedal = false;
1463    
1464                        #if !CONFIG_PROCESS_MUTED_CHANNELS
1465                        if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
1466                        #endif
1467    
1468                        // release voices if the damper pedal is up and their respective key is not pressed
1469                        for (int i = 0; i < SostenutoKeyCount; i++) {
1470                            midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[SostenutoKeys[i]];
1471                            if (!pKey->KeyPressed && !pEngineChannel->SustainPedal) {
1472                                RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
1473                                if (itNewEvent) {
1474                                    *itNewEvent = *itControlChangeEvent; // copy event to the key's own event list
1475                                    itNewEvent->Type = Event::type_release; // transform event type
1476                                }
1477                                else dmsg(1,("Event pool emtpy!\n"));
1478                            }
1479                        }
1480                    }
1481                    break;
1482                }
1483                case 100: { // RPN controller LSB
1484                    pEngineChannel->SetMidiRpnControllerLsb(itControlChangeEvent->Param.CC.Value);
1485                    break;
1486                }
1487                case 101: { // RPN controller MSB
1488                    pEngineChannel->SetMidiRpnControllerMsb(itControlChangeEvent->Param.CC.Value);
1489                    break;
1490                }
1491    
         // update controller value in the engine's controller table  
         pEngineChannel->ControllerTable[itControlChangeEvent->Param.CC.Controller] = itControlChangeEvent->Param.CC.Value;  
1492    
1493          // move event from the unsorted event list to the control change event list              // Channel Mode Messages
1494          itControlChangeEvent.moveToEndOf(pCCEvents);  
1495                case 120: { // all sound off
1496                    KillAllVoices(pEngineChannel, itControlChangeEvent);
1497                    break;
1498                }
1499                case 121: { // reset all controllers
1500                    pEngineChannel->ResetControllers();
1501                    break;
1502                }
1503                case 123: { // all notes off
1504                    #if CONFIG_PROCESS_ALL_NOTES_OFF
1505                    ReleaseAllVoices(pEngineChannel, itControlChangeEvent);
1506                    #endif // CONFIG_PROCESS_ALL_NOTES_OFF
1507                    break;
1508                }
1509                case 126: { // mono mode on
1510                    KillAllVoices(pEngineChannel, itControlChangeEvent);
1511                    pEngineChannel->SoloMode = true;
1512                    break;
1513                }
1514                case 127: { // poly mode on
1515                    KillAllVoices(pEngineChannel, itControlChangeEvent);
1516                    pEngineChannel->SoloMode = false;
1517                    break;
1518                }
1519            }
1520    
1521            // handle FX send controllers
1522            if (!pEngineChannel->fxSends.empty()) {
1523                for (int iFxSend = 0; iFxSend < pEngineChannel->GetFxSendCount(); iFxSend++) {
1524                    FxSend* pFxSend = pEngineChannel->GetFxSend(iFxSend);
1525                    if (pFxSend->MidiController() == itControlChangeEvent->Param.CC.Controller)
1526                        pFxSend->SetLevel(itControlChangeEvent->Param.CC.Value);
1527                }
1528            }
1529      }      }
1530    
1531      /**      /**
# Line 902  namespace LinuxSampler { namespace gig { Line 1534  namespace LinuxSampler { namespace gig {
1534       *  @param itSysexEvent - sysex data size and time stamp of the sysex event       *  @param itSysexEvent - sysex data size and time stamp of the sysex event
1535       */       */
1536      void Engine::ProcessSysex(Pool<Event>::Iterator& itSysexEvent) {      void Engine::ProcessSysex(Pool<Event>::Iterator& itSysexEvent) {
1537          RingBuffer<uint8_t>::NonVolatileReader reader = pSysexBuffer->get_non_volatile_reader();          RingBuffer<uint8_t,false>::NonVolatileReader reader = pSysexBuffer->get_non_volatile_reader();
1538    
1539          uint8_t exclusive_status, id;          uint8_t exclusive_status, id;
1540          if (!reader.pop(&exclusive_status)) goto free_sysex_data;          if (!reader.pop(&exclusive_status)) goto free_sysex_data;
# Line 911  namespace LinuxSampler { namespace gig { Line 1543  namespace LinuxSampler { namespace gig {
1543    
1544          switch (id) {          switch (id) {
1545              case 0x41: { // Roland              case 0x41: { // Roland
1546                    dmsg(3,("Roland Sysex\n"));
1547                  uint8_t device_id, model_id, cmd_id;                  uint8_t device_id, model_id, cmd_id;
1548                  if (!reader.pop(&device_id)) goto free_sysex_data;                  if (!reader.pop(&device_id)) goto free_sysex_data;
1549                  if (!reader.pop(&model_id))  goto free_sysex_data;                  if (!reader.pop(&model_id))  goto free_sysex_data;
# Line 920  namespace LinuxSampler { namespace gig { Line 1553  namespace LinuxSampler { namespace gig {
1553    
1554                  // command address                  // command address
1555                  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)
1556                  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
1557                  if (reader.read(&addr[0], 3) != 3) goto free_sysex_data;                  if (reader.read(&addr[0], 3) != 3) goto free_sysex_data;
1558                  if (addr[0] == 0x40 && addr[1] == 0x00) { // System Parameters                  if (addr[0] == 0x40 && addr[1] == 0x00) { // System Parameters
1559                        dmsg(3,("\tSystem Parameter\n"));
1560                  }                  }
1561                  else if (addr[0] == 0x40 && addr[1] == 0x01) { // Common Parameters                  else if (addr[0] == 0x40 && addr[1] == 0x01) { // Common Parameters
1562                        dmsg(3,("\tCommon Parameter\n"));
1563                  }                  }
1564                  else if (addr[0] == 0x40 && (addr[1] & 0xf0) == 0x10) { // Part Parameters (1)                  else if (addr[0] == 0x40 && (addr[1] & 0xf0) == 0x10) { // Part Parameters (1)
1565                      switch (addr[3]) {                      dmsg(3,("\tPart Parameter\n"));
1566                        switch (addr[2]) {
1567                          case 0x40: { // scale tuning                          case 0x40: { // scale tuning
1568                                dmsg(3,("\t\tScale Tuning\n"));
1569                              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
1570                              if (reader.read(&scale_tunes[0], 12) != 12) goto free_sysex_data;                              if (reader.read(&scale_tunes[0], 12) != 12) goto free_sysex_data;
1571                              uint8_t checksum;                              uint8_t checksum;
1572                              if (!reader.pop(&checksum))                      goto free_sysex_data;                              if (!reader.pop(&checksum)) goto free_sysex_data;
1573                              if (GSCheckSum(checksum_reader, 12) != checksum) goto free_sysex_data;                              #if CONFIG_ASSERT_GS_SYSEX_CHECKSUM
1574                                if (GSCheckSum(checksum_reader, 12)) goto free_sysex_data;
1575                                #endif // CONFIG_ASSERT_GS_SYSEX_CHECKSUM
1576                              for (int i = 0; i < 12; i++) scale_tunes[i] -= 64;                              for (int i = 0; i < 12; i++) scale_tunes[i] -= 64;
1577                              AdjustScale((int8_t*) scale_tunes);                              AdjustScale((int8_t*) scale_tunes);
1578                                dmsg(3,("\t\t\tNew scale applied.\n"));
1579                              break;                              break;
1580                          }                          }
1581                      }                      }
# Line 960  namespace LinuxSampler { namespace gig { Line 1600  namespace LinuxSampler { namespace gig {
1600       *                     question       *                     question
1601       * @param DataSize   - size of the GS message data (in bytes)       * @param DataSize   - size of the GS message data (in bytes)
1602       */       */
1603      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) {
1604          RingBuffer<uint8_t>::NonVolatileReader reader = AddrReader;          RingBuffer<uint8_t,false>::NonVolatileReader reader = AddrReader;
1605          uint bytes = 3 /*addr*/ + DataSize;          uint bytes = 3 /*addr*/ + DataSize;
1606          uint8_t addr_and_data[bytes];          uint8_t addr_and_data[bytes];
1607          reader.read(&addr_and_data[0], bytes);          reader.read(&addr_and_data[0], bytes);
# Line 980  namespace LinuxSampler { namespace gig { Line 1620  namespace LinuxSampler { namespace gig {
1620      }      }
1621    
1622      /**      /**
1623       * Initialize the parameter sequence for the modulation destination given by       * Releases all voices on an engine channel. All voices will go into
1624       * by 'dst' with the constant value given by val.       * the release stage and thus it might take some time (e.g. dependant to
1625         * their envelope release time) until they actually die.
1626         *
1627         * @param pEngineChannel - engine channel on which all voices should be released
1628         * @param itReleaseEvent - event which caused this releasing of all voices
1629       */       */
1630      void Engine::ResetSynthesisParameters(Event::destination_t dst, float val) {      void Engine::ReleaseAllVoices(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itReleaseEvent) {
1631          int maxsamples = pAudioOutputDevice->MaxSamplesPerCycle();          RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
1632          float* m = &pSynthesisParameters[dst][0];          while (iuiKey) {
1633          for (int i = 0; i < maxsamples; i += 4) {              midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
1634             m[i]   = val;              ++iuiKey;
1635             m[i+1] = val;              // append a 'release' event to the key's own event list
1636             m[i+2] = val;              RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
1637             m[i+3] = val;              if (itNewEvent) {
1638                    *itNewEvent = *itReleaseEvent; // copy original event (to the key's event list)
1639                    itNewEvent->Type = Event::type_release; // transform event type
1640                }
1641                else dmsg(1,("Event pool emtpy!\n"));
1642          }          }
1643      }          }
1644    
1645        /**
1646         * Kills all voices on an engine channel as soon as possible. Voices
1647         * won't get into release state, their volume level will be ramped down
1648         * as fast as possible.
1649         *
1650         * @param pEngineChannel - engine channel on which all voices should be killed
1651         * @param itKillEvent    - event which caused this killing of all voices
1652         */
1653        void Engine::KillAllVoices(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itKillEvent) {
1654            RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
1655            RTList<uint>::Iterator end    = pEngineChannel->pActiveKeys->end();
1656            while (iuiKey != end) { // iterate through all active keys
1657                midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
1658                ++iuiKey;
1659                RTList<Voice>::Iterator itVoice     = pKey->pActiveVoices->first();
1660                RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();
1661                for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
1662                    itVoice->Kill(itKillEvent);
1663                    --VoiceSpawnsLeft; //FIXME: just a temporary workaround, we should check the cause in StealVoice() instead
1664                }
1665            }
1666        }
1667    
1668        /**
1669         * Determines whether the specified voice should be released.
1670         *
1671         * @param pEngineChannel - The engine channel on which the voice should be checked
1672         * @param Key - The key number
1673         * @returns true if the specified should be released, false otherwise.
1674         */
1675        bool Engine::ShouldReleaseVoice(EngineChannel* pEngineChannel, int Key) {
1676            if (pEngineChannel->SustainPedal) return false;
1677    
1678            if (pEngineChannel->SostenutoPedal) {
1679                for (int i = 0; i < SostenutoKeyCount; i++)
1680                    if (Key == SostenutoKeys[i]) return false;
1681            }
1682    
1683            return true;
1684        }
1685    
1686      uint Engine::VoiceCount() {      uint Engine::VoiceCount() {
1687          return ActiveVoiceCount;          return ActiveVoiceCount;
# Line 1023  namespace LinuxSampler { namespace gig { Line 1712  namespace LinuxSampler { namespace gig {
1712      }      }
1713    
1714      String Engine::EngineName() {      String Engine::EngineName() {
1715          return "GigEngine";          return LS_GIG_ENGINE_NAME;
1716      }      }
1717    
1718      String Engine::Description() {      String Engine::Description() {
# Line 1031  namespace LinuxSampler { namespace gig { Line 1720  namespace LinuxSampler { namespace gig {
1720      }      }
1721    
1722      String Engine::Version() {      String Engine::Version() {
1723          String s = "$Revision: 1.29 $";          String s = "$Revision: 1.75 $";
1724          return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword          return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword
1725      }      }
1726    
1727        InstrumentManager* Engine::GetInstrumentManager() {
1728            return &instruments;
1729        }
1730    
1731        // static constant initializers
1732        const float* Engine::VolumeCurve(InitVolumeCurve());
1733        const float* Engine::PanCurve(InitPanCurve());
1734        const float* Engine::CrossfadeCurve(InitCrossfadeCurve());
1735    
1736        float* Engine::InitVolumeCurve() {
1737            // line-segment approximation
1738            const float segments[] = {
1739                0, 0, 2, 0.0046, 16, 0.016, 31, 0.051, 45, 0.115, 54.5, 0.2,
1740                64.5, 0.39, 74, 0.74, 92, 1.03, 114, 1.94, 119.2, 2.2, 127, 2.2
1741            };
1742            return InitCurve(segments);
1743        }
1744    
1745        float* Engine::InitPanCurve() {
1746            // line-segment approximation
1747            const float segments[] = {
1748                0, 0, 1, 0,
1749                2, 0.05, 31.5, 0.7, 51, 0.851, 74.5, 1.12,
1750                127, 1.41, 128, 1.41
1751            };
1752            return InitCurve(segments, 129);
1753        }
1754    
1755        float* Engine::InitCrossfadeCurve() {
1756            // line-segment approximation
1757            const float segments[] = {
1758                0, 0, 1, 0.03, 10, 0.1, 51, 0.58, 127, 1
1759            };
1760            return InitCurve(segments);
1761        }
1762    
1763        float* Engine::InitCurve(const float* segments, int size) {
1764            float* y = new float[size];
1765            for (int x = 0 ; x < size ; x++) {
1766                if (x > segments[2]) segments += 2;
1767                y[x] = segments[1] + (x - segments[0]) *
1768                    (segments[3] - segments[1]) / (segments[2] - segments[0]);
1769            }
1770            return y;
1771        }
1772    
1773        /**
1774         * Changes the instrument for an engine channel.
1775         *
1776         * @param pEngineChannel - engine channel on which the instrument
1777         *                         should be changed
1778         * @param pInstrument - new instrument
1779         * @returns a list of dimension regions from the old instrument
1780         *          that are still in use
1781         */
1782        ::gig::DimensionRegion** Engine::ChangeInstrument(EngineChannel* pEngineChannel, ::gig::Instrument* pInstrument) {
1783            instrument_change_command_t command;
1784            command.pEngineChannel = pEngineChannel;
1785            command.pInstrument = pInstrument;
1786            InstrumentChangeQueue->push(&command);
1787    
1788            // wait for the audio thread to confirm that the instrument
1789            // change has been done
1790            instrument_change_reply_t reply;
1791            while (InstrumentChangeReplyQueue->pop(&reply) == 0) {
1792                usleep(10000);
1793            }
1794            return pDimRegionsInUse;
1795        }
1796    
1797  }} // namespace LinuxSampler::gig  }} // namespace LinuxSampler::gig

Legend:
Removed from v.424  
changed lines
  Added in v.1044

  ViewVC Help
Powered by ViewVC