/[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 438 by persson, Wed Mar 9 22:12:15 2005 UTC revision 1043 by schoenebeck, Wed Feb 7 21:02:04 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 57  namespace LinuxSampler { namespace gig { Line 51  namespace LinuxSampler { namespace gig {
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");
# Line 64  namespace LinuxSampler { namespace gig { Line 63  namespace LinuxSampler { namespace gig {
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          // render audio from all active voices      /**
512          {       * Render all 'normal' voices (that is voices which were not stolen in
513              RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();       * this fragment) on the given engine channel.
514              RTList<uint>::Iterator end    = pEngineChannel->pActiveKeys->end();       *
515              while (iuiKey != end) { // iterate through all active keys       * @param pEngineChannel - engine channel on which audio should be
516                  midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];       *                         rendered
517                  ++iuiKey;       * @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                  RTList<Voice>::Iterator itVoice     = pKey->pActiveVoices->first();          RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
526                  RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();          RTList<uint>::Iterator end    = pEngineChannel->pActiveKeys->end();
527                  for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key          while (iuiKey != end) { // iterate through all active keys
528                      // now render current voice              midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
529                      itVoice->Render(Samples);              ++iuiKey;
530                      if (itVoice->IsActive()) ActiveVoiceCountTemp++; // still active  
531                      else { // voice reached end, is now inactive              RTList<Voice>::Iterator itVoice     = pKey->pActiveVoices->first();
532                          FreeVoice(pEngineChannel, itVoice); // remove voice from the list of active voices              RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();
533                      }              for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
534                    // now render current voice
535                    itVoice->Render(Samples);
536                    if (itVoice->IsActive()) ActiveVoiceCountTemp++; // still active
537                    else { // voice reached end, is now inactive
538                        FreeVoice(pEngineChannel, itVoice); // remove voice from the list of active voices
539                  }                  }
540              }              }
541          }          }
542        }
543    
544        /**
545         * Render all stolen voices (only voices which were stolen in this
546         * fragment) on the given engine channel. Stolen voices are rendered
547         * after all normal voices have been rendered; this is needed to render
548         * audio of those voices which were selected for voice stealing until
549         * the point were the stealing (that is the take over of the voice)
550         * actually happened.
551         *
552         * @param pEngineChannel - engine channel on which audio should be
553         *                         rendered
554         * @param Samples        - amount of sample points to be rendered in
555         *                         this audio fragment cycle
556         */
557        void Engine::RenderStolenVoices(uint Samples) {
558            RTList<Event>::Iterator itVoiceStealEvent = pVoiceStealingQueue->first();
559            RTList<Event>::Iterator end               = pVoiceStealingQueue->end();
560            for (; itVoiceStealEvent != end; ++itVoiceStealEvent) {
561                EngineChannel* pEngineChannel = (EngineChannel*) itVoiceStealEvent->pEngineChannel;
562                if (!pEngineChannel->pInstrument) continue; // ignore if no instrument loaded
563                Pool<Voice>::Iterator itNewVoice =
564                    LaunchVoice(pEngineChannel, itVoiceStealEvent, itVoiceStealEvent->Param.Note.Layer, itVoiceStealEvent->Param.Note.ReleaseTrigger, false, false);
565                if (itNewVoice) {
566                    itNewVoice->Render(Samples);
567                    if (itNewVoice->IsActive()) ActiveVoiceCountTemp++; // still active
568                    else { // voice reached end, is now inactive
569                        FreeVoice(pEngineChannel, itNewVoice); // remove voice from the list of active voices
570                    }
571                }
572                else dmsg(1,("gig::Engine: ERROR, voice stealing didn't work out!\n"));
573    
574          // now render all postponed voices from voice stealing              // we need to clear the key's event list explicitly here in case key was never active
575                midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[itVoiceStealEvent->Param.Note.Key];
576                pKey->VoiceTheftsQueued--;
577                if (!pKey->Active && !pKey->VoiceTheftsQueued) pKey->pEvents->clear();
578            }
579        }
580    
581        /**
582         * Will be called 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++;          pKey->RoundRobinIndex++;
786      }      }
787    
# Line 584  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 629  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 671  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 701  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 763  namespace LinuxSampler { namespace gig { Line 1198  namespace LinuxSampler { namespace gig {
1198                  case voice_steal_algo_none:                  case voice_steal_algo_none:
1199                  default: {                  default: {
1200                      dmsg(1,("No free voice (voice stealing disabled)!\n"));                      dmsg(1,("No free voice (voice stealing disabled)!\n"));
1201                      return;                      return -1;
1202                    }
1203                }
1204    
1205                // if we couldn't steal a voice from the same engine channel then
1206                // steal oldest voice on the oldest key from any other engine channel
1207                // (the smaller engine channel number, the higher priority)
1208                if (!itSelectedVoice || !itSelectedVoice->IsStealable()) {
1209                    EngineChannel* pSelectedChannel;
1210                    int            iChannelIndex;
1211                    // select engine channel
1212                    if (pLastStolenChannel) {
1213                        pSelectedChannel = pLastStolenChannel;
1214                        iChannelIndex    = pSelectedChannel->iEngineIndexSelf;
1215                    } else { // pick the engine channel followed by this engine channel
1216                        iChannelIndex    = (pEngineChannel->iEngineIndexSelf + 1) % engineChannels.size();
1217                        pSelectedChannel = engineChannels[iChannelIndex];
1218                    }
1219    
1220                    // if we already stole in this fragment, try to proceed on same key
1221                    if (this->itLastStolenVoiceGlobally) {
1222                        itSelectedVoice = this->itLastStolenVoiceGlobally;
1223                        do {
1224                            ++itSelectedVoice;
1225                        } while (itSelectedVoice && !itSelectedVoice->IsStealable()); // proceed iterating if voice was created in this fragment cycle
1226                    }
1227    
1228                    #if CONFIG_DEVMODE
1229                    EngineChannel* pBegin = pSelectedChannel; // to detect endless loop
1230                    #endif // CONFIG_DEVMODE
1231    
1232                    // did we find a 'stealable' voice?
1233                    if (itSelectedVoice && itSelectedVoice->IsStealable()) {
1234                        // remember which voice we stole, so we can simply proceed on next voice stealing
1235                        this->itLastStolenVoiceGlobally = itSelectedVoice;
1236                    } else while (true) { // iterate through engine channels
1237                        // get (next) oldest key
1238                        RTList<uint>::Iterator iuiSelectedKey = (this->iuiLastStolenKeyGlobally) ? ++this->iuiLastStolenKeyGlobally : pSelectedChannel->pActiveKeys->first();
1239                        this->iuiLastStolenKeyGlobally = RTList<uint>::Iterator(); // to prevent endless loop (see line above)
1240                        while (iuiSelectedKey) {
1241                            midi_key_info_t* pSelectedKey = &pSelectedChannel->pMIDIKeyInfo[*iuiSelectedKey];
1242                            itSelectedVoice = pSelectedKey->pActiveVoices->first();
1243                            // proceed iterating if voice was created in this fragment cycle
1244                            while (itSelectedVoice && !itSelectedVoice->IsStealable()) ++itSelectedVoice;
1245                            // found a "stealable" voice ?
1246                            if (itSelectedVoice && itSelectedVoice->IsStealable()) {
1247                                // remember which voice on which key on which engine channel we stole, so we can simply proceed on next voice stealing
1248                                this->iuiLastStolenKeyGlobally  = iuiSelectedKey;
1249                                this->itLastStolenVoiceGlobally = itSelectedVoice;
1250                                this->pLastStolenChannel        = pSelectedChannel;
1251                                goto stealable_voice_found; // selection succeeded
1252                            }
1253                            ++iuiSelectedKey; // get next key on current engine channel
1254                        }
1255                        // get next engine channel
1256                        iChannelIndex    = (iChannelIndex + 1) % engineChannels.size();
1257                        pSelectedChannel = engineChannels[iChannelIndex];
1258    
1259                        #if CONFIG_DEVMODE
1260                        if (pSelectedChannel == pBegin) {
1261                            dmsg(1,("FATAL ERROR: voice stealing endless loop!\n"));
1262                            dmsg(1,("VoiceSpawnsLeft=%d.\n", VoiceSpawnsLeft));
1263                            dmsg(1,("Exiting.\n"));
1264                            exit(-1);
1265                        }
1266                        #endif // CONFIG_DEVMODE
1267                  }                  }
1268              }              }
1269    
1270              //FIXME: can be removed, just a sanity check for debugging              // jump point if a 'stealable' voice was found
1271              if (!itOldestVoice->IsActive()) dmsg(1,("gig::Engine: ERROR, tried to steal a voice which was not active !!!\n"));              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 794  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 835  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                    break;
1376                }
1377              case 7: { // volume              case 7: { // volume
1378                  //TODO: not sample accurate yet                  //TODO: not sample accurate yet
1379                  pEngineChannel->GlobalVolume = (float) itControlChangeEvent->Param.CC.Value / 127.0f;                  pEngineChannel->MidiVolume = VolumeCurve[itControlChangeEvent->Param.CC.Value];
1380                    pEngineChannel->bStatusChanged = true; // engine channel status has changed, so set notify flag
1381                  break;                  break;
1382              }              }
1383              case 10: { // panpot              case 10: { // panpot
1384                  //TODO: not sample accurate yet                  //TODO: not sample accurate yet
1385                  const int pan = (int) itControlChangeEvent->Param.CC.Value - 64;                  pEngineChannel->GlobalPanLeft  = PanCurve[128 - itControlChangeEvent->Param.CC.Value];
1386                  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;  
1387                  break;                  break;
1388              }              }
1389              case 64: { // sustain              case 64: { // sustain
1390                  if (itControlChangeEvent->Param.CC.Value >= 64 && !pEngineChannel->SustainPedal) {                  if (itControlChangeEvent->Param.CC.Value >= 64 && !pEngineChannel->SustainPedal) {
1391                      dmsg(4,("PEDAL DOWN\n"));                      dmsg(4,("DAMPER (RIGHT) PEDAL DOWN\n"));
1392                      pEngineChannel->SustainPedal = true;                      pEngineChannel->SustainPedal = true;
1393    
1394                        #if !CONFIG_PROCESS_MUTED_CHANNELS
1395                        if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
1396                        #endif
1397    
1398                      // cancel release process of voices if necessary                      // cancel release process of voices if necessary
1399                      RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();                      RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
1400                      if (iuiKey) {                      for (; iuiKey; ++iuiKey) {
1401                          itControlChangeEvent->Type = Event::type_cancel_release; // transform event type                          midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
1402                          while (iuiKey) {                          if (!pKey->KeyPressed) {
1403                              midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];                              RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
1404                              ++iuiKey;                              if (itNewEvent) {
1405                              if (!pKey->KeyPressed) {                                  *itNewEvent = *itControlChangeEvent; // copy event to the key's own event list
1406                                  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"));  
1407                              }                              }
1408                                else dmsg(1,("Event pool emtpy!\n"));
1409                          }                          }
1410                      }                      }
1411                  }                  }
1412                  if (itControlChangeEvent->Param.CC.Value < 64 && pEngineChannel->SustainPedal) {                  if (itControlChangeEvent->Param.CC.Value < 64 && pEngineChannel->SustainPedal) {
1413                      dmsg(4,("PEDAL UP\n"));                      dmsg(4,("DAMPER (RIGHT) PEDAL UP\n"));
1414                      pEngineChannel->SustainPedal = false;                      pEngineChannel->SustainPedal = false;
1415    
1416                        #if !CONFIG_PROCESS_MUTED_CHANNELS
1417                        if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
1418                        #endif
1419    
1420                      // release voices if their respective key is not pressed                      // release voices if their respective key is not pressed
1421                      RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();                      RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
1422                      if (iuiKey) {                      for (; iuiKey; ++iuiKey) {
1423                          itControlChangeEvent->Type = Event::type_release; // transform event type                          midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
1424                          while (iuiKey) {                          if (!pKey->KeyPressed && ShouldReleaseVoice(pEngineChannel, *iuiKey)) {
1425                              midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];                              RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
1426                              ++iuiKey;                              if (itNewEvent) {
1427                              if (!pKey->KeyPressed) {                                  *itNewEvent = *itControlChangeEvent; // copy event to the key's own event list
1428                                  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"));  
1429                              }                              }
1430                                else dmsg(1,("Event pool emtpy!\n"));
1431                          }                          }
1432                      }                      }
1433                  }                  }
1434                  break;                  break;
1435              }              }
1436          }              case 65: { // portamento on / off
1437                    KillAllVoices(pEngineChannel, itControlChangeEvent);
1438                    pEngineChannel->PortamentoMode = itControlChangeEvent->Param.CC.Value >= 64;
1439                    break;
1440                }
1441                case 66: { // sostenuto
1442                    if (itControlChangeEvent->Param.CC.Value >= 64 && !pEngineChannel->SostenutoPedal) {
1443                        dmsg(4,("SOSTENUTO (CENTER) PEDAL DOWN\n"));
1444                        pEngineChannel->SostenutoPedal = true;
1445    
1446                        #if !CONFIG_PROCESS_MUTED_CHANNELS
1447                        if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
1448                        #endif
1449    
1450          // update controller value in the engine's controller table                      SostenutoKeyCount = 0;
1451          pEngineChannel->ControllerTable[itControlChangeEvent->Param.CC.Controller] = itControlChangeEvent->Param.CC.Value;                      // Remeber the pressed keys
1452                        RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
1453                        for (; iuiKey; ++iuiKey) {
1454                            midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
1455                            if (pKey->KeyPressed && SostenutoKeyCount < 128) SostenutoKeys[SostenutoKeyCount++] = *iuiKey;
1456                        }
1457                    }
1458                    if (itControlChangeEvent->Param.CC.Value < 64 && pEngineChannel->SostenutoPedal) {
1459                        dmsg(4,("SOSTENUTO (CENTER) PEDAL UP\n"));
1460                        pEngineChannel->SostenutoPedal = false;
1461    
1462                        #if !CONFIG_PROCESS_MUTED_CHANNELS
1463                        if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
1464                        #endif
1465    
1466                        // release voices if the damper pedal is up and their respective key is not pressed
1467                        for (int i = 0; i < SostenutoKeyCount; i++) {
1468                            midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[SostenutoKeys[i]];
1469                            if (!pKey->KeyPressed && !pEngineChannel->SustainPedal) {
1470                                RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
1471                                if (itNewEvent) {
1472                                    *itNewEvent = *itControlChangeEvent; // copy event to the key's own event list
1473                                    itNewEvent->Type = Event::type_release; // transform event type
1474                                }
1475                                else dmsg(1,("Event pool emtpy!\n"));
1476                            }
1477                        }
1478                    }
1479                    break;
1480                }
1481                case 100: { // RPN controller LSB
1482                    pEngineChannel->SetMidiRpnControllerLsb(itControlChangeEvent->Param.CC.Value);
1483                    break;
1484                }
1485                case 101: { // RPN controller MSB
1486                    pEngineChannel->SetMidiRpnControllerMsb(itControlChangeEvent->Param.CC.Value);
1487                    break;
1488                }
1489    
1490    
1491                // Channel Mode Messages
1492    
1493                case 120: { // all sound off
1494                    KillAllVoices(pEngineChannel, itControlChangeEvent);
1495                    break;
1496                }
1497                case 121: { // reset all controllers
1498                    pEngineChannel->ResetControllers();
1499                    break;
1500                }
1501                case 123: { // all notes off
1502                    #if CONFIG_PROCESS_ALL_NOTES_OFF
1503                    ReleaseAllVoices(pEngineChannel, itControlChangeEvent);
1504                    #endif // CONFIG_PROCESS_ALL_NOTES_OFF
1505                    break;
1506                }
1507                case 126: { // mono mode on
1508                    KillAllVoices(pEngineChannel, itControlChangeEvent);
1509                    pEngineChannel->SoloMode = true;
1510                    break;
1511                }
1512                case 127: { // poly mode on
1513                    KillAllVoices(pEngineChannel, itControlChangeEvent);
1514                    pEngineChannel->SoloMode = false;
1515                    break;
1516                }
1517            }
1518    
1519          // move event from the unsorted event list to the control change event list          // handle FX send controllers
1520          itControlChangeEvent.moveToEndOf(pCCEvents);          if (!pEngineChannel->fxSends.empty()) {
1521                for (int iFxSend = 0; iFxSend < pEngineChannel->GetFxSendCount(); iFxSend++) {
1522                    FxSend* pFxSend = pEngineChannel->GetFxSend(iFxSend);
1523                    if (pFxSend->MidiController() == itControlChangeEvent->Param.CC.Controller)
1524                        pFxSend->SetLevel(itControlChangeEvent->Param.CC.Value);
1525                }
1526            }
1527      }      }
1528    
1529      /**      /**
# Line 904  namespace LinuxSampler { namespace gig { Line 1532  namespace LinuxSampler { namespace gig {
1532       *  @param itSysexEvent - sysex data size and time stamp of the sysex event       *  @param itSysexEvent - sysex data size and time stamp of the sysex event
1533       */       */
1534      void Engine::ProcessSysex(Pool<Event>::Iterator& itSysexEvent) {      void Engine::ProcessSysex(Pool<Event>::Iterator& itSysexEvent) {
1535          RingBuffer<uint8_t>::NonVolatileReader reader = pSysexBuffer->get_non_volatile_reader();          RingBuffer<uint8_t,false>::NonVolatileReader reader = pSysexBuffer->get_non_volatile_reader();
1536    
1537          uint8_t exclusive_status, id;          uint8_t exclusive_status, id;
1538          if (!reader.pop(&exclusive_status)) goto free_sysex_data;          if (!reader.pop(&exclusive_status)) goto free_sysex_data;
# Line 913  namespace LinuxSampler { namespace gig { Line 1541  namespace LinuxSampler { namespace gig {
1541    
1542          switch (id) {          switch (id) {
1543              case 0x41: { // Roland              case 0x41: { // Roland
1544                    dmsg(3,("Roland Sysex\n"));
1545                  uint8_t device_id, model_id, cmd_id;                  uint8_t device_id, model_id, cmd_id;
1546                  if (!reader.pop(&device_id)) goto free_sysex_data;                  if (!reader.pop(&device_id)) goto free_sysex_data;
1547                  if (!reader.pop(&model_id))  goto free_sysex_data;                  if (!reader.pop(&model_id))  goto free_sysex_data;
# Line 922  namespace LinuxSampler { namespace gig { Line 1551  namespace LinuxSampler { namespace gig {
1551    
1552                  // command address                  // command address
1553                  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)
1554                  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
1555                  if (reader.read(&addr[0], 3) != 3) goto free_sysex_data;                  if (reader.read(&addr[0], 3) != 3) goto free_sysex_data;
1556                  if (addr[0] == 0x40 && addr[1] == 0x00) { // System Parameters                  if (addr[0] == 0x40 && addr[1] == 0x00) { // System Parameters
1557                        dmsg(3,("\tSystem Parameter\n"));
1558                  }                  }
1559                  else if (addr[0] == 0x40 && addr[1] == 0x01) { // Common Parameters                  else if (addr[0] == 0x40 && addr[1] == 0x01) { // Common Parameters
1560                        dmsg(3,("\tCommon Parameter\n"));
1561                  }                  }
1562                  else if (addr[0] == 0x40 && (addr[1] & 0xf0) == 0x10) { // Part Parameters (1)                  else if (addr[0] == 0x40 && (addr[1] & 0xf0) == 0x10) { // Part Parameters (1)
1563                      switch (addr[3]) {                      dmsg(3,("\tPart Parameter\n"));
1564                        switch (addr[2]) {
1565                          case 0x40: { // scale tuning                          case 0x40: { // scale tuning
1566                                dmsg(3,("\t\tScale Tuning\n"));
1567                              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
1568                              if (reader.read(&scale_tunes[0], 12) != 12) goto free_sysex_data;                              if (reader.read(&scale_tunes[0], 12) != 12) goto free_sysex_data;
1569                              uint8_t checksum;                              uint8_t checksum;
1570                              if (!reader.pop(&checksum))                      goto free_sysex_data;                              if (!reader.pop(&checksum)) goto free_sysex_data;
1571                              if (GSCheckSum(checksum_reader, 12) != checksum) goto free_sysex_data;                              #if CONFIG_ASSERT_GS_SYSEX_CHECKSUM
1572                                if (GSCheckSum(checksum_reader, 12)) goto free_sysex_data;
1573                                #endif // CONFIG_ASSERT_GS_SYSEX_CHECKSUM
1574                              for (int i = 0; i < 12; i++) scale_tunes[i] -= 64;                              for (int i = 0; i < 12; i++) scale_tunes[i] -= 64;
1575                              AdjustScale((int8_t*) scale_tunes);                              AdjustScale((int8_t*) scale_tunes);
1576                                dmsg(3,("\t\t\tNew scale applied.\n"));
1577                              break;                              break;
1578                          }                          }
1579                      }                      }
# Line 962  namespace LinuxSampler { namespace gig { Line 1598  namespace LinuxSampler { namespace gig {
1598       *                     question       *                     question
1599       * @param DataSize   - size of the GS message data (in bytes)       * @param DataSize   - size of the GS message data (in bytes)
1600       */       */
1601      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) {
1602          RingBuffer<uint8_t>::NonVolatileReader reader = AddrReader;          RingBuffer<uint8_t,false>::NonVolatileReader reader = AddrReader;
1603          uint bytes = 3 /*addr*/ + DataSize;          uint bytes = 3 /*addr*/ + DataSize;
1604          uint8_t addr_and_data[bytes];          uint8_t addr_and_data[bytes];
1605          reader.read(&addr_and_data[0], bytes);          reader.read(&addr_and_data[0], bytes);
# Line 982  namespace LinuxSampler { namespace gig { Line 1618  namespace LinuxSampler { namespace gig {
1618      }      }
1619    
1620      /**      /**
1621       * Initialize the parameter sequence for the modulation destination given by       * Releases all voices on an engine channel. All voices will go into
1622       * by 'dst' with the constant value given by val.       * the release stage and thus it might take some time (e.g. dependant to
1623         * their envelope release time) until they actually die.
1624         *
1625         * @param pEngineChannel - engine channel on which all voices should be released
1626         * @param itReleaseEvent - event which caused this releasing of all voices
1627       */       */
1628      void Engine::ResetSynthesisParameters(Event::destination_t dst, float val) {      void Engine::ReleaseAllVoices(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itReleaseEvent) {
1629          int maxsamples = pAudioOutputDevice->MaxSamplesPerCycle();          RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
1630          float* m = &pSynthesisParameters[dst][0];          while (iuiKey) {
1631          for (int i = 0; i < maxsamples; i += 4) {              midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
1632             m[i]   = val;              ++iuiKey;
1633             m[i+1] = val;              // append a 'release' event to the key's own event list
1634             m[i+2] = val;              RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
1635             m[i+3] = val;              if (itNewEvent) {
1636                    *itNewEvent = *itReleaseEvent; // copy original event (to the key's event list)
1637                    itNewEvent->Type = Event::type_release; // transform event type
1638                }
1639                else dmsg(1,("Event pool emtpy!\n"));
1640          }          }
1641      }      }
1642    
1643        /**
1644         * Kills all voices on an engine channel as soon as possible. Voices
1645         * won't get into release state, their volume level will be ramped down
1646         * as fast as possible.
1647         *
1648         * @param pEngineChannel - engine channel on which all voices should be killed
1649         * @param itKillEvent    - event which caused this killing of all voices
1650         */
1651        void Engine::KillAllVoices(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itKillEvent) {
1652            RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
1653            RTList<uint>::Iterator end    = pEngineChannel->pActiveKeys->end();
1654            while (iuiKey != end) { // iterate through all active keys
1655                midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
1656                ++iuiKey;
1657                RTList<Voice>::Iterator itVoice     = pKey->pActiveVoices->first();
1658                RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();
1659                for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
1660                    itVoice->Kill(itKillEvent);
1661                    --VoiceSpawnsLeft; //FIXME: just a temporary workaround, we should check the cause in StealVoice() instead
1662                }
1663            }
1664        }
1665    
1666        /**
1667         * Determines whether the specified voice should be released.
1668         *
1669         * @param pEngineChannel - The engine channel on which the voice should be checked
1670         * @param Key - The key number
1671         * @returns true if the specified should be released, false otherwise.
1672         */
1673        bool Engine::ShouldReleaseVoice(EngineChannel* pEngineChannel, int Key) {
1674            if (pEngineChannel->SustainPedal) return false;
1675    
1676            if (pEngineChannel->SostenutoPedal) {
1677                for (int i = 0; i < SostenutoKeyCount; i++)
1678                    if (Key == SostenutoKeys[i]) return false;
1679            }
1680    
1681            return true;
1682        }
1683    
1684      uint Engine::VoiceCount() {      uint Engine::VoiceCount() {
1685          return ActiveVoiceCount;          return ActiveVoiceCount;
1686      }      }
# Line 1025  namespace LinuxSampler { namespace gig { Line 1710  namespace LinuxSampler { namespace gig {
1710      }      }
1711    
1712      String Engine::EngineName() {      String Engine::EngineName() {
1713          return "GigEngine";          return LS_GIG_ENGINE_NAME;
1714      }      }
1715    
1716      String Engine::Description() {      String Engine::Description() {
# Line 1033  namespace LinuxSampler { namespace gig { Line 1718  namespace LinuxSampler { namespace gig {
1718      }      }
1719    
1720      String Engine::Version() {      String Engine::Version() {
1721          String s = "$Revision: 1.30 $";          String s = "$Revision: 1.74 $";
1722          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
1723      }      }
1724    
1725        InstrumentManager* Engine::GetInstrumentManager() {
1726            return &instruments;
1727        }
1728    
1729        // static constant initializers
1730        const float* Engine::VolumeCurve(InitVolumeCurve());
1731        const float* Engine::PanCurve(InitPanCurve());
1732        const float* Engine::CrossfadeCurve(InitCrossfadeCurve());
1733    
1734        float* Engine::InitVolumeCurve() {
1735            // line-segment approximation
1736            const float segments[] = {
1737                0, 0, 2, 0.0046, 16, 0.016, 31, 0.051, 45, 0.115, 54.5, 0.2,
1738                64.5, 0.39, 74, 0.74, 92, 1.03, 114, 1.94, 119.2, 2.2, 127, 2.2
1739            };
1740            return InitCurve(segments);
1741        }
1742    
1743        float* Engine::InitPanCurve() {
1744            // line-segment approximation
1745            const float segments[] = {
1746                0, 0, 1, 0,
1747                2, 0.05, 31.5, 0.7, 51, 0.851, 74.5, 1.12,
1748                127, 1.41, 128, 1.41
1749            };
1750            return InitCurve(segments, 129);
1751        }
1752    
1753        float* Engine::InitCrossfadeCurve() {
1754            // line-segment approximation
1755            const float segments[] = {
1756                0, 0, 1, 0.03, 10, 0.1, 51, 0.58, 127, 1
1757            };
1758            return InitCurve(segments);
1759        }
1760    
1761        float* Engine::InitCurve(const float* segments, int size) {
1762            float* y = new float[size];
1763            for (int x = 0 ; x < size ; x++) {
1764                if (x > segments[2]) segments += 2;
1765                y[x] = segments[1] + (x - segments[0]) *
1766                    (segments[3] - segments[1]) / (segments[2] - segments[0]);
1767            }
1768            return y;
1769        }
1770    
1771        /**
1772         * Changes the instrument for an engine channel.
1773         *
1774         * @param pEngineChannel - engine channel on which the instrument
1775         *                         should be changed
1776         * @param pInstrument - new instrument
1777         * @returns a list of dimension regions from the old instrument
1778         *          that are still in use
1779         */
1780        ::gig::DimensionRegion** Engine::ChangeInstrument(EngineChannel* pEngineChannel, ::gig::Instrument* pInstrument) {
1781            instrument_change_command_t command;
1782            command.pEngineChannel = pEngineChannel;
1783            command.pInstrument = pInstrument;
1784            InstrumentChangeQueue->push(&command);
1785    
1786            // wait for the audio thread to confirm that the instrument
1787            // change has been done
1788            instrument_change_reply_t reply;
1789            while (InstrumentChangeReplyQueue->pop(&reply) == 0) {
1790                usleep(10000);
1791            }
1792            return pDimRegionsInUse;
1793        }
1794    
1795  }} // namespace LinuxSampler::gig  }} // namespace LinuxSampler::gig

Legend:
Removed from v.438  
changed lines
  Added in v.1043

  ViewVC Help
Powered by ViewVC