/[svn]/linuxsampler/trunk/src/engines/InstrumentManagerBase.h
ViewVC logotype

Diff of /linuxsampler/trunk/src/engines/InstrumentManagerBase.h

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 2275 by schoenebeck, Mon Sep 19 21:48:45 2011 UTC revision 2687 by schoenebeck, Sun Jan 4 17:16:05 2015 UTC
# Line 3  Line 3 
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 - 2011 Christian Schoenebeck                       *   *   Copyright (C) 2005 - 2008 Christian Schoenebeck                       *
7   *   Copyright (C) 2009 Grigor Iliev                                       *   *   Copyright (C) 2009 - 2013 Christian Schoenebeck and Grigor Iliev      *
8   *                                                                         *   *                                                                         *
9   *   This library is free software; you can redistribute it and/or modify  *   *   This library is free software; you can redistribute it and/or modify  *
10   *   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 25  Line 25 
25  #ifndef __LS_INSTRUMENTMANAGERBASE_H__  #ifndef __LS_INSTRUMENTMANAGERBASE_H__
26  #define __LS_INSTRUMENTMANAGERBASE_H__  #define __LS_INSTRUMENTMANAGERBASE_H__
27    
28  #include "InstrumentManager.h"  #include "common/AbstractInstrumentManager.h"
29    #include "../drivers/audio/AudioOutputDeviceFactory.h"
30  #include "AbstractEngine.h"  #include "AbstractEngine.h"
31  #include "AbstractEngineChannel.h"  #include "AbstractEngineChannel.h"
 #include "../common/ResourceManager.h"  
 #include "../common/global_private.h"  
 #include "../drivers/audio/AudioOutputDeviceFactory.h"  
