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 namespace DLS {
00027
00028
00029
00030
00031 void Connection::Init(conn_block_t* Header) {
00032 Source = (conn_src_t) Header->source;
00033 Control = (conn_src_t) Header->control;
00034 Destination = (conn_dst_t) Header->destination;
00035 Scale = Header->scale;
00036 SourceTransform = (conn_trn_t) CONN_TRANSFORM_SRC(Header->transform);
00037 ControlTransform = (conn_trn_t) CONN_TRANSFORM_CTL(Header->transform);
00038 DestinationTransform = (conn_trn_t) CONN_TRANSFORM_DST(Header->transform);
00039 SourceInvert = CONN_TRANSFORM_INVERT_SRC(Header->transform);
00040 SourceBipolar = CONN_TRANSFORM_BIPOLAR_SRC(Header->transform);
00041 ControlInvert = CONN_TRANSFORM_INVERT_CTL(Header->transform);
00042 ControlBipolar = CONN_TRANSFORM_BIPOLAR_CTL(Header->transform);
00043 }
00044
00045
00046
00047
00048
00049
00050 Articulation::Articulation(RIFF::List* artList) {
00051 if (artList->GetListType() != LIST_TYPE_ART2 &&
00052 artList->GetListType() != LIST_TYPE_ART1) {
00053 throw DLS::Exception("<art1-list> or <art2-list> chunk expected");
00054 }
00055 uint32_t headerSize = artList->ReadUint32();
00056 Connections = artList->ReadUint32();
00057 artList->SetPos(headerSize);
00058
00059 pConnections = new Connection[Connections];
00060 Connection::conn_block_t connblock;
00061 for (uint32_t i = 0; i <= Connections; i++) {
00062 artList->Read(&connblock.source, 1, 2);
00063 artList->Read(&connblock.control, 1, 2);
00064 artList->Read(&connblock.destination, 1, 2);
00065 artList->Read(&connblock.transform, 1, 2);
00066 artList->Read(&connblock.scale, 1, 4);
00067 pConnections[i].Init(&connblock);
00068 }
00069 }
00070
00071 Articulation::~Articulation() {
00072 if (pConnections) delete[] pConnections;
00073 }
00074
00075
00076
00077
00078
00079
00080 Articulator::Articulator(RIFF::List* ParentList) {
00081 pParentList = ParentList;
00082 pArticulations = NULL;
00083 }
00084
00085 Articulation* Articulator::GetFirstArticulation() {
00086 if (!pArticulations) LoadArticulations();
00087 if (!pArticulations) return NULL;
00088 ArticulationsIterator = pArticulations->begin();
00089 return (ArticulationsIterator != pArticulations->end()) ? *ArticulationsIterator : NULL;
00090 }
00091
00092 Articulation* Articulator::GetNextArticulation() {
00093 if (!pArticulations) return NULL;
00094 ArticulationsIterator++;
00095 return (ArticulationsIterator != pArticulations->end()) ? *ArticulationsIterator : NULL;
00096 }
00097
00098 void Articulator::LoadArticulations() {
00099
00100 RIFF::List* lart = pParentList->GetSubList(LIST_TYPE_LAR2);
00101 if (!lart) lart = pParentList->GetSubList(LIST_TYPE_LART);
00102 if (lart) {
00103 uint32_t artCkType = (lart->GetListType() == LIST_TYPE_LAR2) ? LIST_TYPE_ART2
00104 : LIST_TYPE_ART1;
00105 RIFF::List* art = lart->GetFirstSubList();
00106 while (art) {
00107 if (art->GetListType() == artCkType) {
00108 if (!pArticulations) pArticulations = new ArticulationList;
00109 pArticulations->push_back(new Articulation(art));
00110 }
00111 art = lart->GetNextSubList();
00112 }
00113 }
00114 }
00115
00116 Articulator::~Articulator() {
00117 if (pArticulations) {
00118 ArticulationList::iterator iter = pArticulations->begin();
00119 ArticulationList::iterator end = pArticulations->end();
00120 while (iter != end) {
00121 delete *iter;
00122 iter++;
00123 }
00124 delete pArticulations;
00125 }
00126 }
00127
00128
00129
00130
00131
00132
00133 Info::Info(RIFF::List* list) {
00134 if (list) {
00135 RIFF::List* lstINFO = list->GetSubList(LIST_TYPE_INFO);
00136 if (lstINFO) {
00137 LoadString(CHUNK_ID_INAM, lstINFO, Name);
00138 LoadString(CHUNK_ID_IARL, lstINFO, ArchivalLocation);
00139 LoadString(CHUNK_ID_ICRD, lstINFO, CreationDate);
00140 LoadString(CHUNK_ID_ICMT, lstINFO, Comments);
00141 LoadString(CHUNK_ID_IPRD, lstINFO, Product);
00142 LoadString(CHUNK_ID_ICOP, lstINFO, Copyright);
00143 LoadString(CHUNK_ID_IART, lstINFO, Artists);
00144 LoadString(CHUNK_ID_IGNR, lstINFO, Genre);
00145 LoadString(CHUNK_ID_IKEY, lstINFO, Keywords);
00146 LoadString(CHUNK_ID_IENG, lstINFO, Engineer);
00147 LoadString(CHUNK_ID_ITCH, lstINFO, Technician);
00148 LoadString(CHUNK_ID_ISFT, lstINFO, Software);
00149 LoadString(CHUNK_ID_IMED, lstINFO, Medium);
00150 LoadString(CHUNK_ID_ISRC, lstINFO, Source);
00151 LoadString(CHUNK_ID_ISRF, lstINFO, SourceForm);
00152 LoadString(CHUNK_ID_ICMS, lstINFO, Commissioned);
00153 }
00154 }
00155 }
00156
00157
00158
00159
00160
00161
00162 Resource::Resource(Resource* Parent, RIFF::List* lstResource) {
00163 pParent = Parent;
00164
00165 pInfo = new Info(lstResource);
00166
00167 RIFF::Chunk* ckDLSID = lstResource->GetSubChunk(CHUNK_ID_DLID);
00168 if (ckDLSID) {
00169 pDLSID = new dlsid_t;
00170 ckDLSID->Read(&pDLSID->ulData1, 1, 4);
00171 ckDLSID->Read(&pDLSID->usData2, 1, 2);
00172 ckDLSID->Read(&pDLSID->usData3, 1, 2);
00173 ckDLSID->Read(pDLSID->abData, 8, 1);
00174 }
00175 else pDLSID = NULL;
00176 }
00177
00178 Resource::~Resource() {
00179 if (pDLSID) delete pDLSID;
00180 if (pInfo) delete pInfo;
00181 }
00182
00183
00184
00185
00186
00187
00188 Sampler::Sampler(RIFF::List* ParentList) {
00189 RIFF::Chunk* wsmp = ParentList->GetSubChunk(CHUNK_ID_WSMP);
00190 if (!wsmp) throw DLS::Exception("Mandatory <wsmp> chunk not found.");
00191 uint32_t headersize = wsmp->ReadUint32();
00192 UnityNote = wsmp->ReadUint16();
00193 FineTune = wsmp->ReadInt16();
00194 Gain = wsmp->ReadInt32();
00195 SamplerOptions = wsmp->ReadUint32();
00196 NoSampleDepthTruncation = SamplerOptions & F_WSMP_NO_TRUNCATION;
00197 NoSampleCompression = SamplerOptions & F_WSMP_NO_COMPRESSION;
00198 SampleLoops = wsmp->ReadUint32();
00199 pSampleLoops = (SampleLoops) ? new sample_loop_t[SampleLoops] : NULL;
00200 wsmp->SetPos(headersize);
00201 for (uint32_t i = 0; i < SampleLoops; i++) {
00202 wsmp->Read(pSampleLoops + i, 4, 4);
00203 if (pSampleLoops[i].Size > sizeof(sample_loop_t)) {
00204 wsmp->SetPos(pSampleLoops[i].Size - sizeof(sample_loop_t), RIFF::stream_curpos);
00205 }
00206 }
00207 }
00208
00209 Sampler::~Sampler() {
00210 if (pSampleLoops) delete[] pSampleLoops;
00211 }
00212
00213
00214
00215
00216
00217
00218 Sample::Sample(File* pFile, RIFF::List* waveList, unsigned long WavePoolOffset) : Resource(pFile, waveList) {
00219 ulWavePoolOffset = WavePoolOffset - LIST_HEADER_SIZE;
00220 pCkFormat = waveList->GetSubChunk(CHUNK_ID_FMT);
00221 pCkData = waveList->GetSubChunk(CHUNK_ID_DATA);
00222 if (!pCkFormat || !pCkData) throw DLS::Exception("Mandatory chunks in wave list not found.");
00223
00224
00225 FormatTag = pCkFormat->ReadUint16();
00226 Channels = pCkFormat->ReadUint16();
00227 SamplesPerSecond = pCkFormat->ReadUint32();
00228 AverageBytesPerSecond = pCkFormat->ReadUint32();
00229 BlockAlign = pCkFormat->ReadUint16();
00230
00231
00232 if (FormatTag == WAVE_FORMAT_PCM) {
00233 BitDepth = pCkFormat->ReadUint16();
00234 FrameSize = (FormatTag == WAVE_FORMAT_PCM) ? (BitDepth / 8) * Channels
00235 : 0;
00236 SamplesTotal = (FormatTag == WAVE_FORMAT_PCM) ? pCkData->GetSize() / FrameSize
00237 : 0;
00238 }
00239 else {
00240 BitDepth = 0;
00241 FrameSize = 0;
00242 SamplesTotal = 0;
00243 }
00244 }
00245
00246 void* Sample::LoadSampleData() {
00247 return pCkData->LoadChunkData();
00248 }
00249
00250 void Sample::ReleaseSampleData() {
00251 pCkData->ReleaseChunkData();
00252 }
00253
00262 unsigned long Sample::SetPos(unsigned long SampleCount, RIFF::stream_whence_t Whence) {
00263 if (FormatTag != WAVE_FORMAT_PCM) return 0;
00264 unsigned long orderedBytes = SampleCount * FrameSize;
00265 unsigned long result = pCkData->SetPos(orderedBytes, Whence);
00266 return (result == orderedBytes) ? SampleCount
00267 : result / FrameSize;
00268 }
00269
00279 unsigned long Sample::Read(void* pBuffer, unsigned long SampleCount) {
00280 if (FormatTag != WAVE_FORMAT_PCM) return 0;
00281 return pCkData->Read(pBuffer, SampleCount, FrameSize);
00282 }
00283
00284
00285
00286
00287
00288
00289 Region::Region(Instrument* pInstrument, RIFF::List* rgnList) : Resource(pInstrument, rgnList), Articulator(rgnList), Sampler(rgnList) {
00290 pCkRegion = rgnList;
00291
00292 RIFF::Chunk* rgnh = rgnList->GetSubChunk(CHUNK_ID_RGNH);
00293 rgnh->Read(&KeyRange, 2, 2);
00294 rgnh->Read(&VelocityRange, 2, 2);
00295 uint16_t optionflags = rgnh->ReadUint16();
00296 SelfNonExclusive = optionflags & F_RGN_OPTION_SELFNONEXCLUSIVE;
00297 KeyGroup = rgnh->ReadUint16();
00298
00299 if (rgnh->RemainingBytes() >= sizeof(uint16_t)) {
00300 rgnh->Read(&Layer, 1, sizeof(uint16_t));
00301 }
00302 else Layer = 0;
00303
00304 RIFF::Chunk* wlnk = rgnList->GetSubChunk(CHUNK_ID_WLNK);
00305 optionflags = wlnk->ReadUint16();
00306 PhaseMaster = optionflags & F_WAVELINK_PHASE_MASTER;
00307 MultiChannel = optionflags & F_WAVELINK_MULTICHANNEL;
00308 PhaseGroup = wlnk->ReadUint16();
00309 Channel = wlnk->ReadUint32();
00310 WavePoolTableIndex = wlnk->ReadUint32();
00311
00312 pSample = NULL;
00313 }
00314
00315 Region::~Region() {
00316 }
00317
00318 Sample* Region::GetSample() {
00319 if (pSample) return pSample;
00320 File* file = (File*) GetParent()->GetParent();
00321 unsigned long soughtoffset = file->pWavePoolTable[WavePoolTableIndex];
00322 Sample* sample = file->GetFirstSample();
00323 while (sample) {
00324 if (sample->ulWavePoolOffset == soughtoffset) return (pSample = sample);
00325 sample = file->GetNextSample();
00326 }
00327 return NULL;
00328 }
00329
00330
00331
00332
00333
00334
00335 Instrument::Instrument(File* pFile, RIFF::List* insList) : Resource(pFile, insList), Articulator(insList) {
00336 pCkInstrument = insList;
00337
00338 RIFF::Chunk* insh = pCkInstrument->GetSubChunk(CHUNK_ID_INSH);
00339 if (!insh) throw DLS::Exception("Mandatory chunks in <lins> list chunk not found.");
00340 Regions = insh->ReadUint32();
00341 midi_locale_t locale;
00342 insh->Read(&locale, 2, 4);
00343 MIDIProgram = locale.instrument;
00344 IsDrum = locale.bank & DRUM_TYPE_MASK;
00345 MIDIBankCoarse = (uint8_t) MIDI_BANK_COARSE(locale.bank);
00346 MIDIBankFine = (uint8_t) MIDI_BANK_FINE(locale.bank);
00347 MIDIBank = MIDI_BANK_MERGE(MIDIBankCoarse, MIDIBankFine);
00348
00349 pRegions = NULL;
00350 }
00351
00352 Region* Instrument::GetFirstRegion() {
00353 if (!pRegions) LoadRegions();
00354 if (!pRegions) return NULL;
00355 RegionsIterator = pRegions->begin();
00356 return (RegionsIterator != pRegions->end()) ? *RegionsIterator : NULL;
00357 }
00358
00359 Region* Instrument::GetNextRegion() {
00360 if (!pRegions) return NULL;
00361 RegionsIterator++;
00362 return (RegionsIterator != pRegions->end()) ? *RegionsIterator : NULL;
00363 }
00364
00365 void Instrument::LoadRegions() {
00366 RIFF::List* lrgn = pCkInstrument->GetSubList(LIST_TYPE_LRGN);
00367 if (!lrgn) throw DLS::Exception("Mandatory chunks in <ins > chunk not found.");
00368 uint32_t regionCkType = (lrgn->GetSubList(LIST_TYPE_RGN2)) ? LIST_TYPE_RGN2 : LIST_TYPE_RGN;
00369 RIFF::List* rgn = lrgn->GetFirstSubList();
00370 while (rgn) {
00371 if (rgn->GetListType() == regionCkType) {
00372 if (!pRegions) pRegions = new RegionList;
00373 pRegions->push_back(new Region(this, rgn));
00374 }
00375 rgn = lrgn->GetNextSubList();
00376 }
00377 }
00378
00379 Instrument::~Instrument() {
00380 if (pRegions) {
00381 RegionList::iterator iter = pRegions->begin();
00382 RegionList::iterator end = pRegions->end();
00383 while (iter != end) {
00384 delete *iter;
00385 iter++;
00386 }
00387 delete pRegions;
00388 }
00389 }
00390
00391
00392
00393
00394
00395
00396 File::File(RIFF::File* pRIFF) : Resource(NULL, pRIFF) {
00397 if (!pRIFF) throw DLS::Exception("NULL pointer reference to RIFF::File object.");
00398 this->pRIFF = pRIFF;
00399
00400 RIFF::Chunk* ckVersion = pRIFF->GetSubChunk(CHUNK_ID_VERS);
00401 if (ckVersion) {
00402 pVersion = new version_t;
00403 ckVersion->Read(pVersion, 4, 2);
00404 }
00405 else pVersion = NULL;
00406
00407 RIFF::Chunk* colh = pRIFF->GetSubChunk(CHUNK_ID_COLH);
00408 if (!colh) throw DLS::Exception("Mandatory chunks in RIFF list chunk not found.");
00409 Instruments = colh->ReadUint32();
00410
00411 RIFF::Chunk* ptbl = pRIFF->GetSubChunk(CHUNK_ID_PTBL);
00412 if (!ptbl) throw DLS::Exception("Mandatory <ptbl> chunk not found.");
00413 uint32_t headersize = ptbl->ReadUint32();
00414 WavePoolCount = ptbl->ReadUint32();
00415 pWavePoolTable = new uint32_t[WavePoolCount];
00416 ptbl->SetPos(headersize);
00417
00418
00419 if (ptbl->GetSize() - headersize == WavePoolCount * 8) {
00420 for (int i = 0 ; i < WavePoolCount ; i++) {
00421
00422 uint32_t upper = ptbl->ReadUint32();
00423 pWavePoolTable[i] = ptbl->ReadUint32();
00424 if (upper || (pWavePoolTable[i] & 0x80000000))
00425 throw DLS::Exception("Files larger than 2 GB not yet supported");
00426 }
00427 }
00428 else ptbl->Read(pWavePoolTable, WavePoolCount, sizeof(uint32_t));
00429
00430 pSamples = NULL;
00431 pInstruments = NULL;
00432 }
00433
00434 File::~File() {
00435 if (pInstruments) {
00436 InstrumentList::iterator iter = pInstruments->begin();
00437 InstrumentList::iterator end = pInstruments->end();
00438 while (iter != end) {
00439 delete *iter;
00440 iter++;
00441 }
00442 delete pInstruments;
00443 }
00444
00445 if (pSamples) {
00446 SampleList::iterator iter = pSamples->begin();
00447 SampleList::iterator end = pSamples->end();
00448 while (iter != end) {
00449 delete *iter;
00450 iter++;
00451 }
00452 delete pSamples;
00453 }
00454
00455 if (pWavePoolTable) delete[] pWavePoolTable;
00456 if (pVersion) delete pVersion;
00457 }
00458
00459 Sample* File::GetFirstSample() {
00460 if (!pSamples) LoadSamples();
00461 if (!pSamples) return NULL;
00462 SamplesIterator = pSamples->begin();
00463 return (SamplesIterator != pSamples->end()) ? *SamplesIterator : NULL;
00464 }
00465
00466 Sample* File::GetNextSample() {
00467 if (!pSamples) return NULL;
00468 SamplesIterator++;
00469 return (SamplesIterator != pSamples->end()) ? *SamplesIterator : NULL;
00470 }
00471
00472 void File::LoadSamples() {
00473 RIFF::List* wvpl = pRIFF->GetSubList(LIST_TYPE_WVPL);
00474 if (wvpl) {
00475 unsigned long wvplFileOffset = wvpl->GetFilePos();
00476 RIFF::List* wave = wvpl->GetFirstSubList();
00477 while (wave) {
00478 if (wave->GetListType() == LIST_TYPE_WAVE) {
00479 if (!pSamples) pSamples = new SampleList;
00480 unsigned long waveFileOffset = wave->GetFilePos();
00481 pSamples->push_back(new Sample(this, wave, waveFileOffset - wvplFileOffset));
00482 }
00483 wave = wvpl->GetNextSubList();
00484 }
00485 }
00486 else {
00487 RIFF::List* dwpl = pRIFF->GetSubList(LIST_TYPE_DWPL);
00488 if (dwpl) {
00489 unsigned long dwplFileOffset = dwpl->GetFilePos();
00490 RIFF::List* wave = dwpl->GetFirstSubList();
00491 while (wave) {
00492 if (wave->GetListType() == LIST_TYPE_WAVE) {
00493 if (!pSamples) pSamples = new SampleList;
00494 unsigned long waveFileOffset = wave->GetFilePos();
00495 pSamples->push_back(new Sample(this, wave, waveFileOffset - dwplFileOffset));
00496 }
00497 wave = dwpl->GetNextSubList();
00498 }
00499 }
00500 }
00501 }
00502
00503 Instrument* File::GetFirstInstrument() {
00504 if (!pInstruments) LoadInstruments();
00505 if (!pInstruments) return NULL;
00506 InstrumentsIterator = pInstruments->begin();
00507 return (InstrumentsIterator != pInstruments->end()) ? *InstrumentsIterator : NULL;
00508 }
00509
00510 Instrument* File::GetNextInstrument() {
00511 if (!pInstruments) return NULL;
00512 InstrumentsIterator++;
00513 return (InstrumentsIterator != pInstruments->end()) ? *InstrumentsIterator : NULL;
00514 }
00515
00516 void File::LoadInstruments() {
00517 RIFF::List* lstInstruments = pRIFF->GetSubList(LIST_TYPE_LINS);
00518 if (lstInstruments) {
00519 RIFF::List* lstInstr = lstInstruments->GetFirstSubList();
00520 while (lstInstr) {
00521 if (lstInstr->GetListType() == LIST_TYPE_INS) {
00522 if (!pInstruments) pInstruments = new InstrumentList;
00523 pInstruments->push_back(new Instrument(this, lstInstr));
00524 }
00525 lstInstr = lstInstruments->GetNextSubList();
00526 }
00527 }
00528 }
00529
00530
00531
00532
00533
00534
00535 Exception::Exception(String Message) : RIFF::Exception(Message) {
00536 }
00537
00538 void Exception::PrintMessage() {
00539 std::cout << "DLS::Exception: " << Message << std::endl;
00540 }
00541
00542
00543
00544
00545
00551 String libraryName() {
00552 return PACKAGE;
00553 }
00554
00559 String libraryVersion() {
00560 return VERSION;
00561 }
00562
00563 }