/[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 1750 by schoenebeck, Thu Jul 10 15:00:38 2008 UTC revision 1843 by iliev, Sat Feb 21 17:08:18 2009 UTC
# Line 107  namespace LinuxSampler { namespace gig { Line 107  namespace LinuxSampler { namespace gig {
107          pSysexBuffer       = new RingBuffer<uint8_t,false>(CONFIG_SYSEX_BUFFER_SIZE, 0);          pSysexBuffer       = new RingBuffer<uint8_t,false>(CONFIG_SYSEX_BUFFER_SIZE, 0);
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>(GLOBAL_MAX_VOICES);
111          pDimRegionPool[0]  = new Pool< ::gig::DimensionRegion*>(CONFIG_MAX_VOICES);          pDimRegionPool[0]  = new Pool< ::gig::DimensionRegion*>(GLOBAL_MAX_VOICES);
112          pDimRegionPool[1]  = new Pool< ::gig::DimensionRegion*>(CONFIG_MAX_VOICES);          pDimRegionPool[1]  = new Pool< ::gig::DimensionRegion*>(GLOBAL_MAX_VOICES);
113          pVoiceStealingQueue = new RTList<Event>(pEventPool);          pVoiceStealingQueue = new RTList<Event>(pEventPool);
114          pGlobalEvents      = new RTList<Event>(pEventPool);          pGlobalEvents      = new RTList<Event>(pEventPool);
115            iMaxDiskStreams    = GLOBAL_MAX_STREAMS;
116    
117          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()) {
118              iterVoice->SetEngine(this);              iterVoice->SetEngine(this);
# Line 291  namespace LinuxSampler { namespace gig { Line 292  namespace LinuxSampler { namespace gig {
292          // make sure that the engine does not get any sysex messages          // make sure that the engine does not get any sysex messages
293          // while it's reseting          // while it's reseting
294          bool sysexDisabled = MidiInputPort::RemoveSysexListener(this);          bool sysexDisabled = MidiInputPort::RemoveSysexListener(this);
295          ActiveVoiceCount    = 0;          SetVoiceCount(0);
296          ActiveVoiceCountMax = 0;          ActiveVoiceCountMax = 0;
297    
298          // reset voice stealing parameters          // reset voice stealing parameters
# Line 342  namespace LinuxSampler { namespace gig { Line 343  namespace LinuxSampler { namespace gig {
343       * @param pAudioOut - audio output device to connect to       * @param pAudioOut - audio output device to connect to
344       */       */
345      void Engine::Connect(AudioOutputDevice* pAudioOut) {      void Engine::Connect(AudioOutputDevice* pAudioOut) {
346            // caution: don't ignore if connecting to the same device here,
347            // because otherwise SetMaxDiskStreams() implementation won't work anymore!
348    
349          pAudioOutputDevice = pAudioOut;          pAudioOutputDevice = pAudioOut;
350    
351          ResetInternal();          ResetInternal();
# Line 380  namespace LinuxSampler { namespace gig { Line 384  namespace LinuxSampler { namespace gig {
384              delete this->pDiskThread;              delete this->pDiskThread;
385              dmsg(1,("OK\n"));              dmsg(1,("OK\n"));
386          }          }
387          this->pDiskThread = new DiskThread(((pAudioOut->MaxSamplesPerCycle() << CONFIG_MAX_PITCH) << 1) + 6, //FIXME: assuming stereo          this->pDiskThread =
388                                             &instruments);              new DiskThread(
389                    iMaxDiskStreams,
390                    ((pAudioOut->MaxSamplesPerCycle() << CONFIG_MAX_PITCH) << 1) + 6, //FIXME: assuming stereo
391                    &instruments
392                );
393    
394          if (!pDiskThread) {          if (!pDiskThread) {
395              dmsg(0,("gig::Engine  new diskthread = NULL\n"));              dmsg(0,("gig::Engine  new diskthread = NULL\n"));
396              exit(EXIT_FAILURE);              exit(EXIT_FAILURE);
# Line 407  namespace LinuxSampler { namespace gig { Line 416  namespace LinuxSampler { namespace gig {
416                  exit(EXIT_FAILURE);                  exit(EXIT_FAILURE);
417              }              }
418          }          }
419            pVoicePool->clear();
420      }      }
421    
422      /**      /**
# Line 573  namespace LinuxSampler { namespace gig { Line 583  namespace LinuxSampler { namespace gig {
583          // return if engine disabled          // return if engine disabled
584          if (EngineDisabled.Pop()) {          if (EngineDisabled.Pop()) {
585              dmsg(5,("gig::Engine: engine disabled (val=%d)\n",EngineDisabled.GetUnsafe()));              dmsg(5,("gig::Engine: engine disabled (val=%d)\n",EngineDisabled.GetUnsafe()));
586                EngineDisabled.RttDone();
587              return 0;              return 0;
588          }          }
589    
# Line 583  namespace LinuxSampler { namespace gig { Line 594  namespace LinuxSampler { namespace gig {
594          // 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)
595          pEventGenerator->UpdateFragmentTime(Samples);          pEventGenerator->UpdateFragmentTime(Samples);
596    
597          // We only allow a maximum of CONFIG_MAX_VOICES voices to be spawned          // We only allow the given maximum number of voices to be spawned
598          // in each audio fragment. All subsequent request for spawning new          // in each audio fragment. All subsequent request for spawning new
599          // voices in the same audio fragment will be ignored.          // voices in the same audio fragment will be ignored.
600          VoiceSpawnsLeft = CONFIG_MAX_VOICES;          VoiceSpawnsLeft = MaxVoices();
601    
602          // 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
603          // (these are usually just SysEx messages)          // (these are usually just SysEx messages)
# Line 685  namespace LinuxSampler { namespace gig { Line 696  namespace LinuxSampler { namespace gig {
696          pVoiceStealingQueue->clear();          pVoiceStealingQueue->clear();
697    
698          // just some statistics about this engine instance          // just some statistics about this engine instance
699          ActiveVoiceCount = ActiveVoiceCountTemp;          SetVoiceCount(ActiveVoiceCountTemp);
700          if (ActiveVoiceCount > ActiveVoiceCountMax) ActiveVoiceCountMax = ActiveVoiceCount;          if (VoiceCount() > ActiveVoiceCountMax) ActiveVoiceCountMax = VoiceCount();
701    
702          // in case regions were previously suspended and we killed voices          // in case regions were previously suspended and we killed voices
703          // with disk streams due to that, check if those streams have finally          // with disk streams due to that, check if those streams have finally
# Line 698  namespace LinuxSampler { namespace gig { Line 709  namespace LinuxSampler { namespace gig {
709          }          }
710          FrameTime += Samples;          FrameTime += Samples;
711    
712            EngineDisabled.RttDone();
713          return 0;          return 0;
714      }      }
715    
# Line 784  namespace LinuxSampler { namespace gig { Line 796  namespace LinuxSampler { namespace gig {
796                      voiceCount++;                      voiceCount++;
797    
798                      if (itVoice->PlaybackState == Voice::playback_state_disk) {                      if (itVoice->PlaybackState == Voice::playback_state_disk) {
799                          if ((itVoice->DiskStreamRef).State == Stream::state_active) streamCount++;                          if ((itVoice->DiskStreamRef).State != Stream::state_unused) streamCount++;
800                      }                      }
801                  }  else { // voice reached end, is now inactive                  }  else { // voice reached end, is now inactive
802                      FreeVoice(pEngineChannel, itVoice); // remove voice from the list of active voices                      FreeVoice(pEngineChannel, itVoice); // remove voice from the list of active voices
# Line 825  namespace LinuxSampler { namespace gig { Line 837  namespace LinuxSampler { namespace gig {
837                      pEngineChannel->SetVoiceCount(pEngineChannel->GetVoiceCount() + 1);                      pEngineChannel->SetVoiceCount(pEngineChannel->GetVoiceCount() + 1);
838    
839                      if (itNewVoice->PlaybackState == Voice::playback_state_disk) {                      if (itNewVoice->PlaybackState == Voice::playback_state_disk) {
840                          if (itNewVoice->DiskStreamRef.State == Stream::state_active) {                          if (itNewVoice->DiskStreamRef.State != Stream::state_unused) {
841                              pEngineChannel->SetDiskStreamCount(pEngineChannel->GetDiskStreamCount() + 1);                              pEngineChannel->SetDiskStreamCount(pEngineChannel->GetDiskStreamCount() + 1);
842                          }                          }
843                      }                      }
# Line 953  namespace LinuxSampler { namespace gig { Line 965  namespace LinuxSampler { namespace gig {
965       *       *
966       *  @param pData - pointer to sysex data       *  @param pData - pointer to sysex data
967       *  @param Size  - lenght of sysex data (in bytes)       *  @param Size  - lenght of sysex data (in bytes)
968         *  @param pSender - the MIDI input port on which the SysEx message was
969         *                   received
970       */       */
971      void Engine::SendSysex(void* pData, uint Size) {      void Engine::SendSysex(void* pData, uint Size, MidiInputPort* pSender) {
972          Event event             = pEventGenerator->CreateEvent();          Event event             = pEventGenerator->CreateEvent();
973          event.Type              = Event::type_sysex;          event.Type              = Event::type_sysex;
974          event.Param.Sysex.Size  = Size;          event.Param.Sysex.Size  = Size;
975          event.pEngineChannel    = NULL; // as Engine global event          event.pEngineChannel    = NULL; // as Engine global event
976            event.pMidiInputPort    = pSender;
977          if (pEventQueue->write_space() > 0) {          if (pEventQueue->write_space() > 0) {
978              if (pSysexBuffer->write_space() >= Size) {              if (pSysexBuffer->write_space() >= Size) {
979                  // copy sysex data to input buffer                  // copy sysex data to input buffer
# Line 1901  namespace LinuxSampler { namespace gig { Line 1916  namespace LinuxSampler { namespace gig {
1916                  switch (sub_id1) {                  switch (sub_id1) {
1917                      case 0x04: // Device Control                      case 0x04: // Device Control
1918                          switch (sub_id2) {                          switch (sub_id2) {
1919                              case 0x01: // Master Volume                              case 0x01: { // Master Volume
1920                                  GLOBAL_VOLUME =                                  const double volume =
1921                                      double((uint(val_msb)<<7) | uint(val_lsb)) / 16383.0;                                      double((uint(val_msb)<<7) | uint(val_lsb)) / 16383.0;
1922                                    #if CONFIG_MASTER_VOLUME_SYSEX_BY_PORT
1923                                    // apply volume to all sampler channels that
1924                                    // are connected to the same MIDI input port
1925                                    // this sysex message arrived on
1926                                    for (int i = 0; i < engineChannels.size(); ++i) {
1927                                        EngineChannel* pEngineChannel = engineChannels[i];
1928                                        if (pEngineChannel->GetMidiInputPort() ==
1929                                            itSysexEvent->pMidiInputPort)
1930                                        {
1931                                            pEngineChannel->Volume(volume);
1932                                        }
1933                                    }
1934                                    #else
1935                                    // apply volume globally to the whole sampler
1936                                    GLOBAL_VOLUME = volume;
1937                                    #endif // CONFIG_MASTER_VOLUME_SYSEX_BY_PORT
1938                                  break;                                  break;
1939                                }
1940                          }                          }
1941                          break;                          break;
1942                  }                  }
# Line 1953  namespace LinuxSampler { namespace gig { Line 1985  namespace LinuxSampler { namespace gig {
1985                              if (!reader.pop(&map)) goto free_sysex_data;                              if (!reader.pop(&map)) goto free_sysex_data;
1986                              for (int i = 0; i < engineChannels.size(); ++i) {                              for (int i = 0; i < engineChannels.size(); ++i) {
1987                                  EngineChannel* pEngineChannel = engineChannels[i];                                  EngineChannel* pEngineChannel = engineChannels[i];
1988                                  if (pEngineChannel->midiChannel == part ||                                  if (
1989                                      pEngineChannel->midiChannel == midi_chan_all                                      (pEngineChannel->midiChannel == part ||
1990                                         pEngineChannel->midiChannel == midi_chan_all) &&
1991                                         pEngineChannel->GetMidiInputPort() == itSysexEvent->pMidiInputPort
1992                                  ) {                                  ) {
1993                                      try {                                      try {
1994                                          pEngineChannel->SetMidiInstrumentMap(map);                                          pEngineChannel->SetMidiInstrumentMap(map);
# Line 2076  namespace LinuxSampler { namespace gig { Line 2110  namespace LinuxSampler { namespace gig {
2110      }      }
2111    
2112      uint Engine::VoiceCount() {      uint Engine::VoiceCount() {
2113          return ActiveVoiceCount;          return atomic_read(&ActiveVoiceCount);
2114        }
2115    
2116        void Engine::SetVoiceCount(uint Count) {
2117            atomic_set(&ActiveVoiceCount, Count);
2118      }      }
2119    
2120      uint Engine::VoiceCountMax() {      uint Engine::VoiceCountMax() {
2121          return ActiveVoiceCountMax;          return ActiveVoiceCountMax;
2122      }      }
2123    
2124        int Engine::MaxVoices() {
2125            return pVoicePool->poolSize();
2126        }
2127    
2128        void Engine::SetMaxVoices(int iVoices) throw (Exception) {
2129            if (iVoices < 1)
2130                throw Exception("Maximum voices for an engine cannot be set lower than 1");
2131    
2132            SuspendAll();
2133    
2134            // NOTE: we need to clear pDimRegionsInUse before deleting pDimRegionPool,
2135            // otherwise memory corruption will occur if there are active voices (see bug #118)
2136            for (int iChannel = 0; iChannel < engineChannels.size(); iChannel++) {
2137                engineChannels[iChannel]->ClearDimRegionsInUse();
2138            }
2139    
2140            if (pDimRegionPool[0]) delete pDimRegionPool[0];
2141            if (pDimRegionPool[1]) delete pDimRegionPool[1];
2142    
2143            pDimRegionPool[0] = new Pool< ::gig::DimensionRegion*>(iVoices);
2144            pDimRegionPool[1] = new Pool< ::gig::DimensionRegion*>(iVoices);
2145    
2146            for (int iChannel = 0; iChannel < engineChannels.size(); iChannel++) {
2147                engineChannels[iChannel]->ResetDimRegionsInUse();
2148            }
2149    
2150            try {
2151                pVoicePool->resizePool(iVoices);
2152            } catch (...) {
2153                throw Exception("FATAL: Could not resize voice pool!");
2154            }
2155    
2156            for (RTList<Voice>::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
2157                iterVoice->SetEngine(this);
2158                iterVoice->pDiskThread = this->pDiskThread;
2159            }
2160            pVoicePool->clear();
2161    
2162            ResumeAll();
2163        }
2164    
2165      bool Engine::DiskStreamSupported() {      bool Engine::DiskStreamSupported() {
2166          return true;          return true;
2167      }      }
2168    
2169      uint Engine::DiskStreamCount() {      uint Engine::DiskStreamCount() {
2170          return (pDiskThread) ? pDiskThread->ActiveStreamCount : 0;          return (pDiskThread) ? pDiskThread->GetActiveStreamCount() : 0;
2171      }      }
2172    
2173      uint Engine::DiskStreamCountMax() {      uint Engine::DiskStreamCountMax() {
2174          return (pDiskThread) ? pDiskThread->ActiveStreamCountMax : 0;          return (pDiskThread) ? pDiskThread->ActiveStreamCountMax : 0;
2175      }      }
2176    
2177        int Engine::MaxDiskStreams() {
2178            return iMaxDiskStreams;
2179        }
2180    
2181        void Engine::SetMaxDiskStreams(int iStreams) throw (Exception) {
2182            if (iStreams < 0)
2183                throw Exception("Maximum disk streams for an engine cannot be set lower than 0");
2184    
2185            SuspendAll();
2186    
2187            iMaxDiskStreams = iStreams;
2188    
2189            // reconnect to audio output device, because that will automatically
2190            // recreate the disk thread with the required amount of streams
2191            if (pAudioOutputDevice) Connect(pAudioOutputDevice);
2192    
2193            ResumeAll();
2194        }
2195    
2196      String Engine::DiskStreamBufferFillBytes() {      String Engine::DiskStreamBufferFillBytes() {
2197          return pDiskThread->GetBufferFillBytes();          return pDiskThread->GetBufferFillBytes();
2198      }      }
# Line 2112  namespace LinuxSampler { namespace gig { Line 2210  namespace LinuxSampler { namespace gig {
2210      }      }
2211    
2212      String Engine::Version() {      String Engine::Version() {
2213          String s = "$Revision: 1.94 $";          String s = "$Revision: 1.100 $";
2214          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
2215      }      }
2216    

Legend:
Removed from v.1750  
changed lines
  Added in v.1843

  ViewVC Help
Powered by ViewVC