3 |
* LinuxSampler - modular, streaming capable sampler * |
* LinuxSampler - modular, streaming capable sampler * |
4 |
* * |
* * |
5 |
* Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck * |
* Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck * |
6 |
* Copyright (C) 2005 - 2011 Christian Schoenebeck * |
* Copyright (C) 2005 - 2008 Christian Schoenebeck * |
7 |
* Copyright (C) 2009 - 2011 Grigor Iliev * |
* Copyright (C) 2009 - 2012 Christian Schoenebeck and Grigor Iliev * |
8 |
* * |
* * |
9 |
* This program is free software; you can redistribute it and/or modify * |
* This program is free software; you can redistribute it and/or modify * |
10 |
* it under the terms of the GNU General Public License as published by * |
* it under the terms of the GNU General Public License as published by * |
35 |
|
|
36 |
namespace LinuxSampler { namespace sf2 { |
namespace LinuxSampler { namespace sf2 { |
37 |
|
|
|
// data stored as long as an instrument resource exists |
|
|
struct instr_entry_t { |
|
|
InstrumentManager::instrument_id_t ID; |
|
|
::sf2::File* pSf2; |
|
|
uint MaxSamplesPerCycle; ///< if some engine requests an already allocated instrument with a higher value, we have to reallocate the instrument |
|
|
}; |
|
|
|
|
|
// some data needed for the libgig callback function |
|
|
struct progress_callback_arg_t { |
|
|
InstrumentResourceManager* pManager; |
|
|
InstrumentManager::instrument_id_t* pInstrumentKey; |
|
|
}; |
|
|
|
|
|
std::vector<InstrumentResourceManager::instrument_id_t> InstrumentResourceManager::Instruments() { |
|
|
return Entries(); |
|
|
} |
|
|
|
|
38 |
String InstrumentResourceManager::GetInstrumentName(instrument_id_t ID) { |
String InstrumentResourceManager::GetInstrumentName(instrument_id_t ID) { |
39 |
Lock(); |
Lock(); |
40 |
::sf2::Preset* pInstrument = Resource(ID, false); |
::sf2::Preset* pInstrument = Resource(ID, false); |
79 |
::RIFF::File* riff = NULL; |
::RIFF::File* riff = NULL; |
80 |
::sf2::File* sf2 = NULL; |
::sf2::File* sf2 = NULL; |
81 |
try { |
try { |
82 |
if(!loaded) { |
if (!loaded) { |
83 |
riff = new ::RIFF::File(ID.FileName); |
riff = new ::RIFF::File(ID.FileName); |
84 |
sf2 = new ::sf2::File(riff); |
sf2 = new ::sf2::File(riff); |
85 |
pInstrument = GetSfInstrument(sf2, ID.Index); |
pInstrument = GetSfInstrument(sf2, ID.Index); |
140 |
// cache initial samples points (for actually needed samples) |
// cache initial samples points (for actually needed samples) |
141 |
dmsg(1,("Caching initial samples...")); |
dmsg(1,("Caching initial samples...")); |
142 |
float regTotal = 0, regCurrent = 0; |
float regTotal = 0, regCurrent = 0; |
143 |
for(int i = 0 ; i < pInstrument->GetRegionCount(); i++) { |
for (int i = 0 ; i < pInstrument->GetRegionCount() ; i++) { |
144 |
::sf2::Instrument* sf2Instr = pInstrument->GetRegion(i)->pInstrument; |
::sf2::Instrument* sf2Instr = pInstrument->GetRegion(i)->pInstrument; |
145 |
if(sf2Instr) regTotal += sf2Instr->GetRegionCount(); |
if (sf2Instr) regTotal += sf2Instr->GetRegionCount(); |
146 |
} |
} |
147 |
for(int i = 0 ; i < pInstrument->GetRegionCount(); i++) { |
uint maxSamplesPerCycle = GetMaxSamplesPerCycle(pConsumer); |
148 |
|
for (int i = 0 ; i < pInstrument->GetRegionCount() ; i++) { |
149 |
::sf2::Instrument* sf2Instr = pInstrument->GetRegion(i)->pInstrument; |
::sf2::Instrument* sf2Instr = pInstrument->GetRegion(i)->pInstrument; |
150 |
if(sf2Instr != NULL) { |
if (sf2Instr) { |
151 |
// pInstrument is ::sf2::Preset |
// pInstrument is ::sf2::Preset |
152 |
for(int j = 0; j < sf2Instr->GetRegionCount(); j++) { |
for (int j = 0 ; j < sf2Instr->GetRegionCount() ; j++) { |
153 |
const float localProgress = regCurrent++ / regTotal; |
float localProgress = regCurrent++ / regTotal; |
154 |
DispatchResourceProgressEvent(Key, localProgress); |
DispatchResourceProgressEvent(Key, localProgress); |
155 |
CacheInitialSamples(sf2Instr->GetRegion(j)->GetSample(), dynamic_cast<AbstractEngineChannel*>(pConsumer)); |
CacheInitialSamples(sf2Instr->GetRegion(j)->GetSample(), maxSamplesPerCycle); |
156 |
} |
} |
157 |
} |
} |
158 |
} |
} |
163 |
instr_entry_t* pEntry = new instr_entry_t; |
instr_entry_t* pEntry = new instr_entry_t; |
164 |
pEntry->ID.FileName = Key.FileName; |
pEntry->ID.FileName = Key.FileName; |
165 |
pEntry->ID.Index = Key.Index; |
pEntry->ID.Index = Key.Index; |
166 |
pEntry->pSf2 = pSf2; |
pEntry->pFile = pSf2; |
167 |
|
|
168 |
// (try to resolve the audio device context) |
// and we save this to check if we need to reallocate for an engine with higher value of 'MaxSamplesPerSecond' |
169 |
EngineChannel* pEngineChannel = dynamic_cast<EngineChannel*>(pConsumer); |
pEntry->MaxSamplesPerCycle = maxSamplesPerCycle; |
|
AudioOutputDevice* pDevice = |
|
|
(pEngineChannel) ? dynamic_cast<Engine*>(pEngineChannel->GetEngine())->pAudioOutputDevice : NULL; |
|
|
|
|
|
// and we save this to check if we need to reallocate for a engine with higher value of 'MaxSamplesPerSecond' |
|
|
pEntry->MaxSamplesPerCycle = |
|
|
(pDevice) ? pDevice->MaxSamplesPerCycle() : DefaultMaxSamplesPerCycle(); |
|
170 |
|
|
171 |
pArg = pEntry; |
pArg = pEntry; |
172 |
|
|
173 |
return pInstrument; |
return pInstrument; |
174 |
} |
} |
175 |
|
|
176 |
void InstrumentResourceManager::Destroy( ::sf2::Preset* pResource, void* pArg) { |
void InstrumentResourceManager::Destroy(::sf2::Preset* pResource, void* pArg) { |
177 |
instr_entry_t* pEntry = (instr_entry_t*) pArg; |
instr_entry_t* pEntry = (instr_entry_t*) pArg; |
178 |
// we don't need the .sf2 file here anymore |
// we don't need the .sf2 file here anymore |
179 |
Sf2s.HandBack(pEntry->pSf2, reinterpret_cast<Sf2Consumer*>(pEntry->ID.Index)); // conversion kinda hackish :/ |
Sf2s.HandBack(pEntry->pFile, reinterpret_cast<Sf2Consumer*>(pEntry->ID.Index)); // conversion kinda hackish :/ |
180 |
delete pEntry; |
delete pEntry; |
181 |
} |
} |
182 |
|
|
|
void InstrumentResourceManager::OnBorrow(::sf2::Preset* pResource, InstrumentConsumer* pConsumer, void*& pArg) { |
|
|
instr_entry_t* pEntry = (instr_entry_t*) pArg; |
|
|
|
|
|
// (try to resolve the audio device context) |
|
|
EngineChannel* pEngineChannel = dynamic_cast<EngineChannel*>(pConsumer); |
|
|
AudioOutputDevice* pDevice = |
|
|
(pEngineChannel) ? dynamic_cast<Engine*>(pEngineChannel->GetEngine())->pAudioOutputDevice : NULL; |
|
|
|
|
|
uint maxSamplesPerCycle = |
|
|
(pDevice) ? pDevice->MaxSamplesPerCycle() : DefaultMaxSamplesPerCycle(); |
|
|
|
|
|
if (pEntry->MaxSamplesPerCycle < maxSamplesPerCycle) { |
|
|
dmsg(1,("Completely reloading instrument due to insufficient precached samples ...\n")); |
|
|
Update(pResource, pConsumer); |
|
|
} |
|
|
} |
|
|
|
|
183 |
void InstrumentResourceManager::DeleteRegionIfNotUsed(::sf2::Region* pRegion, region_info_t* pRegInfo) { |
void InstrumentResourceManager::DeleteRegionIfNotUsed(::sf2::Region* pRegion, region_info_t* pRegInfo) { |
184 |
// TODO: we could delete Region and Instrument here if they have become unused |
// TODO: we could delete Region and Instrument here if they have become unused |
185 |
} |
} |