/[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 659 by schoenebeck, Thu Jun 16 21:35:30 2005 UTC revision 1041 by schoenebeck, Wed Feb 7 17:45:19 2007 UTC
# Line 2  Line 2 
2   *                                                                         *   *                                                                         *
3   *   LinuxSampler - modular, streaming capable sampler                     *   *   LinuxSampler - modular, streaming capable sampler                     *
4   *                                                                         *   *                                                                         *
5   *   Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck   *   *   Copyright (C) 2003,2004 by Benno Senoner and Christian Schoenebeck   *
6   *   Copyright (C) 2005 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 103  namespace LinuxSampler { namespace gig { Line 102  namespace LinuxSampler { namespace gig {
102          pAudioOutputDevice = NULL;          pAudioOutputDevice = NULL;
103          pDiskThread        = NULL;          pDiskThread        = NULL;
104          pEventGenerator    = NULL;          pEventGenerator    = NULL;
105          pSysexBuffer       = new RingBuffer<uint8_t>(CONFIG_SYSEX_BUFFER_SIZE, 0);          pSysexBuffer       = new RingBuffer<uint8_t,false>(CONFIG_SYSEX_BUFFER_SIZE, 0);
106          pEventQueue        = new RingBuffer<Event>(CONFIG_MAX_EVENTS_PER_FRAGMENT, 0);          pEventQueue        = new RingBuffer<Event,false>(CONFIG_MAX_EVENTS_PER_FRAGMENT, 0);
107          pEventPool         = new Pool<Event>(CONFIG_MAX_EVENTS_PER_FRAGMENT);          pEventPool         = new Pool<Event>(CONFIG_MAX_EVENTS_PER_FRAGMENT);
108          pVoicePool         = new Pool<Voice>(CONFIG_MAX_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          pGlobalEvents      = new RTList<Event>(pEventPool);          pGlobalEvents      = new RTList<Event>(pEventPool);
112            InstrumentChangeQueue      = new RingBuffer<instrument_change_command_t,false>(1, 0);
113            InstrumentChangeReplyQueue = new RingBuffer<instrument_change_reply_t,false>(1, 0);
114    
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();          ResetScaleTuning();
122      }      }
# Line 126  namespace LinuxSampler { namespace gig { Line 125  namespace LinuxSampler { namespace gig {
125       * Destructor       * 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();
# Line 139  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 178  namespace LinuxSampler { namespace gig { Line 175  namespace LinuxSampler { namespace gig {
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    
# Line 203  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      /**      /**
# Line 232  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();
# Line 240  namespace LinuxSampler { namespace gig { Line 245  namespace LinuxSampler { namespace gig {
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) * CONFIG_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("CONFIG_EG_MIN_RELEASE_TIME 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 250  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() << CONFIG_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 266  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 316  namespace LinuxSampler { namespace gig { Line 316  namespace LinuxSampler { namespace gig {
316       *                  current audio cycle       *                  current audio cycle
317       */       */
318      void Engine::ImportEvents(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 339  namespace LinuxSampler { namespace gig { Line 339  namespace LinuxSampler { namespace gig {
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 360  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            // We only allow a maximum of CONFIG_MAX_VOICES voices to be spawned
365            // in each audio fragment. All subsequent request for spawning new
366            // voices in the same audio fragment will be ignored.
367            VoiceSpawnsLeft = CONFIG_MAX_VOICES;
368    
369          // get all events from the engine's global input event queue which belong to the current fragment          // 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(Samples);          ImportEvents(Samples);
# Line 378  namespace LinuxSampler { namespace gig { Line 384  namespace LinuxSampler { namespace gig {
384              }              }
385          }          }
386    
         // We only allow a maximum of CONFIG_MAX_VOICES voices to be stolen  
         // in each audio fragment. All subsequent request for spawning new  
         // voices in the same audio fragment will be ignored.  
         VoiceTheftsLeft = CONFIG_MAX_VOICES;  
   
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            // handle instrument change commands
391            instrument_change_command_t command;
392            if (InstrumentChangeQueue->pop(&command) > 0) {
393                EngineChannel* pEngineChannel = command.pEngineChannel;
394                pEngineChannel->pInstrument = command.pInstrument;
395    
396                // iterate through all active voices and mark their
397                // dimension regions as "in use". The instrument resource
398                // manager may delete all of the instrument except the
399                // dimension regions and samples that are in use.
400                int i = 0;
401                RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
402                RTList<uint>::Iterator end    = pEngineChannel->pActiveKeys->end();
403                while (iuiKey != end) { // iterate through all active keys
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          // handle events on all engine channels
424          for (int i = 0; i < engineChannels.size(); i++) {          for (int i = 0; i < engineChannels.size(); i++) {
             if (!engineChannels[i]->pInstrument) continue; // ignore if no instrument loaded  
425              ProcessEvents(engineChannels[i], Samples);              ProcessEvents(engineChannels[i], Samples);
426          }          }
427    
428          // render all 'normal', active voices on all engine channels          // render all 'normal', active voices on all engine channels
429          for (int i = 0; i < engineChannels.size(); i++) {          for (int i = 0; i < engineChannels.size(); i++) {
             if (!engineChannels[i]->pInstrument) continue; // ignore if no instrument loaded  
430              RenderActiveVoices(engineChannels[i], Samples);              RenderActiveVoices(engineChannels[i], Samples);
431          }          }
432    
433          // now that all ordinary voices on ALL engine channels are rendered, render new stolen voices          // now that all ordinary voices on ALL engine channels are rendered, render new stolen voices
434          RenderStolenVoices(Samples);          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          // handle cleanup on all engine channels for the next audio fragment
443          for (int i = 0; i < engineChannels.size(); i++) {          for (int i = 0; i < engineChannels.size(); i++) {
             if (!engineChannels[i]->pInstrument) continue; // ignore if no instrument loaded  
444              PostProcess(engineChannels[i]);              PostProcess(engineChannels[i]);
445          }          }
446    
# Line 482  namespace LinuxSampler { namespace gig { Line 518  namespace LinuxSampler { namespace gig {
518       *                         this audio fragment cycle       *                         this audio fragment cycle
519       */       */
520      void Engine::RenderActiveVoices(EngineChannel* pEngineChannel, uint Samples) {      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<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();          RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
526          RTList<uint>::Iterator end    = pEngineChannel->pActiveKeys->end();          RTList<uint>::Iterator end    = pEngineChannel->pActiveKeys->end();
527          while (iuiKey != end) { // iterate through all active keys          while (iuiKey != end) { // iterate through all active keys
# Line 519  namespace LinuxSampler { namespace gig { Line 559  namespace LinuxSampler { namespace gig {
559          RTList<Event>::Iterator end               = pVoiceStealingQueue->end();          RTList<Event>::Iterator end               = pVoiceStealingQueue->end();
560          for (; itVoiceStealEvent != end; ++itVoiceStealEvent) {          for (; itVoiceStealEvent != end; ++itVoiceStealEvent) {
561              EngineChannel* pEngineChannel = (EngineChannel*) itVoiceStealEvent->pEngineChannel;              EngineChannel* pEngineChannel = (EngineChannel*) itVoiceStealEvent->pEngineChannel;
562                if (!pEngineChannel->pInstrument) continue; // ignore if no instrument loaded
563              Pool<Voice>::Iterator itNewVoice =              Pool<Voice>::Iterator itNewVoice =
564                  LaunchVoice(pEngineChannel, itVoiceStealEvent, itVoiceStealEvent->Param.Note.Layer, itVoiceStealEvent->Param.Note.ReleaseTrigger, false);                  LaunchVoice(pEngineChannel, itVoiceStealEvent, itVoiceStealEvent->Param.Note.Layer, itVoiceStealEvent->Param.Note.ReleaseTrigger, false, false);
565              if (itNewVoice) {              if (itNewVoice) {
566                  itNewVoice->Render(Samples);                  itNewVoice->Render(Samples);
567                  if (itNewVoice->IsActive()) ActiveVoiceCountTemp++; // still active                  if (itNewVoice->IsActive()) ActiveVoiceCountTemp++; // still active
# Line 538  namespace LinuxSampler { namespace gig { Line 579  namespace LinuxSampler { namespace gig {
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                AudioChannel* pDstL = pAudioOutputDevice->Channel(pEngineChannel->AudioDeviceChannelLeft);
598                AudioChannel* pDstR = pAudioOutputDevice->Channel(pEngineChannel->AudioDeviceChannelRight);
599                pEngineChannel->pChannelLeft->MixTo(pDstL, Samples);
600                pEngineChannel->pChannelRight->MixTo(pDstR, Samples);
601            }
602            // route FX send signal
603            {
604                for (int iFxSend = 0; iFxSend < pEngineChannel->GetFxSendCount(); iFxSend++) {
605                    FxSend* pFxSend = pEngineChannel->GetFxSend(iFxSend);
606                    // left channel
607                    const int iDstL = pFxSend->DestinationChannel(0);
608                    if (iDstL < 0) {
609                        dmsg(1,("Engine::RouteAudio() Error: invalid FX send (L) destination channel"));
610                    } else {
611                        AudioChannel* pDstL = pAudioOutputDevice->Channel(iDstL);
612                        if (!pDstL) {
613                            dmsg(1,("Engine::RouteAudio() Error: invalid FX send (L) destination channel"));
614                        } else pEngineChannel->pChannelLeft->MixTo(pDstL, Samples, pFxSend->Level());
615                    }
616                    // right channel
617                    const int iDstR = pFxSend->DestinationChannel(1);
618                    if (iDstR < 0) {
619                        dmsg(1,("Engine::RouteAudio() Error: invalid FX send (R) destination channel"));
620                    } else {
621                        AudioChannel* pDstR = pAudioOutputDevice->Channel(iDstR);
622                        if (!pDstR) {
623                            dmsg(1,("Engine::RouteAudio() Error: invalid FX send (R) destination channel"));
624                        } else pEngineChannel->pChannelRight->MixTo(pDstR, Samples, pFxSend->Level());
625                    }
626                }
627            }
628            // reset buffers with silence (zero out) for the next audio cycle
629            pEngineChannel->pChannelLeft->Clear();
630            pEngineChannel->pChannelRight->Clear();
631        }
632    
633        /**
634       * Free all keys which have turned inactive in this audio fragment, from       * 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       * the list of active keys and clear all event lists on that engine
636       * channel.       * channel.
# Line 610  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   = itNoteOnEvent->Param.Note.Velocity;          pKey->Velocity   = itNoteOnEventOnKeyList->Param.Note.Velocity;
756          pKey->NoteOnTime = FrameTime + itNoteOnEvent->FragmentPos(); // will be used to calculate note length          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    
         // move note on event to the key's own event list  
         RTList<Event>::Iterator itNoteOnEventOnKeyList = itNoteOnEvent.moveToEndOf(pKey->pEvents);  
   
768          // allocate and trigger new voice(s) for the key          // allocate and trigger new voice(s) for the key
769          {          {
770              // first, get total amount of required voices (dependant on amount of layers)              // first, get total amount of required voices (dependant on amount of layers)
# Line 648  namespace LinuxSampler { namespace gig { Line 773  namespace LinuxSampler { namespace gig {
773                  int voicesRequired = pRegion->Layers;                  int voicesRequired = pRegion->Layers;
774                  // now launch the required amount of voices                  // now launch the required amount of voices
775                  for (int i = 0; i < voicesRequired; i++)                  for (int i = 0; i < voicesRequired; i++)
776                      LaunchVoice(pEngineChannel, itNoteOnEventOnKeyList, i, false, true);                      LaunchVoice(pEngineChannel, itNoteOnEventOnKeyList, i, false, true, true);
777              }              }
778          }          }
779    
# Line 656  namespace LinuxSampler { namespace gig { Line 781  namespace LinuxSampler { namespace gig {
781          if (!pKey->Active && !pKey->VoiceTheftsQueued)          if (!pKey->Active && !pKey->VoiceTheftsQueued)
782              pKey->pEvents->free(itNoteOnEventOnKeyList);              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 669  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            //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            const int iKey = itNoteOffEvent->Param.Note.Key;
806            midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[iKey];
807          pKey->KeyPressed = false; // the MIDI key was now released          pKey->KeyPressed = false; // the MIDI key was now released
808    
809          // release voices on this key if needed          // move event to the key's own event list
810          if (pKey->Active && !pEngineChannel->SustainPedal) {          RTList<Event>::Iterator itNoteOffEventOnKeyList = itNoteOffEvent.moveToEndOf(pKey->pEvents);
811              itNoteOffEvent->Type = Event::type_release; // transform event type  
812            bool bShouldRelease = pKey->Active && ShouldReleaseVoice(pEngineChannel, itNoteOffEventOnKeyList->Param.Note.Key);
813    
814              // move event to the key's own event list          // in case Solo Mode is enabled, kill all voices on this key and respawn a voice on the highest pressed key (if any)
815              RTList<Event>::Iterator itNoteOffEventOnKeyList = itNoteOffEvent.moveToEndOf(pKey->pEvents);          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              // spawn release triggered voice(s) if needed
878              if (pKey->ReleaseTrigger) {              if (pKey->ReleaseTrigger && pEngineChannel->pInstrument) {
879                  // first, get total amount of required voices (dependant on amount of layers)                  // first, get total amount of required voices (dependant on amount of layers)
880                  ::gig::Region* pRegion = pEngineChannel->pInstrument->GetRegion(itNoteOffEventOnKeyList->Param.Note.Key);                  ::gig::Region* pRegion = pEngineChannel->pInstrument->GetRegion(itNoteOffEventOnKeyList->Param.Note.Key);
881                  if (pRegion) {                  if (pRegion) {
# Line 692  namespace LinuxSampler { namespace gig { Line 886  namespace LinuxSampler { namespace gig {
886    
887                      // now launch the required amount of voices                      // now launch the required amount of voices
888                      for (int i = 0; i < voicesRequired; i++)                      for (int i = 0; i < voicesRequired; i++)
889                          LaunchVoice(pEngineChannel, itNoteOffEventOnKeyList, i, true, false); //FIXME: for the moment we don't perform voice stealing for release triggered samples                          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;                  pKey->ReleaseTrigger = false;
892              }              }
   
             // if neither a voice was spawned or postponed then remove note off event from key again  
             if (!pKey->Active && !pKey->VoiceTheftsQueued)  
                 pKey->pEvents->free(itNoteOffEventOnKeyList);  
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(pEngineChannel->pSynthesisEvents[Event::destination_vco]);  
910      }      }
911    
912      /**      /**
# Line 729  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 800  namespace LinuxSampler { namespace gig { Line 1134  namespace LinuxSampler { namespace gig {
1134       *  @returns 0 on success, a value < 0 if no active voice could be picked for voice stealing       *  @returns 0 on success, a value < 0 if no active voice could be picked for voice stealing
1135       */       */
1136      int Engine::StealVoice(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent) {      int Engine::StealVoice(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent) {
1137          if (!VoiceTheftsLeft) {          if (VoiceSpawnsLeft <= 0) {
1138              dmsg(1,("Max. voice thefts per audio fragment reached (you may raise CONFIG_MAX_VOICES).\n"));              dmsg(1,("Max. voice thefts per audio fragment reached (you may raise CONFIG_MAX_VOICES).\n"));
1139              return -1;              return -1;
1140          }          }
# Line 819  namespace LinuxSampler { namespace gig { Line 1153  namespace LinuxSampler { namespace gig {
1153                      midi_key_info_t* pSelectedKey = &pEngineChannel->pMIDIKeyInfo[itNoteOnEvent->Param.Note.Key];                      midi_key_info_t* pSelectedKey = &pEngineChannel->pMIDIKeyInfo[itNoteOnEvent->Param.Note.Key];
1154                      itSelectedVoice = pSelectedKey->pActiveVoices->first();                      itSelectedVoice = pSelectedKey->pActiveVoices->first();
1155                      // proceed iterating if voice was created in this fragment cycle                      // proceed iterating if voice was created in this fragment cycle
1156                      while (itSelectedVoice && !itSelectedVoice->hasRendered()) ++itSelectedVoice;                      while (itSelectedVoice && !itSelectedVoice->IsStealable()) ++itSelectedVoice;
1157                      // if we haven't found a voice then proceed with algorithm 'oldestkey'                      // if we haven't found a voice then proceed with algorithm 'oldestkey'
1158                      if (itSelectedVoice && itSelectedVoice->hasRendered()) break;                      if (itSelectedVoice && itSelectedVoice->IsStealable()) break;
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
# Line 833  namespace LinuxSampler { namespace gig { Line 1167  namespace LinuxSampler { namespace gig {
1167                          itSelectedVoice = this->itLastStolenVoice;                          itSelectedVoice = this->itLastStolenVoice;
1168                          do {                          do {
1169                              ++itSelectedVoice;                              ++itSelectedVoice;
1170                          } while (itSelectedVoice && !itSelectedVoice->hasRendered()); // proceed iterating if voice was created in this fragment cycle                          } while (itSelectedVoice && !itSelectedVoice->IsStealable()); // proceed iterating if voice was created in this fragment cycle
1171                          // found a "stealable" voice ?                          // found a "stealable" voice ?
1172                          if (itSelectedVoice && itSelectedVoice->hasRendered()) {                          if (itSelectedVoice && itSelectedVoice->IsStealable()) {
1173                              // remember which voice we stole, so we can simply proceed on next voice stealing                              // remember which voice we stole, so we can simply proceed on next voice stealing
1174                              this->itLastStolenVoice = itSelectedVoice;                              this->itLastStolenVoice = itSelectedVoice;
1175                              break; // selection succeeded                              break; // selection succeeded
# Line 847  namespace LinuxSampler { namespace gig { Line 1181  namespace LinuxSampler { namespace gig {
1181                          midi_key_info_t* pSelectedKey = &pEngineChannel->pMIDIKeyInfo[*iuiSelectedKey];                          midi_key_info_t* pSelectedKey = &pEngineChannel->pMIDIKeyInfo[*iuiSelectedKey];
1182                          itSelectedVoice = pSelectedKey->pActiveVoices->first();                          itSelectedVoice = pSelectedKey->pActiveVoices->first();
1183                          // proceed iterating if voice was created in this fragment cycle                          // proceed iterating if voice was created in this fragment cycle
1184                          while (itSelectedVoice && !itSelectedVoice->hasRendered()) ++itSelectedVoice;                          while (itSelectedVoice && !itSelectedVoice->IsStealable()) ++itSelectedVoice;
1185                          // found a "stealable" voice ?                          // found a "stealable" voice ?
1186                          if (itSelectedVoice && itSelectedVoice->hasRendered()) {                          if (itSelectedVoice && itSelectedVoice->IsStealable()) {
1187                              // remember which voice on which key we stole, so we can simply proceed on next voice stealing                              // remember which voice on which key we stole, so we can simply proceed on next voice stealing
1188                              this->iuiLastStolenKey  = iuiSelectedKey;                              this->iuiLastStolenKey  = iuiSelectedKey;
1189                              this->itLastStolenVoice = itSelectedVoice;                              this->itLastStolenVoice = itSelectedVoice;
# Line 871  namespace LinuxSampler { namespace gig { Line 1205  namespace LinuxSampler { namespace gig {
1205              // if we couldn't steal a voice from the same engine channel then              // 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              // steal oldest voice on the oldest key from any other engine channel
1207              // (the smaller engine channel number, the higher priority)              // (the smaller engine channel number, the higher priority)
1208              if (!itSelectedVoice || !itSelectedVoice->hasRendered()) {              if (!itSelectedVoice || !itSelectedVoice->IsStealable()) {
1209                  EngineChannel* pSelectedChannel;                  EngineChannel* pSelectedChannel;
1210                  int            iChannelIndex;                  int            iChannelIndex;
1211                  // select engine channel                  // select engine channel
# Line 882  namespace LinuxSampler { namespace gig { Line 1216  namespace LinuxSampler { namespace gig {
1216                      iChannelIndex    = (pEngineChannel->iEngineIndexSelf + 1) % engineChannels.size();                      iChannelIndex    = (pEngineChannel->iEngineIndexSelf + 1) % engineChannels.size();
1217                      pSelectedChannel = engineChannels[iChannelIndex];                      pSelectedChannel = engineChannels[iChannelIndex];
1218                  }                  }
1219                  // iterate through engine channels  
1220                  while (true) {                  // if we already stole in this fragment, try to proceed on same key
1221                      // if we already stole in this fragment, try to proceed on same key                  if (this->itLastStolenVoiceGlobally) {
1222                      if (this->itLastStolenVoiceGlobally) {                      itSelectedVoice = this->itLastStolenVoiceGlobally;
1223                          itSelectedVoice = this->itLastStolenVoiceGlobally;                      do {
1224                          do {                          ++itSelectedVoice;
1225                              ++itSelectedVoice;                      } while (itSelectedVoice && !itSelectedVoice->IsStealable()); // proceed iterating if voice was created in this fragment cycle
1226                          } while (itSelectedVoice && !itSelectedVoice->hasRendered()); // proceed iterating if voice was created in this fragment cycle                  }
1227                          // break if selection succeeded  
1228                          if (itSelectedVoice && itSelectedVoice->hasRendered()) {                  #if CONFIG_DEVMODE
1229                              // remember which voice we stole, so we can simply proceed on next voice stealing                  EngineChannel* pBegin = pSelectedChannel; // to detect endless loop
1230                              this->itLastStolenVoiceGlobally = itSelectedVoice;                  #endif // CONFIG_DEVMODE
1231                              break; // selection succeeded  
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                      // get (next) oldest key
1238                      RTList<uint>::Iterator iuiSelectedKey = (this->iuiLastStolenKey) ? ++this->iuiLastStolenKey : pSelectedChannel->pActiveKeys->first();                      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) {                      while (iuiSelectedKey) {
1241                          midi_key_info_t* pSelectedKey = &pEngineChannel->pMIDIKeyInfo[*iuiSelectedKey];                          midi_key_info_t* pSelectedKey = &pSelectedChannel->pMIDIKeyInfo[*iuiSelectedKey];
1242                          itSelectedVoice = pSelectedKey->pActiveVoices->first();                          itSelectedVoice = pSelectedKey->pActiveVoices->first();
1243                          // proceed iterating if voice was created in this fragment cycle                          // proceed iterating if voice was created in this fragment cycle
1244                          while (itSelectedVoice && !itSelectedVoice->hasRendered()) ++itSelectedVoice;                          while (itSelectedVoice && !itSelectedVoice->IsStealable()) ++itSelectedVoice;
1245                          // found a "stealable" voice ?                          // found a "stealable" voice ?
1246                          if (itSelectedVoice && itSelectedVoice->hasRendered()) {                          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                              // 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;                              this->iuiLastStolenKeyGlobally  = iuiSelectedKey;
1249                              this->itLastStolenVoiceGlobally = itSelectedVoice;                              this->itLastStolenVoiceGlobally = itSelectedVoice;
1250                              this->pLastStolenChannel        = pSelectedChannel;                              this->pLastStolenChannel        = pSelectedChannel;
1251                              break; // selection succeeded                              goto stealable_voice_found; // selection succeeded
1252                          }                          }
1253                          ++iuiSelectedKey; // get next key on current engine channel                          ++iuiSelectedKey; // get next key on current engine channel
1254                      }                      }
1255                      // get next engine channel                      // get next engine channel
1256                      iChannelIndex    = (iChannelIndex + 1) % engineChannels.size();                      iChannelIndex    = (iChannelIndex + 1) % engineChannels.size();
1257                      pSelectedChannel = engineChannels[iChannelIndex];                      pSelectedChannel = engineChannels[iChannelIndex];
1258    
1259                        #if CONFIG_DEVMODE
1260                        if (pSelectedChannel == pBegin) {
1261                            dmsg(1,("FATAL ERROR: voice stealing endless loop!\n"));
1262                            dmsg(1,("VoiceSpawnsLeft=%d.\n", VoiceSpawnsLeft));
1263                            dmsg(1,("Exiting.\n"));
1264                            exit(-1);
1265                        }
1266                        #endif // CONFIG_DEVMODE
1267                  }                  }
1268              }              }
1269    
1270                // jump point if a 'stealable' voice was found
1271                stealable_voice_found:
1272    
1273              #if CONFIG_DEVMODE              #if CONFIG_DEVMODE
1274              if (!itSelectedVoice->IsActive()) {              if (!itSelectedVoice->IsActive()) {
1275                  dmsg(1,("gig::Engine: ERROR, tried to steal a voice which was not active !!!\n"));                  dmsg(1,("gig::Engine: ERROR, tried to steal a voice which was not active !!!\n"));
# Line 930  namespace LinuxSampler { namespace gig { Line 1280  namespace LinuxSampler { namespace gig {
1280              // now kill the selected voice              // now kill the selected voice
1281              itSelectedVoice->Kill(itNoteOnEvent);              itSelectedVoice->Kill(itNoteOnEvent);
1282    
1283              --VoiceTheftsLeft;              --VoiceSpawnsLeft;
1284    
1285              return 0; // success              return 0; // success
1286          }          }
# Line 955  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 999  namespace LinuxSampler { namespace gig { Line 1356  namespace LinuxSampler { namespace gig {
1356          // update controller value in the engine channel's controller table          // update controller value in the engine channel's controller table
1357          pEngineChannel->ControllerTable[itControlChangeEvent->Param.CC.Controller] = itControlChangeEvent->Param.CC.Value;          pEngineChannel->ControllerTable[itControlChangeEvent->Param.CC.Controller] = itControlChangeEvent->Param.CC.Value;
1358    
1359          // move event from the unsorted event list to the control change event list          // handle hard coded MIDI controllers
1360          Pool<Event>::Iterator itControlChangeEventOnCCList = itControlChangeEvent.moveToEndOf(pEngineChannel->pCCEvents);          switch (itControlChangeEvent->Param.CC.Controller) {
1361                case 5: { // portamento time
1362          switch (itControlChangeEventOnCCList->Param.CC.Controller) {                  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                    }
1373                    break;
1374                }
1375              case 7: { // volume              case 7: { // volume
1376                  //TODO: not sample accurate yet                  //TODO: not sample accurate yet
1377                  pEngineChannel->GlobalVolume = (float) itControlChangeEventOnCCList->Param.CC.Value / 127.0f;                  pEngineChannel->MidiVolume = VolumeCurve[itControlChangeEvent->Param.CC.Value];
1378                    pEngineChannel->bStatusChanged = true; // engine channel status has changed, so set notify flag
1379                  break;                  break;
1380              }              }
1381              case 10: { // panpot              case 10: { // panpot
1382                  //TODO: not sample accurate yet                  //TODO: not sample accurate yet
1383                  const int pan = (int) itControlChangeEventOnCCList->Param.CC.Value - 64;                  pEngineChannel->GlobalPanLeft  = PanCurve[128 - itControlChangeEvent->Param.CC.Value];
1384                  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;  
1385                  break;                  break;
1386              }              }
1387              case 64: { // sustain              case 64: { // sustain
1388                  if (itControlChangeEventOnCCList->Param.CC.Value >= 64 && !pEngineChannel->SustainPedal) {                  if (itControlChangeEvent->Param.CC.Value >= 64 && !pEngineChannel->SustainPedal) {
1389                      dmsg(4,("PEDAL DOWN\n"));                      dmsg(4,("DAMPER (RIGHT) PEDAL DOWN\n"));
1390                      pEngineChannel->SustainPedal = true;                      pEngineChannel->SustainPedal = true;
1391    
1392                        #if !CONFIG_PROCESS_MUTED_CHANNELS
1393                        if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
1394                        #endif
1395    
1396                      // cancel release process of voices if necessary                      // cancel release process of voices if necessary
1397                      RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();                      RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
1398                      for (; iuiKey; ++iuiKey) {                      for (; iuiKey; ++iuiKey) {
# Line 1027  namespace LinuxSampler { namespace gig { Line 1400  namespace LinuxSampler { namespace gig {
1400                          if (!pKey->KeyPressed) {                          if (!pKey->KeyPressed) {
1401                              RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();                              RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
1402                              if (itNewEvent) {                              if (itNewEvent) {
1403                                  *itNewEvent = *itControlChangeEventOnCCList; // copy event to the key's own event list                                  *itNewEvent = *itControlChangeEvent; // copy event to the key's own event list
1404                                  itNewEvent->Type = Event::type_cancel_release; // transform event type                                  itNewEvent->Type = Event::type_cancel_release; // transform event type
1405                              }                              }
1406                              else dmsg(1,("Event pool emtpy!\n"));                              else dmsg(1,("Event pool emtpy!\n"));
1407                          }                          }
1408                      }                      }
1409                  }                  }
1410                  if (itControlChangeEventOnCCList->Param.CC.Value < 64 && pEngineChannel->SustainPedal) {                  if (itControlChangeEvent->Param.CC.Value < 64 && pEngineChannel->SustainPedal) {
1411                      dmsg(4,("PEDAL UP\n"));                      dmsg(4,("DAMPER (RIGHT) PEDAL UP\n"));
1412                      pEngineChannel->SustainPedal = false;                      pEngineChannel->SustainPedal = false;
1413    
1414                        #if !CONFIG_PROCESS_MUTED_CHANNELS
1415                        if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
1416                        #endif
1417    
1418                      // release voices if their respective key is not pressed                      // release voices if their respective key is not pressed
1419                      RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();                      RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
1420                      for (; iuiKey; ++iuiKey) {                      for (; iuiKey; ++iuiKey) {
1421                          midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];                          midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
1422                          if (!pKey->KeyPressed) {                          if (!pKey->KeyPressed && ShouldReleaseVoice(pEngineChannel, *iuiKey)) {
1423                                RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
1424                                if (itNewEvent) {
1425                                    *itNewEvent = *itControlChangeEvent; // copy event to the key's own event list
1426                                    itNewEvent->Type = Event::type_release; // transform event type
1427                                }
1428                                else dmsg(1,("Event pool emtpy!\n"));
1429                            }
1430                        }
1431                    }
1432                    break;
1433                }
1434                case 65: { // portamento on / off
1435                    KillAllVoices(pEngineChannel, itControlChangeEvent);
1436                    pEngineChannel->PortamentoMode = itControlChangeEvent->Param.CC.Value >= 64;
1437                    break;
1438                }
1439                case 66: { // sostenuto
1440                    if (itControlChangeEvent->Param.CC.Value >= 64 && !pEngineChannel->SostenutoPedal) {
1441                        dmsg(4,("SOSTENUTO (CENTER) PEDAL DOWN\n"));
1442                        pEngineChannel->SostenutoPedal = true;
1443    
1444                        #if !CONFIG_PROCESS_MUTED_CHANNELS
1445                        if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
1446                        #endif
1447    
1448                        SostenutoKeyCount = 0;
1449                        // Remeber the pressed keys
1450                        RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
1451                        for (; iuiKey; ++iuiKey) {
1452                            midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
1453                            if (pKey->KeyPressed && SostenutoKeyCount < 128) SostenutoKeys[SostenutoKeyCount++] = *iuiKey;
1454                        }
1455                    }
1456                    if (itControlChangeEvent->Param.CC.Value < 64 && pEngineChannel->SostenutoPedal) {
1457                        dmsg(4,("SOSTENUTO (CENTER) PEDAL UP\n"));
1458                        pEngineChannel->SostenutoPedal = false;
1459    
1460                        #if !CONFIG_PROCESS_MUTED_CHANNELS
1461                        if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
1462                        #endif
1463    
1464                        // release voices if the damper pedal is up and their respective key is not pressed
1465                        for (int i = 0; i < SostenutoKeyCount; i++) {
1466                            midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[SostenutoKeys[i]];
1467                            if (!pKey->KeyPressed && !pEngineChannel->SustainPedal) {
1468                              RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();                              RTList<Event>::Iterator itNewEvent = pKey->pEvents->allocAppend();
1469                              if (itNewEvent) {                              if (itNewEvent) {
1470                                  *itNewEvent = *itControlChangeEventOnCCList; // copy event to the key's own event list                                  *itNewEvent = *itControlChangeEvent; // copy event to the key's own event list
1471                                  itNewEvent->Type = Event::type_release; // transform event type                                  itNewEvent->Type = Event::type_release; // transform event type
1472                              }                              }
1473                              else dmsg(1,("Event pool emtpy!\n"));                              else dmsg(1,("Event pool emtpy!\n"));
# Line 1054  namespace LinuxSampler { namespace gig { Line 1476  namespace LinuxSampler { namespace gig {
1476                  }                  }
1477                  break;                  break;
1478              }              }
1479                case 100: { // RPN controller LSB
1480                    pEngineChannel->SetMidiRpnControllerLsb(itControlChangeEvent->Param.CC.Value);
1481                    break;
1482                }
1483                case 101: { // RPN controller MSB
1484                    pEngineChannel->SetMidiRpnControllerMsb(itControlChangeEvent->Param.CC.Value);
1485                    break;
1486                }
1487    
1488    
1489              // Channel Mode Messages              // Channel Mode Messages
1490    
1491              case 120: { // all sound off              case 120: { // all sound off
1492                  KillAllVoices(pEngineChannel, itControlChangeEventOnCCList);                  KillAllVoices(pEngineChannel, itControlChangeEvent);
1493                  break;                  break;
1494              }              }
1495              case 121: { // reset all controllers              case 121: { // reset all controllers
# Line 1067  namespace LinuxSampler { namespace gig { Line 1497  namespace LinuxSampler { namespace gig {
1497                  break;                  break;
1498              }              }
1499              case 123: { // all notes off              case 123: { // all notes off
1500                  ReleaseAllVoices(pEngineChannel, itControlChangeEventOnCCList);                  #if CONFIG_PROCESS_ALL_NOTES_OFF
1501                    ReleaseAllVoices(pEngineChannel, itControlChangeEvent);
1502                    #endif // CONFIG_PROCESS_ALL_NOTES_OFF
1503                    break;
1504                }
1505                case 126: { // mono mode on
1506                    KillAllVoices(pEngineChannel, itControlChangeEvent);
1507                    pEngineChannel->SoloMode = true;
1508                    break;
1509                }
1510                case 127: { // poly mode on
1511                    KillAllVoices(pEngineChannel, itControlChangeEvent);
1512                    pEngineChannel->SoloMode = false;
1513                  break;                  break;
1514              }              }
1515          }          }
1516    
1517            // handle FX send controllers
1518            if (!pEngineChannel->fxSends.empty()) {
1519                for (int iFxSend = 0; iFxSend < pEngineChannel->GetFxSendCount(); iFxSend++) {
1520                    FxSend* pFxSend = pEngineChannel->GetFxSend(iFxSend);
1521                    if (pFxSend->MidiController() == itControlChangeEvent->Param.CC.Controller)
1522                        pFxSend->SetLevel(itControlChangeEvent->Param.CC.Value);
1523                }
1524            }
1525      }      }
1526    
1527      /**      /**
# Line 1079  namespace LinuxSampler { namespace gig { Line 1530  namespace LinuxSampler { namespace gig {
1530       *  @param itSysexEvent - sysex data size and time stamp of the sysex event       *  @param itSysexEvent - sysex data size and time stamp of the sysex event
1531       */       */
1532      void Engine::ProcessSysex(Pool<Event>::Iterator& itSysexEvent) {      void Engine::ProcessSysex(Pool<Event>::Iterator& itSysexEvent) {
1533          RingBuffer<uint8_t>::NonVolatileReader reader = pSysexBuffer->get_non_volatile_reader();          RingBuffer<uint8_t,false>::NonVolatileReader reader = pSysexBuffer->get_non_volatile_reader();
1534    
1535          uint8_t exclusive_status, id;          uint8_t exclusive_status, id;
1536          if (!reader.pop(&exclusive_status)) goto free_sysex_data;          if (!reader.pop(&exclusive_status)) goto free_sysex_data;
# Line 1098  namespace LinuxSampler { namespace gig { Line 1549  namespace LinuxSampler { namespace gig {
1549    
1550                  // command address                  // command address
1551                  uint8_t addr[3]; // 2 byte addr MSB, followed by 1 byte addr LSB)                  uint8_t addr[3]; // 2 byte addr MSB, followed by 1 byte addr LSB)
1552                  const RingBuffer<uint8_t>::NonVolatileReader checksum_reader = reader; // so we can calculate the check sum later                  const RingBuffer<uint8_t,false>::NonVolatileReader checksum_reader = reader; // so we can calculate the check sum later
1553                  if (reader.read(&addr[0], 3) != 3) goto free_sysex_data;                  if (reader.read(&addr[0], 3) != 3) goto free_sysex_data;
1554                  if (addr[0] == 0x40 && addr[1] == 0x00) { // System Parameters                  if (addr[0] == 0x40 && addr[1] == 0x00) { // System Parameters
1555                      dmsg(3,("\tSystem Parameter\n"));                      dmsg(3,("\tSystem Parameter\n"));
# Line 1145  namespace LinuxSampler { namespace gig { Line 1596  namespace LinuxSampler { namespace gig {
1596       *                     question       *                     question
1597       * @param DataSize   - size of the GS message data (in bytes)       * @param DataSize   - size of the GS message data (in bytes)
1598       */       */
1599      uint8_t Engine::GSCheckSum(const RingBuffer<uint8_t>::NonVolatileReader AddrReader, uint DataSize) {      uint8_t Engine::GSCheckSum(const RingBuffer<uint8_t,false>::NonVolatileReader AddrReader, uint DataSize) {
1600          RingBuffer<uint8_t>::NonVolatileReader reader = AddrReader;          RingBuffer<uint8_t,false>::NonVolatileReader reader = AddrReader;
1601          uint bytes = 3 /*addr*/ + DataSize;          uint bytes = 3 /*addr*/ + DataSize;
1602          uint8_t addr_and_data[bytes];          uint8_t addr_and_data[bytes];
1603          reader.read(&addr_and_data[0], bytes);          reader.read(&addr_and_data[0], bytes);
# Line 1205  namespace LinuxSampler { namespace gig { Line 1656  namespace LinuxSampler { namespace gig {
1656              RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();              RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();
1657              for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key              for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
1658                  itVoice->Kill(itKillEvent);                  itVoice->Kill(itKillEvent);
1659                    --VoiceSpawnsLeft; //FIXME: just a temporary workaround, we should check the cause in StealVoice() instead
1660              }              }
1661          }          }
1662      }      }
1663    
1664      /**      /**
1665       * Initialize the parameter sequence for the modulation destination given by       * Determines whether the specified voice should be released.
1666       * by 'dst' with the constant value given by val.       *
1667         * @param pEngineChannel - The engine channel on which the voice should be checked
1668         * @param Key - The key number
1669         * @returns true if the specified should be released, false otherwise.
1670       */       */
1671      void Engine::ResetSynthesisParameters(Event::destination_t dst, float val) {      bool Engine::ShouldReleaseVoice(EngineChannel* pEngineChannel, int Key) {
1672          int maxsamples = pAudioOutputDevice->MaxSamplesPerCycle();          if (pEngineChannel->SustainPedal) return false;
1673          float* m = &pSynthesisParameters[dst][0];  
1674          for (int i = 0; i < maxsamples; i += 4) {          if (pEngineChannel->SostenutoPedal) {
1675             m[i]   = val;              for (int i = 0; i < SostenutoKeyCount; i++)
1676             m[i+1] = val;                  if (Key == SostenutoKeys[i]) return false;
            m[i+2] = val;  
            m[i+3] = val;  
1677          }          }
1678    
1679            return true;
1680      }      }
1681    
1682      uint Engine::VoiceCount() {      uint Engine::VoiceCount() {
# Line 1261  namespace LinuxSampler { namespace gig { Line 1716  namespace LinuxSampler { namespace gig {
1716      }      }
1717    
1718      String Engine::Version() {      String Engine::Version() {
1719          String s = "$Revision: 1.42 $";          String s = "$Revision: 1.73 $";
1720          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
1721      }      }
1722    
1723        InstrumentManager* Engine::GetInstrumentManager() {
1724            return &instruments;
1725        }
1726    
1727        // static constant initializers
1728        const float* Engine::VolumeCurve(InitVolumeCurve());
1729        const float* Engine::PanCurve(InitPanCurve());
1730        const float* Engine::CrossfadeCurve(InitCrossfadeCurve());
1731    
1732        float* Engine::InitVolumeCurve() {
1733            // line-segment approximation
1734            const float segments[] = {
1735                0, 0, 2, 0.0046, 16, 0.016, 31, 0.051, 45, 0.115, 54.5, 0.2,
1736                64.5, 0.39, 74, 0.74, 92, 1.03, 114, 1.94, 119.2, 2.2, 127, 2.2
1737            };
1738            return InitCurve(segments);
1739        }
1740    
1741        float* Engine::InitPanCurve() {
1742            // line-segment approximation
1743            const float segments[] = {
1744                0, 0, 1, 0,
1745                2, 0.05, 31.5, 0.7, 51, 0.851, 74.5, 1.12,
1746                127, 1.41, 128, 1.41
1747            };
1748            return InitCurve(segments, 129);
1749        }
1750    
1751        float* Engine::InitCrossfadeCurve() {
1752            // line-segment approximation
1753            const float segments[] = {
1754                0, 0, 1, 0.03, 10, 0.1, 51, 0.58, 127, 1
1755            };
1756            return InitCurve(segments);
1757        }
1758    
1759        float* Engine::InitCurve(const float* segments, int size) {
1760            float* y = new float[size];
1761            for (int x = 0 ; x < size ; x++) {
1762                if (x > segments[2]) segments += 2;
1763                y[x] = segments[1] + (x - segments[0]) *
1764                    (segments[3] - segments[1]) / (segments[2] - segments[0]);
1765            }
1766            return y;
1767        }
1768    
1769        /**
1770         * Changes the instrument for an engine channel.
1771         *
1772         * @param pEngineChannel - engine channel on which the instrument
1773         *                         should be changed
1774         * @param pInstrument - new instrument
1775         * @returns a list of dimension regions from the old instrument
1776         *          that are still in use
1777         */
1778        ::gig::DimensionRegion** Engine::ChangeInstrument(EngineChannel* pEngineChannel, ::gig::Instrument* pInstrument) {
1779            instrument_change_command_t command;
1780            command.pEngineChannel = pEngineChannel;
1781            command.pInstrument = pInstrument;
1782            InstrumentChangeQueue->push(&command);
1783    
1784            // wait for the audio thread to confirm that the instrument
1785            // change has been done
1786            instrument_change_reply_t reply;
1787            while (InstrumentChangeReplyQueue->pop(&reply) == 0) {
1788                usleep(10000);
1789            }
1790            return pDimRegionsInUse;
1791        }
1792    
1793  }} // namespace LinuxSampler::gig  }} // namespace LinuxSampler::gig

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

  ViewVC Help
Powered by ViewVC