32    
33  // We need to know the maximum number of sample points which are going to  // We need to know the maximum number of sample points which are going to
34  // be processed for each render cycle of the audio output driver, to know  // be processed for each render cycle of the audio output driver, to know
35  // how much initial sample points we need to cache into RAM. If the given  // how much initial sample points we need to cache into RAM. If the given
36  // sampler channel does not have an audio output device assigned yet  // sampler channel does not have an audio output device assigned yet
37  // though, we simply use this default value.  // though, we simply use this default value.
38  #define GIG_RESOURCE_MANAGER_DEFAULT_MAX_SAMPLES_PER_CYCLE     128  #define RESOURCE_MANAGER_DEFAULT_MAX_SAMPLES_PER_CYCLE     128
39    
40  namespace LinuxSampler {  namespace LinuxSampler {
41    
42      template <class F /* Instrument File */, class I /* Instrument */, class R /* Regions */, class S /*Sample */>      template <class F /* Instrument File */, class I /* Instrument */, class R /* Regions */, class S /*Sample */>
43      class InstrumentManagerBase : virtual public InstrumentManager, virtual public ResourceManager<InstrumentManager::instrument_id_t, I> {      class InstrumentManagerBase : public AbstractInstrumentManager, public ResourceManager<InstrumentManager::instrument_id_t, I> {
44          public:          public:
45              struct region_info_t {              struct region_info_t {
46                  int    refCount;                  int    refCount;
# Line 56  namespace LinuxSampler { Line 54  namespace LinuxSampler {
54    
55              typedef ResourceConsumer<I> InstrumentConsumer;              typedef ResourceConsumer<I> InstrumentConsumer;
56    
57              InstrumentManagerBase() { }              InstrumentManagerBase() : AbstractInstrumentManager() { }
58              virtual ~InstrumentManagerBase() { }              virtual ~InstrumentManagerBase() { }
59    
60              virtual InstrumentEditor* LaunchInstrumentEditor(instrument_id_t ID, void* pUserData = NULL) throw (InstrumentManagerException) {              virtual InstrumentEditor* LaunchInstrumentEditor(EngineChannel* pEngineChannel, instrument_id_t ID, void* pUserData = NULL) throw (InstrumentManagerException) OVERRIDE {
61                   throw InstrumentManagerException(                   throw InstrumentManagerException(
62                      "Instrument editing is not supported for this instrument format"                      "Instrument editing is not supported for this instrument format"
63                  );                  );
64              }              }
65    
66              virtual String GetInstrumentDataStructureName(instrument_id_t ID) {              virtual String GetInstrumentDataStructureName(instrument_id_t ID) OVERRIDE {
67                  throw InstrumentManagerException("Not implemented");                  throw InstrumentManagerException("Not implemented");
68              }              }
69    
70              virtual String GetInstrumentDataStructureVersion(instrument_id_t ID) {              virtual String GetInstrumentDataStructureVersion(instrument_id_t ID) OVERRIDE {
71                  throw InstrumentManagerException("Not implemented");                  throw InstrumentManagerException("Not implemented");
72              }              }
73    
# Line 85  namespace LinuxSampler { Line 83  namespace LinuxSampler {
83                  InstrumentConsumer*  pConsumer,                  InstrumentConsumer*  pConsumer,
84                  RTList<R*>*          pRegionsInUse                  RTList<R*>*          pRegionsInUse
85              ) {              ) {
86                  RegionInfoMutex.Lock();                  LockGuard lock(RegionInfoMutex);
87                  for (typename RTList<R*>::Iterator i = pRegionsInUse->first() ; i != pRegionsInUse->end() ; i++) {                  for (typename RTList<R*>::Iterator i = pRegionsInUse->first() ; i != pRegionsInUse->end() ; i++) {
88                      RegionInfo[*i].refCount++;                      RegionInfo[*i].refCount++;
89                      SampleRefCount[(*i)->pSample]++;                      SampleRefCount[(*i)->pSample]++;
90                  }                  }
91                  HandBack(pResource, pConsumer, true);                  this->HandBack(pResource, pConsumer, true);
                 RegionInfoMutex.Unlock();  
92              }              }
93    
94              /**              /**
# Line 99  namespace LinuxSampler { Line 96  namespace LinuxSampler {
96               * was previously handed back.               * was previously handed back.
97               */               */
98              virtual void HandBackRegion(R* pRegion) {              virtual void HandBackRegion(R* pRegion) {
99                  RegionInfoMutex.Lock();                  LockGuard lock(RegionInfoMutex);
100                  if (RegionInfo.find(pRegion) == RegionInfo.end()) {                  if (RegionInfo.find(pRegion) == RegionInfo.end()) {
101                      std::cerr << "Handing back unknown region. This is a BUG!!!" << std::endl;                      std::cerr << "Handing back unknown region. This is a BUG!!!" << std::endl;
102                  }                  }
# Line 117  namespace LinuxSampler { Line 114  namespace LinuxSampler {
114                      }                      }
115                      RegionInfo.erase(pRegion);                      RegionInfo.erase(pRegion);
116                  }                  }
                 RegionInfoMutex.Unlock();  
117              }              }
118    
119              virtual InstrumentManager::mode_t GetMode(const InstrumentManager::instrument_id_t& ID) {              virtual InstrumentManager::mode_t GetMode(const InstrumentManager::instrument_id_t& ID) OVERRIDE {
120                  return static_cast<InstrumentManager::mode_t>(ResourceManager<instrument_id_t, I>::AvailabilityMode(ID));                  return static_cast<InstrumentManager::mode_t>(ResourceManager<instrument_id_t, I>::AvailabilityMode(ID));
121              }              }
122    
123              virtual void SetMode(const InstrumentManager::instrument_id_t& ID, InstrumentManager::mode_t Mode) {              virtual void SetMode(const InstrumentManager::instrument_id_t& ID, InstrumentManager::mode_t Mode) OVERRIDE {
124                  dmsg(2,("InstrumentManagerBase: setting mode for %s (Index=%d) to %d\n",ID.FileName.c_str(),ID.Index,Mode));                  dmsg(2,("InstrumentManagerBase: setting mode for %s (Index=%d) to %d\n",ID.FileName.c_str(),ID.Index,Mode));
125                  SetAvailabilityMode(ID, static_cast<typename ResourceManager<instrument_id_t, I>::mode_t>(Mode));                  this->SetAvailabilityMode(ID, static_cast<typename ResourceManager<instrument_id_t, I>::mode_t>(Mode));
126              }              }
127                
128        protected:
129                // data stored as long as an instrument resource exists
130                struct instr_entry_t {
131                    InstrumentManager::instrument_id_t ID;
132                    F*                                 pFile;
133                    uint                               MaxSamplesPerCycle; ///< if some engine requests an already allocated instrument with a higher value, we have to reallocate the instrument
134                };
135    
136    
137              /**              /**
138               * Used by the implementing instrument manager descendents in case               * Used by the implementing instrument manager descendents in case
139               * they don't have a reference to a sampler channel, which in turn               * they don't have a reference to a sampler channel, which in turn
# Line 155  namespace LinuxSampler { Line 160  namespace LinuxSampler {
160                      if (pDevice->MaxSamplesPerCycle() > samples)                      if (pDevice->MaxSamplesPerCycle() > samples)
161                          samples = pDevice->MaxSamplesPerCycle();                          samples = pDevice->MaxSamplesPerCycle();
162                  }                  }
163                  return (samples != 0) ? samples : 128 /* some fallback default value*/;                  return (samples != 0) ? samples : RESOURCE_MANAGER_DEFAULT_MAX_SAMPLES_PER_CYCLE;
164                }
165    
166                uint GetMaxSamplesPerCycle(InstrumentConsumer* pConsumer) {
167                    // try to resolve the audio device context
168                    AbstractEngineChannel* pEngineChannel = dynamic_cast<AbstractEngineChannel*>(pConsumer);
169                    AudioOutputDevice* pDevice = pEngineChannel ? pEngineChannel->GetAudioOutputDeviceSafe() : 0;
170                    return pDevice ? pDevice->MaxSamplesPerCycle() : DefaultMaxSamplesPerCycle();
171              }              }
172    
         protected:  
