--- libgig/trunk/src/DLS.cpp 2007/08/02 14:12:55 1266 +++ libgig/trunk/src/DLS.cpp 2011/09/19 21:41:34 2274 @@ -2,7 +2,7 @@ * * * libgig - C++ cross-platform Gigasampler format file access library * * * - * Copyright (C) 2003-2007 by Christian Schoenebeck * + * Copyright (C) 2003-2009 by Christian Schoenebeck * * * * * * This library is free software; you can redistribute it and/or modify * @@ -23,6 +23,7 @@ #include "DLS.h" +#include #include #ifdef __APPLE__ @@ -239,7 +240,7 @@ * @param list - pointer to a list chunk which contains an INFO list chunk */ Info::Info(RIFF::List* list) { - FixedStringLengths = NULL; + pFixedStringLengths = NULL; pResourceListChunk = list; if (list) { RIFF::List* lstINFO = list->GetSubList(LIST_TYPE_INFO); @@ -268,6 +269,21 @@ Info::~Info() { } + /** + * Forces specific Info fields to be of a fixed length when being saved + * to a file. By default the respective RIFF chunk of an Info field + * will have a size analogue to its actual string length. With this + * method however this behavior can be overridden, allowing to force an + * arbitrary fixed size individually for each Info field. + * + * This method is used as a workaround for the gig format, not for DLS. + * + * @param lengths - NULL terminated array of string_length_t elements + */ + void Info::SetFixedStringLengths(const string_length_t* lengths) { + pFixedStringLengths = lengths; + } + /** @brief Load given INFO field. * * Load INFO field from INFO chunk with chunk ID \a ChunkID from INFO @@ -295,10 +311,10 @@ */ void Info::SaveString(uint32_t ChunkID, RIFF::List* lstINFO, const String& s, const String& sDefault) { int size = 0; - if (FixedStringLengths) { - for (int i = 0 ; FixedStringLengths[i].length ; i++) { - if (FixedStringLengths[i].chunkId == ChunkID) { - size = FixedStringLengths[i].length; + if (pFixedStringLengths) { + for (int i = 0 ; pFixedStringLengths[i].length ; i++) { + if (pFixedStringLengths[i].chunkId == ChunkID) { + size = pFixedStringLengths[i].length; break; } } @@ -441,8 +457,8 @@ UUID uuid; UuidCreate(&uuid); pDLSID->ulData1 = uuid.Data1; - pDLSID->usData1 = uuid.Data2; - pDLSID->usData2 = uuid.Data3; + pDLSID->usData2 = uuid.Data2; + pDLSID->usData3 = uuid.Data3; memcpy(pDLSID->abData, uuid.Data4, 8); #elif defined(__APPLE__) @@ -487,7 +503,7 @@ SamplerOptions = wsmp->ReadUint32(); SampleLoops = wsmp->ReadUint32(); } else { // 'wsmp' chunk missing - uiHeaderSize = 0; + uiHeaderSize = 20; UnityNote = 60; FineTune = 0; // +- 0 cents Gain = 0; // 0 dB @@ -512,6 +528,10 @@ if (pSampleLoops) delete[] pSampleLoops; } + void Sampler::SetGain(int32_t gain) { + Gain = gain; + } + /** * Apply all sample player options to the respective RIFF chunk. You * have to call File::Save() to make changes persistent. @@ -519,9 +539,11 @@ void Sampler::UpdateChunks() { // make sure 'wsmp' chunk exists RIFF::Chunk* wsmp = pParentList->GetSubChunk(CHUNK_ID_WSMP); + int wsmpSize = uiHeaderSize + SampleLoops * 16; if (!wsmp) { - uiHeaderSize = 20; - wsmp = pParentList->AddSubChunk(CHUNK_ID_WSMP, uiHeaderSize + SampleLoops * 16); + wsmp = pParentList->AddSubChunk(CHUNK_ID_WSMP, wsmpSize); + } else if (wsmp->GetSize() != wsmpSize) { + wsmp->Resize(wsmpSize); } uint8_t* pData = (uint8_t*) wsmp->LoadChunkData(); // update headers size @@ -913,6 +935,41 @@ } /** + * Modifies the key range of this Region and makes sure the respective + * chunks are in correct order. + * + * @param Low - lower end of key range + * @param High - upper end of key range + */ + void Region::SetKeyRange(uint16_t Low, uint16_t High) { + KeyRange.low = Low; + KeyRange.high = High; + + // make sure regions are already loaded + Instrument* pInstrument = (Instrument*) GetParent(); + if (!pInstrument->pRegions) pInstrument->LoadRegions(); + if (!pInstrument->pRegions) return; + + // find the r which is the first one to the right of this region + // at its new position + Region* r = NULL; + Region* prev_region = NULL; + for ( + Instrument::RegionList::iterator iter = pInstrument->pRegions->begin(); + iter != pInstrument->pRegions->end(); iter++ + ) { + if ((*iter)->KeyRange.low > this->KeyRange.low) { + r = *iter; + break; + } + prev_region = *iter; + } + + // place this region before r if it's not already there + if (prev_region != this) pInstrument->MoveRegion(this, r); + } + + /** * Apply Region settings to the respective RIFF chunks. You have to * call File::Save() to make changes persistent. * @@ -1373,6 +1430,17 @@ delete pInstrument; } + /** @brief File name of this DLS file. + * + * This method returns the file name as it was provided when loading + * the respective DLS file. However in case the File object associates + * an empty, that is new DLS file, which was not yet saved to disk, + * this method will return an empty string. + */ + String File::GetFileName() { + return pRIFF->GetFileName(); + } + /** * Apply all the DLS file's current instruments, samples and settings to * the respective RIFF chunks. You have to call Save() to make changes