/[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 53 - (show annotations) (download)
Mon Apr 26 17:15:51 2004 UTC (19 years, 11 months ago) by schoenebeck
File size: 6554 byte(s)
* completely restructured source tree
* implemented multi channel support
* implemented instrument manager, which controls sharing of instruments
  between multiple sampler engines / sampler channels
* created abstract classes 'AudioOutputDevice' and 'MidiInputDevice' for
  convenient implementation of further audio output driver and MIDI input
  driver for LinuxSampler
* implemented following LSCP commands: 'SET CHANNEL MIDI INPUT TYPE',
  'LOAD ENGINE', 'GET CHANNELS', 'ADD CHANNEL', 'REMOVE CHANNEL',
  'SET CHANNEL AUDIO OUTPUT TYPE'
* temporarily removed all command line options
* LSCP server is now launched by default

1 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003 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()->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) 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 ::gig::buffer_t buf = pSample->LoadSampleDataWithNullSamplesExtension((pEngine->pAudioOutputDevice->MaxSamplesPerCycle() << MAX_PITCH) + 3);
101 dmsg(4,("Cached %d Bytes, %d silence bytes.\n", buf.Size, buf.NullExtensionSize));
102 }
103 else { // we only cache NUM_RAM_PRELOAD_SAMPLES and stream the other sample points from disk
104 pSample->LoadSampleData(NUM_RAM_PRELOAD_SAMPLES);
105 }
106
107 if (!pSample->GetCache().Size) std::cerr << "Unable to cache sample - maybe memory full!" << std::endl << std::flush;
108 }
109
110
111
112 // internal gig file manager
113
114 ::gig::File* InstrumentResourceManager::GigResourceManager::Create(String Key, GigConsumer* pConsumer, void*& pArg) {
115 dmsg(1,("Loading gig file \'%s\'...", Key.c_str()));
116 ::RIFF::File* pRIFF = new ::RIFF::File(Key);
117 ::gig::File* pGig = new ::gig::File(pRIFF);
118 pArg = pRIFF;
119 dmsg(1,("OK\n"));
120 return pGig;
121 }
122
123 void InstrumentResourceManager::GigResourceManager::Destroy(::gig::File* pResource, void* pArg) {
124 dmsg(1,("Freeing gig file from memory..."));
125 delete pResource;
126 delete (::RIFF::File*) pArg;
127 dmsg(1,("OK\n"));
128 }
129
130 }} // namespace LinuxSampler::gig

  ViewVC Help
Powered by ViewVC