173              Mutex RegionInfoMutex; ///< protects the RegionInfo and SampleRefCount maps from concurrent access by the instrument loader and disk threads              Mutex RegionInfoMutex; ///< protects the RegionInfo and SampleRefCount maps from concurrent access by the instrument loader and disk threads
174              std::map< R*, region_info_t> RegionInfo; ///< contains dimension regions that are still in use but belong to released instrument              std::map< R*, region_info_t> RegionInfo; ///< contains dimension regions that are still in use but belong to released instrument
175              std::map< S*, int> SampleRefCount; ///< contains samples that are still in use but belong to a released instrument              std::map< S*, int> SampleRefCount; ///< contains samples that are still in use but belong to a released instrument
176    
             /**  
              *  Caches a certain size at the beginning of the given sample in RAM. If the  
              *  sample is very short, the whole sample will be loaded into RAM and thus  
              *  no disk streaming is needed for this sample. Caching an initial part of  
              *  samples is needed to compensate disk reading latency.  
              *  
              *  @param pSample - points to the sample to be cached  
              *  @param pEngine - pointer to Engine which caused this call  
              *                   (may be NULL, in this case default amount of samples  
              *                   will be cached)  
              */  
             virtual void CacheInitialSamples(S* pSample, AbstractEngine* pEngine) = 0;  
   
