/[svn]/linuxsampler/trunk/src/engines/gig/InstrumentResourceManager.cpp
ViewVC logotype

Diff of /linuxsampler/trunk/src/engines/gig/InstrumentResourceManager.cpp

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

revision 411 by schoenebeck, Sat Feb 26 02:01:14 2005 UTC revision 554 by schoenebeck, Thu May 19 19:25:14 2005 UTC
# Line 34  Line 34 
34    
35  namespace LinuxSampler { namespace gig {  namespace LinuxSampler { namespace gig {
36    
37        // some data needed for the libgig callback function
38        struct progress_callback_arg_t {
39            InstrumentResourceManager* pManager;
40            instrument_id_t*           pInstrumentKey;
41        };
42    
43        /**
44         * Callback function which will be called by libgig during loading of
45         * instruments to inform about the current progress. Or to be more
46         * specific; it will be called during the GetInstrument() call.
47         *
48         * @param pProgress - contains current progress value, pointer to the
49         *                    InstrumentResourceManager instance and
50         *                    instrument ID
51         */
52        void InstrumentResourceManager::OnInstrumentLoadingProgress(::gig::progress_t* pProgress) {
53            dmsg(7,("gig::InstrumentResourceManager: progress %f%", pProgress->factor));
54            progress_callback_arg_t* pArg = static_cast<progress_callback_arg_t*>(pProgress->custom);
55            // we randomly schedule 90% for the .gig file loading and the remaining 10% later for sample caching
56            const float localProgress = 0.9f * pProgress->factor;
57            pArg->pManager->DispatchResourceProgressEvent(*pArg->pInstrumentKey, localProgress);
58        }
59    
60      ::gig::Instrument* InstrumentResourceManager::Create(instrument_id_t Key, InstrumentConsumer* pConsumer, void*& pArg) {      ::gig::Instrument* InstrumentResourceManager::Create(instrument_id_t Key, InstrumentConsumer* pConsumer, void*& pArg) {
61          // get gig file from inernal gig file manager          // get gig file from inernal gig file manager
62          ::gig::File* pGig = Gigs.Borrow(Key.FileName, (GigConsumer*) Key.iInstrument); // conversion kinda hackish :/          ::gig::File* pGig = Gigs.Borrow(Key.FileName, (GigConsumer*) Key.iInstrument); // conversion kinda hackish :/
63    
64            // we pass this to the progress callback mechanism of libgig
65            progress_callback_arg_t callbackArg;
66            callbackArg.pManager       = this;
67            callbackArg.pInstrumentKey = &Key;
68    
69            ::gig::progress_t progress;
70            progress.callback = OnInstrumentLoadingProgress;
71            progress.custom   = &callbackArg;
72    
73          dmsg(1,("Loading gig instrument..."));          dmsg(1,("Loading gig instrument..."));
74          ::gig::Instrument* pInstrument = pGig->GetInstrument(Key.iInstrument);          ::gig::Instrument* pInstrument = pGig->GetInstrument(Key.iInstrument, &progress);
75          if (!pInstrument) {          if (!pInstrument) {
76              std::stringstream msg;              std::stringstream msg;
77              msg << "There's no instrument with index " << Key.iInstrument << ".";              msg << "There's no instrument with index " << Key.iInstrument << ".";
# Line 50  namespace LinuxSampler { namespace gig { Line 82  namespace LinuxSampler { namespace gig {
82    
83          // cache initial samples points (for actually needed samples)          // cache initial samples points (for actually needed samples)
84          dmsg(1,("Caching initial samples..."));          dmsg(1,("Caching initial samples..."));
85            uint iRegion = 0; // just for progress calculation
86          ::gig::Region* pRgn = pInstrument->GetFirstRegion();          ::gig::Region* pRgn = pInstrument->GetFirstRegion();
87          while (pRgn) {          while (pRgn) {
88                // we randomly schedule 90% for the .gig file loading and the remaining 10% now for sample caching
89                const float localProgress = 0.9f + 0.1f * (float) iRegion / (float) pInstrument->Regions;
90                DispatchResourceProgressEvent(Key, localProgress);            
91                
92              if (pRgn->GetSample() && !pRgn->GetSample()->GetCache().Size) {              if (pRgn->GetSample() && !pRgn->GetSample()->GetCache().Size) {
93                  dmsg(2,("C"));                  dmsg(2,("C"));
94                  CacheInitialSamples(pRgn->GetSample(), dynamic_cast<gig::EngineChannel*>(pConsumer));                  CacheInitialSamples(pRgn->GetSample(), dynamic_cast<gig::EngineChannel*>(pConsumer));
# Line 61  namespace LinuxSampler { namespace gig { Line 98  namespace LinuxSampler { namespace gig {
98              }              }
99    
100              pRgn = pInstrument->GetNextRegion();              pRgn = pInstrument->GetNextRegion();
101                iRegion++;
102          }          }
103          dmsg(1,("OK\n"));          dmsg(1,("OK\n"));
104            DispatchResourceProgressEvent(Key, 1.0f); // done; notify all consumers about progress 100%
105    
106          // we need the following for destruction later          // we need the following for destruction later
107          instr_entry_t* pEntry = new instr_entry_t;          instr_entry_t* pEntry = new instr_entry_t;
108          pEntry->iInstrument   = Key.iInstrument;          pEntry->iInstrument   = Key.iInstrument;
109          pEntry->pGig          = pGig;          pEntry->pGig          = pGig;
110            
111          gig::EngineChannel* pEngineChannel = dynamic_cast<gig::EngineChannel*>(pConsumer);          gig::EngineChannel* pEngineChannel = dynamic_cast<gig::EngineChannel*>(pConsumer);
112          // and we save this to check if we need to reallocate for a engine with higher value of 'MaxSamplesPerSecond'          // and we save this to check if we need to reallocate for a engine with higher value of 'MaxSamplesPerSecond'
113          pEntry->MaxSamplesPerCycle =          pEntry->MaxSamplesPerCycle =
# Line 106  namespace LinuxSampler { namespace gig { Line 145  namespace LinuxSampler { namespace gig {
145       *  @param pEngineChannel - pointer to Gig Engine Channel which caused this call       *  @param pEngineChannel - pointer to Gig Engine Channel which caused this call
146       */       */
147      void InstrumentResourceManager::CacheInitialSamples(::gig::Sample* pSample, gig::EngineChannel* pEngineChannel) {      void InstrumentResourceManager::CacheInitialSamples(::gig::Sample* pSample, gig::EngineChannel* pEngineChannel) {
148          if (!pSample || pSample->GetCache().Size || !pSample->SamplesTotal) return;          if (!pSample) {
149          if (pSample->SamplesTotal <= NUM_RAM_PRELOAD_SAMPLES) {              dmsg(4,("gig::InstrumentResourceManager: Skipping sample (pSample == NULL)\n"));
150                return;
151            }
152            if (!pSample->SamplesTotal) return; // skip zero size samples
153    
154            if (pSample->SamplesTotal <= CONFIG_PRELOAD_SAMPLES) {
155              // Sample is too short for disk streaming, so we load the whole              // Sample is too short for disk streaming, so we load the whole
156              // sample into RAM and place 'pAudioIO->FragmentSize << MAX_PITCH'              // sample into RAM and place 'pAudioIO->FragmentSize << CONFIG_MAX_PITCH'
157              // number of '0' samples (silence samples) behind the official buffer              // number of '0' samples (silence samples) behind the official buffer
158              // 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
159              // the sample.              // the sample.
             dmsg(3,("Caching whole sample (sample name: \"%s\", sample size: %d)\n", pSample->pInfo->Name.c_str(), pSample->SamplesTotal));  
160              const uint maxSamplesPerCycle =              const uint maxSamplesPerCycle =
161                  (pEngineChannel->GetEngine()) ? dynamic_cast<gig::Engine*>(pEngineChannel->GetEngine())->pAudioOutputDevice->MaxSamplesPerCycle()                  (pEngineChannel->GetEngine()) ? dynamic_cast<gig::Engine*>(pEngineChannel->GetEngine())->pAudioOutputDevice->MaxSamplesPerCycle()
162                                                : GIG_RESOURCE_MANAGER_DEFAULT_MAX_SAMPLES_PER_CYCLE;                                                : GIG_RESOURCE_MANAGER_DEFAULT_MAX_SAMPLES_PER_CYCLE;
163              const uint silenceSamples = (maxSamplesPerCycle << MAX_PITCH) + 3;              const uint neededSilenceSamples = (maxSamplesPerCycle << CONFIG_MAX_PITCH) + 3;
164              ::gig::buffer_t buf = pSample->LoadSampleDataWithNullSamplesExtension(silenceSamples);              const uint currentlyCachedSilenceSamples = pSample->GetCache().NullExtensionSize / pSample->FrameSize;
165              dmsg(4,("Cached %d Bytes, %d silence bytes.\n", buf.Size, buf.NullExtensionSize));              if (currentlyCachedSilenceSamples < neededSilenceSamples) {
166                    dmsg(3,("Caching whole sample (sample name: \"%s\", sample size: %d)\n", pSample->pInfo->Name.c_str(), pSample->SamplesTotal));
167                    ::gig::buffer_t buf = pSample->LoadSampleDataWithNullSamplesExtension(neededSilenceSamples);
168                    dmsg(4,("Cached %d Bytes, %d silence bytes.\n", buf.Size, buf.NullExtensionSize));
169                }
170          }          }
171          else { // we only cache NUM_RAM_PRELOAD_SAMPLES and stream the other sample points from disk          else { // we only cache CONFIG_PRELOAD_SAMPLES and stream the other sample points from disk
172              pSample->LoadSampleData(NUM_RAM_PRELOAD_SAMPLES);              if (!pSample->GetCache().Size) pSample->LoadSampleData(CONFIG_PRELOAD_SAMPLES);
173          }          }
174    
175          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;

Legend:
Removed from v.411  
changed lines
  Added in v.554

  ViewVC Help
Powered by ViewVC