318 |
// *************** Sample *************** |
// *************** Sample *************** |
319 |
// * |
// * |
320 |
|
|
321 |
unsigned int Sample::Instances = 0; |
size_t Sample::Instances = 0; |
322 |
buffer_t Sample::InternalDecompressionBuffer; |
buffer_t Sample::InternalDecompressionBuffer; |
323 |
|
|
324 |
/** @brief Constructor. |
/** @brief Constructor. |
789 |
* FormatTag must be DLS_WAVE_FORMAT_PCM. Trying to resize samples with |
* FormatTag must be DLS_WAVE_FORMAT_PCM. Trying to resize samples with |
790 |
* other formats will fail! |
* other formats will fail! |
791 |
* |
* |
792 |
* @param iNewSize - new sample wave data size in sample points (must be |
* @param NewSize - new sample wave data size in sample points (must be |
793 |
* greater than zero) |
* greater than zero) |
794 |
* @throws DLS::Excecption if FormatTag != DLS_WAVE_FORMAT_PCM |
* @throws DLS::Excecption if FormatTag != DLS_WAVE_FORMAT_PCM |
795 |
* or if \a iNewSize is less than 1 |
* @throws DLS::Exception if \a NewSize is less than 1 or unrealistic large |
796 |
* @throws gig::Exception if existing sample is compressed |
* @throws gig::Exception if existing sample is compressed |
797 |
* @see DLS::Sample::GetSize(), DLS::Sample::FrameSize, |
* @see DLS::Sample::GetSize(), DLS::Sample::FrameSize, |
798 |
* DLS::Sample::FormatTag, File::Save() |
* DLS::Sample::FormatTag, File::Save() |
799 |
*/ |
*/ |
800 |
void Sample::Resize(int iNewSize) { |
void Sample::Resize(file_offset_t NewSize) { |
801 |
if (Compressed) throw gig::Exception("There is no support for modifying compressed samples (yet)"); |
if (Compressed) throw gig::Exception("There is no support for modifying compressed samples (yet)"); |
802 |
DLS::Sample::Resize(iNewSize); |
DLS::Sample::Resize(NewSize); |
803 |
} |
} |
804 |
|
|
805 |
/** |
/** |
1357 |
// *************** DimensionRegion *************** |
// *************** DimensionRegion *************** |
1358 |
// * |
// * |
1359 |
|
|
1360 |
uint DimensionRegion::Instances = 0; |
size_t DimensionRegion::Instances = 0; |
1361 |
DimensionRegion::VelocityTableMap* DimensionRegion::pVelocityTables = NULL; |
DimensionRegion::VelocityTableMap* DimensionRegion::pVelocityTables = NULL; |
1362 |
|
|
1363 |
DimensionRegion::DimensionRegion(Region* pParent, RIFF::List* _3ewl) : DLS::Sampler(_3ewl) { |
DimensionRegion::DimensionRegion(Region* pParent, RIFF::List* _3ewl) : DLS::Sampler(_3ewl) { |
3106 |
int step = 1; |
int step = 1; |
3107 |
for (int i = 0 ; i < veldim ; i++) step <<= pDimensionDefinitions[i].bits; |
for (int i = 0 ; i < veldim ; i++) step <<= pDimensionDefinitions[i].bits; |
3108 |
int skipveldim = (step << pDimensionDefinitions[veldim].bits) - step; |
int skipveldim = (step << pDimensionDefinitions[veldim].bits) - step; |
|
int end = step * pDimensionDefinitions[veldim].zones; |
|
3109 |
|
|
3110 |
// loop through all dimension regions for all dimensions except the velocity dimension |
// loop through all dimension regions for all dimensions except the velocity dimension |
3111 |
int dim[8] = { 0 }; |
int dim[8] = { 0 }; |
3112 |
for (int i = 0 ; i < DimensionRegions ; i++) { |
for (int i = 0 ; i < DimensionRegions ; i++) { |
3113 |
|
const int end = i + step * pDimensionDefinitions[veldim].zones; |
3114 |
|
|
3115 |
|
// create a velocity table for all cases where the velocity zone is zero |
3116 |
if (pDimensionRegions[i]->DimensionUpperLimits[veldim] || |
if (pDimensionRegions[i]->DimensionUpperLimits[veldim] || |
3117 |
pDimensionRegions[i]->VelocityUpperLimit) { |
pDimensionRegions[i]->VelocityUpperLimit) { |
3118 |
// create the velocity table |
// create the velocity table |
3143 |
} |
} |
3144 |
} |
} |
3145 |
|
|
3146 |
|
// jump to the next case where the velocity zone is zero |
3147 |
int j; |
int j; |
3148 |
int shift = 0; |
int shift = 0; |
3149 |
for (j = 0 ; j < Dimensions ; j++) { |
for (j = 0 ; j < Dimensions ; j++) { |
3852 |
if ((int32_t)WavePoolTableIndex == -1) return NULL; |
if ((int32_t)WavePoolTableIndex == -1) return NULL; |
3853 |
File* file = (File*) GetParent()->GetParent(); |
File* file = (File*) GetParent()->GetParent(); |
3854 |
if (!file->pWavePoolTable) return NULL; |
if (!file->pWavePoolTable) return NULL; |
3855 |
if (file->HasMonolithicLargeFilePolicy()) { |
// for new files or files >= 2 GB use 64 bit wave pool offsets |
3856 |
|
if (file->pRIFF->IsNew() || (file->pRIFF->GetCurrentFileSize() >> 31)) { |
3857 |
|
// use 64 bit wave pool offsets (treating this as large file) |
3858 |
uint64_t soughtoffset = |
uint64_t soughtoffset = |
3859 |
uint64_t(file->pWavePoolTable[WavePoolTableIndex]) | |
uint64_t(file->pWavePoolTable[WavePoolTableIndex]) | |
3860 |
uint64_t(file->pWavePoolTableHi[WavePoolTableIndex]) << 32; |
uint64_t(file->pWavePoolTableHi[WavePoolTableIndex]) << 32; |
3865 |
sample = file->GetNextSample(); |
sample = file->GetNextSample(); |
3866 |
} |
} |
3867 |
} else { |
} else { |
3868 |
|
// use extension files and 32 bit wave pool offsets |
3869 |
file_offset_t soughtoffset = file->pWavePoolTable[WavePoolTableIndex]; |
file_offset_t soughtoffset = file->pWavePoolTable[WavePoolTableIndex]; |
3870 |
file_offset_t soughtfileno = file->pWavePoolTableHi[WavePoolTableIndex]; |
file_offset_t soughtfileno = file->pWavePoolTableHi[WavePoolTableIndex]; |
3871 |
Sample* sample = file->GetFirstSample(pProgress); |
Sample* sample = file->GetFirstSample(pProgress); |
5353 |
int iTotalSamples = WavePoolCount; |
int iTotalSamples = WavePoolCount; |
5354 |
|
|
5355 |
// check if samples should be loaded from extension files |
// check if samples should be loaded from extension files |
5356 |
|
// (only for old gig files < 2 GB) |
5357 |
int lastFileNo = 0; |
int lastFileNo = 0; |
5358 |
if (!HasMonolithicLargeFilePolicy()) { |
if (!file->IsNew() && !(file->GetCurrentFileSize() >> 31)) { |
5359 |
for (int i = 0 ; i < WavePoolCount ; i++) { |
for (int i = 0 ; i < WavePoolCount ; i++) { |
5360 |
if (pWavePoolTableHi[i] > lastFileNo) lastFileNo = pWavePoolTableHi[i]; |
if (pWavePoolTableHi[i] > lastFileNo) lastFileNo = pWavePoolTableHi[i]; |
5361 |
} |
} |
5847 |
} |
} |
5848 |
} |
} |
5849 |
|
|
|
/** @brief Returns the version number of libgig's Giga file format extension. |
|
|
* |
|
|
* libgig added several new features which were not available with the |
|
|
* original GigaStudio software. For those purposes libgig's own custom RIFF |
|
|
* chunks were added to the Giga file format. |
|
|
* |
|
|
* This method returns the version number of the Giga file format extension |
|
|
* used in this Giga file. Currently there are 3 possible values that might |
|
|
* be returned by this method: |
|
|
* |
|
|
* - @c 0: This gig file is not using any libgig specific file format |
|
|
* extension at all. |
|
|
* - @c 1: This gig file uses the RT instrument script format extension. |
|
|
* - @c 2: This gig file additionally provides support for monolithic |
|
|
* large gig files (larger than 2 GB). |
|
|
* |
|
|
* @note This method is currently protected and shall not be used as public |
|
|
* API method, since its method signature might change in future. |
|
|
*/ |
|
|
uint File::GetFormatExtensionVersion() const { |
|
|
RIFF::List* lst3LS = pRIFF->GetSubList(LIST_TYPE_3LS); |
|
|
if (!lst3LS) return 0; // is not using custom Giga format extensions at all |
|
|
RIFF::Chunk* ckFFmt = lst3LS->GetSubChunk(CHUNK_ID_FFMT); |
|
|
if (!ckFFmt) return 1; // uses custom Giga format extension(s) but had no format version saved |
|
|
uint8_t* pData = (uint8_t*) ckFFmt->LoadChunkData(); |
|
|
return load32(pData); |
|
|
} |
|
|
|
|
|
/** @brief Returns true in case this file is stored as one, single monolithic gig file. |
|
|
* |
|
|
* To avoid issues with operating systems which did not support large files |
|
|
* (larger than 2 GB) the original Giga file format avoided to ever save gig |
|
|
* files larger than 2 GB, instead such large Giga files were splitted into |
|
|
* several files, each one not being larger than 2 GB. It used a predefined |
|
|
* file name scheme for them like this: |
|
|
* @code |
|
|
* foo.gig |
|
|
* foo.gx01 |
|
|
* foo.gx02 |
|
|
* foo.gx03 |
|
|
* ... |
|
|
* @endcode |
|
|
* So when like in this example foo.gig was loaded, all other files |
|
|
* (foo.gx01, ...) were automatically loaded as well to make up the overall |
|
|
* large gig file (provided they were located at the same directory). Such |
|
|
* additional .gxYY files were called "extension files". |
|
|
* |
|
|
* Since nowadays all modern systems support large files, libgig always |
|
|
* saves large gig files as one single monolithic gig file instead, that |
|
|
* is libgig won't split such a large gig file into separate files like the |
|
|
* original GigaStudio software did. It uses a custom Giga file format |
|
|
* extension for this feature. |
|
|
* |
|
|
* For still being able though to load old splitted gig files and the new |
|
|
* large monolithic ones, this method is used to determine which loading |
|
|
* policy must be used for this gig file. |
|
|
* |
|
|
* @note This method is currently protected and shall not be used as public |
|
|
* API method, since its method signature might change in future and since |
|
|
* this method should not be directly relevant for applications based on |
|
|
* libgig. |
|
|
*/ |
|
|
bool File::HasMonolithicLargeFilePolicy() const { |
|
|
RIFF::List* lst3LS = pRIFF->GetSubList(LIST_TYPE_3LS); |
|
|
if (!lst3LS) return false; |
|
|
RIFF::Chunk* ckFFmt = lst3LS->GetSubChunk(CHUNK_ID_FFMT); |
|
|
if (!ckFFmt) return false; |
|
|
uint8_t* pData = (uint8_t*) ckFFmt->LoadChunkData(); |
|
|
uint32_t formatBitField = load32(&pData[4]); |
|
|
return formatBitField & 1; |
|
|
} |
|
|
|
|
5850 |
/** |
/** |
5851 |
* Apply all the gig file's current instruments, samples, groups and settings |
* Apply all the gig file's current instruments, samples, groups and settings |
5852 |
* to the respective RIFF chunks. You have to call Save() to make changes |
* to the respective RIFF chunks. You have to call Save() to make changes |
5861 |
void File::UpdateChunks(progress_t* pProgress) { |
void File::UpdateChunks(progress_t* pProgress) { |
5862 |
bool newFile = pRIFF->GetSubList(LIST_TYPE_INFO) == NULL; |
bool newFile = pRIFF->GetSubList(LIST_TYPE_INFO) == NULL; |
5863 |
|
|
|
b64BitWavePoolOffsets = pVersion && pVersion->major == 3; |
|
|
|
|
5864 |
// update own gig format extension chunks |
// update own gig format extension chunks |
5865 |
// (not part of the GigaStudio 4 format) |
// (not part of the GigaStudio 4 format) |
5866 |
RIFF::List* lst3LS = pRIFF->GetSubList(LIST_TYPE_3LS); |
RIFF::List* lst3LS = pRIFF->GetSubList(LIST_TYPE_3LS); |
5868 |
lst3LS = pRIFF->AddSubList(LIST_TYPE_3LS); |
lst3LS = pRIFF->AddSubList(LIST_TYPE_3LS); |
5869 |
} |
} |
5870 |
// Make sure <3LS > chunk is placed before <ptbl> chunk. The precise |
// Make sure <3LS > chunk is placed before <ptbl> chunk. The precise |
5871 |
// location of <3LS > is irrelevant, however it MUST BE located BEFORE |
// location of <3LS > is irrelevant, however it should be located |
5872 |
// the actual wave data, otherwise the <3LS > chunk becomes |
// before the actual wave data |
|
// inaccessible on gig files larger than 4GB ! |
|
5873 |
RIFF::Chunk* ckPTBL = pRIFF->GetSubChunk(CHUNK_ID_PTBL); |
RIFF::Chunk* ckPTBL = pRIFF->GetSubChunk(CHUNK_ID_PTBL); |
5874 |
pRIFF->MoveSubChunk(lst3LS, ckPTBL); |
pRIFF->MoveSubChunk(lst3LS, ckPTBL); |
5875 |
|
|
|
// Update <FFmt> chunk with informations about our file format |
|
|
// extensions. Currently this <FFmt> chunk has the following |
|
|
// layout: |
|
|
// |
|
|
// <uint32> -> (libgig's) File Format Extension version |
|
|
// <uint32> -> Format bit field: |
|
|
// bit 0: If flag is not set use separate .gx01 |
|
|
// extension files if file is larger than 2 GB |
|
|
// like with the original Giga format, if flag |
|
|
// is set use 64 bit sample references and keep |
|
|
// everything as one single monolithic gig file. |
|
|
RIFF::Chunk* ckFFmt = lst3LS->GetSubChunk(CHUNK_ID_FFMT); |
|
|
if (!ckFFmt) { |
|
|
const int iChunkSize = 2 * sizeof(uint32_t); |
|
|
ckFFmt = lst3LS->AddSubChunk(CHUNK_ID_FFMT, iChunkSize); |
|
|
} |
|
|
{ |
|
|
uint8_t* pData = (uint8_t*) ckFFmt->LoadChunkData(); |
|
|
store32(&pData[0], GIG_FILE_EXT_VERSION); |
|
|
// for now we always save gig files larger than 2 GB as one |
|
|
// single monolithic file (saving those with extension files is |
|
|
// currently not supported and probably also not desired anymore |
|
|
// nowadays). |
|
|
uint32_t formatBitfield = 1; |
|
|
store32(&pData[4], formatBitfield); |
|
|
} |
|
5876 |
// This must be performed before writing the chunks for instruments, |
// This must be performed before writing the chunks for instruments, |
5877 |
// because the instruments' script slots will write the file offsets |
// because the instruments' script slots will write the file offsets |
5878 |
// of the respective instrument script chunk as reference. |
// of the respective instrument script chunk as reference. |
5885 |
} |
} |
5886 |
} |
} |
5887 |
|
|
5888 |
|
// in case no libgig custom format data was added, then remove the |
5889 |
|
// custom "3LS " chunk again |
5890 |
|
if (!lst3LS->CountSubChunks()) { |
5891 |
|
pRIFF->DeleteSubChunk(lst3LS); |
5892 |
|
lst3LS = NULL; |
5893 |
|
} |
5894 |
|
|
5895 |
// first update base class's chunks |
// first update base class's chunks |
5896 |
DLS::File::UpdateChunks(pProgress); |
DLS::File::UpdateChunks(pProgress); |
5897 |
|
|