177              virtual void DeleteRegionIfNotUsed(R* pRegion, region_info_t* pRegInfo) = 0;              virtual void DeleteRegionIfNotUsed(R* pRegion, region_info_t* pRegInfo) = 0;
178              virtual void DeleteSampleIfNotUsed(S* pSample, region_info_t* pRegInfo) = 0;              virtual void DeleteSampleIfNotUsed(S* pSample, region_info_t* pRegInfo) = 0;
179    
# Line 189  namespace LinuxSampler { Line 187  namespace LinuxSampler {
187                  for (int i = low; i <= high; i++) bindingsArray[i] = 1;                  for (int i = low; i <= high; i++) bindingsArray[i] = 1;
188              }              }
189    
190      };              /**
191                 *  Caches a certain size at the beginning of the given sample in RAM. If the
192      template <class F /* Instrument File */, class I /* Instrument */, class R /* Region */, class S /* Sample */>               *  sample is very short, the whole sample will be loaded into RAM and thus
193      class InstrumentManagerDefaultImpl : public InstrumentManagerBase<F, I, R, S> {               *  no disk streaming is needed for this sample. Caching an initial part of
194          public:               *  samples is needed to compensate disk reading latency.
195              InstrumentManagerDefaultImpl() { }               *
196              virtual ~InstrumentManagerDefaultImpl() { }               *  @param pSample - points to the sample to be cached
197          protected:               *  @param maxSamplesPerCycle - max samples per cycle
198              virtual void CacheInitialSamples(S* pSample, AbstractEngine* pEngine)  {               */
199                void CacheInitialSamples(S* pSample, uint maxSamplesPerCycle)  {
200                  if (!pSample) {                  if (!pSample) {
201                      dmsg(4,("InstrumentManagerBase: Skipping sample (pSample == NULL)\n"));                      dmsg(4,("InstrumentManagerBase: Skipping sample (pSample == NULL)\n"));
202                      return;                      return;
# Line 210  namespace LinuxSampler { Line 209  namespace LinuxSampler {
209                      // number of '0' samples (silence samples) behind the official buffer                      // number of '0' samples (silence samples) behind the official buffer
210                      // border, to allow the interpolator do it's work even at the end of                      // border, to allow the interpolator do it's work even at the end of
211                      // the sample.                      // the sample.
                     const uint maxSamplesPerCycle =  
                         (pEngine) ? pEngine->pAudioOutputDevice->MaxSamplesPerCycle()  
                                   : GIG_RESOURCE_MANAGER_DEFAULT_MAX_SAMPLES_PER_CYCLE;  
212                      const uint neededSilenceSamples = (maxSamplesPerCycle << CONFIG_MAX_PITCH) + 3;                      const uint neededSilenceSamples = (maxSamplesPerCycle << CONFIG_MAX_PITCH) + 3;
213                      const uint currentlyCachedSilenceSamples = pSample->GetCache().NullExtensionSize / pSample->GetFrameSize();                      const uint currentlyCachedSilenceSamples = pSample->GetCache().NullExtensionSize / pSample->GetFrameSize();
214                      if (currentlyCachedSilenceSamples < neededSilenceSamples) {                      if (currentlyCachedSilenceSamples < neededSilenceSamples) {
# Line 228  namespace LinuxSampler { Line 224  namespace LinuxSampler {
224                  if (!pSample->GetCache().Size) std::cerr << "Unable to cache sample - maybe memory full!" << std::endl << std::flush;                  if (!pSample->GetCache().Size) std::cerr << "Unable to cache sample - maybe memory full!" << std::endl << std::flush;
225              }              }
226    
227              /**              // implementation of derived abstract methods from 'InstrumentManager'
228               * Just a wrapper around the other @c CacheInitialSamples() method.              std::vector<instrument_id_t> Instruments() {
229               *                  return ResourceManager<InstrumentManager::instrument_id_t, I>::Entries();
230               *  @param pSample - points to the sample to be cached              }
231               *  @param pEngine - pointer to Gig Engine Channel which caused this call  
232               *                   (may be NULL, in this case default amount of samples              // implementation of derived abstract methods from 'ResourceManager'
233               *                   will be cached)              void OnBorrow(I* pResource, InstrumentConsumer* pConsumer, void*& pArg) {
234               */                  instr_entry_t* pEntry = static_cast<instr_entry_t*>(pArg);
235              virtual void CacheInitialSamples(S* pSample, EngineChannel* pEngineChannel) {          
236                   AbstractEngine* pEngine =                  uint maxSamplesPerCycle = GetMaxSamplesPerCycle(pConsumer);
237                      (pEngineChannel && pEngineChannel->GetEngine()) ?  
238                          dynamic_cast<AbstractEngine*>(pEngineChannel->GetEngine()) : NULL;                  if (pEntry->MaxSamplesPerCycle < maxSamplesPerCycle) {
239                  CacheInitialSamples(pSample, pEngine);                      dmsg(1,("Completely reloading instrument due to insufficient precached samples ...\n"));
240                        this->Update(pResource, pConsumer);
241                    }
242              }              }
243      };      };
244    

Legend:
Removed from v.2275  
changed lines
  Added in v.2687

  ViewVC Help
Powered by ViewVC