/[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 781 by schoenebeck, Mon Sep 26 10:17:00 2005 UTC revision 1248 by persson, Fri Jun 22 10:10:06 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 51  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 97  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          }          }
# Line 116  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 131  namespace LinuxSampler { namespace gig { Line 141  namespace LinuxSampler { namespace gig {
141          if (pEventGenerator) delete pEventGenerator;          if (pEventGenerator) delete pEventGenerator;
142          if (pVoiceStealingQueue) delete pVoiceStealingQueue;          if (pVoiceStealingQueue) delete pVoiceStealingQueue;
143          if (pSysexBuffer) delete pSysexBuffer;          if (pSysexBuffer) delete pSysexBuffer;
144          EngineFactory::Destroy(this);          if (pGlobalEvents) delete pGlobalEvents;
145            if (InstrumentChangeQueue) delete InstrumentChangeQueue;
146            if (InstrumentChangeReplyQueue) delete InstrumentChangeReplyQueue;
147            if (pDimRegionsInUse) delete[] pDimRegionsInUse;
148            Unregister();
149      }      }
150    
151      void Engine::Enable() {      void Engine::Enable() {
# Line 165  namespace LinuxSampler { namespace gig { Line 179  namespace LinuxSampler { namespace gig {
179    
180      /**      /**
181       *  Reset all voices and disk thread and clear input event queue and all       *  Reset all voices and disk thread and clear input event queue and all
182       *  control and status variables. This method is not thread safe!       *  control and status variables. This method is protected by a mutex.
183       */       */
184      void Engine::ResetInternal() {      void Engine::ResetInternal() {
185            ResetInternalMutex.Lock();
186    
187            // make sure that the engine does not get any sysex messages
188            // while it's reseting
189            bool sysexDisabled = MidiInputPort::RemoveSysexListener(this);
190          ActiveVoiceCount    = 0;          ActiveVoiceCount    = 0;
191          ActiveVoiceCountMax = 0;          ActiveVoiceCountMax = 0;
192    
# Line 191  namespace LinuxSampler { namespace gig { Line 210  namespace LinuxSampler { namespace gig {
210          // delete all input events          // delete all input events
211          pEventQueue->init();          pEventQueue->init();
212          pSysexBuffer->init();          pSysexBuffer->init();
213            if (sysexDisabled) MidiInputPort::AddSysexListener(this);
214            ResetInternalMutex.Unlock();
215      }      }
216    
217      /**      /**
# Line 220  namespace LinuxSampler { namespace gig { Line 241  namespace LinuxSampler { namespace gig {
241          }          }
242          catch (AudioOutputException e) {          catch (AudioOutputException e) {
243              String msg = "Audio output device unable to provide 2 audio channels, cause: " + e.Message();              String msg = "Audio output device unable to provide 2 audio channels, cause: " + e.Message();
244              throw LinuxSamplerException(msg);              throw Exception(msg);
245          }          }
246    
247          this->MaxSamplesPerCycle = pAudioOutputDevice->MaxSamplesPerCycle();          this->MaxSamplesPerCycle = pAudioOutputDevice->MaxSamplesPerCycle();
# Line 249  namespace LinuxSampler { namespace gig { Line 270  namespace LinuxSampler { namespace gig {
270              delete this->pDiskThread;              delete this->pDiskThread;
271              dmsg(1,("OK\n"));              dmsg(1,("OK\n"));
272          }          }
273          this->pDiskThread = new DiskThread(((pAudioOut->MaxSamplesPerCycle() << CONFIG_MAX_PITCH) << 1) + 6); //FIXME: assuming stereo          this->pDiskThread = new DiskThread(((pAudioOut->MaxSamplesPerCycle() << CONFIG_MAX_PITCH) << 1) + 6, //FIXME: assuming stereo
274                                               &instruments);
275          if (!pDiskThread) {          if (!pDiskThread) {
276              dmsg(0,("gig::Engine  new diskthread = NULL\n"));              dmsg(0,("gig::Engine  new diskthread = NULL\n"));
277              exit(EXIT_FAILURE);              exit(EXIT_FAILURE);
# Line 298  namespace LinuxSampler { namespace gig { Line 320  namespace LinuxSampler { namespace gig {
320       *                  current audio cycle       *                  current audio cycle
321       */       */
322      void Engine::ImportEvents(uint Samples) {      void Engine::ImportEvents(uint Samples) {
323          RingBuffer<Event>::NonVolatileReader eventQueueReader = pEventQueue->get_non_volatile_reader();          RingBuffer<Event,false>::NonVolatileReader eventQueueReader = pEventQueue->get_non_volatile_reader();
324          Event* pEvent;          Event* pEvent;
325          while (true) {          while (true) {
326              // get next event from input event queue              // get next event from input event queue
# Line 321  namespace LinuxSampler { namespace gig { Line 343  namespace LinuxSampler { namespace gig {
343      }      }
344    
345      /**      /**
346       *  Let this engine proceed to render the given amount of sample points. The       * Let this engine proceed to render the given amount of sample points.
347       *  calculated audio data of all voices of this engine will be placed into       * The engine will iterate through all engine channels and render audio
348       *  the engine's audio sum buffer which has to be copied and eventually be       * for each engine channel independently. The calculated audio data of
349       *  converted to the appropriate value range by the audio output class (e.g.       * all voices of each engine channel will be placed into the audio sum
350       *  AlsaIO or JackIO) right after.       * buffers of the respective audio output device, connected to the
351         * respective engine channel.
352       *       *
353       *  @param Samples - number of sample points to be rendered       *  @param Samples - number of sample points to be rendered
354       *  @returns       0 on success       *  @returns       0 on success
355       */       */
356      int Engine::RenderAudio(uint Samples) {      int Engine::RenderAudio(uint Samples) {
357          dmsg(5,("RenderAudio(Samples=%d)\n", Samples));          dmsg(7,("RenderAudio(Samples=%d)\n", Samples));
358    
359          // return if engine disabled          // return if engine disabled
360          if (EngineDisabled.Pop()) {          if (EngineDisabled.Pop()) {
# Line 368  namespace LinuxSampler { namespace gig { Line 391  namespace LinuxSampler { namespace gig {
391          // reset internal voice counter (just for statistic of active voices)          // reset internal voice counter (just for statistic of active voices)
392          ActiveVoiceCountTemp = 0;          ActiveVoiceCountTemp = 0;
393    
394            // handle instrument change commands
395            instrument_change_command_t command;
396            if (InstrumentChangeQueue->pop(&command) > 0) {
397                EngineChannel* pEngineChannel = command.pEngineChannel;
398                pEngineChannel->pInstrument = command.pInstrument;
399    
400                // iterate through all active voices and mark their
401                // dimension regions as "in use". The instrument resource
402                // manager may delete all of the instrument except the
403                // dimension regions and samples that are in use.
404                int i = 0;
405                RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
406                RTList<uint>::Iterator end    = pEngineChannel->pActiveKeys->end();
407                while (iuiKey != end) { // iterate through all active keys
408                    midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
409                    ++iuiKey;
410    
411                    RTList<Voice>::Iterator itVoice     = pKey->pActiveVoices->first();
412                    RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();
413                    for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
414                        if (!itVoice->Orphan) {
415                            itVoice->Orphan = true;
416                            pDimRegionsInUse[i++] = itVoice->pDimRgn;
417                        }
418                    }
419                }
420                pDimRegionsInUse[i] = 0; // end of list
421    
422                // send a reply to the calling thread, which is waiting
423                instrument_change_reply_t reply;
424                InstrumentChangeReplyQueue->push(&reply);
425            }
426    
427          // handle events on all engine channels          // handle events on all engine channels
428          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  
429              ProcessEvents(engineChannels[i], Samples);              ProcessEvents(engineChannels[i], Samples);
430          }          }
431    
432          // render all 'normal', active voices on all engine channels          // render all 'normal', active voices on all engine channels
433          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  
434              RenderActiveVoices(engineChannels[i], Samples);              RenderActiveVoices(engineChannels[i], Samples);
435          }          }
436    
437          // 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
438          RenderStolenVoices(Samples);          RenderStolenVoices(Samples);
439    
440            // handle audio routing for engine channels with FX sends
441            for (int i = 0; i < engineChannels.size(); i++) {
442                if (engineChannels[i]->fxSends.empty()) continue; // ignore if no FX sends
443                RouteAudio(engineChannels[i], Samples);
444            }
445    
446          // handle cleanup on all engine channels for the next audio fragment          // handle cleanup on all engine channels for the next audio fragment
447          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  
448              PostProcess(engineChannels[i]);              PostProcess(engineChannels[i]);
449          }          }
450    
# Line 504  namespace LinuxSampler { namespace gig { Line 563  namespace LinuxSampler { namespace gig {
563          RTList<Event>::Iterator end               = pVoiceStealingQueue->end();          RTList<Event>::Iterator end               = pVoiceStealingQueue->end();
564          for (; itVoiceStealEvent != end; ++itVoiceStealEvent) {          for (; itVoiceStealEvent != end; ++itVoiceStealEvent) {
565              EngineChannel* pEngineChannel = (EngineChannel*) itVoiceStealEvent->pEngineChannel;              EngineChannel* pEngineChannel = (EngineChannel*) itVoiceStealEvent->pEngineChannel;
566                if (!pEngineChannel->pInstrument) continue; // ignore if no instrument loaded
567              Pool<Voice>::Iterator itNewVoice =              Pool<Voice>::Iterator itNewVoice =
568                  LaunchVoice(pEngineChannel, itVoiceStealEvent, itVoiceStealEvent->Param.Note.Layer, itVoiceStealEvent->Param.Note.ReleaseTrigger, false, false);                  LaunchVoice(pEngineChannel, itVoiceStealEvent, itVoiceStealEvent->Param.Note.Layer, itVoiceStealEvent->Param.Note.ReleaseTrigger, false, false);
569              if (itNewVoice) {              if (itNewVoice) {
# Line 523  namespace LinuxSampler { namespace gig { Line 583  namespace LinuxSampler { namespace gig {
583      }      }
584    
585      /**      /**
586         * Will be called in case the respective engine channel sports FX send
587         * channels. In this particular case, engine channel local buffers are
588         * used to render and mix all voices to. This method is responsible for
589         * copying the audio data from those local buffers to the master audio
590         * output channels as well as to the FX send audio output channels with
591         * their respective FX send levels.
592         *
593         * @param pEngineChannel - engine channel from which audio should be
594         *                         routed
595         * @param Samples        - amount of sample points to be routed in
596         *                         this audio fragment cycle
597         */
598        void Engine::RouteAudio(EngineChannel* pEngineChannel, uint Samples) {
599            // route master signal
600            {
601                AudioChannel* pDstL = pAudioOutputDevice->Channel(pEngineChannel->AudioDeviceChannelLeft);
602                AudioChannel* pDstR = pAudioOutputDevice->Channel(pEngineChannel->AudioDeviceChannelRight);
603                pEngineChannel->pChannelLeft->MixTo(pDstL, Samples);
604                pEngineChannel->pChannelRight->MixTo(pDstR, Samples);
605            }
606            // route FX send signal
607            {
608                for (int iFxSend = 0; iFxSend < pEngineChannel->GetFxSendCount(); iFxSend++) {
609                    FxSend* pFxSend = pEngineChannel->GetFxSend(iFxSend);
610                    // left channel
611                    const int iDstL = pFxSend->DestinationChannel(0);
612                    if (iDstL < 0) {
613                        dmsg(1,("Engine::RouteAudio() Error: invalid FX send (L) destination channel"));
614                    } else {
615                        AudioChannel* pDstL = pAudioOutputDevice->Channel(iDstL);
616                        if (!pDstL) {
617                            dmsg(1,("Engine::RouteAudio() Error: invalid FX send (L) destination channel"));
618                        } else pEngineChannel->pChannelLeft->MixTo(pDstL, Samples, pFxSend->Level());
619                    }
620                    // right channel
621                    const int iDstR = pFxSend->DestinationChannel(1);
622                    if (iDstR < 0) {
623                        dmsg(1,("Engine::RouteAudio() Error: invalid FX send (R) destination channel"));
624                    } else {
625                        AudioChannel* pDstR = pAudioOutputDevice->Channel(iDstR);
626                        if (!pDstR) {
627                            dmsg(1,("Engine::RouteAudio() Error: invalid FX send (R) destination channel"));
628                        } else pEngineChannel->pChannelRight->MixTo(pDstR, Samples, pFxSend->Level());
629                    }
630                }
631            }
632            // reset buffers with silence (zero out) for the next audio cycle
633            pEngineChannel->pChannelLeft->Clear();
634            pEngineChannel->pChannelRight->Clear();
635        }
636    
637        /**
638       * Free all keys which have turned inactive in this audio fragment, from       * Free all keys which have turned inactive in this audio fragment, from
639       * 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
640       * channel.       * channel.
# Line 599  namespace LinuxSampler { namespace gig { Line 711  namespace LinuxSampler { namespace gig {
711          if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted          if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
712          #endif          #endif
713    
714            if (!pEngineChannel->pInstrument) return; // ignore if no instrument loaded
715    
716            //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
717            itNoteOnEvent->Param.Note.Key += pEngineChannel->GlobalTranspose;
718    
719          const int key = itNoteOnEvent->Param.Note.Key;          const int key = itNoteOnEvent->Param.Note.Key;
720            midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[key];
721    
722            // move note on event to the key's own event list
723            RTList<Event>::Iterator itNoteOnEventOnKeyList = itNoteOnEvent.moveToEndOf(pKey->pEvents);
724    
725            // if Solo Mode then kill all already active voices
726            if (pEngineChannel->SoloMode) {
727                Pool<uint>::Iterator itYoungestKey = pEngineChannel->pActiveKeys->last();
728                if (itYoungestKey) {
729                    const int iYoungestKey = *itYoungestKey;
730                    const midi_key_info_t* pOtherKey = &pEngineChannel->pMIDIKeyInfo[iYoungestKey];
731                    if (pOtherKey->Active) {
732                        // get final portamento position of currently active voice
733                        if (pEngineChannel->PortamentoMode) {
734                            RTList<Voice>::Iterator itVoice = pOtherKey->pActiveVoices->last();
735                            if (itVoice) itVoice->UpdatePortamentoPos(itNoteOnEventOnKeyList);
736                        }
737                        // kill all voices on the (other) key
738                        RTList<Voice>::Iterator itVoiceToBeKilled = pOtherKey->pActiveVoices->first();
739                        RTList<Voice>::Iterator end               = pOtherKey->pActiveVoices->end();
740                        for (; itVoiceToBeKilled != end; ++itVoiceToBeKilled) {
741                            if (itVoiceToBeKilled->Type != Voice::type_release_trigger)
742                                itVoiceToBeKilled->Kill(itNoteOnEventOnKeyList);
743                        }
744                    }
745                }
746                // set this key as 'currently active solo key'
747                pEngineChannel->SoloKey = key;
748            }
749    
750          // Change key dimension value if key is in keyswitching area          // Change key dimension value if key is in keyswitching area
751          {          {
752              const ::gig::Instrument* pInstrument = pEngineChannel->pInstrument;              const ::gig::Instrument* pInstrument = pEngineChannel->pInstrument;
753              if (key >= pInstrument->DimensionKeyRange.low && key <= pInstrument->DimensionKeyRange.high)              if (key >= pInstrument->DimensionKeyRange.low && key <= pInstrument->DimensionKeyRange.high)
754                  pEngineChannel->CurrentKeyDimension = ((key - pInstrument->DimensionKeyRange.low) * 128) /                  pEngineChannel->CurrentKeyDimension = float(key - pInstrument->DimensionKeyRange.low) /
755                      (pInstrument->DimensionKeyRange.high - pInstrument->DimensionKeyRange.low + 1);                      (pInstrument->DimensionKeyRange.high - pInstrument->DimensionKeyRange.low + 1);
756          }          }
757    
         midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[key];  
   
758          pKey->KeyPressed = true; // the MIDI key was now pressed down          pKey->KeyPressed = true; // the MIDI key was now pressed down
759          pKey->Velocity   = itNoteOnEvent->Param.Note.Velocity;          pKey->Velocity   = itNoteOnEventOnKeyList->Param.Note.Velocity;
760          pKey->NoteOnTime = FrameTime + itNoteOnEvent->FragmentPos(); // will be used to calculate note length          pKey->NoteOnTime = FrameTime + itNoteOnEventOnKeyList->FragmentPos(); // will be used to calculate note length
761    
762          // cancel release process of voices on this key if needed          // cancel release process of voices on this key if needed
763          if (pKey->Active && !pEngineChannel->SustainPedal) {          if (pKey->Active && !pEngineChannel->SustainPedal) {
764              RTList<Event>::Iterator itCancelReleaseEvent = pKey->pEvents->allocAppend();              RTList<Event>::Iterator itCancelReleaseEvent = pKey->pEvents->allocAppend();
765              if (itCancelReleaseEvent) {              if (itCancelReleaseEvent) {
766                  *itCancelReleaseEvent = *itNoteOnEvent;                  // copy event                  *itCancelReleaseEvent = *itNoteOnEventOnKeyList;         // copy event
767                  itCancelReleaseEvent->Type = Event::type_cancel_release; // transform event type                  itCancelReleaseEvent->Type = Event::type_cancel_release; // transform event type
768              }              }
769              else dmsg(1,("Event pool emtpy!\n"));              else dmsg(1,("Event pool emtpy!\n"));
770          }          }
771    
         // move note on event to the key's own event list  
         RTList<Event>::Iterator itNoteOnEventOnKeyList = itNoteOnEvent.moveToEndOf(pKey->pEvents);  
   
772          // allocate and trigger new voice(s) for the key          // allocate and trigger new voice(s) for the key
773          {          {
774              // 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 644  namespace LinuxSampler { namespace gig { Line 785  namespace LinuxSampler { namespace gig {
785          if (!pKey->Active && !pKey->VoiceTheftsQueued)          if (!pKey->Active && !pKey->VoiceTheftsQueued)
786              pKey->pEvents->free(itNoteOnEventOnKeyList);              pKey->pEvents->free(itNoteOnEventOnKeyList);
787    
788            if (!pEngineChannel->SoloMode || pEngineChannel->PortamentoPos < 0.0f) pEngineChannel->PortamentoPos = (float) key;
789          pKey->RoundRobinIndex++;          pKey->RoundRobinIndex++;
790      }      }
791    
# Line 661  namespace LinuxSampler { namespace gig { Line 803  namespace LinuxSampler { namespace gig {
803          if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted          if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
804          #endif          #endif
805    
806          midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[itNoteOffEvent->Param.Note.Key];          //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
807            itNoteOffEvent->Param.Note.Key += pEngineChannel->GlobalTranspose;
808    
809            const int iKey = itNoteOffEvent->Param.Note.Key;
810            midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[iKey];
811          pKey->KeyPressed = false; // the MIDI key was now released          pKey->KeyPressed = false; // the MIDI key was now released
812    
813          // release voices on this key if needed          // move event to the key's own event list
814          if (pKey->Active && ShouldReleaseVoice(pEngineChannel, itNoteOffEvent->Param.Note.Key)) {          RTList<Event>::Iterator itNoteOffEventOnKeyList = itNoteOffEvent.moveToEndOf(pKey->pEvents);
815              itNoteOffEvent->Type = Event::type_release; // transform event type  
816            bool bShouldRelease = pKey->Active && ShouldReleaseVoice(pEngineChannel, itNoteOffEventOnKeyList->Param.Note.Key);
817    
818            // in case Solo Mode is enabled, kill all voices on this key and respawn a voice on the highest pressed key (if any)
819            if (pEngineChannel->SoloMode && pEngineChannel->pInstrument) { //TODO: this feels like too much code just for handling solo mode :P
820                bool bOtherKeysPressed = false;
821                if (iKey == pEngineChannel->SoloKey) {
822                    pEngineChannel->SoloKey = -1;
823                    // if there's still a key pressed down, respawn a voice (group) on the highest key
824                    for (int i = 127; i > 0; i--) {
825                        midi_key_info_t* pOtherKey = &pEngineChannel->pMIDIKeyInfo[i];
826                        if (pOtherKey->KeyPressed) {
827                            bOtherKeysPressed = true;
828                            // make the other key the new 'currently active solo key'
829                            pEngineChannel->SoloKey = i;
830                            // get final portamento position of currently active voice
831                            if (pEngineChannel->PortamentoMode) {
832                                RTList<Voice>::Iterator itVoice = pKey->pActiveVoices->first();
833                                if (itVoice) itVoice->UpdatePortamentoPos(itNoteOffEventOnKeyList);
834                            }
835                            // create a pseudo note on event
836                            RTList<Event>::Iterator itPseudoNoteOnEvent = pOtherKey->pEvents->allocAppend();
837                            if (itPseudoNoteOnEvent) {
838                                // copy event
839                                *itPseudoNoteOnEvent = *itNoteOffEventOnKeyList;
840                                // transform event to a note on event
841                                itPseudoNoteOnEvent->Type                = Event::type_note_on;
842                                itPseudoNoteOnEvent->Param.Note.Key      = i;
843                                itPseudoNoteOnEvent->Param.Note.Velocity = pOtherKey->Velocity;
844                                // allocate and trigger new voice(s) for the other key
845                                {
846                                    // first, get total amount of required voices (dependant on amount of layers)
847                                    ::gig::Region* pRegion = pEngineChannel->pInstrument->GetRegion(i);
848                                    if (pRegion) {
849                                        int voicesRequired = pRegion->Layers;
850                                        // now launch the required amount of voices
851                                        for (int iLayer = 0; iLayer < voicesRequired; iLayer++)
852                                            LaunchVoice(pEngineChannel, itPseudoNoteOnEvent, iLayer, false, true, false);
853                                    }
854                                }
855                                // if neither a voice was spawned or postponed then remove note on event from key again
856                                if (!pOtherKey->Active && !pOtherKey->VoiceTheftsQueued)
857                                    pOtherKey->pEvents->free(itPseudoNoteOnEvent);
858    
859                            } else dmsg(1,("Could not respawn voice, no free event left\n"));
860                            break; // done
861                        }
862                    }
863                }
864                if (bOtherKeysPressed) {
865                    if (pKey->Active) { // kill all voices on this key
866                        bShouldRelease = false; // no need to release, as we kill it here
867                        RTList<Voice>::Iterator itVoiceToBeKilled = pKey->pActiveVoices->first();
868                        RTList<Voice>::Iterator end               = pKey->pActiveVoices->end();
869                        for (; itVoiceToBeKilled != end; ++itVoiceToBeKilled) {
870                            if (itVoiceToBeKilled->Type != Voice::type_release_trigger)
871                                itVoiceToBeKilled->Kill(itNoteOffEventOnKeyList);
872                        }
873                    }
874                } else pEngineChannel->PortamentoPos = -1.0f;
875            }
876    
877              // move event to the key's own event list          // if no solo mode (the usual case) or if solo mode and no other key pressed, then release voices on this key if needed
878              RTList<Event>::Iterator itNoteOffEventOnKeyList = itNoteOffEvent.moveToEndOf(pKey->pEvents);          if (bShouldRelease) {
879                itNoteOffEventOnKeyList->Type = Event::type_release; // transform event type
880    
881              // spawn release triggered voice(s) if needed              // spawn release triggered voice(s) if needed
882              if (pKey->ReleaseTrigger) {              if (pKey->ReleaseTrigger && pEngineChannel->pInstrument) {
883                  // first, get total amount of required voices (dependant on amount of layers)                  // first, get total amount of required voices (dependant on amount of layers)
884                  ::gig::Region* pRegion = pEngineChannel->pInstrument->GetRegion(itNoteOffEventOnKeyList->Param.Note.Key);                  ::gig::Region* pRegion = pEngineChannel->pInstrument->GetRegion(itNoteOffEventOnKeyList->Param.Note.Key);
885                  if (pRegion) {                  if (pRegion) {
# Line 687  namespace LinuxSampler { namespace gig { Line 894  namespace LinuxSampler { namespace gig {
894                  }                  }
895                  pKey->ReleaseTrigger = false;                  pKey->ReleaseTrigger = false;
896              }              }
   
             // 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);  
897          }          }
898    
899            // if neither a voice was spawned or postponed on this key then remove note off event from key again
900            if (!pKey->Active && !pKey->VoiceTheftsQueued)
901                pKey->pEvents->free(itNoteOffEventOnKeyList);
902      }      }
903    
904      /**      /**
# Line 775  namespace LinuxSampler { namespace gig { Line 982  namespace LinuxSampler { namespace gig {
982                      DimValues[i] = itNoteOnEvent->Param.Note.Velocity;                      DimValues[i] = itNoteOnEvent->Param.Note.Velocity;
983                      break;                      break;
984                  case ::gig::dimension_channelaftertouch:                  case ::gig::dimension_channelaftertouch:
985                      DimValues[i] = 0; //TODO: we currently ignore this dimension                      DimValues[i] = pEngineChannel->ControllerTable[128];
986                      break;                      break;
987                  case ::gig::dimension_releasetrigger:                  case ::gig::dimension_releasetrigger:
988                      VoiceType = (ReleaseTriggerVoice) ? Voice::type_release_trigger : (!iLayer) ? Voice::type_release_trigger_required : Voice::type_normal;                      VoiceType = (ReleaseTriggerVoice) ? Voice::type_release_trigger : (!iLayer) ? Voice::type_release_trigger_required : Voice::type_normal;
989                      DimValues[i] = (uint) ReleaseTriggerVoice;                      DimValues[i] = (uint) ReleaseTriggerVoice;
990                      break;                      break;
991                  case ::gig::dimension_keyboard:                  case ::gig::dimension_keyboard:
992                      DimValues[i] = (uint) pEngineChannel->CurrentKeyDimension;                      DimValues[i] = (uint) (pEngineChannel->CurrentKeyDimension * pRegion->pDimensionDefinitions[i].zones);
993                      break;                      break;
994                  case ::gig::dimension_roundrobin:                  case ::gig::dimension_roundrobin:
995                      DimValues[i] = (uint) pEngineChannel->pMIDIKeyInfo[MIDIKey].RoundRobinIndex; // incremented for each note on                      DimValues[i] = (uint) pEngineChannel->pMIDIKeyInfo[MIDIKey].RoundRobinIndex; // incremented for each note on
# Line 867  namespace LinuxSampler { namespace gig { Line 1074  namespace LinuxSampler { namespace gig {
1074                      std::cerr << "gig::Engine::LaunchVoice() Error: Unknown dimension\n" << std::flush;                      std::cerr << "gig::Engine::LaunchVoice() Error: Unknown dimension\n" << std::flush;
1075              }              }
1076          }          }
1077    
1078            // return if this is a release triggered voice and there is no
1079            // releasetrigger dimension (could happen if an instrument
1080            // change has occured between note on and off)
1081            if (ReleaseTriggerVoice && VoiceType != Voice::type_release_trigger) return Pool<Voice>::Iterator();
1082    
1083          ::gig::DimensionRegion* pDimRgn = pRegion->GetDimensionRegionByValue(DimValues);          ::gig::DimensionRegion* pDimRgn = pRegion->GetDimensionRegionByValue(DimValues);
1084    
1085          // no need to continue if sample is silent          // no need to continue if sample is silent
# Line 1096  namespace LinuxSampler { namespace gig { Line 1309  namespace LinuxSampler { namespace gig {
1309    
1310              uint keygroup = itVoice->KeyGroup;              uint keygroup = itVoice->KeyGroup;
1311    
1312                // if the sample and dimension region belong to an
1313                // instrument that is unloaded, tell the disk thread to
1314                // release them
1315                if (itVoice->Orphan) {
1316                    pDiskThread->OrderDeletionOfDimreg(itVoice->pDimRgn);
1317                }
1318    
1319              // free the voice object              // free the voice object
1320              pVoicePool->free(itVoice);              pVoicePool->free(itVoice);
1321    
# Line 1140  namespace LinuxSampler { namespace gig { Line 1360  namespace LinuxSampler { namespace gig {
1360          // update controller value in the engine channel's controller table          // update controller value in the engine channel's controller table
1361          pEngineChannel->ControllerTable[itControlChangeEvent->Param.CC.Controller] = itControlChangeEvent->Param.CC.Value;          pEngineChannel->ControllerTable[itControlChangeEvent->Param.CC.Controller] = itControlChangeEvent->Param.CC.Value;
1362    
1363            // handle hard coded MIDI controllers
1364          switch (itControlChangeEvent->Param.CC.Controller) {          switch (itControlChangeEvent->Param.CC.Controller) {
1365                case 5: { // portamento time
1366                    pEngineChannel->PortamentoTime = (float) itControlChangeEvent->Param.CC.Value / 127.0f * (float) CONFIG_PORTAMENTO_TIME_MAX + (float) CONFIG_PORTAMENTO_TIME_MIN;
1367                    break;
1368                }
1369                case 6: { // data entry (currently only used for RPN controllers)
1370                    if (pEngineChannel->GetMidiRpnController() == 2) { // coarse tuning in half tones
1371                        int transpose = (int) itControlChangeEvent->Param.CC.Value - 64;
1372                        // limit to +- two octaves for now
1373                        transpose = RTMath::Min(transpose,  24);
1374                        transpose = RTMath::Max(transpose, -24);
1375                        pEngineChannel->GlobalTranspose = transpose;
1376                        // workaround, so we won't have hanging notes
1377                        ReleaseAllVoices(pEngineChannel, itControlChangeEvent);
1378                    }
1379                    // to avoid other MIDI CC #6 messages to be misenterpreted as RPN controller data
1380                    pEngineChannel->ResetMidiRpnController();
1381                    break;
1382                }
1383              case 7: { // volume              case 7: { // volume
1384                  //TODO: not sample accurate yet                  //TODO: not sample accurate yet
1385                  pEngineChannel->GlobalVolume = (float) itControlChangeEvent->Param.CC.Value / 127.0f *  CONFIG_GLOBAL_ATTENUATION;                  pEngineChannel->MidiVolume = VolumeCurve[itControlChangeEvent->Param.CC.Value];
1386                  pEngineChannel->bStatusChanged = true; // engine channel status has changed, so set notify flag                  pEngineChannel->bStatusChanged = true; // engine channel status has changed, so set notify flag
1387                  break;                  break;
1388              }              }
1389              case 10: { // panpot              case 10: { // panpot
1390                  //TODO: not sample accurate yet                  //TODO: not sample accurate yet
1391                  const int pan = (int) itControlChangeEvent->Param.CC.Value - 64;                  pEngineChannel->GlobalPanLeft  = PanCurve[128 - itControlChangeEvent->Param.CC.Value];
1392                  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;  
1393                  break;                  break;
1394              }              }
1395              case 64: { // sustain              case 64: { // sustain
# Line 1201  namespace LinuxSampler { namespace gig { Line 1439  namespace LinuxSampler { namespace gig {
1439                  }                  }
1440                  break;                  break;
1441              }              }
1442                case 65: { // portamento on / off
1443                    KillAllVoices(pEngineChannel, itControlChangeEvent);
1444                    pEngineChannel->PortamentoMode = itControlChangeEvent->Param.CC.Value >= 64;
1445                    break;
1446                }
1447              case 66: { // sostenuto              case 66: { // sostenuto
1448                  if (itControlChangeEvent->Param.CC.Value >= 64 && !pEngineChannel->SostenutoPedal) {                  if (itControlChangeEvent->Param.CC.Value >= 64 && !pEngineChannel->SostenutoPedal) {
1449                      dmsg(4,("SOSTENUTO (CENTER) PEDAL DOWN\n"));                      dmsg(4,("SOSTENUTO (CENTER) PEDAL DOWN\n"));
# Line 1241  namespace LinuxSampler { namespace gig { Line 1484  namespace LinuxSampler { namespace gig {
1484                  }                  }
1485                  break;                  break;
1486              }              }
1487                case 100: { // RPN controller LSB
1488                    pEngineChannel->SetMidiRpnControllerLsb(itControlChangeEvent->Param.CC.Value);
1489                    break;
1490                }
1491                case 101: { // RPN controller MSB
1492                    pEngineChannel->SetMidiRpnControllerMsb(itControlChangeEvent->Param.CC.Value);
1493                    break;
1494                }
1495    
1496    
1497              // Channel Mode Messages              // Channel Mode Messages
# Line 1254  namespace LinuxSampler { namespace gig { Line 1505  namespace LinuxSampler { namespace gig {
1505                  break;                  break;
1506              }              }
1507              case 123: { // all notes off              case 123: { // all notes off
1508                    #if CONFIG_PROCESS_ALL_NOTES_OFF
1509                  ReleaseAllVoices(pEngineChannel, itControlChangeEvent);                  ReleaseAllVoices(pEngineChannel, itControlChangeEvent);
1510                    #endif // CONFIG_PROCESS_ALL_NOTES_OFF
1511                    break;
1512                }
1513                case 126: { // mono mode on
1514                    KillAllVoices(pEngineChannel, itControlChangeEvent);
1515                    pEngineChannel->SoloMode = true;
1516                    break;
1517                }
1518                case 127: { // poly mode on
1519                    KillAllVoices(pEngineChannel, itControlChangeEvent);
1520                    pEngineChannel->SoloMode = false;
1521                  break;                  break;
1522              }              }
1523          }          }
1524    
1525            // handle FX send controllers
1526            if (!pEngineChannel->fxSends.empty()) {
1527                for (int iFxSend = 0; iFxSend < pEngineChannel->GetFxSendCount(); iFxSend++) {
1528                    FxSend* pFxSend = pEngineChannel->GetFxSend(iFxSend);
1529                    if (pFxSend->MidiController() == itControlChangeEvent->Param.CC.Controller)
1530                        pFxSend->SetLevel(itControlChangeEvent->Param.CC.Value);
1531                        pFxSend->SetInfoChanged(true);
1532                }
1533            }
1534      }      }
1535    
1536      /**      /**
# Line 1266  namespace LinuxSampler { namespace gig { Line 1539  namespace LinuxSampler { namespace gig {
1539       *  @param itSysexEvent - sysex data size and time stamp of the sysex event       *  @param itSysexEvent - sysex data size and time stamp of the sysex event
1540       */       */
1541      void Engine::ProcessSysex(Pool<Event>::Iterator& itSysexEvent) {      void Engine::ProcessSysex(Pool<Event>::Iterator& itSysexEvent) {
1542          RingBuffer<uint8_t>::NonVolatileReader reader = pSysexBuffer->get_non_volatile_reader();          RingBuffer<uint8_t,false>::NonVolatileReader reader = pSysexBuffer->get_non_volatile_reader();
1543    
1544          uint8_t exclusive_status, id;          uint8_t exclusive_status, id;
1545          if (!reader.pop(&exclusive_status)) goto free_sysex_data;          if (!reader.pop(&exclusive_status)) goto free_sysex_data;
# Line 1285  namespace LinuxSampler { namespace gig { Line 1558  namespace LinuxSampler { namespace gig {
1558    
1559                  // command address                  // command address
1560                  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)
1561                  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
1562                  if (reader.read(&addr[0], 3) != 3) goto free_sysex_data;                  if (reader.read(&addr[0], 3) != 3) goto free_sysex_data;
1563                  if (addr[0] == 0x40 && addr[1] == 0x00) { // System Parameters                  if (addr[0] == 0x40 && addr[1] == 0x00) { // System Parameters
1564                      dmsg(3,("\tSystem Parameter\n"));                      dmsg(3,("\tSystem Parameter\n"));
# Line 1332  namespace LinuxSampler { namespace gig { Line 1605  namespace LinuxSampler { namespace gig {
1605       *                     question       *                     question
1606       * @param DataSize   - size of the GS message data (in bytes)       * @param DataSize   - size of the GS message data (in bytes)
1607       */       */
1608      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) {
1609          RingBuffer<uint8_t>::NonVolatileReader reader = AddrReader;          RingBuffer<uint8_t,false>::NonVolatileReader reader = AddrReader;
1610          uint bytes = 3 /*addr*/ + DataSize;          uint bytes = 3 /*addr*/ + DataSize;
1611          uint8_t addr_and_data[bytes];          uint8_t addr_and_data[bytes];
1612          reader.read(&addr_and_data[0], bytes);          reader.read(&addr_and_data[0], bytes);
# Line 1452  namespace LinuxSampler { namespace gig { Line 1725  namespace LinuxSampler { namespace gig {
1725      }      }
1726    
1727      String Engine::Version() {      String Engine::Version() {
1728          String s = "$Revision: 1.56 $";          String s = "$Revision: 1.77 $";
1729          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
1730      }      }
1731    
1732        InstrumentManager* Engine::GetInstrumentManager() {
1733            return &instruments;
1734        }
1735    
1736        // static constant initializers
1737        const float* Engine::VolumeCurve(InitVolumeCurve());
1738        const float* Engine::PanCurve(InitPanCurve());
1739        const float* Engine::CrossfadeCurve(InitCrossfadeCurve());
1740    
1741        float* Engine::InitVolumeCurve() {
1742            // line-segment approximation
1743            const float segments[] = {
1744                0, 0, 2, 0.0046, 16, 0.016, 31, 0.051, 45, 0.115, 54.5, 0.2,
1745                64.5, 0.39, 74, 0.74, 92, 1.03, 114, 1.94, 119.2, 2.2, 127, 2.2
1746            };
1747            return InitCurve(segments);
1748        }
1749    
1750        float* Engine::InitPanCurve() {
1751            // line-segment approximation
1752            const float segments[] = {
1753                0, 0, 1, 0,
1754                2, 0.05, 31.5, 0.7, 51, 0.851, 74.5, 1.12,
1755                127, 1.41, 128, 1.41
1756            };
1757            return InitCurve(segments, 129);
1758        }
1759    
1760        float* Engine::InitCrossfadeCurve() {
1761            // line-segment approximation
1762            const float segments[] = {
1763                0, 0, 1, 0.03, 10, 0.1, 51, 0.58, 127, 1
1764            };
1765            return InitCurve(segments);
1766        }
1767    
1768        float* Engine::InitCurve(const float* segments, int size) {
1769            float* y = new float[size];
1770            for (int x = 0 ; x < size ; x++) {
1771                if (x > segments[2]) segments += 2;
1772                y[x] = segments[1] + (x - segments[0]) *
1773                    (segments[3] - segments[1]) / (segments[2] - segments[0]);
1774            }
1775            return y;
1776        }
1777    
1778        /**
1779         * Changes the instrument for an engine channel.
1780         *
1781         * @param pEngineChannel - engine channel on which the instrument
1782         *                         should be changed
1783         * @param pInstrument - new instrument
1784         * @returns a list of dimension regions from the old instrument
1785         *          that are still in use
1786         */
1787        ::gig::DimensionRegion** Engine::ChangeInstrument(EngineChannel* pEngineChannel, ::gig::Instrument* pInstrument) {
1788            instrument_change_command_t command;
1789            command.pEngineChannel = pEngineChannel;
1790            command.pInstrument = pInstrument;
1791            InstrumentChangeQueue->push(&command);
1792    
1793            // wait for the audio thread to confirm that the instrument
1794            // change has been done
1795            instrument_change_reply_t reply;
1796            while (InstrumentChangeReplyQueue->pop(&reply) == 0) {
1797                usleep(10000);
1798            }
1799            return pDimRegionsInUse;
1800        }
1801    
1802  }} // namespace LinuxSampler::gig  }} // namespace LinuxSampler::gig

Legend:
Removed from v.781  
changed lines
  Added in v.1248

  ViewVC Help
Powered by ViewVC