/[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 354 - (show annotations) (download)
Sat Jan 29 15:17:59 2005 UTC (19 years, 2 months ago) by schoenebeck
File size: 6797 byte(s)
* support for keyswitching
* ignore if no sample was defined for region(s) or dimension region(s)
(patch by Andreas Persson)

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

  ViewVC Help
Powered by ViewVC