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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 411 - (show 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 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 * Copyright (C) 2005 Christian Schoenebeck *
7 * *
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 // 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 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 if (pRgn->GetSample() && !pRgn->GetSample()->GetCache().Size) {
56 dmsg(2,("C"));
57 CacheInitialSamples(pRgn->GetSample(), dynamic_cast<gig::EngineChannel*>(pConsumer));
58 }
59 for (uint i = 0; i < pRgn->DimensionRegions; i++) {
60 CacheInitialSamples(pRgn->pDimensionRegions[i]->pSample, dynamic_cast<gig::EngineChannel*>(pConsumer));
61 }
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
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 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 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 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 * @param pEngineChannel - pointer to Gig Engine Channel which caused this call
107 */
108 void InstrumentResourceManager::CacheInitialSamples(::gig::Sample* pSample, gig::EngineChannel* pEngineChannel) {
109 if (!pSample || pSample->GetCache().Size || !pSample->SamplesTotal) return;
110 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 dmsg(3,("Caching whole sample (sample name: \"%s\", sample size: %d)\n", pSample->pInfo->Name.c_str(), pSample->SamplesTotal));
117 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 ::gig::buffer_t buf = pSample->LoadSampleDataWithNullSamplesExtension(silenceSamples);
122 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