00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "DLS.h"
00025
00026 #include <time.h>
00027
00028 #ifdef __APPLE__
00029 #include <CoreFoundation/CFUUID.h>
00030 #elif defined(HAVE_UUID_UUID_H)
00031 #include <uuid/uuid.h>
00032 #endif
00033
00034 #include "helper.h"
00035
00036
00037 #define CONN_TRANSFORM_SRC(x) ((x >> 10) & 0x000F)
00038 #define CONN_TRANSFORM_CTL(x) ((x >> 4) & 0x000F)
00039 #define CONN_TRANSFORM_DST(x) (x & 0x000F)
00040 #define CONN_TRANSFORM_BIPOLAR_SRC(x) (x & 0x4000)
00041 #define CONN_TRANSFORM_BIPOLAR_CTL(x) (x & 0x0100)
00042 #define CONN_TRANSFORM_INVERT_SRC(x) (x & 0x8000)
00043 #define CONN_TRANSFORM_INVERT_CTL(x) (x & 0x0200)
00044
00045
00046 #define CONN_TRANSFORM_SRC_ENCODE(x) ((x & 0x000F) << 10)
00047 #define CONN_TRANSFORM_CTL_ENCODE(x) ((x & 0x000F) << 4)
00048 #define CONN_TRANSFORM_DST_ENCODE(x) (x & 0x000F)
00049 #define CONN_TRANSFORM_BIPOLAR_SRC_ENCODE(x) ((x) ? 0x4000 : 0)
00050 #define CONN_TRANSFORM_BIPOLAR_CTL_ENCODE(x) ((x) ? 0x0100 : 0)
00051 #define CONN_TRANSFORM_INVERT_SRC_ENCODE(x) ((x) ? 0x8000 : 0)
00052 #define CONN_TRANSFORM_INVERT_CTL_ENCODE(x) ((x) ? 0x0200 : 0)
00053
00054 #define DRUM_TYPE_MASK 0x80000000
00055
00056 #define F_RGN_OPTION_SELFNONEXCLUSIVE 0x0001
00057
00058 #define F_WAVELINK_PHASE_MASTER 0x0001
00059 #define F_WAVELINK_MULTICHANNEL 0x0002
00060
00061 #define F_WSMP_NO_TRUNCATION 0x0001
00062 #define F_WSMP_NO_COMPRESSION 0x0002
00063
00064 #define MIDI_BANK_COARSE(x) ((x & 0x00007F00) >> 8) // CC0
00065 #define MIDI_BANK_FINE(x) (x & 0x0000007F) // CC32
00066 #define MIDI_BANK_MERGE(coarse, fine) ((((uint16_t) coarse) << 7) | fine) // CC0 + CC32
00067 #define MIDI_BANK_ENCODE(coarse, fine) (((coarse & 0x0000007F) << 8) | (fine & 0x0000007F))
00068
00069 namespace DLS {
00070
00071
00072
00073
00074 void Connection::Init(conn_block_t* Header) {
00075 Source = (conn_src_t) Header->source;
00076 Control = (conn_src_t) Header->control;
00077 Destination = (conn_dst_t) Header->destination;
00078 Scale = Header->scale;
00079 SourceTransform = (conn_trn_t) CONN_TRANSFORM_SRC(Header->transform);
00080 ControlTransform = (conn_trn_t) CONN_TRANSFORM_CTL(Header->transform);
00081 DestinationTransform = (conn_trn_t) CONN_TRANSFORM_DST(Header->transform);
00082 SourceInvert = CONN_TRANSFORM_INVERT_SRC(Header->transform);
00083 SourceBipolar = CONN_TRANSFORM_BIPOLAR_SRC(Header->transform);
00084 ControlInvert = CONN_TRANSFORM_INVERT_CTL(Header->transform);
00085 ControlBipolar = CONN_TRANSFORM_BIPOLAR_CTL(Header->transform);
00086 }
00087
00088 Connection::conn_block_t Connection::ToConnBlock() {
00089 conn_block_t c;
00090 c.source = Source;
00091 c.control = Control;
00092 c.destination = Destination;
00093 c.scale = Scale;
00094 c.transform = CONN_TRANSFORM_SRC_ENCODE(SourceTransform) |
00095 CONN_TRANSFORM_CTL_ENCODE(ControlTransform) |
00096 CONN_TRANSFORM_DST_ENCODE(DestinationTransform) |
00097 CONN_TRANSFORM_INVERT_SRC_ENCODE(SourceInvert) |
00098 CONN_TRANSFORM_BIPOLAR_SRC_ENCODE(SourceBipolar) |
00099 CONN_TRANSFORM_INVERT_CTL_ENCODE(ControlInvert) |
00100 CONN_TRANSFORM_BIPOLAR_CTL_ENCODE(ControlBipolar);
00101 return c;
00102 }
00103
00104
00105
00106
00107
00108
00117 Articulation::Articulation(RIFF::Chunk* artl) {
00118 pArticulationCk = artl;
00119 if (artl->GetChunkID() != CHUNK_ID_ART2 &&
00120 artl->GetChunkID() != CHUNK_ID_ARTL) {
00121 throw DLS::Exception("<artl-ck> or <art2-ck> chunk expected");
00122 }
00123 HeaderSize = artl->ReadUint32();
00124 Connections = artl->ReadUint32();
00125 artl->SetPos(HeaderSize);
00126
00127 pConnections = new Connection[Connections];
00128 Connection::conn_block_t connblock;
00129 for (uint32_t i = 0; i < Connections; i++) {
00130 artl->Read(&connblock.source, 1, 2);
00131 artl->Read(&connblock.control, 1, 2);
00132 artl->Read(&connblock.destination, 1, 2);
00133 artl->Read(&connblock.transform, 1, 2);
00134 artl->Read(&connblock.scale, 1, 4);
00135 pConnections[i].Init(&connblock);
00136 }
00137 }
00138
00139 Articulation::~Articulation() {
00140 if (pConnections) delete[] pConnections;
00141 }
00142
00147 void Articulation::UpdateChunks() {
00148 const int iEntrySize = 12;
00149 pArticulationCk->Resize(HeaderSize + Connections * iEntrySize);
00150 uint8_t* pData = (uint8_t*) pArticulationCk->LoadChunkData();
00151 store16(&pData[0], HeaderSize);
00152 store16(&pData[2], Connections);
00153 for (uint32_t i = 0; i < Connections; i++) {
00154 Connection::conn_block_t c = pConnections[i].ToConnBlock();
00155 store16(&pData[HeaderSize + i * iEntrySize], c.source);
00156 store16(&pData[HeaderSize + i * iEntrySize + 2], c.control);
00157 store16(&pData[HeaderSize + i * iEntrySize + 4], c.destination);
00158 store16(&pData[HeaderSize + i * iEntrySize + 6], c.transform);
00159 store32(&pData[HeaderSize + i * iEntrySize + 8], c.scale);
00160 }
00161 }
00162
00163
00164
00165
00166
00167
00168 Articulator::Articulator(RIFF::List* ParentList) {
00169 pParentList = ParentList;
00170 pArticulations = NULL;
00171 }
00172
00173 Articulation* Articulator::GetFirstArticulation() {
00174 if (!pArticulations) LoadArticulations();
00175 if (!pArticulations) return NULL;
00176 ArticulationsIterator = pArticulations->begin();
00177 return (ArticulationsIterator != pArticulations->end()) ? *ArticulationsIterator : NULL;
00178 }
00179
00180 Articulation* Articulator::GetNextArticulation() {
00181 if (!pArticulations) return NULL;
00182 ArticulationsIterator++;
00183 return (ArticulationsIterator != pArticulations->end()) ? *ArticulationsIterator : NULL;
00184 }
00185
00186 void Articulator::LoadArticulations() {
00187
00188 RIFF::List* lart = pParentList->GetSubList(LIST_TYPE_LAR2);
00189 if (!lart) lart = pParentList->GetSubList(LIST_TYPE_LART);
00190 if (lart) {
00191 uint32_t artCkType = (lart->GetListType() == LIST_TYPE_LAR2) ? CHUNK_ID_ART2
00192 : CHUNK_ID_ARTL;
00193 RIFF::Chunk* art = lart->GetFirstSubChunk();
00194 while (art) {
00195 if (art->GetChunkID() == artCkType) {
00196 if (!pArticulations) pArticulations = new ArticulationList;
00197 pArticulations->push_back(new Articulation(art));
00198 }
00199 art = lart->GetNextSubChunk();
00200 }
00201 }
00202 }
00203
00204 Articulator::~Articulator() {
00205 if (pArticulations) {
00206 ArticulationList::iterator iter = pArticulations->begin();
00207 ArticulationList::iterator end = pArticulations->end();
00208 while (iter != end) {
00209 delete *iter;
00210 iter++;
00211 }
00212 delete pArticulations;
00213 }
00214 }
00215
00220 void Articulator::UpdateChunks() {
00221 if (pArticulations) {
00222 ArticulationList::iterator iter = pArticulations->begin();
00223 ArticulationList::iterator end = pArticulations->end();
00224 for (; iter != end; ++iter) {
00225 (*iter)->UpdateChunks();
00226 }
00227 }
00228 }
00229
00230
00231
00232
00233
00234
00241 Info::Info(RIFF::List* list) {
00242 pFixedStringLengths = NULL;
00243 pResourceListChunk = list;
00244 if (list) {
00245 RIFF::List* lstINFO = list->GetSubList(LIST_TYPE_INFO);
00246 if (lstINFO) {
00247 LoadString(CHUNK_ID_INAM, lstINFO, Name);
00248 LoadString(CHUNK_ID_IARL, lstINFO, ArchivalLocation);
00249 LoadString(CHUNK_ID_ICRD, lstINFO, CreationDate);
00250 LoadString(CHUNK_ID_ICMT, lstINFO, Comments);
00251 LoadString(CHUNK_ID_IPRD, lstINFO, Product);
00252 LoadString(CHUNK_ID_ICOP, lstINFO, Copyright);
00253 LoadString(CHUNK_ID_IART, lstINFO, Artists);
00254 LoadString(CHUNK_ID_IGNR, lstINFO, Genre);
00255 LoadString(CHUNK_ID_IKEY, lstINFO, Keywords);
00256 LoadString(CHUNK_ID_IENG, lstINFO, Engineer);
00257 LoadString(CHUNK_ID_ITCH, lstINFO, Technician);
00258 LoadString(CHUNK_ID_ISFT, lstINFO, Software);
00259 LoadString(CHUNK_ID_IMED, lstINFO, Medium);
00260 LoadString(CHUNK_ID_ISRC, lstINFO, Source);
00261 LoadString(CHUNK_ID_ISRF, lstINFO, SourceForm);
00262 LoadString(CHUNK_ID_ICMS, lstINFO, Commissioned);
00263 LoadString(CHUNK_ID_ISBJ, lstINFO, Subject);
00264 }
00265 }
00266 }
00267
00268 Info::~Info() {
00269 }
00270
00282 void Info::SetFixedStringLengths(const string_length_t* lengths) {
00283 pFixedStringLengths = lengths;
00284 }
00285
00291 void Info::LoadString(uint32_t ChunkID, RIFF::List* lstINFO, String& s) {
00292 RIFF::Chunk* ck = lstINFO->GetSubChunk(ChunkID);
00293 ::LoadString(ck, s);
00294 }
00295
00311 void Info::SaveString(uint32_t ChunkID, RIFF::List* lstINFO, const String& s, const String& sDefault) {
00312 int size = 0;
00313 if (pFixedStringLengths) {
00314 for (int i = 0 ; pFixedStringLengths[i].length ; i++) {
00315 if (pFixedStringLengths[i].chunkId == ChunkID) {
00316 size = pFixedStringLengths[i].length;
00317 break;
00318 }
00319 }
00320 }
00321 RIFF::Chunk* ck = lstINFO->GetSubChunk(ChunkID);
00322 ::SaveString(ChunkID, ck, lstINFO, s, sDefault, size != 0, size);
00323 }
00324
00330 void Info::UpdateChunks() {
00331 if (!pResourceListChunk) return;
00332
00333
00334 RIFF::List* lstINFO = pResourceListChunk->GetSubList(LIST_TYPE_INFO);
00335
00336 String defaultName = "";
00337 String defaultCreationDate = "";
00338 String defaultSoftware = "";
00339 String defaultComments = "";
00340
00341 uint32_t resourceType = pResourceListChunk->GetListType();
00342
00343 if (!lstINFO) {
00344 lstINFO = pResourceListChunk->AddSubList(LIST_TYPE_INFO);
00345
00346
00347 defaultName = "NONAME";
00348
00349 if (resourceType == RIFF_TYPE_DLS) {
00350
00351 time_t now = time(NULL);
00352 tm* pNowBroken = localtime(&now);
00353 char buf[11];
00354 strftime(buf, 11, "%F", pNowBroken);
00355 defaultCreationDate = buf;
00356
00357 defaultComments = "Created with " + libraryName() + " " + libraryVersion();
00358 }
00359 if (resourceType == RIFF_TYPE_DLS || resourceType == LIST_TYPE_INS)
00360 {
00361 defaultSoftware = libraryName() + " " + libraryVersion();
00362 }
00363 }
00364
00365
00366
00367 SaveString(CHUNK_ID_IARL, lstINFO, ArchivalLocation, String(""));
00368 SaveString(CHUNK_ID_IART, lstINFO, Artists, String(""));
00369 SaveString(CHUNK_ID_ICMS, lstINFO, Commissioned, String(""));
00370 SaveString(CHUNK_ID_ICMT, lstINFO, Comments, defaultComments);
00371 SaveString(CHUNK_ID_ICOP, lstINFO, Copyright, String(""));
00372 SaveString(CHUNK_ID_ICRD, lstINFO, CreationDate, defaultCreationDate);
00373 SaveString(CHUNK_ID_IENG, lstINFO, Engineer, String(""));
00374 SaveString(CHUNK_ID_IGNR, lstINFO, Genre, String(""));
00375 SaveString(CHUNK_ID_IKEY, lstINFO, Keywords, String(""));
00376 SaveString(CHUNK_ID_IMED, lstINFO, Medium, String(""));
00377 SaveString(CHUNK_ID_INAM, lstINFO, Name, defaultName);
00378 SaveString(CHUNK_ID_IPRD, lstINFO, Product, String(""));
00379 SaveString(CHUNK_ID_ISBJ, lstINFO, Subject, String(""));
00380 SaveString(CHUNK_ID_ISFT, lstINFO, Software, defaultSoftware);
00381 SaveString(CHUNK_ID_ISRC, lstINFO, Source, String(""));
00382 SaveString(CHUNK_ID_ISRF, lstINFO, SourceForm, String(""));
00383 SaveString(CHUNK_ID_ITCH, lstINFO, Technician, String(""));
00384 }
00385
00386
00387
00388
00389
00390
00400 Resource::Resource(Resource* Parent, RIFF::List* lstResource) {
00401 pParent = Parent;
00402 pResourceList = lstResource;
00403
00404 pInfo = new Info(lstResource);
00405
00406 RIFF::Chunk* ckDLSID = lstResource->GetSubChunk(CHUNK_ID_DLID);
00407 if (ckDLSID) {
00408 pDLSID = new dlsid_t;
00409 ckDLSID->Read(&pDLSID->ulData1, 1, 4);
00410 ckDLSID->Read(&pDLSID->usData2, 1, 2);
00411 ckDLSID->Read(&pDLSID->usData3, 1, 2);
00412 ckDLSID->Read(pDLSID->abData, 8, 1);
00413 }
00414 else pDLSID = NULL;
00415 }
00416
00417 Resource::~Resource() {
00418 if (pDLSID) delete pDLSID;
00419 if (pInfo) delete pInfo;
00420 }
00421
00430 void Resource::UpdateChunks() {
00431 pInfo->UpdateChunks();
00432
00433 if (pDLSID) {
00434
00435 RIFF::Chunk* ckDLSID = pResourceList->GetSubChunk(CHUNK_ID_DLID);
00436 if (!ckDLSID) ckDLSID = pResourceList->AddSubChunk(CHUNK_ID_DLID, 16);
00437 uint8_t* pData = (uint8_t*)ckDLSID->LoadChunkData();
00438
00439 store32(&pData[0], pDLSID->ulData1);
00440 store16(&pData[4], pDLSID->usData2);
00441 store16(&pData[6], pDLSID->usData3);
00442 memcpy(&pData[8], pDLSID->abData, 8);
00443 }
00444 }
00445
00449 void Resource::GenerateDLSID() {
00450 #if defined(WIN32) || defined(__APPLE__) || defined(HAVE_UUID_GENERATE)
00451
00452 if (!pDLSID) pDLSID = new dlsid_t;
00453
00454 #ifdef WIN32
00455
00456 UUID uuid;
00457 UuidCreate(&uuid);
00458 pDLSID->ulData1 = uuid.Data1;
00459 pDLSID->usData2 = uuid.Data2;
00460 pDLSID->usData3 = uuid.Data3;
00461 memcpy(pDLSID->abData, uuid.Data4, 8);
00462
00463 #elif defined(__APPLE__)
00464
00465 CFUUIDRef uuidRef = CFUUIDCreate(NULL);
00466 CFUUIDBytes uuid = CFUUIDGetUUIDBytes(uuidRef);
00467 CFRelease(uuidRef);
00468 pDLSID->ulData1 = uuid.byte0 | uuid.byte1 << 8 | uuid.byte2 << 16 | uuid.byte3 << 24;
00469 pDLSID->usData2 = uuid.byte4 | uuid.byte5 << 8;
00470 pDLSID->usData3 = uuid.byte6 | uuid.byte7 << 8;
00471 pDLSID->abData[0] = uuid.byte8;
00472 pDLSID->abData[1] = uuid.byte9;
00473 pDLSID->abData[2] = uuid.byte10;
00474 pDLSID->abData[3] = uuid.byte11;
00475 pDLSID->abData[4] = uuid.byte12;
00476 pDLSID->abData[5] = uuid.byte13;
00477 pDLSID->abData[6] = uuid.byte14;
00478 pDLSID->abData[7] = uuid.byte15;
00479 #else
00480 uuid_t uuid;
00481 uuid_generate(uuid);
00482 pDLSID->ulData1 = uuid[0] | uuid[1] << 8 | uuid[2] << 16 | uuid[3] << 24;
00483 pDLSID->usData2 = uuid[4] | uuid[5] << 8;
00484 pDLSID->usData3 = uuid[6] | uuid[7] << 8;
00485 memcpy(pDLSID->abData, &uuid[8], 8);
00486 #endif
00487 #endif
00488 }
00489
00490
00491
00492
00493
00494 Sampler::Sampler(RIFF::List* ParentList) {
00495 pParentList = ParentList;
00496 RIFF::Chunk* wsmp = ParentList->GetSubChunk(CHUNK_ID_WSMP);
00497 if (wsmp) {
00498 uiHeaderSize = wsmp->ReadUint32();
00499 UnityNote = wsmp->ReadUint16();
00500 FineTune = wsmp->ReadInt16();
00501 Gain = wsmp->ReadInt32();
00502 SamplerOptions = wsmp->ReadUint32();
00503 SampleLoops = wsmp->ReadUint32();
00504 } else {
00505 uiHeaderSize = 20;
00506 UnityNote = 60;
00507 FineTune = 0;
00508 Gain = 0;
00509 SamplerOptions = F_WSMP_NO_COMPRESSION;
00510 SampleLoops = 0;
00511 }
00512 NoSampleDepthTruncation = SamplerOptions & F_WSMP_NO_TRUNCATION;
00513 NoSampleCompression = SamplerOptions & F_WSMP_NO_COMPRESSION;
00514 pSampleLoops = (SampleLoops) ? new sample_loop_t[SampleLoops] : NULL;
00515 if (SampleLoops) {
00516 wsmp->SetPos(uiHeaderSize);
00517 for (uint32_t i = 0; i < SampleLoops; i++) {
00518 wsmp->Read(pSampleLoops + i, 4, 4);
00519 if (pSampleLoops[i].Size > sizeof(sample_loop_t)) {
00520 wsmp->SetPos(pSampleLoops[i].Size - sizeof(sample_loop_t), RIFF::stream_curpos);
00521 }
00522 }
00523 }
00524 }
00525
00526 Sampler::~Sampler() {
00527 if (pSampleLoops) delete[] pSampleLoops;
00528 }
00529
00530 void Sampler::SetGain(int32_t gain) {
00531 Gain = gain;
00532 }
00533
00538 void Sampler::UpdateChunks() {
00539
00540 RIFF::Chunk* wsmp = pParentList->GetSubChunk(CHUNK_ID_WSMP);
00541 int wsmpSize = uiHeaderSize + SampleLoops * 16;
00542 if (!wsmp) {
00543 wsmp = pParentList->AddSubChunk(CHUNK_ID_WSMP, wsmpSize);
00544 } else if (wsmp->GetSize() != wsmpSize) {
00545 wsmp->Resize(wsmpSize);
00546 }
00547 uint8_t* pData = (uint8_t*) wsmp->LoadChunkData();
00548
00549 store32(&pData[0], uiHeaderSize);
00550
00551 SamplerOptions = (NoSampleDepthTruncation) ? SamplerOptions | F_WSMP_NO_TRUNCATION
00552 : SamplerOptions & (~F_WSMP_NO_TRUNCATION);
00553 SamplerOptions = (NoSampleCompression) ? SamplerOptions | F_WSMP_NO_COMPRESSION
00554 : SamplerOptions & (~F_WSMP_NO_COMPRESSION);
00555 store16(&pData[4], UnityNote);
00556 store16(&pData[6], FineTune);
00557 store32(&pData[8], Gain);
00558 store32(&pData[12], SamplerOptions);
00559 store32(&pData[16], SampleLoops);
00560
00561 for (uint32_t i = 0; i < SampleLoops; i++) {
00562
00563 store32(&pData[uiHeaderSize + i * 16], pSampleLoops[i].Size);
00564 store32(&pData[uiHeaderSize + i * 16 + 4], pSampleLoops[i].LoopType);
00565 store32(&pData[uiHeaderSize + i * 16 + 8], pSampleLoops[i].LoopStart);
00566 store32(&pData[uiHeaderSize + i * 16 + 12], pSampleLoops[i].LoopLength);
00567 }
00568 }
00569
00575 void Sampler::AddSampleLoop(sample_loop_t* pLoopDef) {
00576 sample_loop_t* pNewLoops = new sample_loop_t[SampleLoops + 1];
00577
00578 for (int i = 0; i < SampleLoops; i++) {
00579 pNewLoops[i] = pSampleLoops[i];
00580 }
00581
00582 pNewLoops[SampleLoops] = *pLoopDef;
00583
00584 pNewLoops[SampleLoops].Size = sizeof(DLS::sample_loop_t);
00585
00586 if (SampleLoops) delete[] pSampleLoops;
00587 pSampleLoops = pNewLoops;
00588 SampleLoops++;
00589 }
00590
00597 void Sampler::DeleteSampleLoop(sample_loop_t* pLoopDef) {
00598 sample_loop_t* pNewLoops = new sample_loop_t[SampleLoops - 1];
00599
00600 for (int i = 0, o = 0; i < SampleLoops; i++) {
00601 if (&pSampleLoops[i] == pLoopDef) continue;
00602 if (o == SampleLoops - 1)
00603 throw Exception("Could not delete Sample Loop, because it does not exist");
00604 pNewLoops[o] = pSampleLoops[i];
00605 o++;
00606 }
00607
00608 if (SampleLoops) delete[] pSampleLoops;
00609 pSampleLoops = pNewLoops;
00610 SampleLoops--;
00611 }
00612
00613
00614
00615
00616
00617
00633 Sample::Sample(File* pFile, RIFF::List* waveList, unsigned long WavePoolOffset) : Resource(pFile, waveList) {
00634 pWaveList = waveList;
00635 ulWavePoolOffset = WavePoolOffset - LIST_HEADER_SIZE;
00636 pCkFormat = waveList->GetSubChunk(CHUNK_ID_FMT);
00637 pCkData = waveList->GetSubChunk(CHUNK_ID_DATA);
00638 if (pCkFormat) {
00639
00640 FormatTag = pCkFormat->ReadUint16();
00641 Channels = pCkFormat->ReadUint16();
00642 SamplesPerSecond = pCkFormat->ReadUint32();
00643 AverageBytesPerSecond = pCkFormat->ReadUint32();
00644 BlockAlign = pCkFormat->ReadUint16();
00645
00646 if (FormatTag == DLS_WAVE_FORMAT_PCM) {
00647 BitDepth = pCkFormat->ReadUint16();
00648 FrameSize = (BitDepth / 8) * Channels;
00649 } else {
00650 BitDepth = 0;
00651 FrameSize = 0;
00652 }
00653 } else {
00654 FormatTag = DLS_WAVE_FORMAT_PCM;
00655 BitDepth = 16;
00656 Channels = 1;
00657 SamplesPerSecond = 44100;
00658 AverageBytesPerSecond = (BitDepth / 8) * SamplesPerSecond * Channels;
00659 FrameSize = (BitDepth / 8) * Channels;
00660 BlockAlign = FrameSize;
00661 }
00662 SamplesTotal = (pCkData) ? (FormatTag == DLS_WAVE_FORMAT_PCM) ? pCkData->GetSize() / FrameSize
00663 : 0
00664 : 0;
00665 }
00666
00672 Sample::~Sample() {
00673 RIFF::List* pParent = pWaveList->GetParent();
00674 pParent->DeleteSubChunk(pWaveList);
00675 }
00676
00703 void* Sample::LoadSampleData() {
00704 return (pCkData) ? pCkData->LoadChunkData() : NULL;
00705 }
00706
00712 void Sample::ReleaseSampleData() {
00713 if (pCkData) pCkData->ReleaseChunkData();
00714 }
00715
00726 unsigned long Sample::GetSize() {
00727 if (FormatTag != DLS_WAVE_FORMAT_PCM) return 0;
00728 return (pCkData) ? pCkData->GetSize() / FrameSize : 0;
00729 }
00730
00759 void Sample::Resize(int iNewSize) {
00760 if (FormatTag != DLS_WAVE_FORMAT_PCM) throw Exception("Sample's format is not DLS_WAVE_FORMAT_PCM");
00761 if (iNewSize < 1) throw Exception("Sample size must be at least one sample point");
00762 const int iSizeInBytes = iNewSize * FrameSize;
00763 pCkData = pWaveList->GetSubChunk(CHUNK_ID_DATA);
00764 if (pCkData) pCkData->Resize(iSizeInBytes);
00765 else pCkData = pWaveList->AddSubChunk(CHUNK_ID_DATA, iSizeInBytes);
00766 }
00767
00784 unsigned long Sample::SetPos(unsigned long SampleCount, RIFF::stream_whence_t Whence) {
00785 if (FormatTag != DLS_WAVE_FORMAT_PCM) return 0;
00786 if (!pCkData) throw Exception("No data chunk created for sample yet, call Sample::Resize() to create one");
00787 unsigned long orderedBytes = SampleCount * FrameSize;
00788 unsigned long result = pCkData->SetPos(orderedBytes, Whence);
00789 return (result == orderedBytes) ? SampleCount
00790 : result / FrameSize;
00791 }
00792
00802 unsigned long Sample::Read(void* pBuffer, unsigned long SampleCount) {
00803 if (FormatTag != DLS_WAVE_FORMAT_PCM) return 0;
00804 return pCkData->Read(pBuffer, SampleCount, FrameSize);
00805 }
00806
00822 unsigned long Sample::Write(void* pBuffer, unsigned long SampleCount) {
00823 if (FormatTag != DLS_WAVE_FORMAT_PCM) return 0;
00824 if (GetSize() < SampleCount) throw Exception("Could not write sample data, current sample size to small");
00825 return pCkData->Write(pBuffer, SampleCount, FrameSize);
00826 }
00827
00835 void Sample::UpdateChunks() {
00836 if (FormatTag != DLS_WAVE_FORMAT_PCM)
00837 throw Exception("Could not save sample, only PCM format is supported");
00838
00839 if (!pCkData)
00840 throw Exception("Could not save sample, there is no sample data to save");
00841
00842 Resource::UpdateChunks();
00843
00844 RIFF::Chunk* pCkFormat = pWaveList->GetSubChunk(CHUNK_ID_FMT);
00845 if (!pCkFormat) pCkFormat = pWaveList->AddSubChunk(CHUNK_ID_FMT, 16);
00846 uint8_t* pData = (uint8_t*) pCkFormat->LoadChunkData();
00847
00848 store16(&pData[0], FormatTag);
00849 store16(&pData[2], Channels);
00850 store32(&pData[4], SamplesPerSecond);
00851 store32(&pData[8], AverageBytesPerSecond);
00852 store16(&pData[12], BlockAlign);
00853 store16(&pData[14], BitDepth);
00854 }
00855
00856
00857
00858
00859
00860
00861 Region::Region(Instrument* pInstrument, RIFF::List* rgnList) : Resource(pInstrument, rgnList), Articulator(rgnList), Sampler(rgnList) {
00862 pCkRegion = rgnList;
00863
00864
00865 RIFF::Chunk* rgnh = rgnList->GetSubChunk(CHUNK_ID_RGNH);
00866 if (rgnh) {
00867 rgnh->Read(&KeyRange, 2, 2);
00868 rgnh->Read(&VelocityRange, 2, 2);
00869 FormatOptionFlags = rgnh->ReadUint16();
00870 KeyGroup = rgnh->ReadUint16();
00871
00872 if (rgnh->RemainingBytes() >= sizeof(uint16_t)) {
00873 rgnh->Read(&Layer, 1, sizeof(uint16_t));
00874 } else Layer = 0;
00875 } else {
00876 KeyRange.low = 0;
00877 KeyRange.high = 127;
00878 VelocityRange.low = 0;
00879 VelocityRange.high = 127;
00880 FormatOptionFlags = F_RGN_OPTION_SELFNONEXCLUSIVE;
00881 KeyGroup = 0;
00882 Layer = 0;
00883 }
00884 SelfNonExclusive = FormatOptionFlags & F_RGN_OPTION_SELFNONEXCLUSIVE;
00885
00886
00887 RIFF::Chunk* wlnk = rgnList->GetSubChunk(CHUNK_ID_WLNK);
00888 if (wlnk) {
00889 WaveLinkOptionFlags = wlnk->ReadUint16();
00890 PhaseGroup = wlnk->ReadUint16();
00891 Channel = wlnk->ReadUint32();
00892 WavePoolTableIndex = wlnk->ReadUint32();
00893 } else {
00894 WaveLinkOptionFlags = 0;
00895 PhaseGroup = 0;
00896 Channel = 0;
00897 WavePoolTableIndex = 0;
00898 }
00899 PhaseMaster = WaveLinkOptionFlags & F_WAVELINK_PHASE_MASTER;
00900 MultiChannel = WaveLinkOptionFlags & F_WAVELINK_MULTICHANNEL;
00901
00902 pSample = NULL;
00903 }
00904
00909 Region::~Region() {
00910 RIFF::List* pParent = pCkRegion->GetParent();
00911 pParent->DeleteSubChunk(pCkRegion);
00912 }
00913
00914 Sample* Region::GetSample() {
00915 if (pSample) return pSample;
00916 File* file = (File*) GetParent()->GetParent();
00917 unsigned long soughtoffset = file->pWavePoolTable[WavePoolTableIndex];
00918 Sample* sample = file->GetFirstSample();
00919 while (sample) {
00920 if (sample->ulWavePoolOffset == soughtoffset) return (pSample = sample);
00921 sample = file->GetNextSample();
00922 }
00923 return NULL;
00924 }
00925
00931 void Region::SetSample(Sample* pSample) {
00932 this->pSample = pSample;
00933 WavePoolTableIndex = 0;
00934 }
00935
00943 void Region::SetKeyRange(uint16_t Low, uint16_t High) {
00944 KeyRange.low = Low;
00945 KeyRange.high = High;
00946
00947
00948 Instrument* pInstrument = (Instrument*) GetParent();
00949 if (!pInstrument->pRegions) pInstrument->LoadRegions();
00950 if (!pInstrument->pRegions) return;
00951
00952
00953
00954 Region* r = NULL;
00955 Region* prev_region = NULL;
00956 for (
00957 Instrument::RegionList::iterator iter = pInstrument->pRegions->begin();
00958 iter != pInstrument->pRegions->end(); iter++
00959 ) {
00960 if ((*iter)->KeyRange.low > this->KeyRange.low) {
00961 r = *iter;
00962 break;
00963 }
00964 prev_region = *iter;
00965 }
00966
00967
00968 if (prev_region != this) pInstrument->MoveRegion(this, r);
00969 }
00970
00977 void Region::UpdateChunks() {
00978
00979 RIFF::Chunk* rgnh = pCkRegion->GetSubChunk(CHUNK_ID_RGNH);
00980 if (!rgnh) rgnh = pCkRegion->AddSubChunk(CHUNK_ID_RGNH, Layer ? 14 : 12);
00981 uint8_t* pData = (uint8_t*) rgnh->LoadChunkData();
00982 FormatOptionFlags = (SelfNonExclusive)
00983 ? FormatOptionFlags | F_RGN_OPTION_SELFNONEXCLUSIVE
00984 : FormatOptionFlags & (~F_RGN_OPTION_SELFNONEXCLUSIVE);
00985
00986 store16(&pData[0], KeyRange.low);
00987 store16(&pData[2], KeyRange.high);
00988 store16(&pData[4], VelocityRange.low);
00989 store16(&pData[6], VelocityRange.high);
00990 store16(&pData[8], FormatOptionFlags);
00991 store16(&pData[10], KeyGroup);
00992 if (rgnh->GetSize() >= 14) store16(&pData[12], Layer);
00993
00994
00995
00996 Articulator::UpdateChunks();
00997 Sampler::UpdateChunks();
00998
00999
01000 RIFF::Chunk* wlnk = pCkRegion->GetSubChunk(CHUNK_ID_WLNK);
01001 if (!wlnk) wlnk = pCkRegion->AddSubChunk(CHUNK_ID_WLNK, 12);
01002 pData = (uint8_t*) wlnk->LoadChunkData();
01003 WaveLinkOptionFlags = (PhaseMaster)
01004 ? WaveLinkOptionFlags | F_WAVELINK_PHASE_MASTER
01005 : WaveLinkOptionFlags & (~F_WAVELINK_PHASE_MASTER);
01006 WaveLinkOptionFlags = (MultiChannel)
01007 ? WaveLinkOptionFlags | F_WAVELINK_MULTICHANNEL
01008 : WaveLinkOptionFlags & (~F_WAVELINK_MULTICHANNEL);
01009
01010 int index = -1;
01011 File* pFile = (File*) GetParent()->GetParent();
01012 if (pFile->pSamples) {
01013 File::SampleList::iterator iter = pFile->pSamples->begin();
01014 File::SampleList::iterator end = pFile->pSamples->end();
01015 for (int i = 0; iter != end; ++iter, i++) {
01016 if (*iter == pSample) {
01017 index = i;
01018 break;
01019 }
01020 }
01021 }
01022 WavePoolTableIndex = index;
01023
01024 store16(&pData[0], WaveLinkOptionFlags);
01025 store16(&pData[2], PhaseGroup);
01026 store32(&pData[4], Channel);
01027 store32(&pData[8], WavePoolTableIndex);
01028 }
01029
01030
01031
01032
01033
01034
01048 Instrument::Instrument(File* pFile, RIFF::List* insList) : Resource(pFile, insList), Articulator(insList) {
01049 pCkInstrument = insList;
01050
01051 midi_locale_t locale;
01052 RIFF::Chunk* insh = pCkInstrument->GetSubChunk(CHUNK_ID_INSH);
01053 if (insh) {
01054 Regions = insh->ReadUint32();
01055 insh->Read(&locale, 2, 4);
01056 } else {
01057 Regions = 0;
01058 locale.bank = 0;
01059 locale.instrument = 0;
01060 }
01061
01062 MIDIProgram = locale.instrument;
01063 IsDrum = locale.bank & DRUM_TYPE_MASK;
01064 MIDIBankCoarse = (uint8_t) MIDI_BANK_COARSE(locale.bank);
01065 MIDIBankFine = (uint8_t) MIDI_BANK_FINE(locale.bank);
01066 MIDIBank = MIDI_BANK_MERGE(MIDIBankCoarse, MIDIBankFine);
01067
01068 pRegions = NULL;
01069 }
01070
01071 Region* Instrument::GetFirstRegion() {
01072 if (!pRegions) LoadRegions();
01073 if (!pRegions) return NULL;
01074 RegionsIterator = pRegions->begin();
01075 return (RegionsIterator != pRegions->end()) ? *RegionsIterator : NULL;
01076 }
01077
01078 Region* Instrument::GetNextRegion() {
01079 if (!pRegions) return NULL;
01080 RegionsIterator++;
01081 return (RegionsIterator != pRegions->end()) ? *RegionsIterator : NULL;
01082 }
01083
01084 void Instrument::LoadRegions() {
01085 if (!pRegions) pRegions = new RegionList;
01086 RIFF::List* lrgn = pCkInstrument->GetSubList(LIST_TYPE_LRGN);
01087 if (lrgn) {
01088 uint32_t regionCkType = (lrgn->GetSubList(LIST_TYPE_RGN2)) ? LIST_TYPE_RGN2 : LIST_TYPE_RGN;
01089 RIFF::List* rgn = lrgn->GetFirstSubList();
01090 while (rgn) {
01091 if (rgn->GetListType() == regionCkType) {
01092 pRegions->push_back(new Region(this, rgn));
01093 }
01094 rgn = lrgn->GetNextSubList();
01095 }
01096 }
01097 }
01098
01099 Region* Instrument::AddRegion() {
01100 if (!pRegions) LoadRegions();
01101 RIFF::List* lrgn = pCkInstrument->GetSubList(LIST_TYPE_LRGN);
01102 if (!lrgn) lrgn = pCkInstrument->AddSubList(LIST_TYPE_LRGN);
01103 RIFF::List* rgn = lrgn->AddSubList(LIST_TYPE_RGN);
01104 Region* pNewRegion = new Region(this, rgn);
01105 pRegions->push_back(pNewRegion);
01106 Regions = pRegions->size();
01107 return pNewRegion;
01108 }
01109
01110 void Instrument::MoveRegion(Region* pSrc, Region* pDst) {
01111 RIFF::List* lrgn = pCkInstrument->GetSubList(LIST_TYPE_LRGN);
01112 lrgn->MoveSubChunk(pSrc->pCkRegion, pDst ? pDst->pCkRegion : 0);
01113
01114 pRegions->remove(pSrc);
01115 RegionList::iterator iter = find(pRegions->begin(), pRegions->end(), pDst);
01116 pRegions->insert(iter, pSrc);
01117 }
01118
01119 void Instrument::DeleteRegion(Region* pRegion) {
01120 if (!pRegions) return;
01121 RegionList::iterator iter = find(pRegions->begin(), pRegions->end(), pRegion);
01122 if (iter == pRegions->end()) return;
01123 pRegions->erase(iter);
01124 Regions = pRegions->size();
01125 delete pRegion;
01126 }
01127
01134 void Instrument::UpdateChunks() {
01135
01136 Resource::UpdateChunks();
01137 Articulator::UpdateChunks();
01138
01139 RIFF::Chunk* insh = pCkInstrument->GetSubChunk(CHUNK_ID_INSH);
01140 if (!insh) insh = pCkInstrument->AddSubChunk(CHUNK_ID_INSH, 12);
01141 uint8_t* pData = (uint8_t*) insh->LoadChunkData();
01142
01143 Regions = (pRegions) ? pRegions->size() : 0;
01144 midi_locale_t locale;
01145 locale.instrument = MIDIProgram;
01146 locale.bank = MIDI_BANK_ENCODE(MIDIBankCoarse, MIDIBankFine);
01147 locale.bank = (IsDrum) ? locale.bank | DRUM_TYPE_MASK : locale.bank & (~DRUM_TYPE_MASK);
01148 MIDIBank = MIDI_BANK_MERGE(MIDIBankCoarse, MIDIBankFine);
01149 store32(&pData[0], Regions);
01150 store32(&pData[4], locale.bank);
01151 store32(&pData[8], locale.instrument);
01152
01153 if (!pRegions) return;
01154 RegionList::iterator iter = pRegions->begin();
01155 RegionList::iterator end = pRegions->end();
01156 for (; iter != end; ++iter) {
01157 (*iter)->UpdateChunks();
01158 }
01159 }
01160
01166 Instrument::~Instrument() {
01167 if (pRegions) {
01168 RegionList::iterator iter = pRegions->begin();
01169 RegionList::iterator end = pRegions->end();
01170 while (iter != end) {
01171 delete *iter;
01172 iter++;
01173 }
01174 delete pRegions;
01175 }
01176
01177 RIFF::List* pParent = pCkInstrument->GetParent();
01178 pParent->DeleteSubChunk(pCkInstrument);
01179 }
01180
01181
01182
01183
01184
01185
01192 File::File() : Resource(NULL, pRIFF = new RIFF::File(RIFF_TYPE_DLS)) {
01193 pRIFF->SetByteOrder(RIFF::endian_little);
01194 pVersion = new version_t;
01195 pVersion->major = 0;
01196 pVersion->minor = 0;
01197 pVersion->release = 0;
01198 pVersion->build = 0;
01199
01200 Instruments = 0;
01201 WavePoolCount = 0;
01202 pWavePoolTable = NULL;
01203 pWavePoolTableHi = NULL;
01204 WavePoolHeaderSize = 8;
01205
01206 pSamples = NULL;
01207 pInstruments = NULL;
01208
01209 b64BitWavePoolOffsets = false;
01210 }
01211
01221 File::File(RIFF::File* pRIFF) : Resource(NULL, pRIFF) {
01222 if (!pRIFF) throw DLS::Exception("NULL pointer reference to RIFF::File object.");
01223 this->pRIFF = pRIFF;
01224
01225 RIFF::Chunk* ckVersion = pRIFF->GetSubChunk(CHUNK_ID_VERS);
01226 if (ckVersion) {
01227 pVersion = new version_t;
01228 ckVersion->Read(pVersion, 4, 2);
01229 }
01230 else pVersion = NULL;
01231
01232 RIFF::Chunk* colh = pRIFF->GetSubChunk(CHUNK_ID_COLH);
01233 if (!colh) throw DLS::Exception("Mandatory chunks in RIFF list chunk not found.");
01234 Instruments = colh->ReadUint32();
01235
01236 RIFF::Chunk* ptbl = pRIFF->GetSubChunk(CHUNK_ID_PTBL);
01237 if (!ptbl) {
01238 WavePoolCount = 0;
01239 pWavePoolTable = NULL;
01240 pWavePoolTableHi = NULL;
01241 WavePoolHeaderSize = 8;
01242 b64BitWavePoolOffsets = false;
01243 } else {
01244 WavePoolHeaderSize = ptbl->ReadUint32();
01245 WavePoolCount = ptbl->ReadUint32();
01246 pWavePoolTable = new uint32_t[WavePoolCount];
01247 pWavePoolTableHi = new uint32_t[WavePoolCount];
01248 ptbl->SetPos(WavePoolHeaderSize);
01249
01250
01251 b64BitWavePoolOffsets = (ptbl->GetSize() - WavePoolHeaderSize == WavePoolCount * 8);
01252 if (b64BitWavePoolOffsets) {
01253 for (int i = 0 ; i < WavePoolCount ; i++) {
01254 pWavePoolTableHi[i] = ptbl->ReadUint32();
01255 pWavePoolTable[i] = ptbl->ReadUint32();
01256 if (pWavePoolTable[i] & 0x80000000)
01257 throw DLS::Exception("Files larger than 2 GB not yet supported");
01258 }
01259 } else {
01260 ptbl->Read(pWavePoolTable, WavePoolCount, sizeof(uint32_t));
01261 for (int i = 0 ; i < WavePoolCount ; i++) pWavePoolTableHi[i] = 0;
01262 }
01263 }
01264
01265 pSamples = NULL;
01266 pInstruments = NULL;
01267 }
01268
01269 File::~File() {
01270 if (pInstruments) {
01271 InstrumentList::iterator iter = pInstruments->begin();
01272 InstrumentList::iterator end = pInstruments->end();
01273 while (iter != end) {
01274 delete *iter;
01275 iter++;
01276 }
01277 delete pInstruments;
01278 }
01279
01280 if (pSamples) {
01281 SampleList::iterator iter = pSamples->begin();
01282 SampleList::iterator end = pSamples->end();
01283 while (iter != end) {
01284 delete *iter;
01285 iter++;
01286 }
01287 delete pSamples;
01288 }
01289
01290 if (pWavePoolTable) delete[] pWavePoolTable;
01291 if (pWavePoolTableHi) delete[] pWavePoolTableHi;
01292 if (pVersion) delete pVersion;
01293 for (std::list<RIFF::File*>::iterator i = ExtensionFiles.begin() ; i != ExtensionFiles.end() ; i++)
01294 delete *i;
01295 }
01296
01297 Sample* File::GetFirstSample() {
01298 if (!pSamples) LoadSamples();
01299 if (!pSamples) return NULL;
01300 SamplesIterator = pSamples->begin();
01301 return (SamplesIterator != pSamples->end()) ? *SamplesIterator : NULL;
01302 }
01303
01304 Sample* File::GetNextSample() {
01305 if (!pSamples) return NULL;
01306 SamplesIterator++;
01307 return (SamplesIterator != pSamples->end()) ? *SamplesIterator : NULL;
01308 }
01309
01310 void File::LoadSamples() {
01311 if (!pSamples) pSamples = new SampleList;
01312 RIFF::List* wvpl = pRIFF->GetSubList(LIST_TYPE_WVPL);
01313 if (wvpl) {
01314 unsigned long wvplFileOffset = wvpl->GetFilePos();
01315 RIFF::List* wave = wvpl->GetFirstSubList();
01316 while (wave) {
01317 if (wave->GetListType() == LIST_TYPE_WAVE) {
01318 unsigned long waveFileOffset = wave->GetFilePos();
01319 pSamples->push_back(new Sample(this, wave, waveFileOffset - wvplFileOffset));
01320 }
01321 wave = wvpl->GetNextSubList();
01322 }
01323 }
01324 else {
01325 RIFF::List* dwpl = pRIFF->GetSubList(LIST_TYPE_DWPL);
01326 if (dwpl) {
01327 unsigned long dwplFileOffset = dwpl->GetFilePos();
01328 RIFF::List* wave = dwpl->GetFirstSubList();
01329 while (wave) {
01330 if (wave->GetListType() == LIST_TYPE_WAVE) {
01331 unsigned long waveFileOffset = wave->GetFilePos();
01332 pSamples->push_back(new Sample(this, wave, waveFileOffset - dwplFileOffset));
01333 }
01334 wave = dwpl->GetNextSubList();
01335 }
01336 }
01337 }
01338 }
01339
01347 Sample* File::AddSample() {
01348 if (!pSamples) LoadSamples();
01349 __ensureMandatoryChunksExist();
01350 RIFF::List* wvpl = pRIFF->GetSubList(LIST_TYPE_WVPL);
01351
01352 RIFF::List* wave = wvpl->AddSubList(LIST_TYPE_WAVE);
01353 Sample* pSample = new Sample(this, wave, 0 );
01354 pSamples->push_back(pSample);
01355 return pSample;
01356 }
01357
01365 void File::DeleteSample(Sample* pSample) {
01366 if (!pSamples) return;
01367 SampleList::iterator iter = find(pSamples->begin(), pSamples->end(), pSample);
01368 if (iter == pSamples->end()) return;
01369 pSamples->erase(iter);
01370 delete pSample;
01371 }
01372
01373 Instrument* File::GetFirstInstrument() {
01374 if (!pInstruments) LoadInstruments();
01375 if (!pInstruments) return NULL;
01376 InstrumentsIterator = pInstruments->begin();
01377 return (InstrumentsIterator != pInstruments->end()) ? *InstrumentsIterator : NULL;
01378 }
01379
01380 Instrument* File::GetNextInstrument() {
01381 if (!pInstruments) return NULL;
01382 InstrumentsIterator++;
01383 return (InstrumentsIterator != pInstruments->end()) ? *InstrumentsIterator : NULL;
01384 }
01385
01386 void File::LoadInstruments() {
01387 if (!pInstruments) pInstruments = new InstrumentList;
01388 RIFF::List* lstInstruments = pRIFF->GetSubList(LIST_TYPE_LINS);
01389 if (lstInstruments) {
01390 RIFF::List* lstInstr = lstInstruments->GetFirstSubList();
01391 while (lstInstr) {
01392 if (lstInstr->GetListType() == LIST_TYPE_INS) {
01393 pInstruments->push_back(new Instrument(this, lstInstr));
01394 }
01395 lstInstr = lstInstruments->GetNextSubList();
01396 }
01397 }
01398 }
01399
01407 Instrument* File::AddInstrument() {
01408 if (!pInstruments) LoadInstruments();
01409 __ensureMandatoryChunksExist();
01410 RIFF::List* lstInstruments = pRIFF->GetSubList(LIST_TYPE_LINS);
01411 RIFF::List* lstInstr = lstInstruments->AddSubList(LIST_TYPE_INS);
01412 Instrument* pInstrument = new Instrument(this, lstInstr);
01413 pInstruments->push_back(pInstrument);
01414 return pInstrument;
01415 }
01416
01424 void File::DeleteInstrument(Instrument* pInstrument) {
01425 if (!pInstruments) return;
01426 InstrumentList::iterator iter = find(pInstruments->begin(), pInstruments->end(), pInstrument);
01427 if (iter == pInstruments->end()) return;
01428 pInstruments->erase(iter);
01429 delete pInstrument;
01430 }
01431
01439 void File::UpdateChunks() {
01440
01441 Resource::UpdateChunks();
01442
01443
01444 if (pVersion) {
01445 RIFF::Chunk* ckVersion = pRIFF->GetSubChunk(CHUNK_ID_VERS);
01446 if (!ckVersion) ckVersion = pRIFF->AddSubChunk(CHUNK_ID_VERS, 8);
01447 uint8_t* pData = (uint8_t*) ckVersion->LoadChunkData();
01448 store16(&pData[0], pVersion->minor);
01449 store16(&pData[2], pVersion->major);
01450 store16(&pData[4], pVersion->build);
01451 store16(&pData[6], pVersion->release);
01452 }
01453
01454
01455 Instruments = (pInstruments) ? pInstruments->size() : 0;
01456 RIFF::Chunk* colh = pRIFF->GetSubChunk(CHUNK_ID_COLH);
01457 if (!colh) colh = pRIFF->AddSubChunk(CHUNK_ID_COLH, 4);
01458 uint8_t* pData = (uint8_t*) colh->LoadChunkData();
01459 store32(pData, Instruments);
01460
01461
01462 if (pInstruments) {
01463 InstrumentList::iterator iter = pInstruments->begin();
01464 InstrumentList::iterator end = pInstruments->end();
01465 for (; iter != end; ++iter) {
01466 (*iter)->UpdateChunks();
01467 }
01468 }
01469
01470
01471 const int iSamples = (pSamples) ? pSamples->size() : 0;
01472 const int iPtblOffsetSize = (b64BitWavePoolOffsets) ? 8 : 4;
01473 RIFF::Chunk* ptbl = pRIFF->GetSubChunk(CHUNK_ID_PTBL);
01474 if (!ptbl) ptbl = pRIFF->AddSubChunk(CHUNK_ID_PTBL, 1 );
01475 const int iPtblSize = WavePoolHeaderSize + iPtblOffsetSize * iSamples;
01476 ptbl->Resize(iPtblSize);
01477 pData = (uint8_t*) ptbl->LoadChunkData();
01478 WavePoolCount = iSamples;
01479 store32(&pData[4], WavePoolCount);
01480
01481 memset(&pData[WavePoolHeaderSize], 0, iPtblSize - WavePoolHeaderSize);
01482
01483
01484 if (pSamples) {
01485 SampleList::iterator iter = pSamples->begin();
01486 SampleList::iterator end = pSamples->end();
01487 for (; iter != end; ++iter) {
01488 (*iter)->UpdateChunks();
01489 }
01490 }
01491 }
01492
01506 void File::Save(const String& Path) {
01507 UpdateChunks();
01508 pRIFF->Save(Path);
01509 __UpdateWavePoolTableChunk();
01510 }
01511
01521 void File::Save() {
01522 UpdateChunks();
01523 pRIFF->Save();
01524 __UpdateWavePoolTableChunk();
01525 }
01526
01532 void File::__ensureMandatoryChunksExist() {
01533
01534 RIFF::List* lstInstruments = pRIFF->GetSubList(LIST_TYPE_LINS);
01535 if (!lstInstruments) pRIFF->AddSubList(LIST_TYPE_LINS);
01536
01537 RIFF::Chunk* ptbl = pRIFF->GetSubChunk(CHUNK_ID_PTBL);
01538 if (!ptbl) {
01539 const int iOffsetSize = (b64BitWavePoolOffsets) ? 8 : 4;
01540 ptbl = pRIFF->AddSubChunk(CHUNK_ID_PTBL, WavePoolHeaderSize + iOffsetSize);
01541 }
01542
01543 RIFF::List* wvpl = pRIFF->GetSubList(LIST_TYPE_WVPL);
01544 if (!wvpl) pRIFF->AddSubList(LIST_TYPE_WVPL);
01545 }
01546
01556 void File::__UpdateWavePoolTableChunk() {
01557 __UpdateWavePoolTable();
01558 RIFF::Chunk* ptbl = pRIFF->GetSubChunk(CHUNK_ID_PTBL);
01559 const int iOffsetSize = (b64BitWavePoolOffsets) ? 8 : 4;
01560
01561 WavePoolCount = (pSamples) ? pSamples->size() : 0;
01562 const unsigned long ulRequiredSize = WavePoolHeaderSize + iOffsetSize * WavePoolCount;
01563 if (ptbl->GetSize() < ulRequiredSize) throw Exception("Fatal error, 'ptbl' chunk too small");
01564
01565 unsigned long ulOriginalPos = ptbl->GetPos();
01566
01567 ptbl->SetPos(0);
01568 uint32_t tmp = WavePoolHeaderSize;
01569 ptbl->WriteUint32(&tmp);
01570 tmp = WavePoolCount;
01571 ptbl->WriteUint32(&tmp);
01572
01573 ptbl->SetPos(WavePoolHeaderSize);
01574 if (b64BitWavePoolOffsets) {
01575 for (int i = 0 ; i < WavePoolCount ; i++) {
01576 tmp = pWavePoolTableHi[i];
01577 ptbl->WriteUint32(&tmp);
01578 tmp = pWavePoolTable[i];
01579 ptbl->WriteUint32(&tmp);
01580 }
01581 } else {
01582 for (int i = 0 ; i < WavePoolCount ; i++) {
01583 tmp = pWavePoolTable[i];
01584 ptbl->WriteUint32(&tmp);
01585 }
01586 }
01587
01588 ptbl->SetPos(ulOriginalPos);
01589 }
01590
01596 void File::__UpdateWavePoolTable() {
01597 WavePoolCount = (pSamples) ? pSamples->size() : 0;
01598
01599 if (pWavePoolTable) delete[] pWavePoolTable;
01600 if (pWavePoolTableHi) delete[] pWavePoolTableHi;
01601 pWavePoolTable = new uint32_t[WavePoolCount];
01602 pWavePoolTableHi = new uint32_t[WavePoolCount];
01603 if (!pSamples) return;
01604
01605 RIFF::List* wvpl = pRIFF->GetSubList(LIST_TYPE_WVPL);
01606 uint64_t wvplFileOffset = wvpl->GetFilePos();
01607 if (b64BitWavePoolOffsets) {
01608 SampleList::iterator iter = pSamples->begin();
01609 SampleList::iterator end = pSamples->end();
01610 for (int i = 0 ; iter != end ; ++iter, i++) {
01611 uint64_t _64BitOffset = (*iter)->pWaveList->GetFilePos() - wvplFileOffset - LIST_HEADER_SIZE;
01612 (*iter)->ulWavePoolOffset = _64BitOffset;
01613 pWavePoolTableHi[i] = (uint32_t) (_64BitOffset >> 32);
01614 pWavePoolTable[i] = (uint32_t) _64BitOffset;
01615 }
01616 } else {
01617 SampleList::iterator iter = pSamples->begin();
01618 SampleList::iterator end = pSamples->end();
01619 for (int i = 0 ; iter != end ; ++iter, i++) {
01620 uint64_t _64BitOffset = (*iter)->pWaveList->GetFilePos() - wvplFileOffset - LIST_HEADER_SIZE;
01621 (*iter)->ulWavePoolOffset = _64BitOffset;
01622 pWavePoolTable[i] = (uint32_t) _64BitOffset;
01623 }
01624 }
01625 }
01626
01627
01628
01629
01630
01631
01632 Exception::Exception(String Message) : RIFF::Exception(Message) {
01633 }
01634
01635 void Exception::PrintMessage() {
01636 std::cout << "DLS::Exception: " << Message << std::endl;
01637 }
01638
01639
01640
01641
01642
01648 String libraryName() {
01649 return PACKAGE;
01650 }
01651
01656 String libraryVersion() {
01657 return VERSION;
01658 }
01659
01660 }