212 |
* call File::Save() to make changes persistent. |
* call File::Save() to make changes persistent. |
213 |
*/ |
*/ |
214 |
void Articulator::UpdateChunks() { |
void Articulator::UpdateChunks() { |
215 |
ArticulationList::iterator iter = pArticulations->begin(); |
if (pArticulations) { |
216 |
ArticulationList::iterator end = pArticulations->end(); |
ArticulationList::iterator iter = pArticulations->begin(); |
217 |
for (; iter != end; ++iter) { |
ArticulationList::iterator end = pArticulations->end(); |
218 |
(*iter)->UpdateChunks(); |
for (; iter != end; ++iter) { |
219 |
|
(*iter)->UpdateChunks(); |
220 |
|
} |
221 |
} |
} |
222 |
} |
} |
223 |
|
|
275 |
* |
* |
276 |
* Apply given info value to info chunk with ID \a ChunkID, which is a |
* Apply given info value to info chunk with ID \a ChunkID, which is a |
277 |
* subchunk of INFO list chunk \a lstINFO. If the given chunk already |
* subchunk of INFO list chunk \a lstINFO. If the given chunk already |
278 |
* exists, value \a s will be applied, otherwise if it doesn't exist yet |
* exists, value \a s will be applied. Otherwise if it doesn't exist yet |
279 |
* and \a sDefault is not an empty string, such a chunk will be created |
* and either \a s or \a sDefault is not an empty string, such a chunk |
280 |
* and \a sDefault will be applied. |
* will be created and either \a s or \a sDefault will be applied |
281 |
|
* (depending on which one is not an empty string, if both are not an |
282 |
|
* empty string \a s will be preferred). |
283 |
* |
* |
284 |
* @param ChunkID - 32 bit RIFF chunk ID of INFO subchunk |
* @param ChunkID - 32 bit RIFF chunk ID of INFO subchunk |
285 |
* @param lstINFO - parent (INFO) RIFF list chunk |
* @param lstINFO - parent (INFO) RIFF list chunk |
292 |
ck->Resize(s.size() + 1); |
ck->Resize(s.size() + 1); |
293 |
char* pData = (char*) ck->LoadChunkData(); |
char* pData = (char*) ck->LoadChunkData(); |
294 |
memcpy(pData, s.c_str(), s.size() + 1); |
memcpy(pData, s.c_str(), s.size() + 1); |
295 |
} else if (sDefault != "") { // create chunk and use default value |
} else if (s != "" || sDefault != "") { // create chunk |
296 |
ck = lstINFO->AddSubChunk(ChunkID, sDefault.size() + 1); |
const String& sToSave = (s != "") ? s : sDefault; |
297 |
|
ck = lstINFO->AddSubChunk(ChunkID, sToSave.size() + 1); |
298 |
char* pData = (char*) ck->LoadChunkData(); |
char* pData = (char*) ck->LoadChunkData(); |
299 |
memcpy(pData, sDefault.c_str(), sDefault.size() + 1); |
memcpy(pData, sToSave.c_str(), sToSave.size() + 1); |
300 |
} |
} |
301 |
} |
} |
302 |
|
|
317 |
// get current date |
// get current date |
318 |
time_t now = time(NULL); |
time_t now = time(NULL); |
319 |
tm* pNowBroken = localtime(&now); |
tm* pNowBroken = localtime(&now); |
320 |
String defaultCreationDate = ToString(pNowBroken->tm_year) + "-" + |
String defaultCreationDate = ToString(1900 + pNowBroken->tm_year) + "-" + |
321 |
ToString(pNowBroken->tm_mon) + "-" + |
ToString(pNowBroken->tm_mon + 1) + "-" + |
322 |
ToString(pNowBroken->tm_mday); |
ToString(pNowBroken->tm_mday); |
323 |
String defaultSoftware = libraryName() + " " + libraryVersion(); |
String defaultSoftware = libraryName() + " " + libraryVersion(); |
324 |
String defaultComments = "Created with " + libraryName() + " " + libraryVersion(); |
String defaultComments = "Created with " + libraryName() + " " + libraryVersion(); |
821 |
// get sample's wave pool table index |
// get sample's wave pool table index |
822 |
int index = -1; |
int index = -1; |
823 |
File* pFile = (File*) GetParent()->GetParent(); |
File* pFile = (File*) GetParent()->GetParent(); |
824 |
File::SampleList::iterator iter = pFile->pSamples->begin(); |
if (pFile->pSamples) { |
825 |
File::SampleList::iterator end = pFile->pSamples->end(); |
File::SampleList::iterator iter = pFile->pSamples->begin(); |
826 |
for (int i = 0; iter != end; ++iter, i++) { |
File::SampleList::iterator end = pFile->pSamples->end(); |
827 |
if (*iter == pSample) { |
for (int i = 0; iter != end; ++iter, i++) { |
828 |
index = i; |
if (*iter == pSample) { |
829 |
break; |
index = i; |
830 |
|
break; |
831 |
|
} |
832 |
} |
} |
833 |
} |
} |
834 |
if (index < 0) throw Exception("Could not save Region, could not find Region's sample"); |
if (index < 0) throw Exception("Could not save Region, could not find Region's sample"); |
896 |
|
|
897 |
void Instrument::LoadRegions() { |
void Instrument::LoadRegions() { |
898 |
RIFF::List* lrgn = pCkInstrument->GetSubList(LIST_TYPE_LRGN); |
RIFF::List* lrgn = pCkInstrument->GetSubList(LIST_TYPE_LRGN); |
899 |
if (!lrgn) throw DLS::Exception("Mandatory chunks in <ins > chunk not found."); |
if (!lrgn) throw DLS::Exception("DLS::Instrument doesn't seem to have any Region (mandatory chunks in <ins > chunk not found)"); |
900 |
uint32_t regionCkType = (lrgn->GetSubList(LIST_TYPE_RGN2)) ? LIST_TYPE_RGN2 : LIST_TYPE_RGN; // prefer regions level 2 |
uint32_t regionCkType = (lrgn->GetSubList(LIST_TYPE_RGN2)) ? LIST_TYPE_RGN2 : LIST_TYPE_RGN; // prefer regions level 2 |
901 |
RIFF::List* rgn = lrgn->GetFirstSubList(); |
RIFF::List* rgn = lrgn->GetFirstSubList(); |
902 |
while (rgn) { |
while (rgn) { |
941 |
if (!insh) insh = pCkInstrument->AddSubChunk(CHUNK_ID_INSH, 12); |
if (!insh) insh = pCkInstrument->AddSubChunk(CHUNK_ID_INSH, 12); |
942 |
uint8_t* pData = (uint8_t*) insh->LoadChunkData(); |
uint8_t* pData = (uint8_t*) insh->LoadChunkData(); |
943 |
// update 'insh' chunk |
// update 'insh' chunk |
944 |
Regions = pRegions->size(); |
Regions = (pRegions) ? pRegions->size() : 0; |
945 |
midi_locale_t locale; |
midi_locale_t locale; |
946 |
locale.instrument = MIDIProgram; |
locale.instrument = MIDIProgram; |
947 |
locale.bank = MIDI_BANK_ENCODE(MIDIBankCoarse, MIDIBankFine); |
locale.bank = MIDI_BANK_ENCODE(MIDIBankCoarse, MIDIBankFine); |
950 |
memccpy(&pData[0], &Regions, 1, 4); |
memccpy(&pData[0], &Regions, 1, 4); |
951 |
memccpy(&pData[4], &locale, 2, 4); |
memccpy(&pData[4], &locale, 2, 4); |
952 |
// update Region's chunks |
// update Region's chunks |
953 |
|
if (!pRegions) return; |
954 |
RegionList::iterator iter = pRegions->begin(); |
RegionList::iterator iter = pRegions->begin(); |
955 |
RegionList::iterator end = pRegions->end(); |
RegionList::iterator end = pRegions->end(); |
956 |
for (; iter != end; ++iter) { |
for (; iter != end; ++iter) { |
1335 |
/** |
/** |
1336 |
* Updates (persistently) the wave pool table with offsets to all |
* Updates (persistently) the wave pool table with offsets to all |
1337 |
* currently available samples. <b>Caution:</b> this method assumes the |
* currently available samples. <b>Caution:</b> this method assumes the |
1338 |
* 'ptbl' chunk to be already of the correct size, so usually this |
* 'ptbl' chunk to be already of the correct size and the file to be |
1339 |
* method is only called after a Save() call. |
* writable, so usually this method is only called after a Save() call. |
1340 |
* |
* |
1341 |
* @throws Exception - if 'ptbl' chunk is too small (should only occur |
* @throws Exception - if 'ptbl' chunk is too small (should only occur |
1342 |
* if there's a bug) |
* if there's a bug) |
1349 |
WavePoolCount = (pSamples) ? pSamples->size() : 0; |
WavePoolCount = (pSamples) ? pSamples->size() : 0; |
1350 |
const unsigned long ulRequiredSize = WavePoolHeaderSize + iOffsetSize * WavePoolCount; |
const unsigned long ulRequiredSize = WavePoolHeaderSize + iOffsetSize * WavePoolCount; |
1351 |
if (ptbl->GetSize() < ulRequiredSize) throw Exception("Fatal error, 'ptbl' chunk too small"); |
if (ptbl->GetSize() < ulRequiredSize) throw Exception("Fatal error, 'ptbl' chunk too small"); |
1352 |
uint8_t* pData = (uint8_t*) ptbl->LoadChunkData(); |
// save the 'ptbl' chunk's current read/write position |
1353 |
|
unsigned long ulOriginalPos = ptbl->GetPos(); |
1354 |
// update headers |
// update headers |
1355 |
memccpy(&pData[0], &WavePoolHeaderSize, 1, 4); |
ptbl->SetPos(0); |
1356 |
memccpy(&pData[4], &WavePoolCount, 1, 4); |
ptbl->WriteUint32(&WavePoolHeaderSize); |
1357 |
|
ptbl->WriteUint32(&WavePoolCount); |
1358 |
// update offsets |
// update offsets |
1359 |
|
ptbl->SetPos(WavePoolHeaderSize); |
1360 |
if (b64BitWavePoolOffsets) { |
if (b64BitWavePoolOffsets) { |
1361 |
for (int i = 0 ; i < WavePoolCount ; i++) { |
for (int i = 0 ; i < WavePoolCount ; i++) { |
1362 |
memccpy(&pData[WavePoolHeaderSize + i*iOffsetSize], &pWavePoolTableHi[i], 1, 4); |
ptbl->WriteUint32(&pWavePoolTableHi[i]); |
1363 |
memccpy(&pData[WavePoolHeaderSize + i*iOffsetSize], &pWavePoolTable[i], 1, 4); |
ptbl->WriteUint32(&pWavePoolTable[i]); |
1364 |
} |
} |
1365 |
} else { // conventional 32 bit offsets |
} else { // conventional 32 bit offsets |
1366 |
for (int i = 0 ; i < WavePoolCount ; i++) |
for (int i = 0 ; i < WavePoolCount ; i++) |
1367 |
memccpy(&pData[WavePoolHeaderSize + i*iOffsetSize], &pWavePoolTable[i], 1, 4); |
ptbl->WriteUint32(&pWavePoolTable[i]); |
1368 |
} |
} |
1369 |
|
// restore 'ptbl' chunk's original read/write position |
1370 |
|
ptbl->SetPos(ulOriginalPos); |
1371 |
} |
} |
1372 |
|
|
1373 |
/** |
/** |
1390 |
SampleList::iterator iter = pSamples->begin(); |
SampleList::iterator iter = pSamples->begin(); |
1391 |
SampleList::iterator end = pSamples->end(); |
SampleList::iterator end = pSamples->end(); |
1392 |
for (int i = 0 ; iter != end ; ++iter, i++) { |
for (int i = 0 ; iter != end ; ++iter, i++) { |
1393 |
uint64_t _64BitOffset = wvplFileOffset - (*iter)->pWaveList->GetFilePos() - LIST_HEADER_SIZE; |
uint64_t _64BitOffset = (*iter)->pWaveList->GetFilePos() - wvplFileOffset - LIST_HEADER_SIZE; |
1394 |
(*iter)->ulWavePoolOffset = _64BitOffset; |
(*iter)->ulWavePoolOffset = _64BitOffset; |
1395 |
pWavePoolTableHi[i] = (uint32_t) (_64BitOffset >> 32); |
pWavePoolTableHi[i] = (uint32_t) (_64BitOffset >> 32); |
1396 |
pWavePoolTable[i] = (uint32_t) _64BitOffset; |
pWavePoolTable[i] = (uint32_t) _64BitOffset; |
1399 |
SampleList::iterator iter = pSamples->begin(); |
SampleList::iterator iter = pSamples->begin(); |
1400 |
SampleList::iterator end = pSamples->end(); |
SampleList::iterator end = pSamples->end(); |
1401 |
for (int i = 0 ; iter != end ; ++iter, i++) { |
for (int i = 0 ; iter != end ; ++iter, i++) { |
1402 |
uint64_t _64BitOffset = wvplFileOffset - (*iter)->pWaveList->GetFilePos() - LIST_HEADER_SIZE; |
uint64_t _64BitOffset = (*iter)->pWaveList->GetFilePos() - wvplFileOffset - LIST_HEADER_SIZE; |
1403 |
(*iter)->ulWavePoolOffset = _64BitOffset; |
(*iter)->ulWavePoolOffset = _64BitOffset; |
1404 |
pWavePoolTable[i] = (uint32_t) _64BitOffset; |
pWavePoolTable[i] = (uint32_t) _64BitOffset; |
1405 |
} |
} |