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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 411 - (hide annotations) (download)
Sat Feb 26 02:01:14 2005 UTC (19 years, 2 months ago) by schoenebeck
File size: 8147 byte(s)
* design change: using now one sampler engine instance and one disk thread
  instance for all sampler channels that are connected to the same audio
  output device (and are using the same engine type of course)
* added EngineFactory / EngineChannelFactory to remove the annoying build
  dependencies e.g. of the lscpserver to the actual sampler engine
  implementations
* bumped version to 0.3.0 (current CVS state is still quite broken,
  previous, stable CVS version was tagged as "v0_2_0" and is also available
  as source tarball)

1 schoenebeck 53 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5 schoenebeck 56 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 schoenebeck 411 * Copyright (C) 2005 Christian Schoenebeck *
7 schoenebeck 53 * *
8     * 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 *
10     * the Free Software Foundation; either version 2 of the License, or *
11     * (at your option) any later version. *
12     * *
13     * This program is distributed in the hope that it will be useful, *
14     * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16     * GNU General Public License for more details. *
17     * *
18     * You should have received a copy of the GNU General Public License *
19     * along with this program; if not, write to the Free Software *
20     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21     * MA 02111-1307 USA *
22     ***************************************************************************/
23    
24     #include <sstream>
25    
26     #include "InstrumentResourceManager.h"
27    
28 schoenebeck 411 // We need to know the maximum number of sample points which are going to
29     // be processed for each render cycle of the audio output driver, to know
30     // how much initial sample points we need to cache into RAM. If the given
31     // sampler channel does not have an audio output device assigned yet
32     // though, we simply use this default value.
33     #define GIG_RESOURCE_MANAGER_DEFAULT_MAX_SAMPLES_PER_CYCLE 128
34    
35 schoenebeck 53 namespace LinuxSampler { namespace gig {
36    
37     ::gig::Instrument* InstrumentResourceManager::Create(instrument_id_t Key, InstrumentConsumer* pConsumer, void*& pArg) {
38     // get gig file from inernal gig file manager
39     ::gig::File* pGig = Gigs.Borrow(Key.FileName, (GigConsumer*) Key.iInstrument); // conversion kinda hackish :/
40    
41     dmsg(1,("Loading gig instrument..."));
42     ::gig::Instrument* pInstrument = pGig->GetInstrument(Key.iInstrument);
43     if (!pInstrument) {
44     std::stringstream msg;
45     msg << "There's no instrument with index " << Key.iInstrument << ".";
46     throw InstrumentResourceManagerException(msg.str());
47     }
48     pGig->GetFirstSample(); // just to force complete instrument loading
49     dmsg(1,("OK\n"));
50    
51     // cache initial samples points (for actually needed samples)
52     dmsg(1,("Caching initial samples..."));
53     ::gig::Region* pRgn = pInstrument->GetFirstRegion();
54     while (pRgn) {
55 schoenebeck 354 if (pRgn->GetSample() && !pRgn->GetSample()->GetCache().Size) {
56 schoenebeck 53 dmsg(2,("C"));
57 schoenebeck 411 CacheInitialSamples(pRgn->GetSample(), dynamic_cast<gig::EngineChannel*>(pConsumer));
58 schoenebeck 53 }
59     for (uint i = 0; i < pRgn->DimensionRegions; i++) {
60 schoenebeck 411 CacheInitialSamples(pRgn->pDimensionRegions[i]->pSample, dynamic_cast<gig::EngineChannel*>(pConsumer));
61 schoenebeck 53 }
62    
63     pRgn = pInstrument->GetNextRegion();
64     }
65     dmsg(1,("OK\n"));
66    
67     // we need the following for destruction later
68     instr_entry_t* pEntry = new instr_entry_t;
69     pEntry->iInstrument = Key.iInstrument;
70     pEntry->pGig = pGig;
71 schoenebeck 411
72     gig::EngineChannel* pEngineChannel = dynamic_cast<gig::EngineChannel*>(pConsumer);
73     // and we save this to check if we need to reallocate for a engine with higher value of 'MaxSamplesPerSecond'
74     pEntry->MaxSamplesPerCycle =
75     (pEngineChannel->GetEngine()) ? dynamic_cast<gig::Engine*>(pEngineChannel->GetEngine())->pAudioOutputDevice->MaxSamplesPerCycle()
76     : GIG_RESOURCE_MANAGER_DEFAULT_MAX_SAMPLES_PER_CYCLE;
77 schoenebeck 53 pArg = pEntry;
78    
79     return pInstrument;
80     }
81    
82     void InstrumentResourceManager::Destroy( ::gig::Instrument* pResource, void* pArg) {
83     instr_entry_t* pEntry = (instr_entry_t*) pArg;
84     Gigs.HandBack(pEntry->pGig, (GigConsumer*) pEntry->iInstrument); // conversion kinda hackish :/
85     delete pEntry;
86     }
87    
88     void InstrumentResourceManager::OnBorrow(::gig::Instrument* pResource, InstrumentConsumer* pConsumer, void*& pArg) {
89     instr_entry_t* pEntry = (instr_entry_t*) pArg;
90 schoenebeck 411 gig::EngineChannel* pEngineChannel = dynamic_cast<gig::EngineChannel*>(pConsumer);
91     uint maxSamplesPerCycle =
92     (pEngineChannel->GetEngine()) ? dynamic_cast<gig::Engine*>(pEngineChannel->GetEngine())->pAudioOutputDevice->MaxSamplesPerCycle()
93     : GIG_RESOURCE_MANAGER_DEFAULT_MAX_SAMPLES_PER_CYCLE;
94     if (pEntry->MaxSamplesPerCycle < maxSamplesPerCycle) {
95 schoenebeck 53 Update(pResource, pConsumer);
96     }
97     }
98    
99     /**
100     * Caches a certain size at the beginning of the given sample in RAM. If the
101     * sample is very short, the whole sample will be loaded into RAM and thus
102     * no disk streaming is needed for this sample. Caching an initial part of
103     * samples is needed to compensate disk reading latency.
104     *
105     * @param pSample - points to the sample to be cached
106 schoenebeck 411 * @param pEngineChannel - pointer to Gig Engine Channel which caused this call
107 schoenebeck 53 */
108 schoenebeck 411 void InstrumentResourceManager::CacheInitialSamples(::gig::Sample* pSample, gig::EngineChannel* pEngineChannel) {
109 schoenebeck 354 if (!pSample || pSample->GetCache().Size || !pSample->SamplesTotal) return;
110 schoenebeck 53 if (pSample->SamplesTotal <= NUM_RAM_PRELOAD_SAMPLES) {
111     // Sample is too short for disk streaming, so we load the whole
112     // sample into RAM and place 'pAudioIO->FragmentSize << MAX_PITCH'
113     // number of '0' samples (silence samples) behind the official buffer
114     // border, to allow the interpolator do it's work even at the end of
115     // the sample.
116 schoenebeck 349 dmsg(3,("Caching whole sample (sample name: \"%s\", sample size: %d)\n", pSample->pInfo->Name.c_str(), pSample->SamplesTotal));
117 schoenebeck 411 const uint maxSamplesPerCycle =
118     (pEngineChannel->GetEngine()) ? dynamic_cast<gig::Engine*>(pEngineChannel->GetEngine())->pAudioOutputDevice->MaxSamplesPerCycle()
119     : GIG_RESOURCE_MANAGER_DEFAULT_MAX_SAMPLES_PER_CYCLE;
120     const uint silenceSamples = (maxSamplesPerCycle << MAX_PITCH) + 3;
121 schoenebeck 349 ::gig::buffer_t buf = pSample->LoadSampleDataWithNullSamplesExtension(silenceSamples);
122 schoenebeck 53 dmsg(4,("Cached %d Bytes, %d silence bytes.\n", buf.Size, buf.NullExtensionSize));
123     }
124     else { // we only cache NUM_RAM_PRELOAD_SAMPLES and stream the other sample points from disk
125     pSample->LoadSampleData(NUM_RAM_PRELOAD_SAMPLES);
126     }
127    
128     if (!pSample->GetCache().Size) std::cerr << "Unable to cache sample - maybe memory full!" << std::endl << std::flush;
129     }
130    
131    
132    
133     // internal gig file manager
134    
135     ::gig::File* InstrumentResourceManager::GigResourceManager::Create(String Key, GigConsumer* pConsumer, void*& pArg) {
136     dmsg(1,("Loading gig file \'%s\'...", Key.c_str()));
137     ::RIFF::File* pRIFF = new ::RIFF::File(Key);
138     ::gig::File* pGig = new ::gig::File(pRIFF);
139     pArg = pRIFF;
140     dmsg(1,("OK\n"));
141     return pGig;
142     }
143    
144     void InstrumentResourceManager::GigResourceManager::Destroy(::gig::File* pResource, void* pArg) {
145     dmsg(1,("Freeing gig file from memory..."));
146     delete pResource;
147     delete (::RIFF::File*) pArg;
148     dmsg(1,("OK\n"));
149     }
150    
151     }} // namespace LinuxSampler::gig

  ViewVC Help
Powered by ViewVC