53 |
|
|
54 |
namespace gig { |
namespace gig { |
55 |
|
|
|
// *************** progress_t *************** |
|
|
// * |
|
|
|
|
|
progress_t::progress_t() { |
|
|
callback = NULL; |
|
|
custom = NULL; |
|
|
__range_min = 0.0f; |
|
|
__range_max = 1.0f; |
|
|
} |
|
|
|
|
|
// private helper function to convert progress of a subprocess into the global progress |
|
|
static void __notify_progress(progress_t* pProgress, float subprogress) { |
|
|
if (pProgress && pProgress->callback) { |
|
|
const float totalrange = pProgress->__range_max - pProgress->__range_min; |
|
|
const float totalprogress = pProgress->__range_min + subprogress * totalrange; |
|
|
pProgress->factor = totalprogress; |
|
|
pProgress->callback(pProgress); // now actually notify about the progress |
|
|
} |
|
|
} |
|
|
|
|
|
// private helper function to divide a progress into subprogresses |
|
|
static void __divide_progress(progress_t* pParentProgress, progress_t* pSubProgress, float totalTasks, float currentTask) { |
|
|
if (pParentProgress && pParentProgress->callback) { |
|
|
const float totalrange = pParentProgress->__range_max - pParentProgress->__range_min; |
|
|
pSubProgress->callback = pParentProgress->callback; |
|
|
pSubProgress->custom = pParentProgress->custom; |
|
|
pSubProgress->__range_min = pParentProgress->__range_min + totalrange * currentTask / totalTasks; |
|
|
pSubProgress->__range_max = pSubProgress->__range_min + totalrange / totalTasks; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
56 |
// *************** Internal functions for sample decompression *************** |
// *************** Internal functions for sample decompression *************** |
57 |
// * |
// * |
58 |
|
|
496 |
* Usually there is absolutely no need to call this method explicitly. |
* Usually there is absolutely no need to call this method explicitly. |
497 |
* It will be called automatically when File::Save() was called. |
* It will be called automatically when File::Save() was called. |
498 |
* |
* |
499 |
|
* @param pProgress - callback function for progress notification |
500 |
* @throws DLS::Exception if FormatTag != DLS_WAVE_FORMAT_PCM or no sample data |
* @throws DLS::Exception if FormatTag != DLS_WAVE_FORMAT_PCM or no sample data |
501 |
* was provided yet |
* was provided yet |
502 |
* @throws gig::Exception if there is any invalid sample setting |
* @throws gig::Exception if there is any invalid sample setting |
503 |
*/ |
*/ |
504 |
void Sample::UpdateChunks() { |
void Sample::UpdateChunks(progress_t* pProgress) { |
505 |
// first update base class's chunks |
// first update base class's chunks |
506 |
DLS::Sample::UpdateChunks(); |
DLS::Sample::UpdateChunks(pProgress); |
507 |
|
|
508 |
// make sure 'smpl' chunk exists |
// make sure 'smpl' chunk exists |
509 |
pCkSmpl = pWaveList->GetSubChunk(CHUNK_ID_SMPL); |
pCkSmpl = pWaveList->GetSubChunk(CHUNK_ID_SMPL); |
1721 |
* |
* |
1722 |
* Usually there is absolutely no need to call this method explicitly. |
* Usually there is absolutely no need to call this method explicitly. |
1723 |
* It will be called automatically when File::Save() was called. |
* It will be called automatically when File::Save() was called. |
1724 |
|
* |
1725 |
|
* @param pProgress - callback function for progress notification |
1726 |
*/ |
*/ |
1727 |
void DimensionRegion::UpdateChunks() { |
void DimensionRegion::UpdateChunks(progress_t* pProgress) { |
1728 |
// first update base class's chunk |
// first update base class's chunk |
1729 |
DLS::Sampler::UpdateChunks(); |
DLS::Sampler::UpdateChunks(pProgress); |
1730 |
|
|
1731 |
RIFF::Chunk* wsmp = pParentList->GetSubChunk(CHUNK_ID_WSMP); |
RIFF::Chunk* wsmp = pParentList->GetSubChunk(CHUNK_ID_WSMP); |
1732 |
uint8_t* pData = (uint8_t*) wsmp->LoadChunkData(); |
uint8_t* pData = (uint8_t*) wsmp->LoadChunkData(); |
2997 |
* Usually there is absolutely no need to call this method explicitly. |
* Usually there is absolutely no need to call this method explicitly. |
2998 |
* It will be called automatically when File::Save() was called. |
* It will be called automatically when File::Save() was called. |
2999 |
* |
* |
3000 |
|
* @param pProgress - callback function for progress notification |
3001 |
* @throws gig::Exception if samples cannot be dereferenced |
* @throws gig::Exception if samples cannot be dereferenced |
3002 |
*/ |
*/ |
3003 |
void Region::UpdateChunks() { |
void Region::UpdateChunks(progress_t* pProgress) { |
3004 |
// in the gig format we don't care about the Region's sample reference |
// in the gig format we don't care about the Region's sample reference |
3005 |
// but we still have to provide some existing one to not corrupt the |
// but we still have to provide some existing one to not corrupt the |
3006 |
// file, so to avoid the latter we simply always assign the sample of |
// file, so to avoid the latter we simply always assign the sample of |
3008 |
pSample = pDimensionRegions[0]->pSample; |
pSample = pDimensionRegions[0]->pSample; |
3009 |
|
|
3010 |
// first update base class's chunks |
// first update base class's chunks |
3011 |
DLS::Region::UpdateChunks(); |
DLS::Region::UpdateChunks(pProgress); |
3012 |
|
|
3013 |
// update dimension region's chunks |
// update dimension region's chunks |
3014 |
for (int i = 0; i < DimensionRegions; i++) { |
for (int i = 0; i < DimensionRegions; i++) { |
3015 |
pDimensionRegions[i]->UpdateChunks(); |
pDimensionRegions[i]->UpdateChunks(pProgress); |
3016 |
} |
} |
3017 |
|
|
3018 |
File* pFile = (File*) GetParent()->GetParent(); |
File* pFile = (File*) GetParent()->GetParent(); |
3624 |
UpdateVelocityTable(); |
UpdateVelocityTable(); |
3625 |
} |
} |
3626 |
|
|
3627 |
|
/** @brief Change type of an existing dimension. |
3628 |
|
* |
3629 |
|
* Alters the dimension type of a dimension already existing on this |
3630 |
|
* region. If there is currently no dimension on this Region with type |
3631 |
|
* @a oldType, then this call with throw an Exception. Likewise there are |
3632 |
|
* cases where the requested dimension type cannot be performed. For example |
3633 |
|
* if the new dimension type shall be gig::dimension_samplechannel, and the |
3634 |
|
* current dimension has more than 2 zones. In such cases an Exception is |
3635 |
|
* thrown as well. |
3636 |
|
* |
3637 |
|
* @param oldType - identifies the existing dimension to be changed |
3638 |
|
* @param newType - to which dimension type it should be changed to |
3639 |
|
* @throws gig::Exception if requested change cannot be performed |
3640 |
|
*/ |
3641 |
|
void Region::SetDimensionType(dimension_t oldType, dimension_t newType) { |
3642 |
|
if (oldType == newType) return; |
3643 |
|
dimension_def_t* def = GetDimensionDefinition(oldType); |
3644 |
|
if (!def) |
3645 |
|
throw gig::Exception("No dimension with provided old dimension type exists on this region"); |
3646 |
|
if (newType == dimension_samplechannel && def->zones != 2) |
3647 |
|
throw gig::Exception("Cannot change to dimension type 'sample channel', because existing dimension does not have 2 zones"); |
3648 |
|
if (GetDimensionDefinition(newType)) |
3649 |
|
throw gig::Exception("There is already a dimension with requested new dimension type on this region"); |
3650 |
|
def->dimension = newType; |
3651 |
|
def->split_type = __resolveSplitType(newType); |
3652 |
|
} |
3653 |
|
|
3654 |
DimensionRegion* Region::GetDimensionRegionByBit(const std::map<dimension_t,int>& DimCase) { |
DimensionRegion* Region::GetDimensionRegionByBit(const std::map<dimension_t,int>& DimCase) { |
3655 |
uint8_t bits[8] = {}; |
uint8_t bits[8] = {}; |
3656 |
for (std::map<dimension_t,int>::const_iterator it = DimCase.begin(); |
for (std::map<dimension_t,int>::const_iterator it = DimCase.begin(); |
3758 |
return dimreg; |
return dimreg; |
3759 |
} |
} |
3760 |
|
|
3761 |
|
int Region::GetDimensionRegionIndexByValue(const uint DimValues[8]) { |
3762 |
|
uint8_t bits; |
3763 |
|
int veldim = -1; |
3764 |
|
int velbitpos; |
3765 |
|
int bitpos = 0; |
3766 |
|
int dimregidx = 0; |
3767 |
|
for (uint i = 0; i < Dimensions; i++) { |
3768 |
|
if (pDimensionDefinitions[i].dimension == dimension_velocity) { |
3769 |
|
// the velocity dimension must be handled after the other dimensions |
3770 |
|
veldim = i; |
3771 |
|
velbitpos = bitpos; |
3772 |
|
} else { |
3773 |
|
switch (pDimensionDefinitions[i].split_type) { |
3774 |
|
case split_type_normal: |
3775 |
|
if (pDimensionRegions[0]->DimensionUpperLimits[i]) { |
3776 |
|
// gig3: all normal dimensions (not just the velocity dimension) have custom zone ranges |
3777 |
|
for (bits = 0 ; bits < pDimensionDefinitions[i].zones ; bits++) { |
3778 |
|
if (DimValues[i] <= pDimensionRegions[bits << bitpos]->DimensionUpperLimits[i]) break; |
3779 |
|
} |
3780 |
|
} else { |
3781 |
|
// gig2: evenly sized zones |
3782 |
|
bits = uint8_t(DimValues[i] / pDimensionDefinitions[i].zone_size); |
3783 |
|
} |
3784 |
|
break; |
3785 |
|
case split_type_bit: // the value is already the sought dimension bit number |
3786 |
|
const uint8_t limiter_mask = (0xff << pDimensionDefinitions[i].bits) ^ 0xff; |
3787 |
|
bits = DimValues[i] & limiter_mask; // just make sure the value doesn't use more bits than allowed |
3788 |
|
break; |
3789 |
|
} |
3790 |
|
dimregidx |= bits << bitpos; |
3791 |
|
} |
3792 |
|
bitpos += pDimensionDefinitions[i].bits; |
3793 |
|
} |
3794 |
|
dimregidx &= 255; |
3795 |
|
DimensionRegion* dimreg = pDimensionRegions[dimregidx]; |
3796 |
|
if (!dimreg) return -1; |
3797 |
|
if (veldim != -1) { |
3798 |
|
// (dimreg is now the dimension region for the lowest velocity) |
3799 |
|
if (dimreg->VelocityTable) // custom defined zone ranges |
3800 |
|
bits = dimreg->VelocityTable[DimValues[veldim] & 127]; |
3801 |
|
else // normal split type |
3802 |
|
bits = uint8_t((DimValues[veldim] & 127) / pDimensionDefinitions[veldim].zone_size); |
3803 |
|
|
3804 |
|
const uint8_t limiter_mask = (1 << pDimensionDefinitions[veldim].bits) - 1; |
3805 |
|
dimregidx |= (bits & limiter_mask) << velbitpos; |
3806 |
|
dimregidx &= 255; |
3807 |
|
} |
3808 |
|
return dimregidx; |
3809 |
|
} |
3810 |
|
|
3811 |
/** |
/** |
3812 |
* Returns the appropriate DimensionRegion for the given dimension bit |
* Returns the appropriate DimensionRegion for the given dimension bit |
3813 |
* numbers (zone index). You usually use <i>GetDimensionRegionByValue</i> |
* numbers (zone index). You usually use <i>GetDimensionRegionByValue</i> |
4093 |
for (int i = 0; i < nameSize; ++i) |
for (int i = 0; i < nameSize; ++i) |
4094 |
Name[i] = ckScri->ReadUint8(); |
Name[i] = ckScri->ReadUint8(); |
4095 |
// to handle potential future extensions of the header |
// to handle potential future extensions of the header |
4096 |
ckScri->SetPos(headerSize - 6*sizeof(int32_t) + nameSize, RIFF::stream_curpos); |
ckScri->SetPos(sizeof(int32_t) + headerSize); |
4097 |
// read actual script data |
// read actual script data |
4098 |
uint32_t scriptSize = ckScri->GetSize() - ckScri->GetPos(); |
uint32_t scriptSize = ckScri->GetSize() - ckScri->GetPos(); |
4099 |
data.resize(scriptSize); |
data.resize(scriptSize); |
4133 |
memcpy(&data[0], &text[0], text.size()); |
memcpy(&data[0], &text[0], text.size()); |
4134 |
} |
} |
4135 |
|
|
4136 |
void Script::UpdateChunks() { |
/** |
4137 |
|
* Apply this script to the respective RIFF chunks. You have to call |
4138 |
|
* File::Save() to make changes persistent. |
4139 |
|
* |
4140 |
|
* Usually there is absolutely no need to call this method explicitly. |
4141 |
|
* It will be called automatically when File::Save() was called. |
4142 |
|
* |
4143 |
|
* @param pProgress - callback function for progress notification |
4144 |
|
*/ |
4145 |
|
void Script::UpdateChunks(progress_t* pProgress) { |
4146 |
// recalculate CRC32 check sum |
// recalculate CRC32 check sum |
4147 |
__resetCRC(crc); |
__resetCRC(crc); |
4148 |
__calculateCRC(&data[0], data.size(), crc); |
__calculateCRC(&data[0], data.size(), crc); |
4187 |
this->pGroup = pGroup; |
this->pGroup = pGroup; |
4188 |
} |
} |
4189 |
|
|
4190 |
|
/** |
4191 |
|
* Returns the script group this script currently belongs to. Each script |
4192 |
|
* is a member of exactly one ScriptGroup. |
4193 |
|
* |
4194 |
|
* @returns current script group |
4195 |
|
*/ |
4196 |
|
ScriptGroup* Script::GetGroup() const { |
4197 |
|
return pGroup; |
4198 |
|
} |
4199 |
|
|
4200 |
void Script::RemoveAllScriptReferences() { |
void Script::RemoveAllScriptReferences() { |
4201 |
File* pFile = pGroup->pFile; |
File* pFile = pGroup->pFile; |
4202 |
for (int i = 0; pFile->GetInstrument(i); ++i) { |
for (int i = 0; pFile->GetInstrument(i); ++i) { |
4232 |
} |
} |
4233 |
} |
} |
4234 |
|
|
4235 |
void ScriptGroup::UpdateChunks() { |
/** |
4236 |
|
* Apply this script group to the respective RIFF chunks. You have to call |
4237 |
|
* File::Save() to make changes persistent. |
4238 |
|
* |
4239 |
|
* Usually there is absolutely no need to call this method explicitly. |
4240 |
|
* It will be called automatically when File::Save() was called. |
4241 |
|
* |
4242 |
|
* @param pProgress - callback function for progress notification |
4243 |
|
*/ |
4244 |
|
void ScriptGroup::UpdateChunks(progress_t* pProgress) { |
4245 |
if (pScripts) { |
if (pScripts) { |
4246 |
if (!pList) |
if (!pList) |
4247 |
pList = pFile->pRIFF->GetSubList(LIST_TYPE_3LS)->AddSubList(LIST_TYPE_RTIS); |
pList = pFile->pRIFF->GetSubList(LIST_TYPE_3LS)->AddSubList(LIST_TYPE_RTIS); |
4252 |
for (std::list<Script*>::iterator it = pScripts->begin(); |
for (std::list<Script*>::iterator it = pScripts->begin(); |
4253 |
it != pScripts->end(); ++it) |
it != pScripts->end(); ++it) |
4254 |
{ |
{ |
4255 |
(*it)->UpdateChunks(); |
(*it)->UpdateChunks(pProgress); |
4256 |
} |
} |
4257 |
} |
} |
4258 |
} |
} |
4415 |
if (lst3LS) { |
if (lst3LS) { |
4416 |
RIFF::Chunk* ckSCSL = lst3LS->GetSubChunk(CHUNK_ID_SCSL); |
RIFF::Chunk* ckSCSL = lst3LS->GetSubChunk(CHUNK_ID_SCSL); |
4417 |
if (ckSCSL) { |
if (ckSCSL) { |
4418 |
int slotCount = ckSCSL->ReadUint32(); |
int headerSize = ckSCSL->ReadUint32(); |
4419 |
int slotSize = ckSCSL->ReadUint32(); |
int slotCount = ckSCSL->ReadUint32(); |
4420 |
int unknownSpace = slotSize - 2*sizeof(uint32_t); // in case of future extensions |
if (slotCount) { |
4421 |
for (int i = 0; i < slotCount; ++i) { |
int slotSize = ckSCSL->ReadUint32(); |
4422 |
_ScriptPooolEntry e; |
ckSCSL->SetPos(headerSize); // in case of future header extensions |
4423 |
e.fileOffset = ckSCSL->ReadUint32(); |
int unknownSpace = slotSize - 2*sizeof(uint32_t); // in case of future slot extensions |
4424 |
e.bypass = ckSCSL->ReadUint32() & 1; |
for (int i = 0; i < slotCount; ++i) { |
4425 |
if (unknownSpace) ckSCSL->SetPos(unknownSpace, RIFF::stream_curpos); // in case of future extensions |
_ScriptPooolEntry e; |
4426 |
scriptPoolFileOffsets.push_back(e); |
e.fileOffset = ckSCSL->ReadUint32(); |
4427 |
|
e.bypass = ckSCSL->ReadUint32() & 1; |
4428 |
|
if (unknownSpace) ckSCSL->SetPos(unknownSpace, RIFF::stream_curpos); // in case of future extensions |
4429 |
|
scriptPoolFileOffsets.push_back(e); |
4430 |
|
} |
4431 |
} |
} |
4432 |
} |
} |
4433 |
} |
} |
4462 |
* Usually there is absolutely no need to call this method explicitly. |
* Usually there is absolutely no need to call this method explicitly. |
4463 |
* It will be called automatically when File::Save() was called. |
* It will be called automatically when File::Save() was called. |
4464 |
* |
* |
4465 |
|
* @param pProgress - callback function for progress notification |
4466 |
* @throws gig::Exception if samples cannot be dereferenced |
* @throws gig::Exception if samples cannot be dereferenced |
4467 |
*/ |
*/ |
4468 |
void Instrument::UpdateChunks() { |
void Instrument::UpdateChunks(progress_t* pProgress) { |
4469 |
// first update base classes' chunks |
// first update base classes' chunks |
4470 |
DLS::Instrument::UpdateChunks(); |
DLS::Instrument::UpdateChunks(pProgress); |
4471 |
|
|
4472 |
// update Regions' chunks |
// update Regions' chunks |
4473 |
{ |
{ |
4474 |
RegionList::iterator iter = pRegions->begin(); |
RegionList::iterator iter = pRegions->begin(); |
4475 |
RegionList::iterator end = pRegions->end(); |
RegionList::iterator end = pRegions->end(); |
4476 |
for (; iter != end; ++iter) |
for (; iter != end; ++iter) |
4477 |
(*iter)->UpdateChunks(); |
(*iter)->UpdateChunks(pProgress); |
4478 |
} |
} |
4479 |
|
|
4480 |
// make sure 'lart' RIFF list chunk exists |
// make sure 'lart' RIFF list chunk exists |
4511 |
} |
} |
4512 |
|
|
4513 |
// own gig format extensions |
// own gig format extensions |
4514 |
if (pScriptRefs) { |
if (ScriptSlotCount()) { |
4515 |
|
// make sure we have converted the original loaded script file |
4516 |
|
// offsets into valid Script object pointers |
4517 |
|
LoadScripts(); |
4518 |
|
|
4519 |
RIFF::List* lst3LS = pCkInstrument->GetSubList(LIST_TYPE_3LS); |
RIFF::List* lst3LS = pCkInstrument->GetSubList(LIST_TYPE_3LS); |
4520 |
if (!lst3LS) lst3LS = pCkInstrument->AddSubList(LIST_TYPE_3LS); |
if (!lst3LS) lst3LS = pCkInstrument->AddSubList(LIST_TYPE_3LS); |
4521 |
const int totalSize = pScriptRefs->size() * 2*sizeof(uint32_t); |
const int slotCount = pScriptRefs->size(); |
4522 |
|
const int headerSize = 3 * sizeof(uint32_t); |
4523 |
|
const int slotSize = 2 * sizeof(uint32_t); |
4524 |
|
const int totalChunkSize = headerSize + slotCount * slotSize; |
4525 |
RIFF::Chunk* ckSCSL = lst3LS->GetSubChunk(CHUNK_ID_SCSL); |
RIFF::Chunk* ckSCSL = lst3LS->GetSubChunk(CHUNK_ID_SCSL); |
4526 |
if (!ckSCSL) ckSCSL = lst3LS->AddSubChunk(CHUNK_ID_SCSL, totalSize); |
if (!ckSCSL) ckSCSL = lst3LS->AddSubChunk(CHUNK_ID_SCSL, totalChunkSize); |
4527 |
else ckSCSL->Resize(totalSize); |
else ckSCSL->Resize(totalChunkSize); |
4528 |
uint8_t* pData = (uint8_t*) ckSCSL->LoadChunkData(); |
uint8_t* pData = (uint8_t*) ckSCSL->LoadChunkData(); |
4529 |
for (int i = 0, pos = 0; i < pScriptRefs->size(); ++i) { |
int pos = 0; |
4530 |
int fileOffset = |
store32(&pData[pos], headerSize); |
4531 |
(*pScriptRefs)[i].script->pChunk->GetFilePos() - |
pos += sizeof(uint32_t); |
4532 |
(*pScriptRefs)[i].script->pChunk->GetPos() - |
store32(&pData[pos], slotCount); |
4533 |
CHUNK_HEADER_SIZE; |
pos += sizeof(uint32_t); |
4534 |
store32(&pData[pos], fileOffset); |
store32(&pData[pos], slotSize); |
4535 |
|
pos += sizeof(uint32_t); |
4536 |
|
for (int i = 0; i < slotCount; ++i) { |
4537 |
|
// arbitrary value, the actual file offset will be updated in |
4538 |
|
// UpdateScriptFileOffsets() after the file has been resized |
4539 |
|
int bogusFileOffset = 0; |
4540 |
|
store32(&pData[pos], bogusFileOffset); |
4541 |
pos += sizeof(uint32_t); |
pos += sizeof(uint32_t); |
4542 |
store32(&pData[pos], (*pScriptRefs)[i].bypass ? 1 : 0); |
store32(&pData[pos], (*pScriptRefs)[i].bypass ? 1 : 0); |
4543 |
pos += sizeof(uint32_t); |
pos += sizeof(uint32_t); |
4544 |
} |
} |
4545 |
|
} else { |
4546 |
|
// no script slots, so get rid of any LS custom RIFF chunks (if any) |
4547 |
|
RIFF::List* lst3LS = pCkInstrument->GetSubList(LIST_TYPE_3LS); |
4548 |
|
if (lst3LS) pCkInstrument->DeleteSubChunk(lst3LS); |
4549 |
} |
} |
4550 |
} |
} |
4551 |
|
|
4552 |
|
void Instrument::UpdateScriptFileOffsets() { |
4553 |
|
// own gig format extensions |
4554 |
|
if (pScriptRefs && pScriptRefs->size() > 0) { |
4555 |
|
RIFF::List* lst3LS = pCkInstrument->GetSubList(LIST_TYPE_3LS); |
4556 |
|
RIFF::Chunk* ckSCSL = lst3LS->GetSubChunk(CHUNK_ID_SCSL); |
4557 |
|
const int slotCount = pScriptRefs->size(); |
4558 |
|
const int headerSize = 3 * sizeof(uint32_t); |
4559 |
|
ckSCSL->SetPos(headerSize); |
4560 |
|
for (int i = 0; i < slotCount; ++i) { |
4561 |
|
uint32_t fileOffset = |
4562 |
|
(*pScriptRefs)[i].script->pChunk->GetFilePos() - |
4563 |
|
(*pScriptRefs)[i].script->pChunk->GetPos() - |
4564 |
|
CHUNK_HEADER_SIZE; |
4565 |
|
ckSCSL->WriteUint32(&fileOffset); |
4566 |
|
// jump over flags entry (containing the bypass flag) |
4567 |
|
ckSCSL->SetPos(sizeof(uint32_t), RIFF::stream_curpos); |
4568 |
|
} |
4569 |
|
} |
4570 |
|
} |
4571 |
|
|
4572 |
/** |
/** |
4573 |
* Returns the appropriate Region for a triggered note. |
* Returns the appropriate Region for a triggered note. |
4574 |
* |
* |
4704 |
if (scriptPoolFileOffsets.empty()) return; |
if (scriptPoolFileOffsets.empty()) return; |
4705 |
File* pFile = (File*) GetParent(); |
File* pFile = (File*) GetParent(); |
4706 |
for (uint k = 0; k < scriptPoolFileOffsets.size(); ++k) { |
for (uint k = 0; k < scriptPoolFileOffsets.size(); ++k) { |
4707 |
uint32_t offset = scriptPoolFileOffsets[k].fileOffset; |
uint32_t soughtOffset = scriptPoolFileOffsets[k].fileOffset; |
4708 |
for (uint i = 0; pFile->GetScriptGroup(i); ++i) { |
for (uint i = 0; pFile->GetScriptGroup(i); ++i) { |
4709 |
ScriptGroup* group = pFile->GetScriptGroup(i); |
ScriptGroup* group = pFile->GetScriptGroup(i); |
4710 |
for (uint s = 0; group->GetScript(s); ++s) { |
for (uint s = 0; group->GetScript(s); ++s) { |
4711 |
Script* script = group->GetScript(s); |
Script* script = group->GetScript(s); |
4712 |
if (script->pChunk) { |
if (script->pChunk) { |
4713 |
script->pChunk->SetPos(0); |
uint32_t offset = script->pChunk->GetFilePos() - |
4714 |
if (script->pChunk->GetFilePos() - |
script->pChunk->GetPos() - |
4715 |
script->pChunk->GetPos() - |
CHUNK_HEADER_SIZE; |
4716 |
CHUNK_HEADER_SIZE == offset) |
if (offset == soughtOffset) |
4717 |
{ |
{ |
4718 |
_ScriptPooolRef ref; |
_ScriptPooolRef ref; |
4719 |
ref.script = script; |
ref.script = script; |
4729 |
scriptPoolFileOffsets.clear(); |
scriptPoolFileOffsets.clear(); |
4730 |
} |
} |
4731 |
|
|
4732 |
/** @brief Add new instrument script slot (gig format extension) |
/** @brief Get instrument script (gig format extension). |
4733 |
|
* |
4734 |
|
* Returns the real-time instrument script of instrument script slot |
4735 |
|
* @a index. |
4736 |
|
* |
4737 |
|
* @note This is an own format extension which did not exist i.e. in the |
4738 |
|
* GigaStudio 4 software. It will currently only work with LinuxSampler and |
4739 |
|
* gigedit. |
4740 |
|
* |
4741 |
|
* @param index - instrument script slot index |
4742 |
|
* @returns script or NULL if index is out of bounds |
4743 |
|
*/ |
4744 |
|
Script* Instrument::GetScriptOfSlot(uint index) { |
4745 |
|
LoadScripts(); |
4746 |
|
if (index >= pScriptRefs->size()) return NULL; |
4747 |
|
return pScriptRefs->at(index).script; |
4748 |
|
} |
4749 |
|
|
4750 |
|
/** @brief Add new instrument script slot (gig format extension). |
4751 |
* |
* |
4752 |
* Add the given real-time instrument script reference to this instrument, |
* Add the given real-time instrument script reference to this instrument, |
4753 |
* which shall be executed by the sampler for for this instrument. The |
* which shall be executed by the sampler for for this instrument. The |
4995 |
* |
* |
4996 |
* Usually there is absolutely no need to call this method explicitly. |
* Usually there is absolutely no need to call this method explicitly. |
4997 |
* It will be called automatically when File::Save() was called. |
* It will be called automatically when File::Save() was called. |
4998 |
|
* |
4999 |
|
* @param pProgress - callback function for progress notification |
5000 |
*/ |
*/ |
5001 |
void Group::UpdateChunks() { |
void Group::UpdateChunks(progress_t* pProgress) { |
5002 |
// make sure <3gri> and <3gnl> list chunks exist |
// make sure <3gri> and <3gnl> list chunks exist |
5003 |
RIFF::List* _3gri = pFile->pRIFF->GetSubList(LIST_TYPE_3GRI); |
RIFF::List* _3gri = pFile->pRIFF->GetSubList(LIST_TYPE_3GRI); |
5004 |
if (!_3gri) { |
if (!_3gri) { |
5774 |
* Usually there is absolutely no need to call this method explicitly. |
* Usually there is absolutely no need to call this method explicitly. |
5775 |
* It will be called automatically when File::Save() was called. |
* It will be called automatically when File::Save() was called. |
5776 |
* |
* |
5777 |
|
* @param pProgress - callback function for progress notification |
5778 |
* @throws Exception - on errors |
* @throws Exception - on errors |
5779 |
*/ |
*/ |
5780 |
void File::UpdateChunks() { |
void File::UpdateChunks(progress_t* pProgress) { |
5781 |
bool newFile = pRIFF->GetSubList(LIST_TYPE_INFO) == NULL; |
bool newFile = pRIFF->GetSubList(LIST_TYPE_INFO) == NULL; |
5782 |
|
|
5783 |
b64BitWavePoolOffsets = pVersion && pVersion->major == 3; |
b64BitWavePoolOffsets = pVersion && pVersion->major == 3; |
5800 |
for (std::list<ScriptGroup*>::iterator it = pScriptGroups->begin(); |
for (std::list<ScriptGroup*>::iterator it = pScriptGroups->begin(); |
5801 |
it != pScriptGroups->end(); ++it) |
it != pScriptGroups->end(); ++it) |
5802 |
{ |
{ |
5803 |
(*it)->UpdateChunks(); |
(*it)->UpdateChunks(pProgress); |
5804 |
} |
} |
5805 |
} |
} |
5806 |
} |
} |
5807 |
|
|
5808 |
// first update base class's chunks |
// first update base class's chunks |
5809 |
DLS::File::UpdateChunks(); |
DLS::File::UpdateChunks(pProgress); |
5810 |
|
|
5811 |
if (newFile) { |
if (newFile) { |
5812 |
// INFO was added by Resource::UpdateChunks - make sure it |
// INFO was added by Resource::UpdateChunks - make sure it |
5843 |
std::list<Group*>::iterator iter = pGroups->begin(); |
std::list<Group*>::iterator iter = pGroups->begin(); |
5844 |
std::list<Group*>::iterator end = pGroups->end(); |
std::list<Group*>::iterator end = pGroups->end(); |
5845 |
for (; iter != end; ++iter) { |
for (; iter != end; ++iter) { |
5846 |
(*iter)->UpdateChunks(); |
(*iter)->UpdateChunks(pProgress); |
5847 |
} |
} |
5848 |
} |
} |
5849 |
|
|
5975 |
if (einf && pVersion && pVersion->major == 3) pRIFF->MoveSubChunk(_3crc, einf); |
if (einf && pVersion && pVersion->major == 3) pRIFF->MoveSubChunk(_3crc, einf); |
5976 |
} |
} |
5977 |
} |
} |
5978 |
|
|
5979 |
|
void File::UpdateFileOffsets() { |
5980 |
|
DLS::File::UpdateFileOffsets(); |
5981 |
|
|
5982 |
|
for (Instrument* instrument = GetFirstInstrument(); instrument; |
5983 |
|
instrument = GetNextInstrument()) |
5984 |
|
{ |
5985 |
|
instrument->UpdateScriptFileOffsets(); |
5986 |
|
} |
5987 |
|
} |
5988 |
|
|
5989 |
/** |
/** |
5990 |
* Enable / disable automatic loading. By default this properyt is |
* Enable / disable automatic loading. By default this properyt is |