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-2007 by Christian Schoenebeck * |
* Copyright (C) 2003-2013 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 * |
25 |
|
|
26 |
#include "helper.h" |
#include "helper.h" |
27 |
|
|
28 |
|
#include <algorithm> |
29 |
#include <math.h> |
#include <math.h> |
30 |
#include <iostream> |
#include <iostream> |
31 |
|
|
367 |
* is located, 0 otherwise |
* is located, 0 otherwise |
368 |
*/ |
*/ |
369 |
Sample::Sample(File* pFile, RIFF::List* waveList, unsigned long WavePoolOffset, unsigned long fileNo) : DLS::Sample((DLS::File*) pFile, waveList, WavePoolOffset) { |
Sample::Sample(File* pFile, RIFF::List* waveList, unsigned long WavePoolOffset, unsigned long fileNo) : DLS::Sample((DLS::File*) pFile, waveList, WavePoolOffset) { |
370 |
static const DLS::Info::FixedStringLength fixedStringLengths[] = { |
static const DLS::Info::string_length_t fixedStringLengths[] = { |
371 |
{ CHUNK_ID_INAM, 64 }, |
{ CHUNK_ID_INAM, 64 }, |
372 |
{ 0, 0 } |
{ 0, 0 } |
373 |
}; |
}; |
374 |
pInfo->FixedStringLengths = fixedStringLengths; |
pInfo->SetFixedStringLengths(fixedStringLengths); |
375 |
Instances++; |
Instances++; |
376 |
FileNo = fileNo; |
FileNo = fileNo; |
377 |
|
|
677 |
if (SampleCount > this->SamplesTotal) SampleCount = this->SamplesTotal; |
if (SampleCount > this->SamplesTotal) SampleCount = this->SamplesTotal; |
678 |
if (RAMCache.pStart) delete[] (int8_t*) RAMCache.pStart; |
if (RAMCache.pStart) delete[] (int8_t*) RAMCache.pStart; |
679 |
unsigned long allocationsize = (SampleCount + NullSamplesCount) * this->FrameSize; |
unsigned long allocationsize = (SampleCount + NullSamplesCount) * this->FrameSize; |
680 |
|
SetPos(0); // reset read position to begin of sample |
681 |
RAMCache.pStart = new int8_t[allocationsize]; |
RAMCache.pStart = new int8_t[allocationsize]; |
682 |
RAMCache.Size = Read(RAMCache.pStart, SampleCount) * this->FrameSize; |
RAMCache.Size = Read(RAMCache.pStart, SampleCount) * this->FrameSize; |
683 |
RAMCache.NullExtensionSize = allocationsize - RAMCache.Size; |
RAMCache.NullExtensionSize = allocationsize - RAMCache.Size; |
715 |
if (RAMCache.pStart) delete[] (int8_t*) RAMCache.pStart; |
if (RAMCache.pStart) delete[] (int8_t*) RAMCache.pStart; |
716 |
RAMCache.pStart = NULL; |
RAMCache.pStart = NULL; |
717 |
RAMCache.Size = 0; |
RAMCache.Size = 0; |
718 |
|
RAMCache.NullExtensionSize = 0; |
719 |
} |
} |
720 |
|
|
721 |
/** @brief Resize sample. |
/** @brief Resize sample. |
910 |
} |
} |
911 |
|
|
912 |
// reverse the sample frames for backward playback |
// reverse the sample frames for backward playback |
913 |
SwapMemoryArea(&pDst[swapareastart * this->FrameSize], (totalreadsamples - swapareastart) * this->FrameSize, this->FrameSize); |
if (totalreadsamples > swapareastart) //FIXME: this if() is just a crash workaround for now (#102), but totalreadsamples <= swapareastart should never be the case, so there's probably still a bug above! |
914 |
|
SwapMemoryArea(&pDst[swapareastart * this->FrameSize], (totalreadsamples - swapareastart) * this->FrameSize, this->FrameSize); |
915 |
} |
} |
916 |
} while (samplestoread && readsamples); |
} while (samplestoread && readsamples); |
917 |
break; |
break; |
1581 |
*/ |
*/ |
1582 |
DimensionRegion::DimensionRegion(RIFF::List* _3ewl, const DimensionRegion& src) : DLS::Sampler(_3ewl) { |
DimensionRegion::DimensionRegion(RIFF::List* _3ewl, const DimensionRegion& src) : DLS::Sampler(_3ewl) { |
1583 |
Instances++; |
Instances++; |
1584 |
|
//NOTE: I think we cannot call CopyAssign() here (in a constructor) as long as its a virtual method |
1585 |
*this = src; // default memberwise shallow copy of all parameters |
*this = src; // default memberwise shallow copy of all parameters |
1586 |
pParentList = _3ewl; // restore the chunk pointer |
pParentList = _3ewl; // restore the chunk pointer |
1587 |
|
|
1597 |
pSampleLoops[k] = src.pSampleLoops[k]; |
pSampleLoops[k] = src.pSampleLoops[k]; |
1598 |
} |
} |
1599 |
} |
} |
1600 |
|
|
1601 |
|
/** |
1602 |
|
* Make a (semi) deep copy of the DimensionRegion object given by @a orig |
1603 |
|
* and assign it to this object. |
1604 |
|
* |
1605 |
|
* Note that all sample pointers referenced by @a orig are simply copied as |
1606 |
|
* memory address. Thus the respective samples are shared, not duplicated! |
1607 |
|
* |
1608 |
|
* @param orig - original DimensionRegion object to be copied from |
1609 |
|
*/ |
1610 |
|
void DimensionRegion::CopyAssign(const DimensionRegion* orig) { |
1611 |
|
// delete all allocated data first |
1612 |
|
if (VelocityTable) delete [] VelocityTable; |
1613 |
|
if (pSampleLoops) delete [] pSampleLoops; |
1614 |
|
|
1615 |
|
// backup parent list pointer |
1616 |
|
RIFF::List* p = pParentList; |
1617 |
|
|
1618 |
|
//NOTE: copy code copied from assignment constructor above, see comment there as well |
1619 |
|
|
1620 |
|
*this = *orig; // default memberwise shallow copy of all parameters |
1621 |
|
pParentList = p; // restore the chunk pointer |
1622 |
|
|
1623 |
|
// deep copy of owned structures |
1624 |
|
if (orig->VelocityTable) { |
1625 |
|
VelocityTable = new uint8_t[128]; |
1626 |
|
for (int k = 0 ; k < 128 ; k++) |
1627 |
|
VelocityTable[k] = orig->VelocityTable[k]; |
1628 |
|
} |
1629 |
|
if (orig->pSampleLoops) { |
1630 |
|
pSampleLoops = new DLS::sample_loop_t[orig->SampleLoops]; |
1631 |
|
for (int k = 0 ; k < orig->SampleLoops ; k++) |
1632 |
|
pSampleLoops[k] = orig->pSampleLoops[k]; |
1633 |
|
} |
1634 |
|
} |
1635 |
|
|
1636 |
/** |
/** |
1637 |
* Updates the respective member variable and updates @c SampleAttenuation |
* Updates the respective member variable and updates @c SampleAttenuation |
1874 |
|
|
1875 |
const uint16_t eg3depth = (EG3Depth >= 0) ? EG3Depth |
const uint16_t eg3depth = (EG3Depth >= 0) ? EG3Depth |
1876 |
: uint16_t(((-EG3Depth) - 1) ^ 0xffff); /* binary complementary for negatives */ |
: uint16_t(((-EG3Depth) - 1) ^ 0xffff); /* binary complementary for negatives */ |
1877 |
pData[116] = eg3depth; |
store16(&pData[116], eg3depth); |
1878 |
|
|
1879 |
// next 2 bytes unknown |
// next 2 bytes unknown |
1880 |
|
|
1921 |
(VCFKeyboardTrackingBreakpoint & 0x7f); /* lower 7 bits */ |
(VCFKeyboardTrackingBreakpoint & 0x7f); /* lower 7 bits */ |
1922 |
pData[137] = vcfbreakpoint; |
pData[137] = vcfbreakpoint; |
1923 |
|
|
1924 |
const uint8_t vcfvelocity = VCFVelocityDynamicRange % 5 | |
const uint8_t vcfvelocity = VCFVelocityDynamicRange % 5 + |
1925 |
VCFVelocityCurve * 5; |
VCFVelocityCurve * 5; |
1926 |
pData[138] = vcfvelocity; |
pData[138] = vcfvelocity; |
1927 |
|
|
2412 |
|
|
2413 |
// Actual Loading |
// Actual Loading |
2414 |
|
|
2415 |
|
if (!file->GetAutoLoad()) return; |
2416 |
|
|
2417 |
LoadDimensionRegions(rgnList); |
LoadDimensionRegions(rgnList); |
2418 |
|
|
2419 |
RIFF::Chunk* _3lnk = rgnList->GetSubChunk(CHUNK_ID_3LNK); |
RIFF::Chunk* _3lnk = rgnList->GetSubChunk(CHUNK_ID_3LNK); |
2457 |
else |
else |
2458 |
_3lnk->SetPos(44); |
_3lnk->SetPos(44); |
2459 |
|
|
2460 |
// load sample references |
// load sample references (if auto loading is enabled) |
2461 |
for (uint i = 0; i < DimensionRegions; i++) { |
if (file->GetAutoLoad()) { |
2462 |
uint32_t wavepoolindex = _3lnk->ReadUint32(); |
for (uint i = 0; i < DimensionRegions; i++) { |
2463 |
if (file->pWavePoolTable) pDimensionRegions[i]->pSample = GetSampleFromWavePool(wavepoolindex); |
uint32_t wavepoolindex = _3lnk->ReadUint32(); |
2464 |
|
if (file->pWavePoolTable) pDimensionRegions[i]->pSample = GetSampleFromWavePool(wavepoolindex); |
2465 |
|
} |
2466 |
|
GetSample(); // load global region sample reference |
2467 |
} |
} |
|
GetSample(); // load global region sample reference |
|
2468 |
} else { |
} else { |
2469 |
DimensionRegions = 0; |
DimensionRegions = 0; |
2470 |
for (int i = 0 ; i < 8 ; i++) { |
for (int i = 0 ; i < 8 ; i++) { |
2961 |
} |
} |
2962 |
return NULL; |
return NULL; |
2963 |
} |
} |
2964 |
|
|
2965 |
|
/** |
2966 |
|
* Make a (semi) deep copy of the Region object given by @a orig |
2967 |
|
* and assign it to this object. |
2968 |
|
* |
2969 |
|
* Note that all sample pointers referenced by @a orig are simply copied as |
2970 |
|
* memory address. Thus the respective samples are shared, not duplicated! |
2971 |
|
* |
2972 |
|
* @param orig - original Region object to be copied from |
2973 |
|
*/ |
2974 |
|
void Region::CopyAssign(const Region* orig) { |
2975 |
|
// handle base classes |
2976 |
|
DLS::Region::CopyAssign(orig); |
2977 |
|
|
2978 |
|
// handle own member variables |
2979 |
|
for (int i = Dimensions - 1; i >= 0; --i) { |
2980 |
|
DeleteDimension(&pDimensionDefinitions[i]); |
2981 |
|
} |
2982 |
|
Layers = 0; // just to be sure |
2983 |
|
for (int i = 0; i < orig->Dimensions; i++) { |
2984 |
|
// we need to copy the dim definition here, to avoid the compiler |
2985 |
|
// complaining about const-ness issue |
2986 |
|
dimension_def_t def = orig->pDimensionDefinitions[i]; |
2987 |
|
AddDimension(&def); |
2988 |
|
} |
2989 |
|
for (int i = 0; i < 256; i++) { |
2990 |
|
if (pDimensionRegions[i] && orig->pDimensionRegions[i]) { |
2991 |
|
pDimensionRegions[i]->CopyAssign( |
2992 |
|
orig->pDimensionRegions[i] |
2993 |
|
); |
2994 |
|
} |
2995 |
|
} |
2996 |
|
Layers = orig->Layers; |
2997 |
|
} |
2998 |
|
|
2999 |
|
|
3000 |
|
// *************** MidiRule *************** |
3001 |
|
// * |
3002 |
|
|
3003 |
|
MidiRuleCtrlTrigger::MidiRuleCtrlTrigger(RIFF::Chunk* _3ewg) { |
3004 |
|
_3ewg->SetPos(36); |
3005 |
|
Triggers = _3ewg->ReadUint8(); |
3006 |
|
_3ewg->SetPos(40); |
3007 |
|
ControllerNumber = _3ewg->ReadUint8(); |
3008 |
|
_3ewg->SetPos(46); |
3009 |
|
for (int i = 0 ; i < Triggers ; i++) { |
3010 |
|
pTriggers[i].TriggerPoint = _3ewg->ReadUint8(); |
3011 |
|
pTriggers[i].Descending = _3ewg->ReadUint8(); |
3012 |
|
pTriggers[i].VelSensitivity = _3ewg->ReadUint8(); |
3013 |
|
pTriggers[i].Key = _3ewg->ReadUint8(); |
3014 |
|
pTriggers[i].NoteOff = _3ewg->ReadUint8(); |
3015 |
|
pTriggers[i].Velocity = _3ewg->ReadUint8(); |
3016 |
|
pTriggers[i].OverridePedal = _3ewg->ReadUint8(); |
3017 |
|
_3ewg->ReadUint8(); |
3018 |
|
} |
3019 |
|
} |
3020 |
|
|
3021 |
|
|
3022 |
// *************** Instrument *************** |
// *************** Instrument *************** |
3023 |
// * |
// * |
3024 |
|
|
3025 |
Instrument::Instrument(File* pFile, RIFF::List* insList, progress_t* pProgress) : DLS::Instrument((DLS::File*)pFile, insList) { |
Instrument::Instrument(File* pFile, RIFF::List* insList, progress_t* pProgress) : DLS::Instrument((DLS::File*)pFile, insList) { |
3026 |
static const DLS::Info::FixedStringLength fixedStringLengths[] = { |
static const DLS::Info::string_length_t fixedStringLengths[] = { |
3027 |
{ CHUNK_ID_INAM, 64 }, |
{ CHUNK_ID_INAM, 64 }, |
3028 |
{ CHUNK_ID_ISFT, 12 }, |
{ CHUNK_ID_ISFT, 12 }, |
3029 |
{ 0, 0 } |
{ 0, 0 } |
3030 |
}; |
}; |
3031 |
pInfo->FixedStringLengths = fixedStringLengths; |
pInfo->SetFixedStringLengths(fixedStringLengths); |
3032 |
|
|
3033 |
// Initialization |
// Initialization |
3034 |
for (int i = 0; i < 128; i++) RegionKeyTable[i] = NULL; |
for (int i = 0; i < 128; i++) RegionKeyTable[i] = NULL; |
3039 |
PianoReleaseMode = false; |
PianoReleaseMode = false; |
3040 |
DimensionKeyRange.low = 0; |
DimensionKeyRange.low = 0; |
3041 |
DimensionKeyRange.high = 0; |
DimensionKeyRange.high = 0; |
3042 |
|
pMidiRules = new MidiRule*[3]; |
3043 |
|
pMidiRules[0] = NULL; |
3044 |
|
|
3045 |
// Loading |
// Loading |
3046 |
RIFF::List* lart = insList->GetSubList(LIST_TYPE_LART); |
RIFF::List* lart = insList->GetSubList(LIST_TYPE_LART); |
3055 |
PianoReleaseMode = dimkeystart & 0x01; |
PianoReleaseMode = dimkeystart & 0x01; |
3056 |
DimensionKeyRange.low = dimkeystart >> 1; |
DimensionKeyRange.low = dimkeystart >> 1; |
3057 |
DimensionKeyRange.high = _3ewg->ReadUint8(); |
DimensionKeyRange.high = _3ewg->ReadUint8(); |
3058 |
|
|
3059 |
|
if (_3ewg->GetSize() > 32) { |
3060 |
|
// read MIDI rules |
3061 |
|
int i = 0; |
3062 |
|
_3ewg->SetPos(32); |
3063 |
|
uint8_t id1 = _3ewg->ReadUint8(); |
3064 |
|
uint8_t id2 = _3ewg->ReadUint8(); |
3065 |
|
|
3066 |
|
if (id1 == 4 && id2 == 16) { |
3067 |
|
pMidiRules[i++] = new MidiRuleCtrlTrigger(_3ewg); |
3068 |
|
} |
3069 |
|
//TODO: all the other types of rules |
3070 |
|
|
3071 |
|
pMidiRules[i] = NULL; |
3072 |
|
} |
3073 |
} |
} |
3074 |
} |
} |
3075 |
|
|
3076 |
if (!pRegions) pRegions = new RegionList; |
if (pFile->GetAutoLoad()) { |
3077 |
RIFF::List* lrgn = insList->GetSubList(LIST_TYPE_LRGN); |
if (!pRegions) pRegions = new RegionList; |
3078 |
if (lrgn) { |
RIFF::List* lrgn = insList->GetSubList(LIST_TYPE_LRGN); |
3079 |
RIFF::List* rgn = lrgn->GetFirstSubList(); |
if (lrgn) { |
3080 |
while (rgn) { |
RIFF::List* rgn = lrgn->GetFirstSubList(); |
3081 |
if (rgn->GetListType() == LIST_TYPE_RGN) { |
while (rgn) { |
3082 |
__notify_progress(pProgress, (float) pRegions->size() / (float) Regions); |
if (rgn->GetListType() == LIST_TYPE_RGN) { |
3083 |
pRegions->push_back(new Region(this, rgn)); |
__notify_progress(pProgress, (float) pRegions->size() / (float) Regions); |
3084 |
|
pRegions->push_back(new Region(this, rgn)); |
3085 |
|
} |
3086 |
|
rgn = lrgn->GetNextSubList(); |
3087 |
} |
} |
3088 |
rgn = lrgn->GetNextSubList(); |
// Creating Region Key Table for fast lookup |
3089 |
|
UpdateRegionKeyTable(); |
3090 |
} |
} |
|
// Creating Region Key Table for fast lookup |
|
|
UpdateRegionKeyTable(); |
|
3091 |
} |
} |
3092 |
|
|
3093 |
__notify_progress(pProgress, 1.0f); // notify done |
__notify_progress(pProgress, 1.0f); // notify done |
3106 |
} |
} |
3107 |
|
|
3108 |
Instrument::~Instrument() { |
Instrument::~Instrument() { |
3109 |
|
for (int i = 0 ; pMidiRules[i] ; i++) { |
3110 |
|
delete pMidiRules[i]; |
3111 |
|
} |
3112 |
|
delete[] pMidiRules; |
3113 |
} |
} |
3114 |
|
|
3115 |
/** |
/** |
3224 |
UpdateRegionKeyTable(); |
UpdateRegionKeyTable(); |
3225 |
} |
} |
3226 |
|
|
3227 |
|
/** |
3228 |
|
* Returns a MIDI rule of the instrument. |
3229 |
|
* |
3230 |
|
* The list of MIDI rules, at least in gig v3, always contains at |
3231 |
|
* most two rules. The second rule can only be the DEF filter |
3232 |
|
* (which currently isn't supported by libgig). |
3233 |
|
* |
3234 |
|
* @param i - MIDI rule number |
3235 |
|
* @returns pointer address to MIDI rule number i or NULL if there is none |
3236 |
|
*/ |
3237 |
|
MidiRule* Instrument::GetMidiRule(int i) { |
3238 |
|
return pMidiRules[i]; |
3239 |
|
} |
3240 |
|
|
3241 |
|
/** |
3242 |
|
* Make a (semi) deep copy of the Instrument object given by @a orig |
3243 |
|
* and assign it to this object. |
3244 |
|
* |
3245 |
|
* Note that all sample pointers referenced by @a orig are simply copied as |
3246 |
|
* memory address. Thus the respective samples are shared, not duplicated! |
3247 |
|
* |
3248 |
|
* @param orig - original Instrument object to be copied from |
3249 |
|
*/ |
3250 |
|
void Instrument::CopyAssign(const Instrument* orig) { |
3251 |
|
// handle base class |
3252 |
|
// (without copying DLS region stuff) |
3253 |
|
DLS::Instrument::CopyAssignCore(orig); |
3254 |
|
|
3255 |
|
// handle own member variables |
3256 |
|
Attenuation = orig->Attenuation; |
3257 |
|
EffectSend = orig->EffectSend; |
3258 |
|
FineTune = orig->FineTune; |
3259 |
|
PitchbendRange = orig->PitchbendRange; |
3260 |
|
PianoReleaseMode = orig->PianoReleaseMode; |
3261 |
|
DimensionKeyRange = orig->DimensionKeyRange; |
3262 |
|
|
3263 |
|
// free old midi rules |
3264 |
|
for (int i = 0 ; pMidiRules[i] ; i++) { |
3265 |
|
delete pMidiRules[i]; |
3266 |
|
} |
3267 |
|
//TODO: MIDI rule copying |
3268 |
|
pMidiRules[0] = NULL; |
3269 |
|
|
3270 |
|
// delete all old regions |
3271 |
|
while (Regions) DeleteRegion(GetFirstRegion()); |
3272 |
|
// create new regions and copy them from original |
3273 |
|
{ |
3274 |
|
RegionList::const_iterator it = orig->pRegions->begin(); |
3275 |
|
for (int i = 0; i < orig->Regions; ++i, ++it) { |
3276 |
|
Region* dstRgn = AddRegion(); |
3277 |
|
//NOTE: Region does semi-deep copy ! |
3278 |
|
dstRgn->CopyAssign( |
3279 |
|
static_cast<gig::Region*>(*it) |
3280 |
|
); |
3281 |
|
} |
3282 |
|
} |
3283 |
|
|
3284 |
|
UpdateRegionKeyTable(); |
3285 |
|
} |
3286 |
|
|
3287 |
|
|
3288 |
// *************** Group *************** |
// *************** Group *************** |
3408 |
// *************** File *************** |
// *************** File *************** |
3409 |
// * |
// * |
3410 |
|
|
3411 |
// File version 2.0, 1998-06-28 |
/// Reflects Gigasampler file format version 2.0 (1998-06-28). |
3412 |
const DLS::version_t File::VERSION_2 = { |
const DLS::version_t File::VERSION_2 = { |
3413 |
0, 2, 19980628 & 0xffff, 19980628 >> 16 |
0, 2, 19980628 & 0xffff, 19980628 >> 16 |
3414 |
}; |
}; |
3415 |
|
|
3416 |
// File version 3.0, 2003-03-31 |
/// Reflects Gigasampler file format version 3.0 (2003-03-31). |
3417 |
const DLS::version_t File::VERSION_3 = { |
const DLS::version_t File::VERSION_3 = { |
3418 |
0, 3, 20030331 & 0xffff, 20030331 >> 16 |
0, 3, 20030331 & 0xffff, 20030331 >> 16 |
3419 |
}; |
}; |
3420 |
|
|
3421 |
const DLS::Info::FixedStringLength File::FixedStringLengths[] = { |
static const DLS::Info::string_length_t _FileFixedStringLengths[] = { |
3422 |
{ CHUNK_ID_IARL, 256 }, |
{ CHUNK_ID_IARL, 256 }, |
3423 |
{ CHUNK_ID_IART, 128 }, |
{ CHUNK_ID_IART, 128 }, |
3424 |
{ CHUNK_ID_ICMS, 128 }, |
{ CHUNK_ID_ICMS, 128 }, |
3440 |
}; |
}; |
3441 |
|
|
3442 |
File::File() : DLS::File() { |
File::File() : DLS::File() { |
3443 |
|
bAutoLoad = true; |
3444 |
*pVersion = VERSION_3; |
*pVersion = VERSION_3; |
3445 |
pGroups = NULL; |
pGroups = NULL; |
3446 |
pInfo->FixedStringLengths = FixedStringLengths; |
pInfo->SetFixedStringLengths(_FileFixedStringLengths); |
3447 |
pInfo->ArchivalLocation = String(256, ' '); |
pInfo->ArchivalLocation = String(256, ' '); |
3448 |
|
|
3449 |
// add some mandatory chunks to get the file chunks in right |
// add some mandatory chunks to get the file chunks in right |
3456 |
} |
} |
3457 |
|
|
3458 |
File::File(RIFF::File* pRIFF) : DLS::File(pRIFF) { |
File::File(RIFF::File* pRIFF) : DLS::File(pRIFF) { |
3459 |
|
bAutoLoad = true; |
3460 |
pGroups = NULL; |
pGroups = NULL; |
3461 |
pInfo->FixedStringLengths = FixedStringLengths; |
pInfo->SetFixedStringLengths(_FileFixedStringLengths); |
3462 |
} |
} |
3463 |
|
|
3464 |
File::~File() { |
File::~File() { |
3526 |
pSamples->erase(iter); |
pSamples->erase(iter); |
3527 |
delete pSample; |
delete pSample; |
3528 |
|
|
3529 |
|
SampleList::iterator tmp = SamplesIterator; |
3530 |
// remove all references to the sample |
// remove all references to the sample |
3531 |
for (Instrument* instrument = GetFirstInstrument() ; instrument ; |
for (Instrument* instrument = GetFirstInstrument() ; instrument ; |
3532 |
instrument = GetNextInstrument()) { |
instrument = GetNextInstrument()) { |
3541 |
} |
} |
3542 |
} |
} |
3543 |
} |
} |
3544 |
|
SamplesIterator = tmp; // restore iterator |
3545 |
} |
} |
3546 |
|
|
3547 |
void File::LoadSamples() { |
void File::LoadSamples() { |
3632 |
progress_t subprogress; |
progress_t subprogress; |
3633 |
__divide_progress(pProgress, &subprogress, 3.0f, 0.0f); // randomly schedule 33% for this subtask |
__divide_progress(pProgress, &subprogress, 3.0f, 0.0f); // randomly schedule 33% for this subtask |
3634 |
__notify_progress(&subprogress, 0.0f); |
__notify_progress(&subprogress, 0.0f); |
3635 |
GetFirstSample(&subprogress); // now force all samples to be loaded |
if (GetAutoLoad()) |
3636 |
|
GetFirstSample(&subprogress); // now force all samples to be loaded |
3637 |
__notify_progress(&subprogress, 1.0f); |
__notify_progress(&subprogress, 1.0f); |
3638 |
|
|
3639 |
// instrument loading subtask |
// instrument loading subtask |
3682 |
pInstruments->push_back(pInstrument); |
pInstruments->push_back(pInstrument); |
3683 |
return pInstrument; |
return pInstrument; |
3684 |
} |
} |
3685 |
|
|
3686 |
|
/** @brief Add a duplicate of an existing instrument. |
3687 |
|
* |
3688 |
|
* Duplicates the instrument definition given by @a orig and adds it |
3689 |
|
* to this file. This allows in an instrument editor application to |
3690 |
|
* easily create variations of an instrument, which will be stored in |
3691 |
|
* the same .gig file, sharing i.e. the same samples. |
3692 |
|
* |
3693 |
|
* Note that all sample pointers referenced by @a orig are simply copied as |
3694 |
|
* memory address. Thus the respective samples are shared, not duplicated! |
3695 |
|
* |
3696 |
|
* You have to call Save() to make this persistent to the file. |
3697 |
|
* |
3698 |
|
* @param orig - original instrument to be copied |
3699 |
|
* @returns duplicated copy of the given instrument |
3700 |
|
*/ |
3701 |
|
Instrument* File::AddDuplicateInstrument(const Instrument* orig) { |
3702 |
|
Instrument* instr = AddInstrument(); |
3703 |
|
instr->CopyAssign(orig); |
3704 |
|
return instr; |
3705 |
|
} |
3706 |
|
|
3707 |
/** @brief Delete an instrument. |
/** @brief Delete an instrument. |
3708 |
* |
* |
4061 |
} |
} |
4062 |
} |
} |
4063 |
|
|
4064 |
|
/** |
4065 |
|
* Enable / disable automatic loading. By default this properyt is |
4066 |
|
* enabled and all informations are loaded automatically. However |
4067 |
|
* loading all Regions, DimensionRegions and especially samples might |
4068 |
|
* take a long time for large .gig files, and sometimes one might only |
4069 |
|
* be interested in retrieving very superficial informations like the |
4070 |
|
* amount of instruments and their names. In this case one might disable |
4071 |
|
* automatic loading to avoid very slow response times. |
4072 |
|
* |
4073 |
|
* @e CAUTION: by disabling this property many pointers (i.e. sample |
4074 |
|
* references) and informations will have invalid or even undefined |
4075 |
|
* data! This feature is currently only intended for retrieving very |
4076 |
|
* superficial informations in a very fast way. Don't use it to retrieve |
4077 |
|
* details like synthesis informations or even to modify .gig files! |
4078 |
|
*/ |
4079 |
|
void File::SetAutoLoad(bool b) { |
4080 |
|
bAutoLoad = b; |
4081 |
|
} |
4082 |
|
|
4083 |
|
/** |
4084 |
|
* Returns whether automatic loading is enabled. |
4085 |
|
* @see SetAutoLoad() |
4086 |
|
*/ |
4087 |
|
bool File::GetAutoLoad() { |
4088 |
|
return bAutoLoad; |
4089 |
|
} |
4090 |
|
|
4091 |
|
|
4092 |
|
|
4093 |
// *************** Exception *************** |
// *************** Exception *************** |