/[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 1321 by schoenebeck, Tue Sep 4 01:12:49 2007 UTC revision 1722 by schoenebeck, Thu Apr 10 17:41:32 2008 UTC
# Line 2  Line 2 
2   *                                                                         *   *                                                                         *
3   *   LinuxSampler - modular, streaming capable sampler                     *   *   LinuxSampler - modular, streaming capable sampler                     *
4   *                                                                         *   *                                                                         *
5   *   Copyright (C) 2003,2004 by Benno Senoner and Christian Schoenebeck   *   *   Copyright (C) 2003,2004 by Benno Senoner and Christian Schoenebeck    *
6   *   Copyright (C) 2005-2007 Christian Schoenebeck                        *   *   Copyright (C) 2005-2008 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    
32    #include "../../common/global_private.h"
33    
34  namespace LinuxSampler { namespace gig {  namespace LinuxSampler { namespace gig {
35    
36      InstrumentResourceManager Engine::instruments;      InstrumentResourceManager Engine::instruments;
# Line 72  namespace LinuxSampler { namespace gig { Line 74  namespace LinuxSampler { namespace gig {
74    
75      /**      /**
76       * Once an engine channel is disconnected from an audio output device,       * Once an engine channel is disconnected from an audio output device,
77       * it wil immediately call this method to unregister itself from the       * it will immediately call this method to unregister itself from the
78       * engine instance and if that engine instance is not used by any other       * engine instance and if that engine instance is not used by any other
79       * engine channel anymore, then that engine instance will be destroyed.       * engine channel anymore, then that engine instance will be destroyed.
80       *       *
# Line 106  namespace LinuxSampler { namespace gig { Line 108  namespace LinuxSampler { namespace gig {
108          pEventQueue        = new RingBuffer<Event,false>(CONFIG_MAX_EVENTS_PER_FRAGMENT, 0);          pEventQueue        = new RingBuffer<Event,false>(CONFIG_MAX_EVENTS_PER_FRAGMENT, 0);
109          pEventPool         = new Pool<Event>(CONFIG_MAX_EVENTS_PER_FRAGMENT);          pEventPool         = new Pool<Event>(CONFIG_MAX_EVENTS_PER_FRAGMENT);
110          pVoicePool         = new Pool<Voice>(CONFIG_MAX_VOICES);          pVoicePool         = new Pool<Voice>(CONFIG_MAX_VOICES);
111          pDimRegionsInUse   = new ::gig::DimensionRegion*[CONFIG_MAX_VOICES + 1];          pDimRegionPool[0]  = new Pool< ::gig::DimensionRegion*>(CONFIG_MAX_VOICES);
112            pDimRegionPool[1]  = new Pool< ::gig::DimensionRegion*>(CONFIG_MAX_VOICES);
113          pVoiceStealingQueue = new RTList<Event>(pEventPool);          pVoiceStealingQueue = new RTList<Event>(pEventPool);
114          pGlobalEvents      = new RTList<Event>(pEventPool);          pGlobalEvents      = new RTList<Event>(pEventPool);
         InstrumentChangeQueue      = new RingBuffer<instrument_change_command_t,false>(1, 0);  
         InstrumentChangeReplyQueue = new RingBuffer<instrument_change_reply_t,false>(1, 0);  
115    
116          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()) {
117              iterVoice->SetEngine(this);              iterVoice->SetEngine(this);
# Line 143  namespace LinuxSampler { namespace gig { Line 144  namespace LinuxSampler { namespace gig {
144          if (pVoiceStealingQueue) delete pVoiceStealingQueue;          if (pVoiceStealingQueue) delete pVoiceStealingQueue;
145          if (pSysexBuffer) delete pSysexBuffer;          if (pSysexBuffer) delete pSysexBuffer;
146          if (pGlobalEvents) delete pGlobalEvents;          if (pGlobalEvents) delete pGlobalEvents;
147          if (InstrumentChangeQueue) delete InstrumentChangeQueue;          if (pDimRegionPool[0]) delete pDimRegionPool[0];
148          if (InstrumentChangeReplyQueue) delete InstrumentChangeReplyQueue;          if (pDimRegionPool[1]) delete pDimRegionPool[1];
         if (pDimRegionsInUse) delete[] pDimRegionsInUse;  
149          ResetSuspendedRegions();          ResetSuspendedRegions();
150          Unregister();          Unregister();
151      }      }
# Line 189  namespace LinuxSampler { namespace gig { Line 189  namespace LinuxSampler { namespace gig {
189       * engine afterwards by calling @c ResumeAll() later on!       * engine afterwards by calling @c ResumeAll() later on!
190       */       */
191      void Engine::SuspendAll() {      void Engine::SuspendAll() {
192          dmsg(1,("gig::Engine: Suspending all ...\n"));          dmsg(2,("gig::Engine: Suspending all ...\n"));
193          // stop the engine, so we can safely modify the engine's          // stop the engine, so we can safely modify the engine's
194          // data structures from this foreign thread          // data structures from this foreign thread
195          DisableAndLock();          DisableAndLock();
# Line 223  namespace LinuxSampler { namespace gig { Line 223  namespace LinuxSampler { namespace gig {
223              if (!iPendingStreamDeletions) break;              if (!iPendingStreamDeletions) break;
224              usleep(10000); // sleep for 10ms              usleep(10000); // sleep for 10ms
225          }          }
226          dmsg(1,("gig::Engine: Everything suspended.\n"));          dmsg(2,("gig::Engine: Everything suspended.\n"));
227      }      }
228    
229      /**      /**
# Line 245  namespace LinuxSampler { namespace gig { Line 245  namespace LinuxSampler { namespace gig {
245       * @param pRegion - region the engine shall stop using       * @param pRegion - region the engine shall stop using
246       */       */
247      void Engine::Suspend(::gig::Region* pRegion) {      void Engine::Suspend(::gig::Region* pRegion) {
248          dmsg(1,("gig::Engine: Suspending Region %x ...\n",pRegion));          dmsg(2,("gig::Engine: Suspending Region %x ...\n",pRegion));
249          SuspendedRegionsMutex.Lock();          SuspendedRegionsMutex.Lock();
250          SuspensionChangeOngoing.Set(true);          SuspensionChangeOngoing.Set(true);
251          pPendingRegionSuspension = pRegion;          pPendingRegionSuspension = pRegion;
252          SuspensionChangeOngoing.WaitAndUnlockIf(true);          SuspensionChangeOngoing.WaitAndUnlockIf(true);
253          SuspendedRegionsMutex.Unlock();          SuspendedRegionsMutex.Unlock();
254          dmsg(1,("gig::Engine: Region %x suspended.",pRegion));          dmsg(2,("gig::Engine: Region %x suspended.",pRegion));
255      }      }
256    
257      /**      /**
# Line 261  namespace LinuxSampler { namespace gig { Line 261  namespace LinuxSampler { namespace gig {
261       * @param pRegion - region the engine shall be allowed to use again       * @param pRegion - region the engine shall be allowed to use again
262       */       */
263      void Engine::Resume(::gig::Region* pRegion) {      void Engine::Resume(::gig::Region* pRegion) {
264          dmsg(1,("gig::Engine: Resuming Region %x ...\n",pRegion));          dmsg(2,("gig::Engine: Resuming Region %x ...\n",pRegion));
265          SuspendedRegionsMutex.Lock();          SuspendedRegionsMutex.Lock();
266          SuspensionChangeOngoing.Set(true);          SuspensionChangeOngoing.Set(true);
267          pPendingRegionResumption = pRegion;          pPendingRegionResumption = pRegion;
268          SuspensionChangeOngoing.WaitAndUnlockIf(true);          SuspensionChangeOngoing.WaitAndUnlockIf(true);
269          SuspendedRegionsMutex.Unlock();          SuspendedRegionsMutex.Unlock();
270          dmsg(1,("gig::Engine: Region %x resumed.\n",pRegion));          dmsg(2,("gig::Engine: Region %x resumed.\n",pRegion));
271      }      }
272    
273      /**      /**
# Line 458  namespace LinuxSampler { namespace gig { Line 458  namespace LinuxSampler { namespace gig {
458              // free request slot for next caller (and to make sure that              // free request slot for next caller (and to make sure that
459              // we're not going to process the same request in the next cycle)              // we're not going to process the same request in the next cycle)
460              pPendingRegionSuspension = NULL;              pPendingRegionSuspension = NULL;
461              // if no disk stream deletions are pending, awaker other side, as              // if no disk stream deletions are pending, awaken other side, as
462              // we're done in this case              // we're done in this case
463              if (!iPendingStreamDeletions) SuspensionChangeOngoing.Set(false);              if (!iPendingStreamDeletions) SuspensionChangeOngoing.Set(false);
464          }          }
# Line 569  namespace LinuxSampler { namespace gig { Line 569  namespace LinuxSampler { namespace gig {
569       *  @returns       0 on success       *  @returns       0 on success
570       */       */
571      int Engine::RenderAudio(uint Samples) {      int Engine::RenderAudio(uint Samples) {
572          dmsg(7,("RenderAudio(Samples=%d)\n", Samples));          dmsg(8,("RenderAudio(Samples=%d)\n", Samples));
573    
574          // return if engine disabled          // return if engine disabled
575          if (EngineDisabled.Pop()) {          if (EngineDisabled.Pop()) {
# Line 611  namespace LinuxSampler { namespace gig { Line 611  namespace LinuxSampler { namespace gig {
611          ActiveVoiceCountTemp = 0;          ActiveVoiceCountTemp = 0;
612    
613          // handle instrument change commands          // handle instrument change commands
614          instrument_change_command_t command;          bool instrumentChanged = false;
615          if (InstrumentChangeQueue->pop(&command) > 0) {          for (int i = 0; i < engineChannels.size(); i++) {
616              EngineChannel* pEngineChannel = command.pEngineChannel;              EngineChannel* pEngineChannel = engineChannels[i];
             pEngineChannel->pInstrument = command.pInstrument;  
   
             //TODO: this is a lazy solution ATM and not safe in case somebody is currently editing the instrument we're currently switching to (we should store all suspended regions on instrument manager side and when switching to another instrument copy that list to the engine's local list of suspensions  
             ResetSuspendedRegions();  
617    
618              // iterate through all active voices and mark their              // as we're going to (carefully) write some status to the
619              // dimension regions as "in use". The instrument resource              // synchronized struct, we cast away the const
620              // manager may delete all of the instrument except the              EngineChannel::instrument_change_command_t& cmd =
621              // dimension regions and samples that are in use.                  const_cast<EngineChannel::instrument_change_command_t&>(pEngineChannel->InstrumentChangeCommandReader.Lock());
622              int i = 0;  
623              RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();              pEngineChannel->pDimRegionsInUse = cmd.pDimRegionsInUse;
624              RTList<uint>::Iterator end    = pEngineChannel->pActiveKeys->end();              pEngineChannel->pDimRegionsInUse->clear();
625              while (iuiKey != end) { // iterate through all active keys  
626                  midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];              if (cmd.bChangeInstrument) {
627                  ++iuiKey;                  // change instrument
628                    dmsg(5,("Engine: instrument change command received\n"));
629                    cmd.bChangeInstrument = false;
630                    pEngineChannel->pInstrument = cmd.pInstrument;
631                    instrumentChanged = true;
632    
633                    // Iterate through all active voices and mark them as
634                    // "orphans", which means that the dimension regions
635                    // and samples they use should be released to the
636                    // instrument resource manager when the voices die.
637                    int i = 0;
638                    RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
639                    RTList<uint>::Iterator end    = pEngineChannel->pActiveKeys->end();
640                    while (iuiKey != end) { // iterate through all active keys
641                        midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
642                        ++iuiKey;
643    
644                  RTList<Voice>::Iterator itVoice     = pKey->pActiveVoices->first();                      RTList<Voice>::Iterator itVoice     = pKey->pActiveVoices->first();
645                  RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();                      RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();
646                  for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key                      for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
                     if (!itVoice->Orphan) {  
647                          itVoice->Orphan = true;                          itVoice->Orphan = true;
                         pDimRegionsInUse[i++] = itVoice->pDimRgn;  
648                      }                      }
649                  }                  }
650              }              }
651              pDimRegionsInUse[i] = 0; // end of list          }
652            if (instrumentChanged) {
653              // send a reply to the calling thread, which is waiting              //TODO: this is a lazy solution ATM and not safe in case somebody is currently editing the instrument we're currently switching to (we should store all suspended regions on instrument manager side and when switching to another instrument copy that list to the engine's local list of suspensions
654              instrument_change_reply_t reply;              ResetSuspendedRegions();
             InstrumentChangeReplyQueue->push(&reply);  
655          }          }
656    
657          // handle events on all engine channels          // handle events on all engine channels
# Line 686  namespace LinuxSampler { namespace gig { Line 694  namespace LinuxSampler { namespace gig {
694          // been deleted by the disk thread          // been deleted by the disk thread
695          if (iPendingStreamDeletions) ProcessPendingStreamDeletions();          if (iPendingStreamDeletions) ProcessPendingStreamDeletions();
696    
697            for (int i = 0; i < engineChannels.size(); i++) {
698                engineChannels[i]->InstrumentChangeCommandReader.Unlock();
699            }
700          FrameTime += Samples;          FrameTime += Samples;
701    
702          return 0;          return 0;
# Line 767  namespace LinuxSampler { namespace gig { Line 778  namespace LinuxSampler { namespace gig {
778                  // now render current voice                  // now render current voice
779                  itVoice->Render(Samples);                  itVoice->Render(Samples);
780                  if (itVoice->IsActive()) { // still active                  if (itVoice->IsActive()) { // still active
781                        if (!itVoice->Orphan) {
782                            *(pEngineChannel->pDimRegionsInUse->allocAppend()) = itVoice->pDimRgn;
783                        }
784                      ActiveVoiceCountTemp++;                      ActiveVoiceCountTemp++;
785                      voiceCount++;                      voiceCount++;
786    
# Line 778  namespace LinuxSampler { namespace gig { Line 792  namespace LinuxSampler { namespace gig {
792                  }                  }
793              }              }
794          }          }
795            
796          pEngineChannel->SetVoiceCount(voiceCount);          pEngineChannel->SetVoiceCount(voiceCount);
797          pEngineChannel->SetDiskStreamCount(streamCount);          pEngineChannel->SetDiskStreamCount(streamCount);
798      }      }
# Line 807  namespace LinuxSampler { namespace gig { Line 821  namespace LinuxSampler { namespace gig {
821              if (itNewVoice) {              if (itNewVoice) {
822                  itNewVoice->Render(Samples);                  itNewVoice->Render(Samples);
823                  if (itNewVoice->IsActive()) { // still active                  if (itNewVoice->IsActive()) { // still active
824                        *(pEngineChannel->pDimRegionsInUse->allocAppend()) = itNewVoice->pDimRgn;
825                      ActiveVoiceCountTemp++;                      ActiveVoiceCountTemp++;
826                      pEngineChannel->SetVoiceCount(pEngineChannel->GetVoiceCount() + 1);                      pEngineChannel->SetVoiceCount(pEngineChannel->GetVoiceCount() + 1);
827    
# Line 842  namespace LinuxSampler { namespace gig { Line 857  namespace LinuxSampler { namespace gig {
857       *                         this audio fragment cycle       *                         this audio fragment cycle
858       */       */
859      void Engine::RouteAudio(EngineChannel* pEngineChannel, uint Samples) {      void Engine::RouteAudio(EngineChannel* pEngineChannel, uint Samples) {
860          // route master signal          // route dry signal
861          {          {
862              AudioChannel* pDstL = pAudioOutputDevice->Channel(pEngineChannel->AudioDeviceChannelLeft);              AudioChannel* pDstL = pAudioOutputDevice->Channel(pEngineChannel->AudioDeviceChannelLeft);
863              AudioChannel* pDstR = pAudioOutputDevice->Channel(pEngineChannel->AudioDeviceChannelRight);              AudioChannel* pDstR = pAudioOutputDevice->Channel(pEngineChannel->AudioDeviceChannelRight);
# Line 853  namespace LinuxSampler { namespace gig { Line 868  namespace LinuxSampler { namespace gig {
868          {          {
869              for (int iFxSend = 0; iFxSend < pEngineChannel->GetFxSendCount(); iFxSend++) {              for (int iFxSend = 0; iFxSend < pEngineChannel->GetFxSendCount(); iFxSend++) {
870                  FxSend* pFxSend = pEngineChannel->GetFxSend(iFxSend);                  FxSend* pFxSend = pEngineChannel->GetFxSend(iFxSend);
871                  // left channel                  for (int iChan = 0; iChan < 2; ++iChan) {
872                  const int iDstL = pFxSend->DestinationChannel(0);                      AudioChannel* pSource =
873                  if (iDstL < 0) {                          (iChan)
874                      dmsg(1,("Engine::RouteAudio() Error: invalid FX send (L) destination channel"));                              ? pEngineChannel->pChannelRight
875                  } else {                              : pEngineChannel->pChannelLeft;
876                      AudioChannel* pDstL = pAudioOutputDevice->Channel(iDstL);                      const int iDstChan = pFxSend->DestinationChannel(iChan);
877                      if (!pDstL) {                      if (iDstChan < 0) {
878                          dmsg(1,("Engine::RouteAudio() Error: invalid FX send (L) destination channel"));                          dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination channel (%d->%d)", ((iChan) ? "R" : "L"), iChan, iDstChan));
879                      } else pEngineChannel->pChannelLeft->MixTo(pDstL, Samples, pFxSend->Level());                          goto channel_cleanup;
880                  }                      }
881                  // right channel                      AudioChannel* pDstChan = NULL;
882                  const int iDstR = pFxSend->DestinationChannel(1);                      if (pFxSend->DestinationMasterEffectChain() >= 0) { // fx send routed to an internal master effect
883                  if (iDstR < 0) {                          EffectChain* pEffectChain =
884                      dmsg(1,("Engine::RouteAudio() Error: invalid FX send (R) destination channel"));                              pAudioOutputDevice->MasterEffectChain(
885                  } else {                                  pFxSend->DestinationMasterEffectChain()
886                      AudioChannel* pDstR = pAudioOutputDevice->Channel(iDstR);                              );
887                      if (!pDstR) {                          if (!pEffectChain) {
888                          dmsg(1,("Engine::RouteAudio() Error: invalid FX send (R) destination channel"));                              dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination effect chain %d", ((iChan) ? "R" : "L"), pFxSend->DestinationMasterEffectChain()));
889                      } else pEngineChannel->pChannelRight->MixTo(pDstR, Samples, pFxSend->Level());                              goto channel_cleanup;
890                            }
891                            Effect* pEffect =
892                                pEffectChain->GetEffect(
893                                    pFxSend->DestinationMasterEffect()
894                                );
895                            if (!pEffect) {
896                                dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination effect %d of effect chain %d", ((iChan) ? "R" : "L"), pFxSend->DestinationMasterEffect(), pFxSend->DestinationMasterEffectChain()));
897                                goto channel_cleanup;
898                            }
899                            pDstChan = pEffect->InputChannel(iDstChan);
900                        } else { // FX send routed directly to an audio output channel
901                            pDstChan = pAudioOutputDevice->Channel(iDstChan);
902                        }
903                        if (!pDstChan) {
904                            dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination channel (%d->%d)", ((iChan) ? "R" : "L"), iChan, iDstChan));
905                            goto channel_cleanup;
906                        }
907                        pSource->MixTo(pDstChan, Samples, pFxSend->Level());
908                  }                  }
909              }              }
910          }          }
911            channel_cleanup:
912          // reset buffers with silence (zero out) for the next audio cycle          // reset buffers with silence (zero out) for the next audio cycle
913          pEngineChannel->pChannelLeft->Clear();          pEngineChannel->pChannelLeft->Clear();
914          pEngineChannel->pChannelRight->Clear();          pEngineChannel->pChannelRight->Clear();
# Line 1603  namespace LinuxSampler { namespace gig { Line 1637  namespace LinuxSampler { namespace gig {
1637      void Engine::ProcessControlChange(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itControlChangeEvent) {      void Engine::ProcessControlChange(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itControlChangeEvent) {
1638          dmsg(4,("Engine::ContinuousController cc=%d v=%d\n", itControlChangeEvent->Param.CC.Controller, itControlChangeEvent->Param.CC.Value));          dmsg(4,("Engine::ContinuousController cc=%d v=%d\n", itControlChangeEvent->Param.CC.Controller, itControlChangeEvent->Param.CC.Value));
1639    
1640            // handle the "control triggered" MIDI rule: a control change
1641            // event can trigger a new note on or note off event
1642            if (pEngineChannel->pInstrument) {
1643    
1644                ::gig::MidiRule* rule;
1645                for (int i = 0 ; (rule = pEngineChannel->pInstrument->GetMidiRule(i)) ; i++) {
1646    
1647                    if (::gig::MidiRuleCtrlTrigger* ctrlTrigger =
1648                        dynamic_cast< ::gig::MidiRuleCtrlTrigger*>(rule)) {
1649                        if (itControlChangeEvent->Param.CC.Controller ==
1650                            ctrlTrigger->ControllerNumber) {
1651    
1652                            uint8_t oldCCValue = pEngineChannel->ControllerTable[
1653                                itControlChangeEvent->Param.CC.Controller];
1654                            uint8_t newCCValue = itControlChangeEvent->Param.CC.Value;
1655    
1656                            for (int i = 0 ; i < ctrlTrigger->Triggers ; i++) {
1657                                ::gig::MidiRuleCtrlTrigger::trigger_t* pTrigger =
1658                                      &ctrlTrigger->pTriggers[i];
1659    
1660                                // check if the controller has passed the
1661                                // trigger point in the right direction
1662                                if ((pTrigger->Descending &&
1663                                     oldCCValue > pTrigger->TriggerPoint &&
1664                                     newCCValue <= pTrigger->TriggerPoint) ||
1665                                    (!pTrigger->Descending &&
1666                                     oldCCValue < pTrigger->TriggerPoint &&
1667                                     newCCValue >= pTrigger->TriggerPoint)) {
1668    
1669                                    RTList<Event>::Iterator itNewEvent = pGlobalEvents->allocAppend();
1670                                    if (itNewEvent) {
1671                                        *itNewEvent = *itControlChangeEvent;
1672                                        itNewEvent->Param.Note.Key = pTrigger->Key;
1673    
1674                                        if (pTrigger->NoteOff || pTrigger->Velocity == 0) {
1675                                            itNewEvent->Type = Event::type_note_off;
1676                                            itNewEvent->Param.Note.Velocity = 100;
1677    
1678                                            ProcessNoteOff(pEngineChannel, itNewEvent);
1679                                        } else {
1680                                            itNewEvent->Type = Event::type_note_on;
1681                                            //TODO: if Velocity is 255, the triggered velocity should
1682                                            // depend on how fast the controller is moving
1683                                            itNewEvent->Param.Note.Velocity =
1684                                                pTrigger->Velocity == 255 ? 100 :
1685                                                pTrigger->Velocity;
1686    
1687                                            ProcessNoteOn(pEngineChannel, itNewEvent);
1688                                        }
1689                                    }
1690                                    else dmsg(1,("Event pool emtpy!\n"));
1691                                }
1692                            }
1693                        }
1694                    }
1695                }
1696            }
1697    
1698          // update controller value in the engine channel's controller table          // update controller value in the engine channel's controller table
1699          pEngineChannel->ControllerTable[itControlChangeEvent->Param.CC.Controller] = itControlChangeEvent->Param.CC.Value;          pEngineChannel->ControllerTable[itControlChangeEvent->Param.CC.Controller] = itControlChangeEvent->Param.CC.Value;
1700    
# Line 1686  namespace LinuxSampler { namespace gig { Line 1778  namespace LinuxSampler { namespace gig {
1778                  break;                  break;
1779              }              }
1780              case 65: { // portamento on / off              case 65: { // portamento on / off
1781                  KillAllVoices(pEngineChannel, itControlChangeEvent);                  const bool bPortamento = itControlChangeEvent->Param.CC.Value >= 64;
1782                  pEngineChannel->PortamentoMode = itControlChangeEvent->Param.CC.Value >= 64;                  if (bPortamento != pEngineChannel->PortamentoMode)
1783                        KillAllVoices(pEngineChannel, itControlChangeEvent);
1784                    pEngineChannel->PortamentoMode = bPortamento;
1785                  break;                  break;
1786              }              }
1787              case 66: { // sostenuto              case 66: { // sostenuto
# Line 1757  namespace LinuxSampler { namespace gig { Line 1851  namespace LinuxSampler { namespace gig {
1851                  break;                  break;
1852              }              }
1853              case 126: { // mono mode on              case 126: { // mono mode on
1854                  KillAllVoices(pEngineChannel, itControlChangeEvent);                  if (!pEngineChannel->SoloMode)
1855                        KillAllVoices(pEngineChannel, itControlChangeEvent);
1856                  pEngineChannel->SoloMode = true;                  pEngineChannel->SoloMode = true;
1857                  break;                  break;
1858              }              }
1859              case 127: { // poly mode on              case 127: { // poly mode on
1860                  KillAllVoices(pEngineChannel, itControlChangeEvent);                  if (pEngineChannel->SoloMode)
1861                        KillAllVoices(pEngineChannel, itControlChangeEvent);
1862                  pEngineChannel->SoloMode = false;                  pEngineChannel->SoloMode = false;
1863                  break;                  break;
1864              }              }
# Line 1772  namespace LinuxSampler { namespace gig { Line 1868  namespace LinuxSampler { namespace gig {
1868          if (!pEngineChannel->fxSends.empty()) {          if (!pEngineChannel->fxSends.empty()) {
1869              for (int iFxSend = 0; iFxSend < pEngineChannel->GetFxSendCount(); iFxSend++) {              for (int iFxSend = 0; iFxSend < pEngineChannel->GetFxSendCount(); iFxSend++) {
1870                  FxSend* pFxSend = pEngineChannel->GetFxSend(iFxSend);                  FxSend* pFxSend = pEngineChannel->GetFxSend(iFxSend);
1871                  if (pFxSend->MidiController() == itControlChangeEvent->Param.CC.Controller)                  if (pFxSend->MidiController() == itControlChangeEvent->Param.CC.Controller) {
1872                      pFxSend->SetLevel(itControlChangeEvent->Param.CC.Value);                      pFxSend->SetLevel(itControlChangeEvent->Param.CC.Value);
1873                      pFxSend->SetInfoChanged(true);                      pFxSend->SetInfoChanged(true);
1874                    }
1875              }              }
1876          }          }
1877      }      }
# Line 1967  namespace LinuxSampler { namespace gig { Line 2064  namespace LinuxSampler { namespace gig {
2064      }      }
2065    
2066      String Engine::Description() {      String Engine::Description() {
2067          return "Gigasampler Engine";          return "Gigasampler Format Engine";
2068      }      }
2069    
2070      String Engine::Version() {      String Engine::Version() {
2071          String s = "$Revision: 1.80 $";          String s = "$Revision: 1.90 $";
2072          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
2073      }      }
2074    
# Line 1980  namespace LinuxSampler { namespace gig { Line 2077  namespace LinuxSampler { namespace gig {
2077      }      }
2078    
2079      // static constant initializers      // static constant initializers
2080      const float* Engine::VolumeCurve(InitVolumeCurve());      const Engine::FloatTable Engine::VolumeCurve(InitVolumeCurve());
2081      const float* Engine::PanCurve(InitPanCurve());      const Engine::FloatTable Engine::PanCurve(InitPanCurve());
2082      const float* Engine::CrossfadeCurve(InitCrossfadeCurve());      const Engine::FloatTable Engine::CrossfadeCurve(InitCrossfadeCurve());
2083    
2084      float* Engine::InitVolumeCurve() {      float* Engine::InitVolumeCurve() {
2085          // line-segment approximation          // line-segment approximation
# Line 2021  namespace LinuxSampler { namespace gig { Line 2118  namespace LinuxSampler { namespace gig {
2118          return y;          return y;
2119      }      }
2120    
     /**  
      * Changes the instrument for an engine channel.  
      *  
      * @param pEngineChannel - engine channel on which the instrument  
      *                         should be changed  
      * @param pInstrument - new instrument  
      * @returns a list of dimension regions from the old instrument  
      *          that are still in use  
      */  
     ::gig::DimensionRegion** Engine::ChangeInstrument(EngineChannel* pEngineChannel, ::gig::Instrument* pInstrument) {  
         instrument_change_command_t command;  
         command.pEngineChannel = pEngineChannel;  
         command.pInstrument = pInstrument;  
         InstrumentChangeQueue->push(&command);  
   
         // wait for the audio thread to confirm that the instrument  
         // change has been done  
         instrument_change_reply_t reply;  
         while (InstrumentChangeReplyQueue->pop(&reply) == 0) {  
             usleep(10000);  
         }  
         return pDimRegionsInUse;  
     }  
   
2121  }} // namespace LinuxSampler::gig  }} // namespace LinuxSampler::gig

Legend:
Removed from v.1321  
changed lines
  Added in v.1722

  ViewVC Help
Powered by ViewVC