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() : Software.length()) : 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 == 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 = 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 == 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 != WAVE_FORMAT_PCM) return 0;
00599 return (pCkData) ? pCkData->GetSize() / FrameSize : 0;
00600 }
00601
00630 void Sample::Resize(int iNewSize) {
00631 if (FormatTag != WAVE_FORMAT_PCM) throw Exception("Sample's format is not 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 != 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 != 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 != 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 != 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::DeleteRegion(Region* pRegion) {
00946 if (!pRegions) return;
00947 RegionList::iterator iter = find(pRegions->begin(), pRegions->end(), pRegion);
00948 if (iter == pRegions->end()) return;
00949 pRegions->erase(iter);
00950 Regions = pRegions->size();
00951 delete pRegion;
00952 }
00953
00960 void Instrument::UpdateChunks() {
00961
00962 Resource::UpdateChunks();
00963 Articulator::UpdateChunks();
00964
00965 RIFF::Chunk* insh = pCkInstrument->GetSubChunk(CHUNK_ID_INSH);
00966 if (!insh) insh = pCkInstrument->AddSubChunk(CHUNK_ID_INSH, 12);
00967 uint8_t* pData = (uint8_t*) insh->LoadChunkData();
00968
00969 Regions = (pRegions) ? pRegions->size() : 0;
00970 midi_locale_t locale;
00971 locale.instrument = MIDIProgram;
00972 locale.bank = MIDI_BANK_ENCODE(MIDIBankCoarse, MIDIBankFine);
00973 locale.bank = (IsDrum) ? locale.bank | DRUM_TYPE_MASK : locale.bank & (~DRUM_TYPE_MASK);
00974 MIDIBank = MIDI_BANK_MERGE(MIDIBankCoarse, MIDIBankFine);
00975 memcpy(&pData[0], &Regions, 4);
00976 memcpy(&pData[4], &locale, 2 * 4);
00977
00978 if (!pRegions) return;
00979 RegionList::iterator iter = pRegions->begin();
00980 RegionList::iterator end = pRegions->end();
00981 for (; iter != end; ++iter) {
00982 (*iter)->UpdateChunks();
00983 }
00984 }
00985
00991 Instrument::~Instrument() {
00992 if (pRegions) {
00993 RegionList::iterator iter = pRegions->begin();
00994 RegionList::iterator end = pRegions->end();
00995 while (iter != end) {
00996 delete *iter;
00997 iter++;
00998 }
00999 delete pRegions;
01000 }
01001
01002 RIFF::List* pParent = pCkInstrument->GetParent();
01003 pParent->DeleteSubChunk(pCkInstrument);
01004 }
01005
01006
01007
01008
01009
01010
01017 File::File() : Resource(NULL, pRIFF = new RIFF::File(RIFF_TYPE_DLS)) {
01018 pVersion = new version_t;
01019 pVersion->major = 0;
01020 pVersion->minor = 0;
01021 pVersion->release = 0;
01022 pVersion->build = 0;
01023
01024 Instruments = 0;
01025 WavePoolCount = 0;
01026 pWavePoolTable = NULL;
01027 pWavePoolTableHi = NULL;
01028 WavePoolHeaderSize = 8;
01029
01030 pSamples = NULL;
01031 pInstruments = NULL;
01032
01033 b64BitWavePoolOffsets = false;
01034 }
01035
01045 File::File(RIFF::File* pRIFF) : Resource(NULL, pRIFF) {
01046 if (!pRIFF) throw DLS::Exception("NULL pointer reference to RIFF::File object.");
01047 this->pRIFF = pRIFF;
01048
01049 RIFF::Chunk* ckVersion = pRIFF->GetSubChunk(CHUNK_ID_VERS);
01050 if (ckVersion) {
01051 pVersion = new version_t;
01052 ckVersion->Read(pVersion, 4, 2);
01053 }
01054 else pVersion = NULL;
01055
01056 RIFF::Chunk* colh = pRIFF->GetSubChunk(CHUNK_ID_COLH);
01057 if (!colh) throw DLS::Exception("Mandatory chunks in RIFF list chunk not found.");
01058 Instruments = colh->ReadUint32();
01059
01060 RIFF::Chunk* ptbl = pRIFF->GetSubChunk(CHUNK_ID_PTBL);
01061 if (!ptbl) {
01062 WavePoolCount = 0;
01063 pWavePoolTable = NULL;
01064 pWavePoolTableHi = NULL;
01065 WavePoolHeaderSize = 8;
01066 b64BitWavePoolOffsets = false;
01067 } else {
01068 WavePoolHeaderSize = ptbl->ReadUint32();
01069 WavePoolCount = ptbl->ReadUint32();
01070 pWavePoolTable = new uint32_t[WavePoolCount];
01071 pWavePoolTableHi = new uint32_t[WavePoolCount];
01072 ptbl->SetPos(WavePoolHeaderSize);
01073
01074
01075 b64BitWavePoolOffsets = (ptbl->GetSize() - WavePoolHeaderSize == WavePoolCount * 8);
01076 if (b64BitWavePoolOffsets) {
01077 for (int i = 0 ; i < WavePoolCount ; i++) {
01078 pWavePoolTableHi[i] = ptbl->ReadUint32();
01079 pWavePoolTable[i] = ptbl->ReadUint32();
01080 if (pWavePoolTable[i] & 0x80000000)
01081 throw DLS::Exception("Files larger than 2 GB not yet supported");
01082 }
01083 } else {
01084 ptbl->Read(pWavePoolTable, WavePoolCount, sizeof(uint32_t));
01085 for (int i = 0 ; i < WavePoolCount ; i++) pWavePoolTableHi[i] = 0;
01086 }
01087 }
01088
01089 pSamples = NULL;
01090 pInstruments = NULL;
01091 }
01092
01093 File::~File() {
01094 if (pInstruments) {
01095 InstrumentList::iterator iter = pInstruments->begin();
01096 InstrumentList::iterator end = pInstruments->end();
01097 while (iter != end) {
01098 delete *iter;
01099 iter++;
01100 }
01101 delete pInstruments;
01102 }
01103
01104 if (pSamples) {
01105 SampleList::iterator iter = pSamples->begin();
01106 SampleList::iterator end = pSamples->end();
01107 while (iter != end) {
01108 delete *iter;
01109 iter++;
01110 }
01111 delete pSamples;
01112 }
01113
01114 if (pWavePoolTable) delete[] pWavePoolTable;
01115 if (pWavePoolTableHi) delete[] pWavePoolTableHi;
01116 if (pVersion) delete pVersion;
01117 for (std::list<RIFF::File*>::iterator i = ExtensionFiles.begin() ; i != ExtensionFiles.end() ; i++)
01118 delete *i;
01119 }
01120
01121 Sample* File::GetFirstSample() {
01122 if (!pSamples) LoadSamples();
01123 if (!pSamples) return NULL;
01124 SamplesIterator = pSamples->begin();
01125 return (SamplesIterator != pSamples->end()) ? *SamplesIterator : NULL;
01126 }
01127
01128 Sample* File::GetNextSample() {
01129 if (!pSamples) return NULL;
01130 SamplesIterator++;
01131 return (SamplesIterator != pSamples->end()) ? *SamplesIterator : NULL;
01132 }
01133
01134 void File::LoadSamples() {
01135 if (!pSamples) pSamples = new SampleList;
01136 RIFF::List* wvpl = pRIFF->GetSubList(LIST_TYPE_WVPL);
01137 if (wvpl) {
01138 unsigned long wvplFileOffset = wvpl->GetFilePos();
01139 RIFF::List* wave = wvpl->GetFirstSubList();
01140 while (wave) {
01141 if (wave->GetListType() == LIST_TYPE_WAVE) {
01142 unsigned long waveFileOffset = wave->GetFilePos();
01143 pSamples->push_back(new Sample(this, wave, waveFileOffset - wvplFileOffset));
01144 }
01145 wave = wvpl->GetNextSubList();
01146 }
01147 }
01148 else {
01149 RIFF::List* dwpl = pRIFF->GetSubList(LIST_TYPE_DWPL);
01150 if (dwpl) {
01151 unsigned long dwplFileOffset = dwpl->GetFilePos();
01152 RIFF::List* wave = dwpl->GetFirstSubList();
01153 while (wave) {
01154 if (wave->GetListType() == LIST_TYPE_WAVE) {
01155 unsigned long waveFileOffset = wave->GetFilePos();
01156 pSamples->push_back(new Sample(this, wave, waveFileOffset - dwplFileOffset));
01157 }
01158 wave = dwpl->GetNextSubList();
01159 }
01160 }
01161 }
01162 }
01163
01171 Sample* File::AddSample() {
01172 if (!pSamples) LoadSamples();
01173 __ensureMandatoryChunksExist();
01174 RIFF::List* wvpl = pRIFF->GetSubList(LIST_TYPE_WVPL);
01175
01176 RIFF::List* wave = wvpl->AddSubList(LIST_TYPE_WAVE);
01177 Sample* pSample = new Sample(this, wave, 0 );
01178 pSamples->push_back(pSample);
01179 return pSample;
01180 }
01181
01189 void File::DeleteSample(Sample* pSample) {
01190 if (!pSamples) return;
01191 SampleList::iterator iter = find(pSamples->begin(), pSamples->end(), pSample);
01192 if (iter == pSamples->end()) return;
01193 pSamples->erase(iter);
01194 delete pSample;
01195 }
01196
01197 Instrument* File::GetFirstInstrument() {
01198 if (!pInstruments) LoadInstruments();
01199 if (!pInstruments) return NULL;
01200 InstrumentsIterator = pInstruments->begin();
01201 return (InstrumentsIterator != pInstruments->end()) ? *InstrumentsIterator : NULL;
01202 }
01203
01204 Instrument* File::GetNextInstrument() {
01205 if (!pInstruments) return NULL;
01206 InstrumentsIterator++;
01207 return (InstrumentsIterator != pInstruments->end()) ? *InstrumentsIterator : NULL;
01208 }
01209
01210 void File::LoadInstruments() {
01211 if (!pInstruments) pInstruments = new InstrumentList;
01212 RIFF::List* lstInstruments = pRIFF->GetSubList(LIST_TYPE_LINS);
01213 if (lstInstruments) {
01214 RIFF::List* lstInstr = lstInstruments->GetFirstSubList();
01215 while (lstInstr) {
01216 if (lstInstr->GetListType() == LIST_TYPE_INS) {
01217 pInstruments->push_back(new Instrument(this, lstInstr));
01218 }
01219 lstInstr = lstInstruments->GetNextSubList();
01220 }
01221 }
01222 }
01223
01231 Instrument* File::AddInstrument() {
01232 if (!pInstruments) LoadInstruments();
01233 __ensureMandatoryChunksExist();
01234 RIFF::List* lstInstruments = pRIFF->GetSubList(LIST_TYPE_LINS);
01235 RIFF::List* lstInstr = lstInstruments->AddSubList(LIST_TYPE_INS);
01236 Instrument* pInstrument = new Instrument(this, lstInstr);
01237 pInstruments->push_back(pInstrument);
01238 return pInstrument;
01239 }
01240
01248 void File::DeleteInstrument(Instrument* pInstrument) {
01249 if (!pInstruments) return;
01250 InstrumentList::iterator iter = find(pInstruments->begin(), pInstruments->end(), pInstrument);
01251 if (iter == pInstruments->end()) return;
01252 pInstruments->erase(iter);
01253 delete pInstrument;
01254 }
01255
01263 void File::UpdateChunks() {
01264
01265 Resource::UpdateChunks();
01266
01267
01268 if (pVersion) {
01269 RIFF::Chunk* ckVersion = pRIFF->GetSubChunk(CHUNK_ID_VERS);
01270 if (!ckVersion) ckVersion = pRIFF->AddSubChunk(CHUNK_ID_VERS, 8);
01271 uint8_t* pData = (uint8_t*) ckVersion->LoadChunkData();
01272 memcpy(pData, pVersion, 2 * 4);
01273 }
01274
01275
01276 Instruments = (pInstruments) ? pInstruments->size() : 0;
01277 RIFF::Chunk* colh = pRIFF->GetSubChunk(CHUNK_ID_COLH);
01278 if (!colh) colh = pRIFF->AddSubChunk(CHUNK_ID_COLH, 4);
01279 uint8_t* pData = (uint8_t*) colh->LoadChunkData();
01280 memcpy(pData, &Instruments, 4);
01281
01282
01283 if (pInstruments) {
01284 InstrumentList::iterator iter = pInstruments->begin();
01285 InstrumentList::iterator end = pInstruments->end();
01286 for (; iter != end; ++iter) {
01287 (*iter)->UpdateChunks();
01288 }
01289 }
01290
01291
01292 const int iSamples = (pSamples) ? pSamples->size() : 0;
01293 const int iPtblOffsetSize = (b64BitWavePoolOffsets) ? 8 : 4;
01294 RIFF::Chunk* ptbl = pRIFF->GetSubChunk(CHUNK_ID_PTBL);
01295 if (!ptbl) ptbl = pRIFF->AddSubChunk(CHUNK_ID_PTBL, 1 );
01296 const int iPtblSize = WavePoolHeaderSize + iPtblOffsetSize * iSamples;
01297 ptbl->Resize(iPtblSize);
01298 pData = (uint8_t*) ptbl->LoadChunkData();
01299 WavePoolCount = iSamples;
01300 memcpy(&pData[4], &WavePoolCount, 4);
01301
01302 memset(&pData[WavePoolHeaderSize], 0, iPtblSize - WavePoolHeaderSize);
01303
01304
01305 if (pSamples) {
01306 SampleList::iterator iter = pSamples->begin();
01307 SampleList::iterator end = pSamples->end();
01308 for (; iter != end; ++iter) {
01309 (*iter)->UpdateChunks();
01310 }
01311 }
01312 }
01313
01327 void File::Save(const String& Path) {
01328 UpdateChunks();
01329 pRIFF->Save(Path);
01330 __UpdateWavePoolTableChunk();
01331 }
01332
01342 void File::Save() {
01343 UpdateChunks();
01344 pRIFF->Save();
01345 __UpdateWavePoolTableChunk();
01346 }
01347
01353 void File::__ensureMandatoryChunksExist() {
01354
01355 RIFF::List* lstInstruments = pRIFF->GetSubList(LIST_TYPE_LINS);
01356 if (!lstInstruments) pRIFF->AddSubList(LIST_TYPE_LINS);
01357
01358 RIFF::Chunk* ptbl = pRIFF->GetSubChunk(CHUNK_ID_PTBL);
01359 if (!ptbl) {
01360 const int iOffsetSize = (b64BitWavePoolOffsets) ? 8 : 4;
01361 ptbl = pRIFF->AddSubChunk(CHUNK_ID_PTBL, WavePoolHeaderSize + iOffsetSize);
01362 }
01363
01364 RIFF::List* wvpl = pRIFF->GetSubList(LIST_TYPE_WVPL);
01365 if (!wvpl) pRIFF->AddSubList(LIST_TYPE_WVPL);
01366 }
01367
01377 void File::__UpdateWavePoolTableChunk() {
01378 __UpdateWavePoolTable();
01379 RIFF::Chunk* ptbl = pRIFF->GetSubChunk(CHUNK_ID_PTBL);
01380 const int iOffsetSize = (b64BitWavePoolOffsets) ? 8 : 4;
01381
01382 WavePoolCount = (pSamples) ? pSamples->size() : 0;
01383 const unsigned long ulRequiredSize = WavePoolHeaderSize + iOffsetSize * WavePoolCount;
01384 if (ptbl->GetSize() < ulRequiredSize) throw Exception("Fatal error, 'ptbl' chunk too small");
01385
01386 unsigned long ulOriginalPos = ptbl->GetPos();
01387
01388 ptbl->SetPos(0);
01389 ptbl->WriteUint32(&WavePoolHeaderSize);
01390 ptbl->WriteUint32(&WavePoolCount);
01391
01392 ptbl->SetPos(WavePoolHeaderSize);
01393 if (b64BitWavePoolOffsets) {
01394 for (int i = 0 ; i < WavePoolCount ; i++) {
01395 ptbl->WriteUint32(&pWavePoolTableHi[i]);
01396 ptbl->WriteUint32(&pWavePoolTable[i]);
01397 }
01398 } else {
01399 for (int i = 0 ; i < WavePoolCount ; i++)
01400 ptbl->WriteUint32(&pWavePoolTable[i]);
01401 }
01402
01403 ptbl->SetPos(ulOriginalPos);
01404 }
01405
01411 void File::__UpdateWavePoolTable() {
01412 WavePoolCount = (pSamples) ? pSamples->size() : 0;
01413
01414 if (pWavePoolTable) delete[] pWavePoolTable;
01415 if (pWavePoolTableHi) delete[] pWavePoolTableHi;
01416 pWavePoolTable = new uint32_t[WavePoolCount];
01417 pWavePoolTableHi = new uint32_t[WavePoolCount];
01418 if (!pSamples) return;
01419
01420 RIFF::List* wvpl = pRIFF->GetSubList(LIST_TYPE_WVPL);
01421 uint64_t wvplFileOffset = wvpl->GetFilePos();
01422 if (b64BitWavePoolOffsets) {
01423 SampleList::iterator iter = pSamples->begin();
01424 SampleList::iterator end = pSamples->end();
01425 for (int i = 0 ; iter != end ; ++iter, i++) {
01426 uint64_t _64BitOffset = (*iter)->pWaveList->GetFilePos() - wvplFileOffset - LIST_HEADER_SIZE;
01427 (*iter)->ulWavePoolOffset = _64BitOffset;
01428 pWavePoolTableHi[i] = (uint32_t) (_64BitOffset >> 32);
01429 pWavePoolTable[i] = (uint32_t) _64BitOffset;
01430 }
01431 } else {
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 pWavePoolTable[i] = (uint32_t) _64BitOffset;
01438 }
01439 }
01440 }
01441
01442
01443
01444
01445
01446
01447 Exception::Exception(String Message) : RIFF::Exception(Message) {
01448 }
01449
01450 void Exception::PrintMessage() {
01451 std::cout << "DLS::Exception: " << Message << std::endl;
01452 }
01453
01454
01455
01456
01457
01463 String libraryName() {
01464 return PACKAGE;
01465 }
01466
01471 String libraryVersion() {
01472 return VERSION;
01473 }
01474
01475 }