2 |
* * |
* * |
3 |
* libgig - C++ cross-platform Gigasampler format file access library * |
* libgig - C++ cross-platform Gigasampler format file access library * |
4 |
* * |
* * |
5 |
* Copyright (C) 2003-2019 by Christian Schoenebeck * |
* Copyright (C) 2003-2021 by Christian Schoenebeck * |
6 |
* <cuse@users.sourceforge.net> * |
* <cuse@users.sourceforge.net> * |
7 |
* * |
* * |
8 |
* This library is free software; you can redistribute it and/or modify * |
* This library is free software; you can redistribute it and/or modify * |
189 |
pArticulations = NULL; |
pArticulations = NULL; |
190 |
} |
} |
191 |
|
|
192 |
|
/** |
193 |
|
* Returns Articulation at supplied @a pos position within the articulation |
194 |
|
* list. If supplied @a pos is out of bounds then @c NULL is returned. |
195 |
|
* |
196 |
|
* @param pos - position of sought Articulation in articulation list |
197 |
|
* @returns pointer address to requested articulation or @c NULL if @a pos |
198 |
|
* is out of bounds |
199 |
|
*/ |
200 |
|
Articulation* Articulator::GetArticulation(size_t pos) { |
201 |
|
if (!pArticulations) LoadArticulations(); |
202 |
|
if (!pArticulations) return NULL; |
203 |
|
if (pos >= pArticulations->size()) return NULL; |
204 |
|
return (*pArticulations)[pos]; |
205 |
|
} |
206 |
|
|
207 |
|
/** |
208 |
|
* Returns the first Articulation in the list of articulations. You have to |
209 |
|
* call this method once before you can use GetNextArticulation(). |
210 |
|
* |
211 |
|
* @returns pointer address to first Articulation or NULL if there is none |
212 |
|
* @see GetNextArticulation() |
213 |
|
* @deprecated This method is not reentrant-safe, use GetArticulation() |
214 |
|
* instead. |
215 |
|
*/ |
216 |
Articulation* Articulator::GetFirstArticulation() { |
Articulation* Articulator::GetFirstArticulation() { |
217 |
if (!pArticulations) LoadArticulations(); |
if (!pArticulations) LoadArticulations(); |
218 |
if (!pArticulations) return NULL; |
if (!pArticulations) return NULL; |
220 |
return (ArticulationsIterator != pArticulations->end()) ? *ArticulationsIterator : NULL; |
return (ArticulationsIterator != pArticulations->end()) ? *ArticulationsIterator : NULL; |
221 |
} |
} |
222 |
|
|
223 |
|
/** |
224 |
|
* Returns the next Articulation from the list of articulations. You have |
225 |
|
* to call GetFirstArticulation() once before you can use this method. By |
226 |
|
* calling this method multiple times it iterates through the available |
227 |
|
* articulations. |
228 |
|
* |
229 |
|
* @returns pointer address to the next Articulation or NULL if end reached |
230 |
|
* @see GetFirstArticulation() |
231 |
|
* @deprecated This method is not reentrant-safe, use GetArticulation() |
232 |
|
* instead. |
233 |
|
*/ |
234 |
Articulation* Articulator::GetNextArticulation() { |
Articulation* Articulator::GetNextArticulation() { |
235 |
if (!pArticulations) return NULL; |
if (!pArticulations) return NULL; |
236 |
ArticulationsIterator++; |
ArticulationsIterator++; |
244 |
if (lart) { |
if (lart) { |
245 |
uint32_t artCkType = (lart->GetListType() == LIST_TYPE_LAR2) ? CHUNK_ID_ART2 |
uint32_t artCkType = (lart->GetListType() == LIST_TYPE_LAR2) ? CHUNK_ID_ART2 |
246 |
: CHUNK_ID_ARTL; |
: CHUNK_ID_ARTL; |
247 |
RIFF::Chunk* art = lart->GetFirstSubChunk(); |
size_t i = 0; |
248 |
while (art) { |
for (RIFF::Chunk* art = lart->GetSubChunkAt(i); art; |
249 |
|
art = lart->GetSubChunkAt(++i)) |
250 |
|
{ |
251 |
if (art->GetChunkID() == artCkType) { |
if (art->GetChunkID() == artCkType) { |
252 |
if (!pArticulations) pArticulations = new ArticulationList; |
if (!pArticulations) pArticulations = new ArticulationList; |
253 |
pArticulations->push_back(new Articulation(art)); |
pArticulations->push_back(new Articulation(art)); |
254 |
} |
} |
|
art = lart->GetNextSubChunk(); |
|
255 |
} |
} |
256 |
} |
} |
257 |
} |
} |
592 |
} |
} |
593 |
|
|
594 |
void Resource::GenerateDLSID(dlsid_t* pDLSID) { |
void Resource::GenerateDLSID(dlsid_t* pDLSID) { |
|
#if defined(WIN32) || defined(__APPLE__) || defined(HAVE_UUID_GENERATE) |
|
595 |
#ifdef WIN32 |
#ifdef WIN32 |
596 |
UUID uuid; |
UUID uuid; |
597 |
UuidCreate(&uuid); |
UuidCreate(&uuid); |
616 |
pDLSID->abData[5] = uuid.byte13; |
pDLSID->abData[5] = uuid.byte13; |
617 |
pDLSID->abData[6] = uuid.byte14; |
pDLSID->abData[6] = uuid.byte14; |
618 |
pDLSID->abData[7] = uuid.byte15; |
pDLSID->abData[7] = uuid.byte15; |
619 |
#else |
#elif defined(HAVE_UUID_GENERATE) |
620 |
uuid_t uuid; |
uuid_t uuid; |
621 |
uuid_generate(uuid); |
uuid_generate(uuid); |
622 |
pDLSID->ulData1 = uuid[0] | uuid[1] << 8 | uuid[2] << 16 | uuid[3] << 24; |
pDLSID->ulData1 = uuid[0] | uuid[1] << 8 | uuid[2] << 16 | uuid[3] << 24; |
623 |
pDLSID->usData2 = uuid[4] | uuid[5] << 8; |
pDLSID->usData2 = uuid[4] | uuid[5] << 8; |
624 |
pDLSID->usData3 = uuid[6] | uuid[7] << 8; |
pDLSID->usData3 = uuid[6] | uuid[7] << 8; |
625 |
memcpy(pDLSID->abData, &uuid[8], 8); |
memcpy(pDLSID->abData, &uuid[8], 8); |
626 |
#endif |
#else |
627 |
|
# error "Missing support for uuid generation" |
628 |
#endif |
#endif |
629 |
} |
} |
630 |
|
|
1199 |
if (pSample) return pSample; |
if (pSample) return pSample; |
1200 |
File* file = (File*) GetParent()->GetParent(); |
File* file = (File*) GetParent()->GetParent(); |
1201 |
uint64_t soughtoffset = file->pWavePoolTable[WavePoolTableIndex]; |
uint64_t soughtoffset = file->pWavePoolTable[WavePoolTableIndex]; |
1202 |
Sample* sample = file->GetFirstSample(); |
size_t i = 0; |
1203 |
while (sample) { |
for (Sample* sample = file->GetSample(i); sample; |
1204 |
|
sample = file->GetSample(++i)) |
1205 |
|
{ |
1206 |
if (sample->ullWavePoolOffset == soughtoffset) return (pSample = sample); |
if (sample->ullWavePoolOffset == soughtoffset) return (pSample = sample); |
|
sample = file->GetNextSample(); |
|
1207 |
} |
} |
1208 |
return NULL; |
return NULL; |
1209 |
} |
} |
1394 |
pRegions = NULL; |
pRegions = NULL; |
1395 |
} |
} |
1396 |
|
|
1397 |
|
/** |
1398 |
|
* Returns Region at supplied @a pos position within the region list of |
1399 |
|
* this instrument. If supplied @a pos is out of bounds then @c NULL is |
1400 |
|
* returned. |
1401 |
|
* |
1402 |
|
* @param pos - position of sought Region in region list |
1403 |
|
* @returns pointer address to requested region or @c NULL if @a pos is |
1404 |
|
* out of bounds |
1405 |
|
*/ |
1406 |
|
Region* Instrument::GetRegionAt(size_t pos) { |
1407 |
|
if (!pRegions) LoadRegions(); |
1408 |
|
if (!pRegions) return NULL; |
1409 |
|
if (pos >= pRegions->size()) return NULL; |
1410 |
|
return (*pRegions)[pos]; |
1411 |
|
} |
1412 |
|
|
1413 |
|
/** |
1414 |
|
* Returns the first Region of the instrument. You have to call this |
1415 |
|
* method once before you use GetNextRegion(). |
1416 |
|
* |
1417 |
|
* @returns pointer address to first region or NULL if there is none |
1418 |
|
* @see GetNextRegion() |
1419 |
|
* @deprecated This method is not reentrant-safe, use GetRegionAt() |
1420 |
|
* instead. |
1421 |
|
*/ |
1422 |
Region* Instrument::GetFirstRegion() { |
Region* Instrument::GetFirstRegion() { |
1423 |
if (!pRegions) LoadRegions(); |
if (!pRegions) LoadRegions(); |
1424 |
if (!pRegions) return NULL; |
if (!pRegions) return NULL; |
1426 |
return (RegionsIterator != pRegions->end()) ? *RegionsIterator : NULL; |
return (RegionsIterator != pRegions->end()) ? *RegionsIterator : NULL; |
1427 |
} |
} |
1428 |
|
|
1429 |
|
/** |
1430 |
|
* Returns the next Region of the instrument. You have to call |
1431 |
|
* GetFirstRegion() once before you can use this method. By calling this |
1432 |
|
* method multiple times it iterates through the available Regions. |
1433 |
|
* |
1434 |
|
* @returns pointer address to the next region or NULL if end reached |
1435 |
|
* @see GetFirstRegion() |
1436 |
|
* @deprecated This method is not reentrant-safe, use GetRegionAt() |
1437 |
|
* instead. |
1438 |
|
*/ |
1439 |
Region* Instrument::GetNextRegion() { |
Region* Instrument::GetNextRegion() { |
1440 |
if (!pRegions) return NULL; |
if (!pRegions) return NULL; |
1441 |
RegionsIterator++; |
RegionsIterator++; |
1447 |
RIFF::List* lrgn = pCkInstrument->GetSubList(LIST_TYPE_LRGN); |
RIFF::List* lrgn = pCkInstrument->GetSubList(LIST_TYPE_LRGN); |
1448 |
if (lrgn) { |
if (lrgn) { |
1449 |
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 |
1450 |
RIFF::List* rgn = lrgn->GetFirstSubList(); |
size_t i = 0; |
1451 |
while (rgn) { |
for (RIFF::List* rgn = lrgn->GetSubListAt(i); rgn; |
1452 |
|
rgn = lrgn->GetSubListAt(++i)) |
1453 |
|
{ |
1454 |
if (rgn->GetListType() == regionCkType) { |
if (rgn->GetListType() == regionCkType) { |
1455 |
pRegions->push_back(new Region(this, rgn)); |
pRegions->push_back(new Region(this, rgn)); |
1456 |
} |
} |
|
rgn = lrgn->GetNextSubList(); |
|
1457 |
} |
} |
1458 |
} |
} |
1459 |
} |
} |
1472 |
void Instrument::MoveRegion(Region* pSrc, Region* pDst) { |
void Instrument::MoveRegion(Region* pSrc, Region* pDst) { |
1473 |
RIFF::List* lrgn = pCkInstrument->GetSubList(LIST_TYPE_LRGN); |
RIFF::List* lrgn = pCkInstrument->GetSubList(LIST_TYPE_LRGN); |
1474 |
lrgn->MoveSubChunk(pSrc->pCkRegion, (RIFF::Chunk*) (pDst ? pDst->pCkRegion : 0)); |
lrgn->MoveSubChunk(pSrc->pCkRegion, (RIFF::Chunk*) (pDst ? pDst->pCkRegion : 0)); |
1475 |
|
for (size_t i = 0; i < pRegions->size(); ++i) { |
1476 |
pRegions->remove(pSrc); |
if ((*pRegions)[i] == pSrc) { |
1477 |
RegionList::iterator iter = find(pRegions->begin(), pRegions->end(), pDst); |
pRegions->erase(pRegions->begin() + i); |
1478 |
pRegions->insert(iter, pSrc); |
RegionList::iterator iter = find(pRegions->begin(), pRegions->end(), pDst); |
1479 |
|
pRegions->insert(iter, pSrc); |
1480 |
|
} |
1481 |
|
} |
1482 |
} |
} |
1483 |
|
|
1484 |
void Instrument::DeleteRegion(Region* pRegion) { |
void Instrument::DeleteRegion(Region* pRegion) { |
1521 |
RegionList::iterator iter = pRegions->begin(); |
RegionList::iterator iter = pRegions->begin(); |
1522 |
RegionList::iterator end = pRegions->end(); |
RegionList::iterator end = pRegions->end(); |
1523 |
for (int i = 0; iter != end; ++iter, ++i) { |
for (int i = 0; iter != end; ++iter, ++i) { |
1524 |
// divide local progress into subprogress |
if (pProgress) { |
1525 |
progress_t subprogress; |
// divide local progress into subprogress |
1526 |
__divide_progress(pProgress, &subprogress, pRegions->size(), i); |
progress_t subprogress; |
1527 |
// do the actual work |
__divide_progress(pProgress, &subprogress, pRegions->size(), i); |
1528 |
(*iter)->UpdateChunks(&subprogress); |
// do the actual work |
1529 |
|
(*iter)->UpdateChunks(&subprogress); |
1530 |
|
} else |
1531 |
|
(*iter)->UpdateChunks(NULL); |
1532 |
} |
} |
1533 |
__notify_progress(pProgress, 1.0); // notify done |
if (pProgress) |
1534 |
|
__notify_progress(pProgress, 1.0); // notify done |
1535 |
} |
} |
1536 |
|
|
1537 |
/** @brief Destructor. |
/** @brief Destructor. |
1600 |
void Instrument::CopyAssign(const Instrument* orig) { |
void Instrument::CopyAssign(const Instrument* orig) { |
1601 |
CopyAssignCore(orig); |
CopyAssignCore(orig); |
1602 |
// delete all regions first |
// delete all regions first |
1603 |
while (Regions) DeleteRegion(GetFirstRegion()); |
while (Regions) DeleteRegion(GetRegionAt(0)); |
1604 |
// now recreate and copy regions |
// now recreate and copy regions |
1605 |
{ |
{ |
1606 |
RegionList::const_iterator it = orig->pRegions->begin(); |
RegionList::const_iterator it = orig->pRegions->begin(); |
1736 |
delete pRIFF; |
delete pRIFF; |
1737 |
} |
} |
1738 |
|
|
1739 |
|
/** |
1740 |
|
* Returns Sample object of @a index. |
1741 |
|
* |
1742 |
|
* @param index - position of sample in sample list (0..n) |
1743 |
|
* @returns sample object or NULL if index is out of bounds |
1744 |
|
*/ |
1745 |
|
Sample* File::GetSample(size_t index) { |
1746 |
|
if (!pSamples) LoadSamples(); |
1747 |
|
if (!pSamples) return NULL; |
1748 |
|
if (index >= pSamples->size()) return NULL; |
1749 |
|
return (*pSamples)[index]; |
1750 |
|
} |
1751 |
|
|
1752 |
|
/** |
1753 |
|
* Returns a pointer to the first <i>Sample</i> object of the file, |
1754 |
|
* <i>NULL</i> otherwise. |
1755 |
|
* |
1756 |
|
* @deprecated This method is not reentrant-safe, use GetSample() |
1757 |
|
* instead. |
1758 |
|
*/ |
1759 |
Sample* File::GetFirstSample() { |
Sample* File::GetFirstSample() { |
1760 |
if (!pSamples) LoadSamples(); |
if (!pSamples) LoadSamples(); |
1761 |
if (!pSamples) return NULL; |
if (!pSamples) return NULL; |
1763 |
return (SamplesIterator != pSamples->end()) ? *SamplesIterator : NULL; |
return (SamplesIterator != pSamples->end()) ? *SamplesIterator : NULL; |
1764 |
} |
} |
1765 |
|
|
1766 |
|
/** |
1767 |
|
* Returns a pointer to the next <i>Sample</i> object of the file, |
1768 |
|
* <i>NULL</i> otherwise. |
1769 |
|
* |
1770 |
|
* @deprecated This method is not reentrant-safe, use GetSample() |
1771 |
|
* instead. |
1772 |
|
*/ |
1773 |
Sample* File::GetNextSample() { |
Sample* File::GetNextSample() { |
1774 |
if (!pSamples) return NULL; |
if (!pSamples) return NULL; |
1775 |
SamplesIterator++; |
SamplesIterator++; |
1782 |
if (wvpl) { |
if (wvpl) { |
1783 |
file_offset_t wvplFileOffset = wvpl->GetFilePos() - |
file_offset_t wvplFileOffset = wvpl->GetFilePos() - |
1784 |
wvpl->GetPos(); // should be zero, but just to be sure |
wvpl->GetPos(); // should be zero, but just to be sure |
1785 |
RIFF::List* wave = wvpl->GetFirstSubList(); |
size_t i = 0; |
1786 |
while (wave) { |
for (RIFF::List* wave = wvpl->GetSubListAt(i); wave; |
1787 |
|
wave = wvpl->GetSubListAt(++i)) |
1788 |
|
{ |
1789 |
if (wave->GetListType() == LIST_TYPE_WAVE) { |
if (wave->GetListType() == LIST_TYPE_WAVE) { |
1790 |
file_offset_t waveFileOffset = wave->GetFilePos() - |
file_offset_t waveFileOffset = wave->GetFilePos() - |
1791 |
wave->GetPos(); // should be zero, but just to be sure |
wave->GetPos(); // should be zero, but just to be sure |
1792 |
pSamples->push_back(new Sample(this, wave, waveFileOffset - wvplFileOffset)); |
pSamples->push_back(new Sample(this, wave, waveFileOffset - wvplFileOffset)); |
1793 |
} |
} |
|
wave = wvpl->GetNextSubList(); |
|
1794 |
} |
} |
1795 |
} |
} |
1796 |
else { // Seen a dwpl list chunk instead of a wvpl list chunk in some file (officially not DLS compliant) |
else { // Seen a dwpl list chunk instead of a wvpl list chunk in some file (officially not DLS compliant) |
1798 |
if (dwpl) { |
if (dwpl) { |
1799 |
file_offset_t dwplFileOffset = dwpl->GetFilePos() - |
file_offset_t dwplFileOffset = dwpl->GetFilePos() - |
1800 |
dwpl->GetPos(); // should be zero, but just to be sure |
dwpl->GetPos(); // should be zero, but just to be sure |
1801 |
RIFF::List* wave = dwpl->GetFirstSubList(); |
size_t i = 0; |
1802 |
while (wave) { |
for (RIFF::List* wave = dwpl->GetSubListAt(i); wave; |
1803 |
|
wave = dwpl->GetSubListAt(++i)) |
1804 |
|
{ |
1805 |
if (wave->GetListType() == LIST_TYPE_WAVE) { |
if (wave->GetListType() == LIST_TYPE_WAVE) { |
1806 |
file_offset_t waveFileOffset = wave->GetFilePos() - |
file_offset_t waveFileOffset = wave->GetFilePos() - |
1807 |
wave->GetPos(); // should be zero, but just to be sure |
wave->GetPos(); // should be zero, but just to be sure |
1808 |
pSamples->push_back(new Sample(this, wave, waveFileOffset - dwplFileOffset)); |
pSamples->push_back(new Sample(this, wave, waveFileOffset - dwplFileOffset)); |
1809 |
} |
} |
|
wave = dwpl->GetNextSubList(); |
|
1810 |
} |
} |
1811 |
} |
} |
1812 |
} |
} |
1846 |
delete pSample; |
delete pSample; |
1847 |
} |
} |
1848 |
|
|
1849 |
|
/** |
1850 |
|
* Returns the instrument with the given @a index from the list of |
1851 |
|
* instruments of this file. |
1852 |
|
* |
1853 |
|
* @param index - number of the sought instrument (0..n) |
1854 |
|
* @returns sought instrument or NULL if there's no such instrument |
1855 |
|
*/ |
1856 |
|
Instrument* File::GetInstrument(size_t index) { |
1857 |
|
if (!pInstruments) LoadInstruments(); |
1858 |
|
if (!pInstruments) return NULL; |
1859 |
|
if (index >= pInstruments->size()) return NULL; |
1860 |
|
return (*pInstruments)[index]; |
1861 |
|
} |
1862 |
|
|
1863 |
|
/** |
1864 |
|
* Returns a pointer to the first <i>Instrument</i> object of the file, |
1865 |
|
* <i>NULL</i> otherwise. |
1866 |
|
* |
1867 |
|
* @deprecated This method is not reentrant-safe, use GetInstrument() |
1868 |
|
* instead. |
1869 |
|
*/ |
1870 |
Instrument* File::GetFirstInstrument() { |
Instrument* File::GetFirstInstrument() { |
1871 |
if (!pInstruments) LoadInstruments(); |
if (!pInstruments) LoadInstruments(); |
1872 |
if (!pInstruments) return NULL; |
if (!pInstruments) return NULL; |
1874 |
return (InstrumentsIterator != pInstruments->end()) ? *InstrumentsIterator : NULL; |
return (InstrumentsIterator != pInstruments->end()) ? *InstrumentsIterator : NULL; |
1875 |
} |
} |
1876 |
|
|
1877 |
|
/** |
1878 |
|
* Returns a pointer to the next <i>Instrument</i> object of the file, |
1879 |
|
* <i>NULL</i> otherwise. |
1880 |
|
* |
1881 |
|
* @deprecated This method is not reentrant-safe, use GetInstrument() |
1882 |
|
* instead. |
1883 |
|
*/ |
1884 |
Instrument* File::GetNextInstrument() { |
Instrument* File::GetNextInstrument() { |
1885 |
if (!pInstruments) return NULL; |
if (!pInstruments) return NULL; |
1886 |
InstrumentsIterator++; |
InstrumentsIterator++; |
1891 |
if (!pInstruments) pInstruments = new InstrumentList; |
if (!pInstruments) pInstruments = new InstrumentList; |
1892 |
RIFF::List* lstInstruments = pRIFF->GetSubList(LIST_TYPE_LINS); |
RIFF::List* lstInstruments = pRIFF->GetSubList(LIST_TYPE_LINS); |
1893 |
if (lstInstruments) { |
if (lstInstruments) { |
1894 |
RIFF::List* lstInstr = lstInstruments->GetFirstSubList(); |
size_t i = 0; |
1895 |
while (lstInstr) { |
for (RIFF::List* lstInstr = lstInstruments->GetSubListAt(i); |
1896 |
|
lstInstr; lstInstr = lstInstruments->GetSubListAt(++i)) |
1897 |
|
{ |
1898 |
if (lstInstr->GetListType() == LIST_TYPE_INS) { |
if (lstInstr->GetListType() == LIST_TYPE_INS) { |
1899 |
pInstruments->push_back(new Instrument(this, lstInstr)); |
pInstruments->push_back(new Instrument(this, lstInstr)); |
1900 |
} |
} |
|
lstInstr = lstInstruments->GetNextSubList(); |
|
1901 |
} |
} |
1902 |
} |
} |
1903 |
} |
} |
2016 |
|
|
2017 |
// update instrument's chunks |
// update instrument's chunks |
2018 |
if (pInstruments) { |
if (pInstruments) { |
2019 |
// divide local progress into subprogress |
if (pProgress) { |
2020 |
progress_t subprogress; |
// divide local progress into subprogress |
2021 |
__divide_progress(pProgress, &subprogress, 20.f, 0.f); // arbitrarily subdivided into 5% of total progress |
progress_t subprogress; |
2022 |
|
__divide_progress(pProgress, &subprogress, 20.f, 0.f); // arbitrarily subdivided into 5% of total progress |
2023 |
|
|
|
// do the actual work |
|
|
InstrumentList::iterator iter = pInstruments->begin(); |
|
|
InstrumentList::iterator end = pInstruments->end(); |
|
|
for (int i = 0; iter != end; ++iter, ++i) { |
|
|
// divide subprogress into sub-subprogress |
|
|
progress_t subsubprogress; |
|
|
__divide_progress(&subprogress, &subsubprogress, pInstruments->size(), i); |
|
2024 |
// do the actual work |
// do the actual work |
2025 |
(*iter)->UpdateChunks(&subsubprogress); |
InstrumentList::iterator iter = pInstruments->begin(); |
2026 |
} |
InstrumentList::iterator end = pInstruments->end(); |
2027 |
|
for (int i = 0; iter != end; ++iter, ++i) { |
2028 |
|
// divide subprogress into sub-subprogress |
2029 |
|
progress_t subsubprogress; |
2030 |
|
__divide_progress(&subprogress, &subsubprogress, pInstruments->size(), i); |
2031 |
|
// do the actual work |
2032 |
|
(*iter)->UpdateChunks(&subsubprogress); |
2033 |
|
} |
2034 |
|
|
2035 |
__notify_progress(&subprogress, 1.0); // notify subprogress done |
__notify_progress(&subprogress, 1.0); // notify subprogress done |
2036 |
|
} else { |
2037 |
|
InstrumentList::iterator iter = pInstruments->begin(); |
2038 |
|
InstrumentList::iterator end = pInstruments->end(); |
2039 |
|
for (int i = 0; iter != end; ++iter, ++i) { |
2040 |
|
(*iter)->UpdateChunks(NULL); |
2041 |
|
} |
2042 |
|
} |
2043 |
} |
} |
2044 |
|
|
2045 |
// update 'ptbl' chunk |
// update 'ptbl' chunk |
2057 |
|
|
2058 |
// update sample's chunks |
// update sample's chunks |
2059 |
if (pSamples) { |
if (pSamples) { |
2060 |
// divide local progress into subprogress |
if (pProgress) { |
2061 |
progress_t subprogress; |
// divide local progress into subprogress |
2062 |
__divide_progress(pProgress, &subprogress, 20.f, 1.f); // arbitrarily subdivided into 95% of total progress |
progress_t subprogress; |
2063 |
|
__divide_progress(pProgress, &subprogress, 20.f, 1.f); // arbitrarily subdivided into 95% of total progress |
2064 |
|
|
|
// do the actual work |
|
|
SampleList::iterator iter = pSamples->begin(); |
|
|
SampleList::iterator end = pSamples->end(); |
|
|
for (int i = 0; iter != end; ++iter, ++i) { |
|
|
// divide subprogress into sub-subprogress |
|
|
progress_t subsubprogress; |
|
|
__divide_progress(&subprogress, &subsubprogress, pSamples->size(), i); |
|
2065 |
// do the actual work |
// do the actual work |
2066 |
(*iter)->UpdateChunks(&subsubprogress); |
SampleList::iterator iter = pSamples->begin(); |
2067 |
} |
SampleList::iterator end = pSamples->end(); |
2068 |
|
for (int i = 0; iter != end; ++iter, ++i) { |
2069 |
|
// divide subprogress into sub-subprogress |
2070 |
|
progress_t subsubprogress; |
2071 |
|
__divide_progress(&subprogress, &subsubprogress, pSamples->size(), i); |
2072 |
|
// do the actual work |
2073 |
|
(*iter)->UpdateChunks(&subsubprogress); |
2074 |
|
} |
2075 |
|
|
2076 |
__notify_progress(&subprogress, 1.0); // notify subprogress done |
__notify_progress(&subprogress, 1.0); // notify subprogress done |
2077 |
|
} else { |
2078 |
|
SampleList::iterator iter = pSamples->begin(); |
2079 |
|
SampleList::iterator end = pSamples->end(); |
2080 |
|
for (int i = 0; iter != end; ++iter, ++i) { |
2081 |
|
(*iter)->UpdateChunks(NULL); |
2082 |
|
} |
2083 |
|
} |
2084 |
} |
} |
2085 |
|
|
2086 |
// if there are any extension files, gather which ones are regular |
// if there are any extension files, gather which ones are regular |
2216 |
ptbl->Resize(iPtblSize); |
ptbl->Resize(iPtblSize); |
2217 |
} |
} |
2218 |
|
|
2219 |
__notify_progress(pProgress, 1.0); // notify done |
if (pProgress) |
2220 |
|
__notify_progress(pProgress, 1.0); // notify done |
2221 |
} |
} |
2222 |
|
|
2223 |
/** @brief Save changes to another file. |
/** @brief Save changes to another file. |
2246 |
// save the individual extension files |
// save the individual extension files |
2247 |
std::list<RIFF::File*>::iterator it = ExtensionFiles.begin(); |
std::list<RIFF::File*>::iterator it = ExtensionFiles.begin(); |
2248 |
for (int i = 0; it != ExtensionFiles.end(); ++i, ++it) { |
for (int i = 0; it != ExtensionFiles.end(); ++i, ++it) { |
|
// divide local progress into subprogress |
|
|
progress_t subprogress; |
|
|
__divide_progress(pProgress, &subprogress, tasks, 0.f + i); // subdivided into amount of extension files |
|
2249 |
//FIXME: the .gx99 file is always used by GSt for convolution |
//FIXME: the .gx99 file is always used by GSt for convolution |
2250 |
// data (GigaPulse); so we should better detect by subchunk |
// data (GigaPulse); so we should better detect by subchunk |
2251 |
// whether the extension file is intended for convolution |
// whether the extension file is intended for convolution |
2256 |
std::string ext = (isGigaPulseFile) ? ".gx99" : strPrint(".gx%02d", i+1); |
std::string ext = (isGigaPulseFile) ? ".gx99" : strPrint(".gx%02d", i+1); |
2257 |
std::string newPath = baseName + ext; |
std::string newPath = baseName + ext; |
2258 |
// save extension file to its new location |
// save extension file to its new location |
2259 |
(*it)->Save(newPath, &subprogress); |
if (pProgress) { |
2260 |
|
// divide local progress into subprogress |
2261 |
|
progress_t subprogress; |
2262 |
|
__divide_progress(pProgress, &subprogress, tasks, 0.f + i); // subdivided into amount of extension files |
2263 |
|
// do the actual work |
2264 |
|
(*it)->Save(newPath, &subprogress); |
2265 |
|
} else |
2266 |
|
(*it)->Save(newPath); |
2267 |
} |
} |
2268 |
} |
} |
2269 |
|
|
2270 |
{ |
if (pProgress) { |
2271 |
// divide local progress into subprogress |
// divide local progress into subprogress |
2272 |
progress_t subprogress; |
progress_t subprogress; |
2273 |
__divide_progress(pProgress, &subprogress, tasks, 1.f + nExtFiles); // arbitrarily subdivided into 50% (minus extension files progress) |
__divide_progress(pProgress, &subprogress, tasks, 1.f + nExtFiles); // arbitrarily subdivided into 50% (minus extension files progress) |
2274 |
// do the actual work |
// do the actual work |
2275 |
UpdateChunks(&subprogress); |
UpdateChunks(&subprogress); |
2276 |
} |
} else |
2277 |
{ |
UpdateChunks(NULL); |
2278 |
|
|
2279 |
|
if (pProgress) { |
2280 |
// divide local progress into subprogress |
// divide local progress into subprogress |
2281 |
progress_t subprogress; |
progress_t subprogress; |
2282 |
__divide_progress(pProgress, &subprogress, tasks, 2.f + nExtFiles); // arbitrarily subdivided into 50% (minus extension files progress) |
__divide_progress(pProgress, &subprogress, tasks, 2.f + nExtFiles); // arbitrarily subdivided into 50% (minus extension files progress) |
2283 |
// do the actual work |
// do the actual work |
2284 |
pRIFF->Save(Path, &subprogress); |
pRIFF->Save(Path, &subprogress); |
2285 |
} |
} else |
2286 |
|
pRIFF->Save(Path); |
2287 |
|
|
2288 |
UpdateFileOffsets(); |
UpdateFileOffsets(); |
2289 |
__notify_progress(pProgress, 1.0); // notify done |
|
2290 |
|
if (pProgress) |
2291 |
|
__notify_progress(pProgress, 1.0); // notify done |
2292 |
} |
} |
2293 |
|
|
2294 |
/** @brief Save changes to same file. |
/** @brief Save changes to same file. |
2310 |
if (!ExtensionFiles.empty()) { |
if (!ExtensionFiles.empty()) { |
2311 |
std::list<RIFF::File*>::iterator it = ExtensionFiles.begin(); |
std::list<RIFF::File*>::iterator it = ExtensionFiles.begin(); |
2312 |
for (int i = 0; it != ExtensionFiles.end(); ++i, ++it) { |
for (int i = 0; it != ExtensionFiles.end(); ++i, ++it) { |
|
// divide local progress into subprogress |
|
|
progress_t subprogress; |
|
|
__divide_progress(pProgress, &subprogress, tasks, 0.f + i); // subdivided into amount of extension files |
|
2313 |
// save extension file |
// save extension file |
2314 |
(*it)->Save(&subprogress); |
if (pProgress) { |
2315 |
|
// divide local progress into subprogress |
2316 |
|
progress_t subprogress; |
2317 |
|
__divide_progress(pProgress, &subprogress, tasks, 0.f + i); // subdivided into amount of extension files |
2318 |
|
// do the actual work |
2319 |
|
(*it)->Save(&subprogress); |
2320 |
|
} else |
2321 |
|
(*it)->Save(); |
2322 |
} |
} |
2323 |
} |
} |
2324 |
|
|
2325 |
{ |
if (pProgress) { |
2326 |
// divide local progress into subprogress |
// divide local progress into subprogress |
2327 |
progress_t subprogress; |
progress_t subprogress; |
2328 |
__divide_progress(pProgress, &subprogress, tasks, 1.f + nExtFiles); // arbitrarily subdivided into 50% (minus extension files progress) |
__divide_progress(pProgress, &subprogress, tasks, 1.f + nExtFiles); // arbitrarily subdivided into 50% (minus extension files progress) |
2329 |
// do the actual work |
// do the actual work |
2330 |
UpdateChunks(&subprogress); |
UpdateChunks(&subprogress); |
2331 |
} |
} else |
2332 |
{ |
UpdateChunks(NULL); |
2333 |
|
|
2334 |
|
if (pProgress) { |
2335 |
// divide local progress into subprogress |
// divide local progress into subprogress |
2336 |
progress_t subprogress; |
progress_t subprogress; |
2337 |
__divide_progress(pProgress, &subprogress, tasks, 2.f + nExtFiles); // arbitrarily subdivided into 50% (minus extension files progress) |
__divide_progress(pProgress, &subprogress, tasks, 2.f + nExtFiles); // arbitrarily subdivided into 50% (minus extension files progress) |
2338 |
// do the actual work |
// do the actual work |
2339 |
pRIFF->Save(&subprogress); |
pRIFF->Save(&subprogress); |
2340 |
} |
} else |
2341 |
|
pRIFF->Save(); |
2342 |
|
|
2343 |
UpdateFileOffsets(); |
UpdateFileOffsets(); |
2344 |
__notify_progress(pProgress, 1.0); // notify done |
|
2345 |
|
if (pProgress) |
2346 |
|
__notify_progress(pProgress, 1.0); // notify done |
2347 |
} |
} |
2348 |
|
|
2349 |
/** @brief Updates all file offsets stored all over the file. |
/** @brief Updates all file offsets stored all over the file. |