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 #include "helper.h"
00029
00030
00031 #define CONN_TRANSFORM_SRC(x) ((x >> 10) & 0x000F)
00032 #define CONN_TRANSFORM_CTL(x) ((x >> 4) & 0x000F)
00033 #define CONN_TRANSFORM_DST(x) (x & 0x000F)
00034 #define CONN_TRANSFORM_BIPOLAR_SRC(x) (x & 0x4000)
00035 #define CONN_TRANSFORM_BIPOLAR_CTL(x) (x & 0x0100)
00036 #define CONN_TRANSFORM_INVERT_SRC(x) (x & 0x8000)
00037 #define CONN_TRANSFORM_INVERT_CTL(x) (x & 0x0200)
00038
00039
00040 #define CONN_TRANSFORM_SRC_ENCODE(x) ((x & 0x000F) << 10)
00041 #define CONN_TRANSFORM_CTL_ENCODE(x) ((x & 0x000F) << 4)
00042 #define CONN_TRANSFORM_DST_ENCODE(x) (x & 0x000F)
00043 #define CONN_TRANSFORM_BIPOLAR_SRC_ENCODE(x) ((x) ? 0x4000 : 0)
00044 #define CONN_TRANSFORM_BIPOLAR_CTL_ENCODE(x) ((x) ? 0x0100 : 0)
00045 #define CONN_TRANSFORM_INVERT_SRC_ENCODE(x) ((x) ? 0x8000 : 0)
00046 #define CONN_TRANSFORM_INVERT_CTL_ENCODE(x) ((x) ? 0x0200 : 0)
00047
00048 #define DRUM_TYPE_MASK 0x80000000
00049
00050 #define F_RGN_OPTION_SELFNONEXCLUSIVE 0x0001
00051
00052 #define F_WAVELINK_PHASE_MASTER 0x0001
00053 #define F_WAVELINK_MULTICHANNEL 0x0002
00054
00055 #define F_WSMP_NO_TRUNCATION 0x0001
00056 #define F_WSMP_NO_COMPRESSION 0x0002
00057
00058 #define MIDI_BANK_COARSE(x) ((x & 0x00007F00) >> 8) // CC0
00059 #define MIDI_BANK_FINE(x) (x & 0x0000007F) // CC32
00060 #define MIDI_BANK_MERGE(coarse, fine) ((((uint16_t) coarse) << 7) | fine) // CC0 + CC32
00061 #define MIDI_BANK_ENCODE(coarse, fine) (((coarse & 0x0000007F) << 8) | (fine & 0x0000007F))
00062
00063 namespace DLS {
00064
00065
00066
00067
00068 void Connection::Init(conn_block_t* Header) {
00069 Source = (conn_src_t) Header->source;
00070 Control = (conn_src_t) Header->control;
00071 Destination = (conn_dst_t) Header->destination;
00072 Scale = Header->scale;
00073 SourceTransform = (conn_trn_t) CONN_TRANSFORM_SRC(Header->transform);
00074 ControlTransform = (conn_trn_t) CONN_TRANSFORM_CTL(Header->transform);
00075 DestinationTransform = (conn_trn_t) CONN_TRANSFORM_DST(Header->transform);
00076 SourceInvert = CONN_TRANSFORM_INVERT_SRC(Header->transform);
00077 SourceBipolar = CONN_TRANSFORM_BIPOLAR_SRC(Header->transform);
00078 ControlInvert = CONN_TRANSFORM_INVERT_CTL(Header->transform);
00079 ControlBipolar = CONN_TRANSFORM_BIPOLAR_CTL(Header->transform);
00080 }
00081
00082 Connection::conn_block_t Connection::ToConnBlock() {
00083 conn_block_t c;
00084 c.source = Source;
00085 c.control = Control;
00086 c.destination = Destination;
00087 c.scale = Scale;
00088 c.transform = CONN_TRANSFORM_SRC_ENCODE(SourceTransform) |
00089 CONN_TRANSFORM_CTL_ENCODE(ControlTransform) |
00090 CONN_TRANSFORM_DST_ENCODE(DestinationTransform) |
00091 CONN_TRANSFORM_INVERT_SRC_ENCODE(SourceInvert) |
00092 CONN_TRANSFORM_BIPOLAR_SRC_ENCODE(SourceBipolar) |
00093 CONN_TRANSFORM_INVERT_CTL_ENCODE(ControlInvert) |
00094 CONN_TRANSFORM_BIPOLAR_CTL_ENCODE(ControlBipolar);
00095 return c;
00096 }
00097
00098
00099
00100
00101
00102
00111 Articulation::Articulation(RIFF::Chunk* artl) {
00112 pArticulationCk = artl;
00113 if (artl->GetChunkID() != CHUNK_ID_ART2 &&
00114 artl->GetChunkID() != CHUNK_ID_ARTL) {
00115 throw DLS::Exception("<artl-ck> or <art2-ck> chunk expected");
00116 }
00117 HeaderSize = artl->ReadUint32();
00118 Connections = artl->ReadUint32();
00119 artl->SetPos(HeaderSize);
00120
00121 pConnections = new Connection[Connections];
00122 Connection::conn_block_t connblock;
00123 for (uint32_t i = 0; i < Connections; i++) {
00124 artl->Read(&connblock.source, 1, 2);
00125 artl->Read(&connblock.control, 1, 2);
00126 artl->Read(&connblock.destination, 1, 2);
00127 artl->Read(&connblock.transform, 1, 2);
00128 artl->Read(&connblock.scale, 1, 4);
00129 pConnections[i].Init(&connblock);
00130 }
00131 }
00132
00133 Articulation::~Articulation() {
00134 if (pConnections) delete[] pConnections;
00135 }
00136
00141 void Articulation::UpdateChunks() {
00142 const int iEntrySize = 12;
00143 pArticulationCk->Resize(HeaderSize + Connections * iEntrySize);
00144 uint8_t* pData = (uint8_t*) pArticulationCk->LoadChunkData();
00145 memcpy(&pData[0], &HeaderSize, 2);
00146 memcpy(&pData[2], &Connections, 2);
00147 for (uint32_t i = 0; i < Connections; i++) {
00148 Connection::conn_block_t c = pConnections[i].ToConnBlock();
00149 memcpy(&pData[HeaderSize + i * iEntrySize], &c.source, 2);
00150 memcpy(&pData[HeaderSize + i * iEntrySize + 2], &c.control, 2);
00151 memcpy(&pData[HeaderSize + i * iEntrySize + 4], &c.destination, 2);
00152 memcpy(&pData[HeaderSize + i * iEntrySize + 6], &c.transform, 2);
00153 memcpy(&pData[HeaderSize + i * iEntrySize + 8], &c.scale, 4);
00154 }
00155 }
00156
00157
00158
00159
00160
00161
00162 Articulator::Articulator(RIFF::List* ParentList) {
00163 pParentList = ParentList;
00164 pArticulations = NULL;
00165 }
00166
00167 Articulation* Articulator::GetFirstArticulation() {
00168 if (!pArticulations) LoadArticulations();
00169 if (!pArticulations) return NULL;
00170 ArticulationsIterator = pArticulations->begin();
00171 return (ArticulationsIterator != pArticulations->end()) ? *ArticulationsIterator : NULL;
00172 }
00173
00174 Articulation* Articulator::GetNextArticulation() {
00175 if (!pArticulations) return NULL;
00176 ArticulationsIterator++;
00177 return (ArticulationsIterator != pArticulations->end()) ? *ArticulationsIterator : NULL;
00178 }
00179
00180 void Articulator::LoadArticulations() {
00181
00182 RIFF::List* lart = pParentList->GetSubList(LIST_TYPE_LAR2);
00183 if (!lart) lart = pParentList->GetSubList(LIST_TYPE_LART);
00184 if (lart) {
00185 uint32_t artCkType = (lart->GetListType() == LIST_TYPE_LAR2) ? CHUNK_ID_ART2
00186 : CHUNK_ID_ARTL;
00187 RIFF::Chunk* art = lart->GetFirstSubChunk();
00188 while (art) {
00189 if (art->GetChunkID() == artCkType) {
00190 if (!pArticulations) pArticulations = new ArticulationList;
00191 pArticulations->push_back(new Articulation(art));
00192 }
00193 art = lart->GetNextSubChunk();
00194 }
00195 }
00196 }
00197
00198 Articulator::~Articulator() {
00199 if (pArticulations) {
00200 ArticulationList::iterator iter = pArticulations->begin();
00201 ArticulationList::iterator end = pArticulations->end();
00202 while (iter != end) {
00203 delete *iter;
00204 iter++;
00205 }
00206 delete pArticulations;
00207 }
00208 }
00209
00214 void Articulator::UpdateChunks() {
00215 if (pArticulations) {
00216 ArticulationList::iterator iter = pArticulations->begin();
00217 ArticulationList::iterator end = pArticulations->end();
00218 for (; iter != end; ++iter) {
00219 (*iter)->UpdateChunks();
00220 }
00221 }
00222 }
00223
00224
00225
00226
00227
00228
00235 Info::Info(RIFF::List* list) {
00236 UseFixedLengthStrings = false;
00237 pResourceListChunk = list;
00238 if (list) {
00239 RIFF::List* lstINFO = list->GetSubList(LIST_TYPE_INFO);
00240 if (lstINFO) {
00241 LoadString(CHUNK_ID_INAM, lstINFO, Name);
00242 LoadString(CHUNK_ID_IARL, lstINFO, ArchivalLocation);
00243 LoadString(CHUNK_ID_ICRD, lstINFO, CreationDate);
00244 LoadString(CHUNK_ID_ICMT, lstINFO, Comments);
00245 LoadString(CHUNK_ID_IPRD, lstINFO, Product);
00246 LoadString(CHUNK_ID_ICOP, lstINFO, Copyright);
00247 LoadString(CHUNK_ID_IART, lstINFO, Artists);
00248 LoadString(CHUNK_ID_IGNR, lstINFO, Genre);
00249 LoadString(CHUNK_ID_IKEY, lstINFO, Keywords);
00250 LoadString(CHUNK_ID_IENG, lstINFO, Engineer);
00251 LoadString(CHUNK_ID_ITCH, lstINFO, Technician);
00252 LoadString(CHUNK_ID_ISFT, lstINFO, Software);
00253 LoadString(CHUNK_ID_IMED, lstINFO, Medium);
00254 LoadString(CHUNK_ID_ISRC, lstINFO, Source);
00255 LoadString(CHUNK_ID_ISRF, lstINFO, SourceForm);
00256 LoadString(CHUNK_ID_ICMS, lstINFO, Commissioned);
00257 LoadString(CHUNK_ID_ISBJ, lstINFO, Subject);
00258 }
00259 }
00260 }
00261
00262 Info::~Info() {
00263 }
00264
00270 void Info::LoadString(uint32_t ChunkID, RIFF::List* lstINFO, String& s) {
00271 RIFF::Chunk* ck = lstINFO->GetSubChunk(ChunkID);
00272 ::LoadString(ck, s);
00273 }
00274
00292 void Info::SaveString(uint32_t ChunkID, RIFF::List* lstINFO, const String& s, const String& sDefault, bool bUseFixedLengthStrings, int size) {
00293 RIFF::Chunk* ck = lstINFO->GetSubChunk(ChunkID);
00294 ::SaveString(ChunkID, ck, lstINFO, s, sDefault, bUseFixedLengthStrings, size);
00295 }
00296
00302 void Info::UpdateChunks() {
00303 if (!pResourceListChunk) return;
00304
00305
00306 RIFF::List* lstINFO = pResourceListChunk->GetSubList(LIST_TYPE_INFO);
00307
00308 String defaultName = "";
00309 String defaultCreationDate = "";
00310 String defaultSoftware = "";
00311 String defaultComments = "";
00312
00313 uint32_t resourceType = pResourceListChunk->GetListType();
00314
00315 if (!lstINFO) {
00316 lstINFO = pResourceListChunk->AddSubList(LIST_TYPE_INFO);
00317
00318
00319 defaultName = "NONAME";
00320
00321 if (resourceType == RIFF_TYPE_DLS) {
00322
00323 time_t now = time(NULL);
00324 tm* pNowBroken = localtime(&now);
00325 char buf[11];
00326 strftime(buf, 11, "%F", pNowBroken);
00327 defaultCreationDate = buf;
00328
00329 defaultComments = "Created with " + libraryName() + " " + libraryVersion();
00330 }
00331 if (resourceType == RIFF_TYPE_DLS || resourceType == LIST_TYPE_INS)
00332 {
00333 defaultSoftware = libraryName() + " " + libraryVersion();
00334 }
00335 }
00336
00337
00338
00339
00340
00341 SaveString(CHUNK_ID_INAM, lstINFO, Name, defaultName, UseFixedLengthStrings,
00342 resourceType == RIFF_TYPE_DLS ? 128 : 64);
00343 SaveString(CHUNK_ID_IARL, lstINFO, ArchivalLocation, String(""), UseFixedLengthStrings, 256);
00344 SaveString(CHUNK_ID_ICRD, lstINFO, CreationDate, defaultCreationDate, UseFixedLengthStrings, 128);
00345 SaveString(CHUNK_ID_ICMT, lstINFO, Comments, defaultComments, UseFixedLengthStrings, 1024);
00346 SaveString(CHUNK_ID_IPRD, lstINFO, Product, String(""), UseFixedLengthStrings, 128);
00347 SaveString(CHUNK_ID_ICOP, lstINFO, Copyright, String(""), UseFixedLengthStrings, 128);
00348 SaveString(CHUNK_ID_IART, lstINFO, Artists, String(""), UseFixedLengthStrings, 128);
00349 SaveString(CHUNK_ID_IGNR, lstINFO, Genre, String(""), UseFixedLengthStrings, 128);
00350 SaveString(CHUNK_ID_IKEY, lstINFO, Keywords, String(""), UseFixedLengthStrings, 128);
00351 SaveString(CHUNK_ID_IENG, lstINFO, Engineer, String(""), UseFixedLengthStrings, 128);
00352 SaveString(CHUNK_ID_ITCH, lstINFO, Technician, String(""), UseFixedLengthStrings, 128);
00353 SaveString(CHUNK_ID_ISFT, lstINFO, Software, defaultSoftware, UseFixedLengthStrings,
00354 resourceType == LIST_TYPE_INS ?
00355 (Software == "" ? defaultSoftware.length()+1 : Software.length()+1) : 128);
00356 SaveString(CHUNK_ID_IMED, lstINFO, Medium, String(""), UseFixedLengthStrings, 128);
00357 SaveString(CHUNK_ID_ISRC, lstINFO, Source, String(""), UseFixedLengthStrings, 128);
00358 SaveString(CHUNK_ID_ISRF, lstINFO, SourceForm, String(""), UseFixedLengthStrings, 128);
00359 SaveString(CHUNK_ID_ICMS, lstINFO, Commissioned, String(""), UseFixedLengthStrings, 128);
00360 SaveString(CHUNK_ID_ISBJ, lstINFO, Subject, String(""), UseFixedLengthStrings, 128);
00361 }
00362
00363
00364
00365
00366
00367
00377 Resource::Resource(Resource* Parent, RIFF::List* lstResource) {
00378 pParent = Parent;
00379 pResourceList = lstResource;
00380
00381 pInfo = new Info(lstResource);
00382
00383 RIFF::Chunk* ckDLSID = lstResource->GetSubChunk(CHUNK_ID_DLID);
00384 if (ckDLSID) {
00385 pDLSID = new dlsid_t;
00386 ckDLSID->Read(&pDLSID->ulData1, 1, 4);
00387 ckDLSID->Read(&pDLSID->usData2, 1, 2);
00388 ckDLSID->Read(&pDLSID->usData3, 1, 2);
00389 ckDLSID->Read(pDLSID->abData, 8, 1);
00390 }
00391 else pDLSID = NULL;
00392 }
00393
00394 Resource::~Resource() {
00395 if (pDLSID) delete pDLSID;
00396 if (pInfo) delete pInfo;
00397 }
00398
00407 void Resource::UpdateChunks() {
00408 pInfo->UpdateChunks();
00409
00410 }
00411
00412
00413
00414
00415
00416
00417 Sampler::Sampler(RIFF::List* ParentList) {
00418 pParentList = ParentList;
00419 RIFF::Chunk* wsmp = ParentList->GetSubChunk(CHUNK_ID_WSMP);
00420 if (wsmp) {
00421 uiHeaderSize = wsmp->ReadUint32();
00422 UnityNote = wsmp->ReadUint16();
00423 FineTune = wsmp->ReadInt16();
00424 Gain = wsmp->ReadInt32();
00425 SamplerOptions = wsmp->ReadUint32();
00426 SampleLoops = wsmp->ReadUint32();
00427 } else {
00428 uiHeaderSize = 0;
00429 UnityNote = 64;
00430 FineTune = 0;
00431 Gain = 0;
00432 SamplerOptions = F_WSMP_NO_COMPRESSION;
00433 SampleLoops = 0;
00434 }
00435 NoSampleDepthTruncation = SamplerOptions & F_WSMP_NO_TRUNCATION;
00436 NoSampleCompression = SamplerOptions & F_WSMP_NO_COMPRESSION;
00437 pSampleLoops = (SampleLoops) ? new sample_loop_t[SampleLoops] : NULL;
00438 if (SampleLoops) {
00439 wsmp->SetPos(uiHeaderSize);
00440 for (uint32_t i = 0; i < SampleLoops; i++) {
00441 wsmp->Read(pSampleLoops + i, 4, 4);
00442 if (pSampleLoops[i].Size > sizeof(sample_loop_t)) {
00443 wsmp->SetPos(pSampleLoops[i].Size - sizeof(sample_loop_t), RIFF::stream_curpos);
00444 }
00445 }
00446 }
00447 }
00448
00449 Sampler::~Sampler() {
00450 if (pSampleLoops) delete[] pSampleLoops;
00451 }
00452
00457 void Sampler::UpdateChunks() {
00458
00459 RIFF::Chunk* wsmp = pParentList->GetSubChunk(CHUNK_ID_WSMP);
00460 if (!wsmp) {
00461 uiHeaderSize = 20;
00462 wsmp = pParentList->AddSubChunk(CHUNK_ID_WSMP, uiHeaderSize + SampleLoops * 16);
00463 }
00464 uint8_t* pData = (uint8_t*) wsmp->LoadChunkData();
00465
00466 memcpy(&pData[0], &uiHeaderSize, 4);
00467
00468 SamplerOptions = (NoSampleDepthTruncation) ? SamplerOptions | F_WSMP_NO_TRUNCATION
00469 : SamplerOptions & (~F_WSMP_NO_TRUNCATION);
00470 SamplerOptions = (NoSampleCompression) ? SamplerOptions | F_WSMP_NO_COMPRESSION
00471 : SamplerOptions & (~F_WSMP_NO_COMPRESSION);
00472 memcpy(&pData[4], &UnityNote, 2);
00473 memcpy(&pData[6], &FineTune, 2);
00474 memcpy(&pData[8], &Gain, 4);
00475 memcpy(&pData[12], &SamplerOptions, 4);
00476 memcpy(&pData[16], &SampleLoops, 4);
00477
00478 for (uint32_t i = 0; i < SampleLoops; i++) {
00479
00480 memcpy(&pData[uiHeaderSize + i * 16], pSampleLoops + i, 4 * 4);
00481 }
00482 }
00483
00484
00485
00486
00487
00488
00504 Sample::Sample(File* pFile, RIFF::List* waveList, unsigned long WavePoolOffset) : Resource(pFile, waveList) {
00505 pWaveList = waveList;
00506 ulWavePoolOffset = WavePoolOffset - LIST_HEADER_SIZE;
00507 pCkFormat = waveList->GetSubChunk(CHUNK_ID_FMT);
00508 pCkData = waveList->GetSubChunk(CHUNK_ID_DATA);
00509 if (pCkFormat) {
00510
00511 FormatTag = pCkFormat->ReadUint16();
00512 Channels = pCkFormat->ReadUint16();
00513 SamplesPerSecond = pCkFormat->ReadUint32();
00514 AverageBytesPerSecond = pCkFormat->ReadUint32();
00515 BlockAlign = pCkFormat->ReadUint16();
00516
00517 if (FormatTag == DLS_WAVE_FORMAT_PCM) {
00518 BitDepth = pCkFormat->ReadUint16();
00519 FrameSize = (BitDepth / 8) * Channels;
00520 } else {
00521 BitDepth = 0;
00522 FrameSize = 0;
00523 }
00524 } else {
00525 FormatTag = DLS_WAVE_FORMAT_PCM;
00526 BitDepth = 16;
00527 Channels = 1;
00528 SamplesPerSecond = 44100;
00529 AverageBytesPerSecond = (BitDepth / 8) * SamplesPerSecond * Channels;
00530 FrameSize = (BitDepth / 8) * Channels;
00531 BlockAlign = FrameSize;
00532 }
00533 SamplesTotal = (pCkData) ? (FormatTag == DLS_WAVE_FORMAT_PCM) ? pCkData->GetSize() / FrameSize
00534 : 0
00535 : 0;
00536 }
00537
00543 Sample::~Sample() {
00544 RIFF::List* pParent = pWaveList->GetParent();
00545 pParent->DeleteSubChunk(pWaveList);
00546 }
00547
00574 void* Sample::LoadSampleData() {
00575 return (pCkData) ? pCkData->LoadChunkData() : NULL;
00576 }
00577
00583 void Sample::ReleaseSampleData() {
00584 if (pCkData) pCkData->ReleaseChunkData();
00585 }
00586
00597 unsigned long Sample::GetSize() {
00598 if (FormatTag != DLS_WAVE_FORMAT_PCM) return 0;
00599 return (pCkData) ? pCkData->GetSize() / FrameSize : 0;
00600 }
00601
00630 void Sample::Resize(int iNewSize) {
00631 if (FormatTag != DLS_WAVE_FORMAT_PCM) throw Exception("Sample's format is not DLS_WAVE_FORMAT_PCM");
00632 if (iNewSize < 1) throw Exception("Sample size must be at least one sample point");
00633 const int iSizeInBytes = iNewSize * FrameSize;
00634 pCkData = pWaveList->GetSubChunk(CHUNK_ID_DATA);
00635 if (pCkData) pCkData->Resize(iSizeInBytes);
00636 else pCkData = pWaveList->AddSubChunk(CHUNK_ID_DATA, iSizeInBytes);
00637 }
00638
00655 unsigned long Sample::SetPos(unsigned long SampleCount, RIFF::stream_whence_t Whence) {
00656 if (FormatTag != DLS_WAVE_FORMAT_PCM) return 0;
00657 if (!pCkData) throw Exception("No data chunk created for sample yet, call Sample::Resize() to create one");
00658 unsigned long orderedBytes = SampleCount * FrameSize;
00659 unsigned long result = pCkData->SetPos(orderedBytes, Whence);
00660 return (result == orderedBytes) ? SampleCount
00661 : result / FrameSize;
00662 }
00663
00673 unsigned long Sample::Read(void* pBuffer, unsigned long SampleCount) {
00674 if (FormatTag != DLS_WAVE_FORMAT_PCM) return 0;
00675 return pCkData->Read(pBuffer, SampleCount, FrameSize);
00676 }
00677
00693 unsigned long Sample::Write(void* pBuffer, unsigned long SampleCount) {
00694 if (FormatTag != DLS_WAVE_FORMAT_PCM) return 0;
00695 if (GetSize() < SampleCount) throw Exception("Could not write sample data, current sample size to small");
00696 return pCkData->Write(pBuffer, SampleCount, FrameSize);
00697 }
00698
00706 void Sample::UpdateChunks() {
00707 if (FormatTag != DLS_WAVE_FORMAT_PCM)
00708 throw Exception("Could not save sample, only PCM format is supported");
00709
00710 if (!pCkData)
00711 throw Exception("Could not save sample, there is no sample data to save");
00712
00713 Resource::UpdateChunks();
00714
00715 RIFF::Chunk* pCkFormat = pWaveList->GetSubChunk(CHUNK_ID_FMT);
00716 if (!pCkFormat) pCkFormat = pWaveList->AddSubChunk(CHUNK_ID_FMT, 16);
00717 uint8_t* pData = (uint8_t*) pCkFormat->LoadChunkData();
00718
00719 memcpy(&pData[0], &FormatTag, 2);
00720 memcpy(&pData[2], &Channels, 2);
00721 memcpy(&pData[4], &SamplesPerSecond, 4);
00722 memcpy(&pData[8], &AverageBytesPerSecond, 4);
00723 memcpy(&pData[12], &BlockAlign, 2);
00724 memcpy(&pData[14], &BitDepth, 2);
00725 }
00726
00727
00728
00729
00730
00731
00732 Region::Region(Instrument* pInstrument, RIFF::List* rgnList) : Resource(pInstrument, rgnList), Articulator(rgnList), Sampler(rgnList) {
00733 pCkRegion = rgnList;
00734
00735
00736 RIFF::Chunk* rgnh = rgnList->GetSubChunk(CHUNK_ID_RGNH);
00737 if (rgnh) {
00738 rgnh->Read(&KeyRange, 2, 2);
00739 rgnh->Read(&VelocityRange, 2, 2);
00740 FormatOptionFlags = rgnh->ReadUint16();
00741 KeyGroup = rgnh->ReadUint16();
00742
00743 if (rgnh->RemainingBytes() >= sizeof(uint16_t)) {
00744 rgnh->Read(&Layer, 1, sizeof(uint16_t));
00745 } else Layer = 0;
00746 } else {
00747 KeyRange.low = 0;
00748 KeyRange.high = 127;
00749 VelocityRange.low = 0;
00750 VelocityRange.high = 127;
00751 FormatOptionFlags = F_RGN_OPTION_SELFNONEXCLUSIVE;
00752 KeyGroup = 0;
00753 Layer = 0;
00754 }
00755 SelfNonExclusive = FormatOptionFlags & F_RGN_OPTION_SELFNONEXCLUSIVE;
00756
00757
00758 RIFF::Chunk* wlnk = rgnList->GetSubChunk(CHUNK_ID_WLNK);
00759 if (wlnk) {
00760 WaveLinkOptionFlags = wlnk->ReadUint16();
00761 PhaseGroup = wlnk->ReadUint16();
00762 Channel = wlnk->ReadUint32();
00763 WavePoolTableIndex = wlnk->ReadUint32();
00764 } else {
00765 WaveLinkOptionFlags = 0;
00766 PhaseGroup = 0;
00767 Channel = 0;
00768 WavePoolTableIndex = 0;
00769 }
00770 PhaseMaster = WaveLinkOptionFlags & F_WAVELINK_PHASE_MASTER;
00771 MultiChannel = WaveLinkOptionFlags & F_WAVELINK_MULTICHANNEL;
00772
00773 pSample = NULL;
00774 }
00775
00780 Region::~Region() {
00781 RIFF::List* pParent = pCkRegion->GetParent();
00782 pParent->DeleteSubChunk(pCkRegion);
00783 }
00784
00785 Sample* Region::GetSample() {
00786 if (pSample) return pSample;
00787 File* file = (File*) GetParent()->GetParent();
00788 unsigned long soughtoffset = file->pWavePoolTable[WavePoolTableIndex];
00789 Sample* sample = file->GetFirstSample();
00790 while (sample) {
00791 if (sample->ulWavePoolOffset == soughtoffset) return (pSample = sample);
00792 sample = file->GetNextSample();
00793 }
00794 return NULL;
00795 }
00796
00802 void Region::SetSample(Sample* pSample) {
00803 this->pSample = pSample;
00804 WavePoolTableIndex = 0;
00805 }
00806
00813 void Region::UpdateChunks() {
00814
00815 RIFF::Chunk* rgnh = pCkRegion->GetSubChunk(CHUNK_ID_RGNH);
00816 if (!rgnh) rgnh = pCkRegion->AddSubChunk(CHUNK_ID_RGNH, Layer ? 14 : 12);
00817 uint8_t* pData = (uint8_t*) rgnh->LoadChunkData();
00818 FormatOptionFlags = (SelfNonExclusive)
00819 ? FormatOptionFlags | F_RGN_OPTION_SELFNONEXCLUSIVE
00820 : FormatOptionFlags & (~F_RGN_OPTION_SELFNONEXCLUSIVE);
00821
00822 memcpy(&pData[0], &KeyRange, 2 * 2);
00823 memcpy(&pData[4], &VelocityRange, 2 * 2);
00824 memcpy(&pData[8], &FormatOptionFlags, 2);
00825 memcpy(&pData[10], &KeyGroup, 2);
00826 if (rgnh->GetSize() >= 14) memcpy(&pData[12], &Layer, 2);
00827
00828
00829
00830 Articulator::UpdateChunks();
00831 Sampler::UpdateChunks();
00832
00833
00834 RIFF::Chunk* wlnk = pCkRegion->GetSubChunk(CHUNK_ID_WLNK);
00835 if (!wlnk) wlnk = pCkRegion->AddSubChunk(CHUNK_ID_WLNK, 12);
00836 pData = (uint8_t*) wlnk->LoadChunkData();
00837 WaveLinkOptionFlags = (PhaseMaster)
00838 ? WaveLinkOptionFlags | F_WAVELINK_PHASE_MASTER
00839 : WaveLinkOptionFlags & (~F_WAVELINK_PHASE_MASTER);
00840 WaveLinkOptionFlags = (MultiChannel)
00841 ? WaveLinkOptionFlags | F_WAVELINK_MULTICHANNEL
00842 : WaveLinkOptionFlags & (~F_WAVELINK_MULTICHANNEL);
00843
00844 int index = -1;
00845 File* pFile = (File*) GetParent()->GetParent();
00846 if (pFile->pSamples) {
00847 File::SampleList::iterator iter = pFile->pSamples->begin();
00848 File::SampleList::iterator end = pFile->pSamples->end();
00849 for (int i = 0; iter != end; ++iter, i++) {
00850 if (*iter == pSample) {
00851 index = i;
00852 break;
00853 }
00854 }
00855 }
00856 if (index < 0) throw Exception("Could not save Region, could not find Region's sample");
00857 WavePoolTableIndex = index;
00858
00859 memcpy(&pData[0], &WaveLinkOptionFlags, 2);
00860 memcpy(&pData[2], &PhaseGroup, 2);
00861 memcpy(&pData[4], &Channel, 4);
00862 memcpy(&pData[8], &WavePoolTableIndex, 4);
00863 }
00864
00865
00866
00867
00868
00869
00883 Instrument::Instrument(File* pFile, RIFF::List* insList) : Resource(pFile, insList), Articulator(insList) {
00884 pCkInstrument = insList;
00885
00886 midi_locale_t locale;
00887 RIFF::Chunk* insh = pCkInstrument->GetSubChunk(CHUNK_ID_INSH);
00888 if (insh) {
00889 Regions = insh->ReadUint32();
00890 insh->Read(&locale, 2, 4);
00891 } else {
00892 Regions = 0;
00893 locale.bank = 0;
00894 locale.instrument = 0;
00895 }
00896
00897 MIDIProgram = locale.instrument;
00898 IsDrum = locale.bank & DRUM_TYPE_MASK;
00899 MIDIBankCoarse = (uint8_t) MIDI_BANK_COARSE(locale.bank);
00900 MIDIBankFine = (uint8_t) MIDI_BANK_FINE(locale.bank);
00901 MIDIBank = MIDI_BANK_MERGE(MIDIBankCoarse, MIDIBankFine);
00902
00903 pRegions = NULL;
00904 }
00905
00906 Region* Instrument::GetFirstRegion() {
00907 if (!pRegions) LoadRegions();
00908 if (!pRegions) return NULL;
00909 RegionsIterator = pRegions->begin();
00910 return (RegionsIterator != pRegions->end()) ? *RegionsIterator : NULL;
00911 }
00912
00913 Region* Instrument::GetNextRegion() {
00914 if (!pRegions) return NULL;
00915 RegionsIterator++;
00916 return (RegionsIterator != pRegions->end()) ? *RegionsIterator : NULL;
00917 }
00918
00919 void Instrument::LoadRegions() {
00920 if (!pRegions) pRegions = new RegionList;
00921 RIFF::List* lrgn = pCkInstrument->GetSubList(LIST_TYPE_LRGN);
00922 if (lrgn) {
00923 uint32_t regionCkType = (lrgn->GetSubList(LIST_TYPE_RGN2)) ? LIST_TYPE_RGN2 : LIST_TYPE_RGN;
00924 RIFF::List* rgn = lrgn->GetFirstSubList();
00925 while (rgn) {
00926 if (rgn->GetListType() == regionCkType) {
00927 pRegions->push_back(new Region(this, rgn));
00928 }
00929 rgn = lrgn->GetNextSubList();
00930 }
00931 }
00932 }
00933
00934 Region* Instrument::AddRegion() {
00935 if (!pRegions) LoadRegions();
00936 RIFF::List* lrgn = pCkInstrument->GetSubList(LIST_TYPE_LRGN);
00937 if (!lrgn) lrgn = pCkInstrument->AddSubList(LIST_TYPE_LRGN);
00938 RIFF::List* rgn = lrgn->AddSubList(LIST_TYPE_RGN);
00939 Region* pNewRegion = new Region(this, rgn);
00940 pRegions->push_back(pNewRegion);
00941 Regions = pRegions->size();
00942 return pNewRegion;
00943 }
00944
00945 void Instrument::MoveRegion(Region* pSrc, Region* pDst) {
00946 RIFF::List* lrgn = pCkInstrument->GetSubList(LIST_TYPE_LRGN);
00947 lrgn->MoveSubChunk(pSrc->pCkRegion, pDst ? pDst->pCkRegion : 0);
00948
00949 pRegions->remove(pSrc);
00950 RegionList::iterator iter = find(pRegions->begin(), pRegions->end(), pDst);
00951 pRegions->insert(iter, pSrc);
00952 }
00953
00954 void Instrument::DeleteRegion(Region* pRegion) {
00955 if (!pRegions) return;
00956 RegionList::iterator iter = find(pRegions->begin(), pRegions->end(), pRegion);
00957 if (iter == pRegions->end()) return;
00958 pRegions->erase(iter);
00959 Regions = pRegions->size();
00960 delete pRegion;
00961 }
00962
00969 void Instrument::UpdateChunks() {
00970
00971 Resource::UpdateChunks();
00972 Articulator::UpdateChunks();
00973
00974 RIFF::Chunk* insh = pCkInstrument->GetSubChunk(CHUNK_ID_INSH);
00975 if (!insh) insh = pCkInstrument->AddSubChunk(CHUNK_ID_INSH, 12);
00976 uint8_t* pData = (uint8_t*) insh->LoadChunkData();
00977
00978 Regions = (pRegions) ? pRegions->size() : 0;
00979 midi_locale_t locale;
00980 locale.instrument = MIDIProgram;
00981 locale.bank = MIDI_BANK_ENCODE(MIDIBankCoarse, MIDIBankFine);
00982 locale.bank = (IsDrum) ? locale.bank | DRUM_TYPE_MASK : locale.bank & (~DRUM_TYPE_MASK);
00983 MIDIBank = MIDI_BANK_MERGE(MIDIBankCoarse, MIDIBankFine);
00984 memcpy(&pData[0], &Regions, 4);
00985 memcpy(&pData[4], &locale, 2 * 4);
00986
00987 if (!pRegions) return;
00988 RegionList::iterator iter = pRegions->begin();
00989 RegionList::iterator end = pRegions->end();
00990 for (; iter != end; ++iter) {
00991 (*iter)->UpdateChunks();
00992 }
00993 }
00994
01000 Instrument::~Instrument() {
01001 if (pRegions) {
01002 RegionList::iterator iter = pRegions->begin();
01003 RegionList::iterator end = pRegions->end();
01004 while (iter != end) {
01005 delete *iter;
01006 iter++;
01007 }
01008 delete pRegions;
01009 }
01010
01011 RIFF::List* pParent = pCkInstrument->GetParent();
01012 pParent->DeleteSubChunk(pCkInstrument);
01013 }
01014
01015
01016
01017
01018
01019
01026 File::File() : Resource(NULL, pRIFF = new RIFF::File(RIFF_TYPE_DLS)) {
01027 pVersion = new version_t;
01028 pVersion->major = 0;
01029 pVersion->minor = 0;
01030 pVersion->release = 0;
01031 pVersion->build = 0;
01032
01033 Instruments = 0;
01034 WavePoolCount = 0;
01035 pWavePoolTable = NULL;
01036 pWavePoolTableHi = NULL;
01037 WavePoolHeaderSize = 8;
01038
01039 pSamples = NULL;
01040 pInstruments = NULL;
01041
01042 b64BitWavePoolOffsets = false;
01043 }
01044
01054 File::File(RIFF::File* pRIFF) : Resource(NULL, pRIFF) {
01055 if (!pRIFF) throw DLS::Exception("NULL pointer reference to RIFF::File object.");
01056 this->pRIFF = pRIFF;
01057
01058 RIFF::Chunk* ckVersion = pRIFF->GetSubChunk(CHUNK_ID_VERS);
01059 if (ckVersion) {
01060 pVersion = new version_t;
01061 ckVersion->Read(pVersion, 4, 2);
01062 }
01063 else pVersion = NULL;
01064
01065 RIFF::Chunk* colh = pRIFF->GetSubChunk(CHUNK_ID_COLH);
01066 if (!colh) throw DLS::Exception("Mandatory chunks in RIFF list chunk not found.");
01067 Instruments = colh->ReadUint32();
01068
01069 RIFF::Chunk* ptbl = pRIFF->GetSubChunk(CHUNK_ID_PTBL);
01070 if (!ptbl) {
01071 WavePoolCount = 0;
01072 pWavePoolTable = NULL;
01073 pWavePoolTableHi = NULL;
01074 WavePoolHeaderSize = 8;
01075 b64BitWavePoolOffsets = false;
01076 } else {
01077 WavePoolHeaderSize = ptbl->ReadUint32();
01078 WavePoolCount = ptbl->ReadUint32();
01079 pWavePoolTable = new uint32_t[WavePoolCount];
01080 pWavePoolTableHi = new uint32_t[WavePoolCount];
01081 ptbl->SetPos(WavePoolHeaderSize);
01082
01083
01084 b64BitWavePoolOffsets = (ptbl->GetSize() - WavePoolHeaderSize == WavePoolCount * 8);
01085 if (b64BitWavePoolOffsets) {
01086 for (int i = 0 ; i < WavePoolCount ; i++) {
01087 pWavePoolTableHi[i] = ptbl->ReadUint32();
01088 pWavePoolTable[i] = ptbl->ReadUint32();
01089 if (pWavePoolTable[i] & 0x80000000)
01090 throw DLS::Exception("Files larger than 2 GB not yet supported");
01091 }
01092 } else {
01093 ptbl->Read(pWavePoolTable, WavePoolCount, sizeof(uint32_t));
01094 for (int i = 0 ; i < WavePoolCount ; i++) pWavePoolTableHi[i] = 0;
01095 }
01096 }
01097
01098 pSamples = NULL;
01099 pInstruments = NULL;
01100 }
01101
01102 File::~File() {
01103 if (pInstruments) {
01104 InstrumentList::iterator iter = pInstruments->begin();
01105 InstrumentList::iterator end = pInstruments->end();
01106 while (iter != end) {
01107 delete *iter;
01108 iter++;
01109 }
01110 delete pInstruments;
01111 }
01112
01113 if (pSamples) {
01114 SampleList::iterator iter = pSamples->begin();
01115 SampleList::iterator end = pSamples->end();
01116 while (iter != end) {
01117 delete *iter;
01118 iter++;
01119 }
01120 delete pSamples;
01121 }
01122
01123 if (pWavePoolTable) delete[] pWavePoolTable;
01124 if (pWavePoolTableHi) delete[] pWavePoolTableHi;
01125 if (pVersion) delete pVersion;
01126 for (std::list<RIFF::File*>::iterator i = ExtensionFiles.begin() ; i != ExtensionFiles.end() ; i++)
01127 delete *i;
01128 }
01129
01130 Sample* File::GetFirstSample() {
01131 if (!pSamples) LoadSamples();
01132 if (!pSamples) return NULL;
01133 SamplesIterator = pSamples->begin();
01134 return (SamplesIterator != pSamples->end()) ? *SamplesIterator : NULL;
01135 }
01136
01137 Sample* File::GetNextSample() {
01138 if (!pSamples) return NULL;
01139 SamplesIterator++;
01140 return (SamplesIterator != pSamples->end()) ? *SamplesIterator : NULL;
01141 }
01142
01143 void File::LoadSamples() {
01144 if (!pSamples) pSamples = new SampleList;
01145 RIFF::List* wvpl = pRIFF->GetSubList(LIST_TYPE_WVPL);
01146 if (wvpl) {
01147 unsigned long wvplFileOffset = wvpl->GetFilePos();
01148 RIFF::List* wave = wvpl->GetFirstSubList();
01149 while (wave) {
01150 if (wave->GetListType() == LIST_TYPE_WAVE) {
01151 unsigned long waveFileOffset = wave->GetFilePos();
01152 pSamples->push_back(new Sample(this, wave, waveFileOffset - wvplFileOffset));
01153 }
01154 wave = wvpl->GetNextSubList();
01155 }
01156 }
01157 else {
01158 RIFF::List* dwpl = pRIFF->GetSubList(LIST_TYPE_DWPL);
01159 if (dwpl) {
01160 unsigned long dwplFileOffset = dwpl->GetFilePos();
01161 RIFF::List* wave = dwpl->GetFirstSubList();
01162 while (wave) {
01163 if (wave->GetListType() == LIST_TYPE_WAVE) {
01164 unsigned long waveFileOffset = wave->GetFilePos();
01165 pSamples->push_back(new Sample(this, wave, waveFileOffset - dwplFileOffset));
01166 }
01167 wave = dwpl->GetNextSubList();
01168 }
01169 }
01170 }
01171 }
01172
01180 Sample* File::AddSample() {
01181 if (!pSamples) LoadSamples();
01182 __ensureMandatoryChunksExist();
01183 RIFF::List* wvpl = pRIFF->GetSubList(LIST_TYPE_WVPL);
01184
01185 RIFF::List* wave = wvpl->AddSubList(LIST_TYPE_WAVE);
01186 Sample* pSample = new Sample(this, wave, 0 );
01187 pSamples->push_back(pSample);
01188 return pSample;
01189 }
01190
01198 void File::DeleteSample(Sample* pSample) {
01199 if (!pSamples) return;
01200 SampleList::iterator iter = find(pSamples->begin(), pSamples->end(), pSample);
01201 if (iter == pSamples->end()) return;
01202 pSamples->erase(iter);
01203 delete pSample;
01204 }
01205
01206 Instrument* File::GetFirstInstrument() {
01207 if (!pInstruments) LoadInstruments();
01208 if (!pInstruments) return NULL;
01209 InstrumentsIterator = pInstruments->begin();
01210 return (InstrumentsIterator != pInstruments->end()) ? *InstrumentsIterator : NULL;
01211 }
01212
01213 Instrument* File::GetNextInstrument() {
01214 if (!pInstruments) return NULL;
01215 InstrumentsIterator++;
01216 return (InstrumentsIterator != pInstruments->end()) ? *InstrumentsIterator : NULL;
01217 }
01218
01219 void File::LoadInstruments() {
01220 if (!pInstruments) pInstruments = new InstrumentList;
01221 RIFF::List* lstInstruments = pRIFF->GetSubList(LIST_TYPE_LINS);
01222 if (lstInstruments) {
01223 RIFF::List* lstInstr = lstInstruments->GetFirstSubList();
01224 while (lstInstr) {
01225 if (lstInstr->GetListType() == LIST_TYPE_INS) {
01226 pInstruments->push_back(new Instrument(this, lstInstr));
01227 }
01228 lstInstr = lstInstruments->GetNextSubList();
01229 }
01230 }
01231 }
01232
01240 Instrument* File::AddInstrument() {
01241 if (!pInstruments) LoadInstruments();
01242 __ensureMandatoryChunksExist();
01243 RIFF::List* lstInstruments = pRIFF->GetSubList(LIST_TYPE_LINS);
01244 RIFF::List* lstInstr = lstInstruments->AddSubList(LIST_TYPE_INS);
01245 Instrument* pInstrument = new Instrument(this, lstInstr);
01246 pInstruments->push_back(pInstrument);
01247 return pInstrument;
01248 }
01249
01257 void File::DeleteInstrument(Instrument* pInstrument) {
01258 if (!pInstruments) return;
01259 InstrumentList::iterator iter = find(pInstruments->begin(), pInstruments->end(), pInstrument);
01260 if (iter == pInstruments->end()) return;
01261 pInstruments->erase(iter);
01262 delete pInstrument;
01263 }
01264
01272 void File::UpdateChunks() {
01273
01274 Resource::UpdateChunks();
01275
01276
01277 if (pVersion) {
01278 RIFF::Chunk* ckVersion = pRIFF->GetSubChunk(CHUNK_ID_VERS);
01279 if (!ckVersion) ckVersion = pRIFF->AddSubChunk(CHUNK_ID_VERS, 8);
01280 uint8_t* pData = (uint8_t*) ckVersion->LoadChunkData();
01281 memcpy(pData, pVersion, 2 * 4);
01282 }
01283
01284
01285 Instruments = (pInstruments) ? pInstruments->size() : 0;
01286 RIFF::Chunk* colh = pRIFF->GetSubChunk(CHUNK_ID_COLH);
01287 if (!colh) colh = pRIFF->AddSubChunk(CHUNK_ID_COLH, 4);
01288 uint8_t* pData = (uint8_t*) colh->LoadChunkData();
01289 memcpy(pData, &Instruments, 4);
01290
01291
01292 if (pInstruments) {
01293 InstrumentList::iterator iter = pInstruments->begin();
01294 InstrumentList::iterator end = pInstruments->end();
01295 for (; iter != end; ++iter) {
01296 (*iter)->UpdateChunks();
01297 }
01298 }
01299
01300
01301 const int iSamples = (pSamples) ? pSamples->size() : 0;
01302 const int iPtblOffsetSize = (b64BitWavePoolOffsets) ? 8 : 4;
01303 RIFF::Chunk* ptbl = pRIFF->GetSubChunk(CHUNK_ID_PTBL);
01304 if (!ptbl) ptbl = pRIFF->AddSubChunk(CHUNK_ID_PTBL, 1 );
01305 const int iPtblSize = WavePoolHeaderSize + iPtblOffsetSize * iSamples;
01306 ptbl->Resize(iPtblSize);
01307 pData = (uint8_t*) ptbl->LoadChunkData();
01308 WavePoolCount = iSamples;
01309 memcpy(&pData[4], &WavePoolCount, 4);
01310
01311 memset(&pData[WavePoolHeaderSize], 0, iPtblSize - WavePoolHeaderSize);
01312
01313
01314 if (pSamples) {
01315 SampleList::iterator iter = pSamples->begin();
01316 SampleList::iterator end = pSamples->end();
01317 for (; iter != end; ++iter) {
01318 (*iter)->UpdateChunks();
01319 }
01320 }
01321 }
01322
01336 void File::Save(const String& Path) {
01337 UpdateChunks();
01338 pRIFF->Save(Path);
01339 __UpdateWavePoolTableChunk();
01340 }
01341
01351 void File::Save() {
01352 UpdateChunks();
01353 pRIFF->Save();
01354 __UpdateWavePoolTableChunk();
01355 }
01356
01362 void File::__ensureMandatoryChunksExist() {
01363
01364 RIFF::List* lstInstruments = pRIFF->GetSubList(LIST_TYPE_LINS);
01365 if (!lstInstruments) pRIFF->AddSubList(LIST_TYPE_LINS);
01366
01367 RIFF::Chunk* ptbl = pRIFF->GetSubChunk(CHUNK_ID_PTBL);
01368 if (!ptbl) {
01369 const int iOffsetSize = (b64BitWavePoolOffsets) ? 8 : 4;
01370 ptbl = pRIFF->AddSubChunk(CHUNK_ID_PTBL, WavePoolHeaderSize + iOffsetSize);
01371 }
01372
01373 RIFF::List* wvpl = pRIFF->GetSubList(LIST_TYPE_WVPL);
01374 if (!wvpl) pRIFF->AddSubList(LIST_TYPE_WVPL);
01375 }
01376
01386 void File::__UpdateWavePoolTableChunk() {
01387 __UpdateWavePoolTable();
01388 RIFF::Chunk* ptbl = pRIFF->GetSubChunk(CHUNK_ID_PTBL);
01389 const int iOffsetSize = (b64BitWavePoolOffsets) ? 8 : 4;
01390
01391 WavePoolCount = (pSamples) ? pSamples->size() : 0;
01392 const unsigned long ulRequiredSize = WavePoolHeaderSize + iOffsetSize * WavePoolCount;
01393 if (ptbl->GetSize() < ulRequiredSize) throw Exception("Fatal error, 'ptbl' chunk too small");
01394
01395 unsigned long ulOriginalPos = ptbl->GetPos();
01396
01397 ptbl->SetPos(0);
01398 ptbl->WriteUint32(&WavePoolHeaderSize);
01399 ptbl->WriteUint32(&WavePoolCount);
01400
01401 ptbl->SetPos(WavePoolHeaderSize);
01402 if (b64BitWavePoolOffsets) {
01403 for (int i = 0 ; i < WavePoolCount ; i++) {
01404 ptbl->WriteUint32(&pWavePoolTableHi[i]);
01405 ptbl->WriteUint32(&pWavePoolTable[i]);
01406 }
01407 } else {
01408 for (int i = 0 ; i < WavePoolCount ; i++)
01409 ptbl->WriteUint32(&pWavePoolTable[i]);
01410 }
01411
01412 ptbl->SetPos(ulOriginalPos);
01413 }
01414
01420 void File::__UpdateWavePoolTable() {
01421 WavePoolCount = (pSamples) ? pSamples->size() : 0;
01422
01423 if (pWavePoolTable) delete[] pWavePoolTable;
01424 if (pWavePoolTableHi) delete[] pWavePoolTableHi;
01425 pWavePoolTable = new uint32_t[WavePoolCount];
01426 pWavePoolTableHi = new uint32_t[WavePoolCount];
01427 if (!pSamples) return;
01428
01429 RIFF::List* wvpl = pRIFF->GetSubList(LIST_TYPE_WVPL);
01430 uint64_t wvplFileOffset = wvpl->GetFilePos();
01431 if (b64BitWavePoolOffsets) {
01432 SampleList::iterator iter = pSamples->begin();
01433 SampleList::iterator end = pSamples->end();
01434 for (int i = 0 ; iter != end ; ++iter, i++) {
01435 uint64_t _64BitOffset = (*iter)->pWaveList->GetFilePos() - wvplFileOffset - LIST_HEADER_SIZE;
01436 (*iter)->ulWavePoolOffset = _64BitOffset;
01437 pWavePoolTableHi[i] = (uint32_t) (_64BitOffset >> 32);
01438 pWavePoolTable[i] = (uint32_t) _64BitOffset;
01439 }
01440 } else {
01441 SampleList::iterator iter = pSamples->begin();
01442 SampleList::iterator end = pSamples->end();
01443 for (int i = 0 ; iter != end ; ++iter, i++) {
01444 uint64_t _64BitOffset = (*iter)->pWaveList->GetFilePos() - wvplFileOffset - LIST_HEADER_SIZE;
01445 (*iter)->ulWavePoolOffset = _64BitOffset;
01446 pWavePoolTable[i] = (uint32_t) _64BitOffset;
01447 }
01448 }
01449 }
01450
01451
01452
01453
01454
01455
01456 Exception::Exception(String Message) : RIFF::Exception(Message) {
01457 }
01458
01459 void Exception::PrintMessage() {
01460 std::cout << "DLS::Exception: " << Message << std::endl;
01461 }
01462
01463
01464
01465
01466
01472 String libraryName() {
01473 return PACKAGE;
01474 }
01475
01480 String libraryVersion() {
01481 return VERSION;
01482 }
01483
01484 }