2 |
* * |
* * |
3 |
* libgig - C++ cross-platform Gigasampler format file loader library * |
* libgig - C++ cross-platform Gigasampler format file loader library * |
4 |
* * |
* * |
5 |
* Copyright (C) 2003-2005 by Christian Schoenebeck * |
* Copyright (C) 2003-2006 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 * |
285 |
|
|
286 |
pCk3gix = waveList->GetSubChunk(CHUNK_ID_3GIX); |
pCk3gix = waveList->GetSubChunk(CHUNK_ID_3GIX); |
287 |
if (pCk3gix) { |
if (pCk3gix) { |
288 |
SampleGroup = pCk3gix->ReadInt16(); |
uint16_t iSampleGroup = pCk3gix->ReadInt16(); |
289 |
|
// caution: sample groups in .gig files are indexed (1..n) whereas Groups in libgig (0..n-1) |
290 |
|
pGroup = pFile->GetGroup(iSampleGroup - 1); |
291 |
} else { // '3gix' chunk missing |
} else { // '3gix' chunk missing |
292 |
// use default value(s) |
// not assigned to a group by default |
293 |
SampleGroup = 0; |
pGroup = NULL; |
294 |
} |
} |
295 |
|
|
296 |
pCkSmpl = waveList->GetSubChunk(CHUNK_ID_SMPL); |
pCkSmpl = waveList->GetSubChunk(CHUNK_ID_SMPL); |
400 |
// make sure '3gix' chunk exists |
// make sure '3gix' chunk exists |
401 |
pCk3gix = pWaveList->GetSubChunk(CHUNK_ID_3GIX); |
pCk3gix = pWaveList->GetSubChunk(CHUNK_ID_3GIX); |
402 |
if (!pCk3gix) pCk3gix = pWaveList->AddSubChunk(CHUNK_ID_3GIX, 4); |
if (!pCk3gix) pCk3gix = pWaveList->AddSubChunk(CHUNK_ID_3GIX, 4); |
403 |
|
// determine appropriate sample group index (to be stored in chunk) |
404 |
|
uint16_t iSampleGroup = 0; // no sample group by default |
405 |
|
File* pFile = static_cast<File*>(pParent); |
406 |
|
if (pFile->pGroups) { |
407 |
|
std::list<Group*>::iterator iter = pFile->pGroups->begin(); |
408 |
|
std::list<Group*>::iterator end = pFile->pGroups->end(); |
409 |
|
// caution: sample groups in .gig files are indexed (1..n) whereas Groups in libgig (0..n-1) |
410 |
|
for (int i = 1; iter != end; i++, iter++) { |
411 |
|
if (*iter == pGroup) { |
412 |
|
iSampleGroup = i; |
413 |
|
break; // found |
414 |
|
} |
415 |
|
} |
416 |
|
} |
417 |
// update '3gix' chunk |
// update '3gix' chunk |
418 |
pData = (uint8_t*) pCk3gix->LoadChunkData(); |
pData = (uint8_t*) pCk3gix->LoadChunkData(); |
419 |
memcpy(&pData[0], &SampleGroup, 2); |
memcpy(&pData[0], &iSampleGroup, 2); |
420 |
} |
} |
421 |
|
|
422 |
/// Scans compressed samples for mandatory informations (e.g. actual number of total sample points). |
/// Scans compressed samples for mandatory informations (e.g. actual number of total sample points). |
2685 |
|
|
2686 |
|
|
2687 |
|
|
2688 |
|
// *************** Group *************** |
2689 |
|
// * |
2690 |
|
|
2691 |
|
/** @brief Constructor. |
2692 |
|
* |
2693 |
|
* @param file - pointer to the RIFF::File object of this .gig file |
2694 |
|
* @param ck3gnm - pointer to 3gnm chunk associated with this group |
2695 |
|
*/ |
2696 |
|
Group::Group(RIFF::File* file, RIFF::Chunk* ck3gnm) { |
2697 |
|
pFile = file; |
2698 |
|
pNameChunk = ck3gnm; |
2699 |
|
::LoadString(pNameChunk, Name); |
2700 |
|
} |
2701 |
|
|
2702 |
|
Group::~Group() { |
2703 |
|
} |
2704 |
|
|
2705 |
|
/** @brief Update chunks with current group settings. |
2706 |
|
* |
2707 |
|
* Apply current Group field values to the respective. You have to call |
2708 |
|
* File::Save() to make changes persistent. |
2709 |
|
*/ |
2710 |
|
void Group::UpdateChunks() { |
2711 |
|
// make sure <3gri> and <3gnl> list chunks exist |
2712 |
|
RIFF::List* _3gri = pFile->GetSubList(LIST_TYPE_3GRI); |
2713 |
|
if (!_3gri) _3gri = pFile->AddSubList(LIST_TYPE_3GRI); |
2714 |
|
RIFF::List* _3gnl = _3gri->GetSubList(LIST_TYPE_3GNL); |
2715 |
|
if (!_3gnl) _3gnl = pFile->AddSubList(LIST_TYPE_3GNL); |
2716 |
|
// now store the name of this group as <3gnm> chunk as subchunk of the <3gnl> list chunk |
2717 |
|
::SaveString(CHUNK_ID_3GNM, pNameChunk, _3gnl, Name, String("Unnamed Group"), true, 64); |
2718 |
|
} |
2719 |
|
|
2720 |
|
|
2721 |
|
|
2722 |
// *************** File *************** |
// *************** File *************** |
2723 |
// * |
// * |
2724 |
|
|
2725 |
File::File() : DLS::File() { |
File::File() : DLS::File() { |
2726 |
|
pGroups = NULL; |
2727 |
pInfo->UseFixedLengthStrings = true; |
pInfo->UseFixedLengthStrings = true; |
2728 |
} |
} |
2729 |
|
|
2730 |
File::File(RIFF::File* pRIFF) : DLS::File(pRIFF) { |
File::File(RIFF::File* pRIFF) : DLS::File(pRIFF) { |
2731 |
|
pGroups = NULL; |
2732 |
pInfo->UseFixedLengthStrings = true; |
pInfo->UseFixedLengthStrings = true; |
2733 |
} |
} |
2734 |
|
|
2735 |
|
File::~File() { |
2736 |
|
if (pGroups) { |
2737 |
|
std::list<Group*>::iterator iter = pGroups->begin(); |
2738 |
|
std::list<Group*>::iterator end = pGroups->end(); |
2739 |
|
while (iter != end) { |
2740 |
|
delete *iter; |
2741 |
|
++iter; |
2742 |
|
} |
2743 |
|
delete pGroups; |
2744 |
|
} |
2745 |
|
} |
2746 |
|
|
2747 |
Sample* File::GetFirstSample(progress_t* pProgress) { |
Sample* File::GetFirstSample(progress_t* pProgress) { |
2748 |
if (!pSamples) LoadSamples(pProgress); |
if (!pSamples) LoadSamples(pProgress); |
2749 |
if (!pSamples) return NULL; |
if (!pSamples) return NULL; |
2959 |
} |
} |
2960 |
} |
} |
2961 |
|
|
2962 |
|
Group* File::GetFirstGroup() { |
2963 |
|
if (!pGroups) LoadGroups(); |
2964 |
|
if (!pGroups) return NULL; |
2965 |
|
GroupsIterator = pGroups->begin(); |
2966 |
|
return (GroupsIterator == pGroups->end()) ? NULL : *GroupsIterator; |
2967 |
|
} |
2968 |
|
|
2969 |
|
Group* File::GetNextGroup() { |
2970 |
|
if (!pGroups) return NULL; |
2971 |
|
++GroupsIterator; |
2972 |
|
return (GroupsIterator == pGroups->end()) ? NULL : *GroupsIterator; |
2973 |
|
} |
2974 |
|
|
2975 |
|
/** |
2976 |
|
* Returns the group with the given index. |
2977 |
|
* |
2978 |
|
* @param index - number of the sought group (0..n) |
2979 |
|
* @returns sought group or NULL if there's no such group |
2980 |
|
*/ |
2981 |
|
Group* File::GetGroup(uint index) { |
2982 |
|
if (!pGroups) LoadGroups(); |
2983 |
|
if (!pGroups) return NULL; |
2984 |
|
GroupsIterator = pGroups->begin(); |
2985 |
|
for (uint i = 0; GroupsIterator != pGroups->end(); i++) { |
2986 |
|
if (i == index) return *GroupsIterator; |
2987 |
|
++GroupsIterator; |
2988 |
|
} |
2989 |
|
return NULL; |
2990 |
|
} |
2991 |
|
|
2992 |
|
Group* File::AddGroup() { |
2993 |
|
if (!pGroups) LoadGroups(); |
2994 |
|
if (!pGroups) pGroups = new std::list<Group*>; |
2995 |
|
__ensureMandatoryChunksExist(); |
2996 |
|
Group* pGroup = new Group(pRIFF, NULL); |
2997 |
|
pGroups->push_back(pGroup); |
2998 |
|
return pGroup; |
2999 |
|
} |
3000 |
|
|
3001 |
|
void File::DeleteGroup(Group* pGroup) { |
3002 |
|
if (!pGroups) throw gig::Exception("Could not delete group as there are no groups"); |
3003 |
|
std::list<Group*>::iterator iter = find(pGroups->begin(), pGroups->end(), pGroup); |
3004 |
|
if (iter == pGroups->end()) throw gig::Exception("Could not delete group, could not find given group"); |
3005 |
|
pGroups->erase(iter); |
3006 |
|
delete pGroup; |
3007 |
|
} |
3008 |
|
|
3009 |
|
void File::LoadGroups() { |
3010 |
|
if (!pGroups) pGroups = new std::list<Group*>; |
3011 |
|
RIFF::List* lst3gri = pRIFF->GetSubList(LIST_TYPE_3GRI); |
3012 |
|
if (!lst3gri) return; |
3013 |
|
RIFF::List* lst3gnl = lst3gri->GetSubList(LIST_TYPE_3GNL); |
3014 |
|
if (!lst3gnl) return; |
3015 |
|
{ |
3016 |
|
RIFF::Chunk* ck = lst3gnl->GetFirstSubChunk(); |
3017 |
|
while (ck) { |
3018 |
|
if (ck->GetChunkID() == CHUNK_ID_3GNM) { |
3019 |
|
pGroups->push_back(new Group(pRIFF, ck)); |
3020 |
|
} |
3021 |
|
ck = lst3gnl->GetNextSubChunk(); |
3022 |
|
} |
3023 |
|
} |
3024 |
|
} |
3025 |
|
|
3026 |
|
|
3027 |
|
|
3028 |
// *************** Exception *************** |
// *************** Exception *************** |