31 #include <CoreFoundation/CFUUID.h>
32 #elif defined(HAVE_UUID_UUID_H)
33 #include <uuid/uuid.h>
39 #define CONN_TRANSFORM_SRC(x) ((x >> 10) & 0x000F)
40 #define CONN_TRANSFORM_CTL(x) ((x >> 4) & 0x000F)
41 #define CONN_TRANSFORM_DST(x) (x & 0x000F)
42 #define CONN_TRANSFORM_BIPOLAR_SRC(x) (x & 0x4000)
43 #define CONN_TRANSFORM_BIPOLAR_CTL(x) (x & 0x0100)
44 #define CONN_TRANSFORM_INVERT_SRC(x) (x & 0x8000)
45 #define CONN_TRANSFORM_INVERT_CTL(x) (x & 0x0200)
48 #define CONN_TRANSFORM_SRC_ENCODE(x) ((x & 0x000F) << 10)
49 #define CONN_TRANSFORM_CTL_ENCODE(x) ((x & 0x000F) << 4)
50 #define CONN_TRANSFORM_DST_ENCODE(x) (x & 0x000F)
51 #define CONN_TRANSFORM_BIPOLAR_SRC_ENCODE(x) ((x) ? 0x4000 : 0)
52 #define CONN_TRANSFORM_BIPOLAR_CTL_ENCODE(x) ((x) ? 0x0100 : 0)
53 #define CONN_TRANSFORM_INVERT_SRC_ENCODE(x) ((x) ? 0x8000 : 0)
54 #define CONN_TRANSFORM_INVERT_CTL_ENCODE(x) ((x) ? 0x0200 : 0)
56 #define DRUM_TYPE_MASK 0x80000000
58 #define F_RGN_OPTION_SELFNONEXCLUSIVE 0x0001
60 #define F_WAVELINK_PHASE_MASTER 0x0001
61 #define F_WAVELINK_MULTICHANNEL 0x0002
63 #define F_WSMP_NO_TRUNCATION 0x0001
64 #define F_WSMP_NO_COMPRESSION 0x0002
66 #define MIDI_BANK_COARSE(x) ((x & 0x00007F00) >> 8)
67 #define MIDI_BANK_FINE(x) (x & 0x0000007F)
68 #define MIDI_BANK_MERGE(coarse, fine) ((((uint16_t) coarse) << 7) | fine)
69 #define MIDI_BANK_ENCODE(coarse, fine) (((coarse & 0x0000007F) << 8) | (fine & 0x0000007F))
76 void Connection::Init(conn_block_t* Header) {
79 Destination = (
conn_dst_t) Header->destination;
80 Scale = Header->scale;
81 SourceTransform = (
conn_trn_t) CONN_TRANSFORM_SRC(Header->transform);
82 ControlTransform = (
conn_trn_t) CONN_TRANSFORM_CTL(Header->transform);
83 DestinationTransform = (
conn_trn_t) CONN_TRANSFORM_DST(Header->transform);
84 SourceInvert = CONN_TRANSFORM_INVERT_SRC(Header->transform);
85 SourceBipolar = CONN_TRANSFORM_BIPOLAR_SRC(Header->transform);
86 ControlInvert = CONN_TRANSFORM_INVERT_CTL(Header->transform);
87 ControlBipolar = CONN_TRANSFORM_BIPOLAR_CTL(Header->transform);
90 Connection::conn_block_t Connection::ToConnBlock() {
94 c.destination = Destination;
96 c.transform = CONN_TRANSFORM_SRC_ENCODE(SourceTransform) |
97 CONN_TRANSFORM_CTL_ENCODE(ControlTransform) |
98 CONN_TRANSFORM_DST_ENCODE(DestinationTransform) |
99 CONN_TRANSFORM_INVERT_SRC_ENCODE(SourceInvert) |
100 CONN_TRANSFORM_BIPOLAR_SRC_ENCODE(SourceBipolar) |
101 CONN_TRANSFORM_INVERT_CTL_ENCODE(ControlInvert) |
102 CONN_TRANSFORM_BIPOLAR_CTL_ENCODE(ControlBipolar);
120 pArticulationCk = artl;
133 Connection::conn_block_t connblock;
135 artl->
Read(&connblock.source, 1, 2);
136 artl->
Read(&connblock.control, 1, 2);
137 artl->
Read(&connblock.destination, 1, 2);
138 artl->
Read(&connblock.transform, 1, 2);
139 artl->
Read(&connblock.scale, 1, 4);
144 Articulation::~Articulation() {
155 const int iEntrySize = 12;
157 uint8_t* pData = (uint8_t*) pArticulationCk->
LoadChunkData();
158 store16(&pData[0], HeaderSize);
161 Connection::conn_block_t c =
pConnections[i].ToConnBlock();
162 store16(&pData[HeaderSize + i * iEntrySize], c.source);
163 store16(&pData[HeaderSize + i * iEntrySize + 2], c.control);
164 store16(&pData[HeaderSize + i * iEntrySize + 4], c.destination);
165 store16(&pData[HeaderSize + i * iEntrySize + 6], c.transform);
166 store32(&pData[HeaderSize + i * iEntrySize + 8], c.scale);
187 Articulator::Articulator(
RIFF::List* ParentList) {
188 pParentList = ParentList;
189 pArticulations = NULL;
201 if (!pArticulations) LoadArticulations();
202 if (!pArticulations)
return NULL;
203 if (pos >= pArticulations->size())
return NULL;
204 return (*pArticulations)[pos];
217 if (!pArticulations) LoadArticulations();
218 if (!pArticulations)
return NULL;
219 ArticulationsIterator = pArticulations->begin();
220 return (ArticulationsIterator != pArticulations->end()) ? *ArticulationsIterator : NULL;
235 if (!pArticulations)
return NULL;
236 ArticulationsIterator++;
237 return (ArticulationsIterator != pArticulations->end()) ? *ArticulationsIterator : NULL;
240 void Articulator::LoadArticulations() {
243 if (!lart) lart = pParentList->
GetSubList(LIST_TYPE_LART);
245 uint32_t artCkType = (lart->
GetListType() == LIST_TYPE_LAR2) ? CHUNK_ID_ART2
251 if (art->GetChunkID() == artCkType) {
252 if (!pArticulations) pArticulations =
new ArticulationList;
259 Articulator::~Articulator() {
260 if (pArticulations) {
261 ArticulationList::iterator iter = pArticulations->begin();
262 ArticulationList::iterator end = pArticulations->end();
263 while (iter != end) {
267 delete pArticulations;
278 if (pArticulations) {
279 ArticulationList::iterator iter = pArticulations->begin();
280 ArticulationList::iterator end = pArticulations->end();
281 for (; iter != end; ++iter) {
282 (*iter)->UpdateChunks(pProgress);
292 if (pArticulations) {
293 ArticulationList::iterator iter = pArticulations->begin();
294 ArticulationList::iterator end = pArticulations->end();
295 for (; iter != end; ++iter) {
296 (*iter)->DeleteChunks();
321 #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
322 # pragma GCC diagnostic push
323 # pragma GCC diagnostic ignored "-Wdeprecated-declarations"
333 UseFixedLengthStrings(false)
336 #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
337 # pragma GCC diagnostic pop
339 pFixedStringLengths = NULL;
340 pResourceListChunk = list;
344 LoadString(CHUNK_ID_INAM, lstINFO,
Name);
347 LoadString(CHUNK_ID_ICMT, lstINFO,
Comments);
348 LoadString(CHUNK_ID_IPRD, lstINFO,
Product);
349 LoadString(CHUNK_ID_ICOP, lstINFO,
Copyright);
350 LoadString(CHUNK_ID_IART, lstINFO,
Artists);
351 LoadString(CHUNK_ID_IGNR, lstINFO,
Genre);
352 LoadString(CHUNK_ID_IKEY, lstINFO,
Keywords);
353 LoadString(CHUNK_ID_IENG, lstINFO,
Engineer);
354 LoadString(CHUNK_ID_ITCH, lstINFO,
Technician);
355 LoadString(CHUNK_ID_ISFT, lstINFO,
Software);
356 LoadString(CHUNK_ID_IMED, lstINFO,
Medium);
357 LoadString(CHUNK_ID_ISRC, lstINFO,
Source);
358 LoadString(CHUNK_ID_ISRF, lstINFO,
SourceForm);
360 LoadString(CHUNK_ID_ISBJ, lstINFO,
Subject);
380 pFixedStringLengths = lengths;
388 void Info::LoadString(uint32_t ChunkID,
RIFF::List* lstINFO, String& s) {
408 void Info::SaveString(uint32_t ChunkID,
RIFF::List* lstINFO,
const String& s,
const String& sDefault) {
410 if (pFixedStringLengths) {
411 for (
int i = 0 ; pFixedStringLengths[i].length ; i++) {
412 if (pFixedStringLengths[i].chunkId == ChunkID) {
413 size = pFixedStringLengths[i].length;
419 ::SaveString(ChunkID, ck, lstINFO, s, sDefault, size != 0, size);
430 if (!pResourceListChunk)
return;
435 String defaultName =
"";
436 String defaultCreationDate =
"";
437 String defaultSoftware =
"";
438 String defaultComments =
"";
440 uint32_t resourceType = pResourceListChunk->
GetListType();
443 lstINFO = pResourceListChunk->
AddSubList(LIST_TYPE_INFO);
446 defaultName =
"NONAME";
448 if (resourceType == RIFF_TYPE_DLS) {
450 time_t now = time(NULL);
451 tm* pNowBroken = localtime(&now);
453 strftime(buf, 11,
"%F", pNowBroken);
454 defaultCreationDate = buf;
458 if (resourceType == RIFF_TYPE_DLS || resourceType == LIST_TYPE_INS)
467 SaveString(CHUNK_ID_IART, lstINFO,
Artists, String(
""));
468 SaveString(CHUNK_ID_ICMS, lstINFO,
Commissioned, String(
""));
469 SaveString(CHUNK_ID_ICMT, lstINFO,
Comments, defaultComments);
470 SaveString(CHUNK_ID_ICOP, lstINFO,
Copyright, String(
""));
471 SaveString(CHUNK_ID_ICRD, lstINFO,
CreationDate, defaultCreationDate);
472 SaveString(CHUNK_ID_IENG, lstINFO,
Engineer, String(
""));
473 SaveString(CHUNK_ID_IGNR, lstINFO,
Genre, String(
""));
474 SaveString(CHUNK_ID_IKEY, lstINFO,
Keywords, String(
""));
475 SaveString(CHUNK_ID_IMED, lstINFO,
Medium, String(
""));
476 SaveString(CHUNK_ID_INAM, lstINFO,
Name, defaultName);
477 SaveString(CHUNK_ID_IPRD, lstINFO,
Product, String(
""));
478 SaveString(CHUNK_ID_ISBJ, lstINFO,
Subject, String(
""));
479 SaveString(CHUNK_ID_ISFT, lstINFO,
Software, defaultSoftware);
480 SaveString(CHUNK_ID_ISRC, lstINFO,
Source, String(
""));
481 SaveString(CHUNK_ID_ISRF, lstINFO,
SourceForm, String(
""));
482 SaveString(CHUNK_ID_ITCH, lstINFO,
Technician, String(
""));
522 pFixedStringLengths = orig->pFixedStringLengths;
541 pResourceList = lstResource;
558 Resource::~Resource() {
591 if (!ckDLSID) ckDLSID = pResourceList->
AddSubChunk(CHUNK_ID_DLID, 16);
594 store32(&pData[0],
pDLSID->ulData1);
595 store16(&pData[4],
pDLSID->usData2);
596 store16(&pData[6],
pDLSID->usData3);
597 memcpy(&pData[8],
pDLSID->abData, 8);
605 #if defined(WIN32) || defined(__APPLE__) || defined(HAVE_UUID_GENERATE)
615 pDLSID->ulData1 = uuid.Data1;
616 pDLSID->usData2 = uuid.Data2;
617 pDLSID->usData3 = uuid.Data3;
618 memcpy(
pDLSID->abData, uuid.Data4, 8);
620 #elif defined(__APPLE__)
622 CFUUIDRef uuidRef = CFUUIDCreate(NULL);
623 CFUUIDBytes uuid = CFUUIDGetUUIDBytes(uuidRef);
625 pDLSID->ulData1 = uuid.byte0 | uuid.byte1 << 8 | uuid.byte2 << 16 | uuid.byte3 << 24;
626 pDLSID->usData2 = uuid.byte4 | uuid.byte5 << 8;
627 pDLSID->usData3 = uuid.byte6 | uuid.byte7 << 8;
628 pDLSID->abData[0] = uuid.byte8;
629 pDLSID->abData[1] = uuid.byte9;
630 pDLSID->abData[2] = uuid.byte10;
631 pDLSID->abData[3] = uuid.byte11;
632 pDLSID->abData[4] = uuid.byte12;
633 pDLSID->abData[5] = uuid.byte13;
634 pDLSID->abData[6] = uuid.byte14;
635 pDLSID->abData[7] = uuid.byte15;
636 #elif defined(HAVE_UUID_GENERATE)
639 pDLSID->ulData1 = uuid[0] | uuid[1] << 8 | uuid[2] << 16 | uuid[3] << 24;
640 pDLSID->usData2 = uuid[4] | uuid[5] << 8;
641 pDLSID->usData3 = uuid[6] | uuid[7] << 8;
642 memcpy(
pDLSID->abData, &uuid[8], 8);
644 # error "Missing support for uuid generation"
663 pParentList = ParentList;
679 SamplerOptions = F_WSMP_NO_COMPRESSION;
682 NoSampleDepthTruncation = SamplerOptions & F_WSMP_NO_TRUNCATION;
683 NoSampleCompression = SamplerOptions & F_WSMP_NO_COMPRESSION;
686 wsmp->
SetPos(uiHeaderSize);
696 Sampler::~Sampler() {
700 void Sampler::SetGain(int32_t gain) {
715 wsmp = pParentList->
AddSubChunk(CHUNK_ID_WSMP, wsmpSize);
716 }
else if (wsmp->
GetSize() != wsmpSize) {
721 store32(&pData[0], uiHeaderSize);
723 SamplerOptions = (NoSampleDepthTruncation) ? SamplerOptions | F_WSMP_NO_TRUNCATION
724 : SamplerOptions & (~F_WSMP_NO_TRUNCATION);
725 SamplerOptions = (NoSampleCompression) ? SamplerOptions | F_WSMP_NO_COMPRESSION
726 : SamplerOptions & (~F_WSMP_NO_COMPRESSION);
727 store16(&pData[4], UnityNote);
728 store16(&pData[6], FineTune);
729 store32(&pData[8],
Gain);
730 store32(&pData[12], SamplerOptions);
735 store32(&pData[uiHeaderSize + i * 16],
pSampleLoops[i].Size);
736 store32(&pData[uiHeaderSize + i * 16 + 4],
pSampleLoops[i].LoopType);
737 store32(&pData[uiHeaderSize + i * 16 + 8],
pSampleLoops[i].LoopStart);
738 store32(&pData[uiHeaderSize + i * 16 + 12],
pSampleLoops[i].LoopLength);
788 throw Exception(
"Could not delete Sample Loop, because it does not exist");
807 UnityNote = orig->UnityNote;
808 FineTune = orig->FineTune;
810 NoSampleDepthTruncation = orig->NoSampleDepthTruncation;
811 NoSampleCompression = orig->NoSampleCompression;
812 SamplerOptions = orig->SamplerOptions;
841 pWaveList = waveList;
941 const file_offset_t restorePos = pOrig->pCkData->
GetPos();
943 for (file_offset_t todo = pOrig->
GetSize(), i = 0; todo; ) {
944 const int iReadAtOnce = 64*1024;
945 file_offset_t n = (iReadAtOnce < todo) ? iReadAtOnce : todo;
946 n = pOrig->
Read(&buf[i], n);
951 pOrig->pCkData->
SetPos(restorePos);
1004 if (
FormatTag != DLS_WAVE_FORMAT_PCM)
return 0;
1037 if (
FormatTag != DLS_WAVE_FORMAT_PCM)
throw Exception(
"Sample's format is not DLS_WAVE_FORMAT_PCM");
1038 if (NewSize < 1)
throw Exception(
"Sample size must be at least one sample point");
1039 if ((NewSize >> 48) != 0)
1040 throw Exception(
"Unrealistic high DLS sample size detected");
1041 const file_offset_t sizeInBytes = NewSize *
FrameSize;
1043 if (pCkData) pCkData->
Resize(sizeInBytes);
1044 else pCkData = pWaveList->
AddSubChunk(CHUNK_ID_DATA, sizeInBytes);
1064 if (
FormatTag != DLS_WAVE_FORMAT_PCM)
return 0;
1065 if (!pCkData)
throw Exception(
"No data chunk created for sample yet, call Sample::Resize() to create one");
1066 file_offset_t orderedBytes = SampleCount *
FrameSize;
1067 file_offset_t result = pCkData->
SetPos(orderedBytes, Whence);
1068 return (result == orderedBytes) ? SampleCount
1082 if (
FormatTag != DLS_WAVE_FORMAT_PCM)
return 0;
1102 if (
FormatTag != DLS_WAVE_FORMAT_PCM)
return 0;
1103 if (
GetSize() < SampleCount)
throw Exception(
"Could not write sample data, current sample size to small");
1117 throw Exception(
"Could not save sample, only PCM format is supported");
1120 throw Exception(
"Could not save sample, there is no sample data to save");
1125 if (!pCkFormat) pCkFormat = pWaveList->
AddSubChunk(CHUNK_ID_FMT, 16);
1142 pCkRegion = rgnList;
1149 rgnh->
Read(&KeyRange, 2, 2);
1150 rgnh->
Read(&VelocityRange, 2, 2);
1155 rgnh->
Read(&Layer, 1,
sizeof(uint16_t));
1159 KeyRange.high = 127;
1160 VelocityRange.low = 0;
1161 VelocityRange.high = 127;
1162 FormatOptionFlags = F_RGN_OPTION_SELFNONEXCLUSIVE;
1166 SelfNonExclusive = FormatOptionFlags & F_RGN_OPTION_SELFNONEXCLUSIVE;
1178 WaveLinkOptionFlags = 0;
1181 WavePoolTableIndex = 0;
1183 PhaseMaster = WaveLinkOptionFlags & F_WAVELINK_PHASE_MASTER;
1184 MultiChannel = WaveLinkOptionFlags & F_WAVELINK_MULTICHANNEL;
1215 Sample* Region::GetSample() {
1216 if (pSample)
return pSample;
1217 File* file = (
File*) GetParent()->GetParent();
1218 uint64_t soughtoffset = file->pWavePoolTable[WavePoolTableIndex];
1223 if (sample->ullWavePoolOffset == soughtoffset)
return (pSample = sample);
1234 this->pSample = pSample;
1235 WavePoolTableIndex = 0;
1251 if (!pInstrument->pRegions) pInstrument->LoadRegions();
1252 if (!pInstrument->pRegions)
return;
1257 Region* prev_region = NULL;
1259 Instrument::RegionList::iterator iter = pInstrument->pRegions->begin();
1260 iter != pInstrument->pRegions->end(); iter++
1262 if ((*iter)->KeyRange.low > this->KeyRange.low) {
1266 prev_region = *iter;
1270 if (prev_region !=
this) pInstrument->MoveRegion(
this, r);
1283 if (!rgnh) rgnh = pCkRegion->
AddSubChunk(CHUNK_ID_RGNH, Layer ? 14 : 12);
1285 FormatOptionFlags = (SelfNonExclusive)
1286 ? FormatOptionFlags | F_RGN_OPTION_SELFNONEXCLUSIVE
1287 : FormatOptionFlags & (~F_RGN_OPTION_SELFNONEXCLUSIVE);
1291 store16(&pData[4], VelocityRange.
low);
1292 store16(&pData[6], VelocityRange.
high);
1293 store16(&pData[8], FormatOptionFlags);
1294 store16(&pData[10], KeyGroup);
1295 if (rgnh->
GetSize() >= 14) store16(&pData[12], Layer);
1304 if (!wlnk) wlnk = pCkRegion->
AddSubChunk(CHUNK_ID_WLNK, 12);
1306 WaveLinkOptionFlags = (PhaseMaster)
1307 ? WaveLinkOptionFlags | F_WAVELINK_PHASE_MASTER
1308 : WaveLinkOptionFlags & (~F_WAVELINK_PHASE_MASTER);
1309 WaveLinkOptionFlags = (MultiChannel)
1310 ? WaveLinkOptionFlags | F_WAVELINK_MULTICHANNEL
1311 : WaveLinkOptionFlags & (~F_WAVELINK_MULTICHANNEL);
1314 File* pFile = (
File*) GetParent()->GetParent();
1315 if (pFile->pSamples) {
1316 File::SampleList::iterator iter = pFile->pSamples->begin();
1317 File::SampleList::iterator end = pFile->pSamples->end();
1318 for (
int i = 0; iter != end; ++iter, i++) {
1319 if (*iter == pSample) {
1325 WavePoolTableIndex = index;
1327 store16(&pData[0], WaveLinkOptionFlags);
1328 store16(&pData[2], PhaseGroup);
1329 store32(&pData[4], Channel);
1330 store32(&pData[8], WavePoolTableIndex);
1349 VelocityRange = orig->VelocityRange;
1350 KeyGroup = orig->KeyGroup;
1351 Layer = orig->Layer;
1352 SelfNonExclusive = orig->SelfNonExclusive;
1353 PhaseMaster = orig->PhaseMaster;
1354 PhaseGroup = orig->PhaseGroup;
1355 MultiChannel = orig->MultiChannel;
1356 Channel = orig->Channel;
1359 if (GetParent()->GetParent() == orig->GetParent()->GetParent()) {
1360 WavePoolTableIndex = orig->WavePoolTableIndex;
1361 pSample = orig->pSample;
1363 WavePoolTableIndex = -1;
1366 FormatOptionFlags = orig->FormatOptionFlags;
1367 WaveLinkOptionFlags = orig->WaveLinkOptionFlags;
1390 pCkInstrument = insList;
1392 midi_locale_t locale;
1398 insh->
Read(&locale, 2, 4);
1402 locale.instrument = 0;
1406 IsDrum = locale.bank & DRUM_TYPE_MASK;
1420 if (!pRegions) LoadRegions();
1421 if (!pRegions)
return 0;
1422 return pRegions->size();
1436 if (!pRegions) LoadRegions();
1437 if (!pRegions)
return NULL;
1438 if (pos >= pRegions->size())
return NULL;
1439 return (*pRegions)[pos];
1452 if (!pRegions) LoadRegions();
1453 if (!pRegions)
return NULL;
1454 RegionsIterator = pRegions->begin();
1455 return (RegionsIterator != pRegions->end()) ? *RegionsIterator : NULL;
1469 if (!pRegions)
return NULL;
1471 return (RegionsIterator != pRegions->end()) ? *RegionsIterator : NULL;
1474 void Instrument::LoadRegions() {
1475 if (!pRegions) pRegions =
new RegionList;
1478 uint32_t regionCkType = (lrgn->
GetSubList(LIST_TYPE_RGN2)) ? LIST_TYPE_RGN2 : LIST_TYPE_RGN;
1483 if (rgn->GetListType() == regionCkType) {
1484 pRegions->push_back(
new Region(
this, rgn));
1490 Region* Instrument::AddRegion() {
1491 if (!pRegions) LoadRegions();
1493 if (!lrgn) lrgn = pCkInstrument->
AddSubList(LIST_TYPE_LRGN);
1495 Region* pNewRegion =
new Region(
this, rgn);
1496 const size_t idxIt = RegionsIterator - pRegions->begin();
1497 pRegions->push_back(pNewRegion);
1498 RegionsIterator = pRegions->begin() + std::min(idxIt, pRegions->size());
1499 Regions = (uint32_t) pRegions->size();
1503 void Instrument::MoveRegion(Region* pSrc, Region* pDst) {
1506 for (
size_t i = 0; i < pRegions->size(); ++i) {
1507 if ((*pRegions)[i] == pSrc) {
1508 const size_t idxIt = RegionsIterator - pRegions->begin();
1509 pRegions->erase(pRegions->begin() + i);
1510 RegionList::iterator iter = find(pRegions->begin(), pRegions->end(), pDst);
1511 pRegions->insert(iter, pSrc);
1512 RegionsIterator = pRegions->begin() + std::min(idxIt, pRegions->size());
1517 void Instrument::DeleteRegion(Region* pRegion) {
1518 if (!pRegions)
return;
1519 RegionList::iterator iter = find(pRegions->begin(), pRegions->end(), pRegion);
1520 if (iter == pRegions->end())
return;
1521 const size_t idxIt = RegionsIterator - pRegions->begin();
1522 pRegions->erase(iter);
1523 RegionsIterator = pRegions->begin() + std::min(idxIt, pRegions->size());
1524 Regions = (uint32_t) pRegions->size();
1525 pRegion->DeleteChunks();
1542 if (!insh) insh = pCkInstrument->
AddSubChunk(CHUNK_ID_INSH, 12);
1545 Regions = (pRegions) ? uint32_t(pRegions->size()) : 0;
1546 midi_locale_t locale;
1549 locale.bank = (
IsDrum) ? locale.bank | DRUM_TYPE_MASK : locale.bank & (~DRUM_TYPE_MASK);
1552 store32(&pData[4], locale.bank);
1553 store32(&pData[8], locale.instrument);
1555 if (!pRegions)
return;
1556 RegionList::iterator iter = pRegions->begin();
1557 RegionList::iterator end = pRegions->end();
1558 for (
int i = 0; iter != end; ++iter, ++i) {
1562 __divide_progress(pProgress, &subprogress, pRegions->size(), i);
1564 (*iter)->UpdateChunks(&subprogress);
1566 (*iter)->UpdateChunks(NULL);
1569 __notify_progress(pProgress, 1.0);
1578 RegionList::iterator iter = pRegions->begin();
1579 RegionList::iterator end = pRegions->end();
1580 while (iter != end) {
1599 RegionList::iterator it = pRegions->begin();
1600 RegionList::iterator end = pRegions->end();
1601 for (; it != end; ++it)
1602 (*it)->DeleteChunks();
1606 if (pCkInstrument) {
1609 pCkInstrument = NULL;
1613 void Instrument::CopyAssignCore(
const Instrument* orig) {
1636 CopyAssignCore(orig);
1641 RegionList::const_iterator it = orig->pRegions->begin();
1642 for (
int i = 0; i < orig->
Regions; ++i, ++it) {
1643 Region* dstRgn = AddRegion();
1671 pWavePoolTable = NULL;
1672 pWavePoolTableHi = NULL;
1673 WavePoolHeaderSize = 8;
1676 pInstruments = NULL;
1678 b64BitWavePoolOffsets =
false;
1691 if (!pRIFF)
throw DLS::Exception(
"NULL pointer reference to RIFF::File object.");
1692 this->pRIFF = pRIFF;
1704 if (!colh)
throw DLS::Exception(
"Mandatory chunks in RIFF list chunk not found.");
1711 pWavePoolTable = NULL;
1712 pWavePoolTableHi = NULL;
1713 WavePoolHeaderSize = 8;
1714 b64BitWavePoolOffsets =
false;
1720 pWavePoolTable =
new uint32_t[WavePoolCount];
1721 pWavePoolTableHi =
new uint32_t[WavePoolCount];
1722 ptbl->
SetPos(WavePoolHeaderSize);
1725 b64BitWavePoolOffsets = (ptbl->
GetSize() - WavePoolHeaderSize == WavePoolCount * 8);
1726 if (b64BitWavePoolOffsets) {
1727 for (
int i = 0 ; i < WavePoolCount ; i++) {
1735 ptbl->
Read(pWavePoolTable, WavePoolCount,
sizeof(uint32_t));
1736 for (
int i = 0 ; i < WavePoolCount ; i++) pWavePoolTableHi[i] = 0;
1741 pInstruments = NULL;
1746 InstrumentList::iterator iter = pInstruments->begin();
1747 InstrumentList::iterator end = pInstruments->end();
1748 while (iter != end) {
1752 delete pInstruments;
1756 SampleList::iterator iter = pSamples->begin();
1757 SampleList::iterator end = pSamples->end();
1758 while (iter != end) {
1765 if (pWavePoolTable)
delete[] pWavePoolTable;
1766 if (pWavePoolTableHi)
delete[] pWavePoolTableHi;
1768 for (std::list<RIFF::File*>::iterator i = ExtensionFiles.begin() ; i != ExtensionFiles.end() ; i++)
1781 if (!pSamples) LoadSamples();
1782 if (!pSamples)
return NULL;
1783 if (index >= pSamples->size())
return NULL;
1784 return (*pSamples)[index];
1795 if (!pSamples) LoadSamples();
1796 if (!pSamples)
return NULL;
1797 SamplesIterator = pSamples->begin();
1798 return (SamplesIterator != pSamples->end()) ? *SamplesIterator : NULL;
1809 if (!pSamples)
return NULL;
1811 return (SamplesIterator != pSamples->end()) ? *SamplesIterator : NULL;
1814 void File::LoadSamples() {
1815 if (!pSamples) pSamples =
new SampleList;
1818 file_offset_t wvplFileOffset = wvpl->
GetFilePos() -
1824 if (wave->GetListType() == LIST_TYPE_WAVE) {
1825 file_offset_t waveFileOffset = wave->GetFilePos() -
1827 pSamples->push_back(
new Sample(
this, wave, waveFileOffset - wvplFileOffset));
1840 if (wave->GetListType() == LIST_TYPE_WAVE) {
1843 pSamples->push_back(
new Sample(
this, wave, waveFileOffset - dwplFileOffset));
1859 if (!pSamples) LoadSamples();
1860 if (!pSamples)
return 0;
1861 return pSamples->size();
1872 if (!pSamples) LoadSamples();
1878 const size_t idxIt = SamplesIterator - pSamples->begin();
1879 pSamples->push_back(pSample);
1880 SamplesIterator = pSamples->begin() + std::min(idxIt, pSamples->size());
1892 if (!pSamples)
return;
1893 SampleList::iterator iter = find(pSamples->begin(), pSamples->end(), pSample);
1894 if (iter == pSamples->end())
return;
1895 const size_t idxIt = SamplesIterator - pSamples->begin();
1896 pSamples->erase(iter);
1897 SamplesIterator = pSamples->begin() + std::min(idxIt, pSamples->size());
1910 if (!pInstruments) LoadInstruments();
1911 if (!pInstruments)
return NULL;
1912 if (index >= pInstruments->size())
return NULL;
1913 return (*pInstruments)[index];
1924 if (!pInstruments) LoadInstruments();
1925 if (!pInstruments)
return NULL;
1926 InstrumentsIterator = pInstruments->begin();
1927 return (InstrumentsIterator != pInstruments->end()) ? *InstrumentsIterator : NULL;
1938 if (!pInstruments)
return NULL;
1939 InstrumentsIterator++;
1940 return (InstrumentsIterator != pInstruments->end()) ? *InstrumentsIterator : NULL;
1943 void File::LoadInstruments() {
1944 if (!pInstruments) pInstruments =
new InstrumentList;
1946 if (lstInstruments) {
1949 lstInstr; lstInstr = lstInstruments->
GetSubListAt(++i))
1951 if (lstInstr->GetListType() == LIST_TYPE_INS) {
1952 pInstruments->push_back(
new Instrument(
this, lstInstr));
1966 if (!pInstruments) LoadInstruments();
1971 const size_t idxIt = InstrumentsIterator - pInstruments->begin();
1972 pInstruments->push_back(pInstrument);
1973 InstrumentsIterator = pInstruments->begin() + std::min(idxIt, pInstruments->size());
1985 if (!pInstruments)
return;
1986 InstrumentList::iterator iter = find(pInstruments->begin(), pInstruments->end(), pInstrument);
1987 if (iter == pInstruments->end())
return;
1988 const size_t idxIt = InstrumentsIterator - pInstruments->begin();
1989 pInstruments->erase(iter);
1990 InstrumentsIterator = pInstruments->begin() + std::min(idxIt, pInstruments->size());
2016 if (index < 0 || index >= ExtensionFiles.size())
return NULL;
2017 std::list<RIFF::File*>::iterator iter = ExtensionFiles.begin();
2018 for (
int i = 0; iter != ExtensionFiles.end(); ++iter, ++i)
2019 if (i == index)
return *iter;
2033 return pRIFF->GetFileName();
2041 pRIFF->SetFileName(name);
2059 if (!ckVersion) ckVersion = pRIFF->
AddSubChunk(CHUNK_ID_VERS, 8);
2061 store16(&pData[0],
pVersion->minor);
2062 store16(&pData[2],
pVersion->major);
2063 store16(&pData[4],
pVersion->build);
2064 store16(&pData[6],
pVersion->release);
2068 Instruments = (pInstruments) ? uint32_t(pInstruments->size()) : 0;
2070 if (!colh) colh = pRIFF->
AddSubChunk(CHUNK_ID_COLH, 4);
2079 __divide_progress(pProgress, &subprogress, 20.f, 0.f);
2082 InstrumentList::iterator iter = pInstruments->begin();
2083 InstrumentList::iterator end = pInstruments->end();
2084 for (
int i = 0; iter != end; ++iter, ++i) {
2087 __divide_progress(&subprogress, &subsubprogress, pInstruments->size(), i);
2089 (*iter)->UpdateChunks(&subsubprogress);
2092 __notify_progress(&subprogress, 1.0);
2094 InstrumentList::iterator iter = pInstruments->begin();
2095 InstrumentList::iterator end = pInstruments->end();
2096 for (
int i = 0; iter != end; ++iter, ++i) {
2097 (*iter)->UpdateChunks(NULL);
2103 const int iSamples = (pSamples) ?
int(pSamples->size()) : 0;
2104 int iPtblOffsetSize = (b64BitWavePoolOffsets) ? 8 : 4;
2106 if (!ptbl) ptbl = pRIFF->
AddSubChunk(CHUNK_ID_PTBL, 1 );
2107 int iPtblSize = WavePoolHeaderSize + iPtblOffsetSize * iSamples;
2110 WavePoolCount = iSamples;
2111 store32(&pData[4], WavePoolCount);
2113 memset(&pData[WavePoolHeaderSize], 0, iPtblSize - WavePoolHeaderSize);
2120 __divide_progress(pProgress, &subprogress, 20.f, 1.f);
2123 SampleList::iterator iter = pSamples->begin();
2124 SampleList::iterator end = pSamples->end();
2125 for (
int i = 0; iter != end; ++iter, ++i) {
2128 __divide_progress(&subprogress, &subsubprogress, pSamples->size(), i);
2130 (*iter)->UpdateChunks(&subsubprogress);
2133 __notify_progress(&subprogress, 1.0);
2135 SampleList::iterator iter = pSamples->begin();
2136 SampleList::iterator end = pSamples->end();
2137 for (
int i = 0; iter != end; ++iter, ++i) {
2138 (*iter)->UpdateChunks(NULL);
2147 std::list<RIFF::File*> poolFiles;
2149 if (!ExtensionFiles.empty()) {
2150 std::list<RIFF::File*>::iterator it = ExtensionFiles.begin();
2151 for (; it != ExtensionFiles.end(); ++it) {
2157 const std::string oldName = (*it)->GetFileName();
2158 const bool isGigaPulseFile = (extensionOfPath(oldName) ==
"gx99");
2159 if (isGigaPulseFile)
2160 pGigaPulseFile = *it;
2162 poolFiles.push_back(*it);
2168 if (!poolFiles.empty()) {
2169 const int n = poolFiles.size();
2170 const int iHeaderSize = 4;
2171 const int iEntrySize = 144;
2176 ckXfil->
Resize(iHeaderSize + n * iEntrySize);
2178 ckXfil = pRIFF->
AddSubChunk(CHUNK_ID_XFIL, iHeaderSize + n * iEntrySize);
2184 std::list<RIFF::File*>::iterator itExtFile = poolFiles.begin();
2185 for (
int i = 0, iOffset = 4; i < n;
2186 ++itExtFile, ++i, iOffset += iEntrySize)
2189 std::string file = lastPathComponent(
2190 (*itExtFile)->GetFileName()
2192 if (file.length() + 6 > 128)
2193 throw Exception(
"Fatal error, extension filename length exceeds 122 byte maximum");
2194 uint8_t* pStrings = &pData[iOffset];
2195 memset(pStrings, 0, 128);
2196 memcpy(pStrings, file.c_str(), file.length());
2197 pStrings += file.length() + 1;
2198 std::string ext = file.substr(file.length()-5);
2199 memcpy(pStrings, ext.c_str(), 5);
2201 uint8_t* pId = &pData[iOffset + 128];
2203 RIFF::Chunk* ckDLSID = (*itExtFile)->GetSubChunk(CHUNK_ID_DLID);
2205 ckDLSID->
Read(&
id.ulData1, 1, 4);
2206 ckDLSID->
Read(&
id.usData2, 1, 2);
2207 ckDLSID->
Read(&
id.usData3, 1, 2);
2208 ckDLSID->
Read(
id.abData, 8, 1);
2210 ckDLSID = (*itExtFile)->AddSubChunk(CHUNK_ID_DLID, 16);
2213 store32(&pData[0],
id.ulData1);
2214 store16(&pData[4],
id.usData2);
2215 store16(&pData[6],
id.usData3);
2216 memcpy(&pData[8],
id.abData, 8);
2218 store32(&pId[0],
id.ulData1);
2219 store16(&pId[4],
id.usData2);
2220 store16(&pId[6],
id.usData3);
2221 memcpy(&pId[8],
id.abData, 8);
2231 if (pGigaPulseFile) {
2233 if (!ckDoxf) ckDoxf = pRIFF->
AddSubChunk(CHUNK_ID_DOXF, 148);
2238 uint8_t* pId = &pData[132];
2241 throw Exception(
"Fatal error, GigaPulse file does not contain a DLS ID chunk");
2246 id.ulData1 = load32(&pData[0]);
2247 id.usData2 = load16(&pData[4]);
2248 id.usData3 = load16(&pData[6]);
2249 memcpy(
id.abData, &pData[8], 8);
2251 store32(&pId[0],
id.ulData1);
2252 store16(&pId[4],
id.usData2);
2253 store16(&pId[6],
id.usData3);
2254 memcpy(&pId[8],
id.abData, 8);
2267 const bool bRequires64Bit = (finalFileSize >> 32) != 0 ||
2268 poolFiles.size() > 0;
2269 if (b64BitWavePoolOffsets != bRequires64Bit) {
2270 b64BitWavePoolOffsets = bRequires64Bit;
2271 iPtblOffsetSize = (b64BitWavePoolOffsets) ? 8 : 4;
2272 iPtblSize = WavePoolHeaderSize + iPtblOffsetSize * iSamples;
2277 __notify_progress(pProgress, 1.0);
2298 if (pRIFF->
GetMode() == RIFF::stream_mode_closed && !pRIFF->
IsNew())
2299 pRIFF->
SetMode(RIFF::stream_mode_read);
2302 const size_t nExtFiles = ExtensionFiles.size();
2303 const float tasks = nExtFiles + 1.f;
2306 if (!ExtensionFiles.empty()) {
2308 pProgress->
activity =
"Saving extension files ...";
2309 __notify_progress(pProgress, 0.f);
2312 const std::string baseName = pathWithoutExtension(Path);
2314 std::list<RIFF::File*>::iterator it = ExtensionFiles.begin();
2315 for (
int i = 0; it != ExtensionFiles.end(); ++i, ++it) {
2321 const std::string oldName = (*it)->GetFileName();
2322 const bool isGigaPulseFile = (extensionOfPath(oldName) ==
"gx99");
2323 std::string ext = (isGigaPulseFile) ?
".gx99" : strPrint(
".gx%02d", i+1);
2324 std::string newPath = baseName + ext;
2329 __divide_progress(pProgress, &subprogress, tasks,
float(i));
2331 (*it)->Save(newPath, &subprogress);
2333 (*it)->Save(newPath);
2339 __divide_progress(pProgress, &subprogress, tasks, nExtFiles);
2344 __divide_progress(&subprogress, &subsubprogress, 1.f, 0.f, 0.05f);
2345 subsubprogress.
activity =
"Updating chunks ...";
2346 __notify_progress(&subsubprogress, 0.f);
2355 __divide_progress(&subprogress, &subsubprogress, 1.f, 0.05f, 0.98f);
2356 subsubprogress.
activity =
"Writing file ...";
2357 __notify_progress(&subsubprogress, 0.f);
2359 pRIFF->
Save(Path, &subsubprogress);
2364 pProgress->
activity =
"Updating file offsets ...";
2365 __notify_progress(pProgress, 0.98);
2371 __notify_progress(pProgress, 1.0);
2389 if (pRIFF->
GetMode() != RIFF::stream_mode_read_write && !pRIFF->
IsNew())
2390 pRIFF->
SetMode(RIFF::stream_mode_read_write);
2393 const size_t nExtFiles = ExtensionFiles.size();
2394 const float tasks = nExtFiles + 1.f;
2397 if (!ExtensionFiles.empty()) {
2399 pProgress->
activity =
"Saving extension files ...";
2400 __notify_progress(pProgress, 0.f);
2402 std::list<RIFF::File*>::iterator it = ExtensionFiles.begin();
2403 for (
int i = 0; it != ExtensionFiles.end(); ++i, ++it) {
2408 __divide_progress(pProgress, &subprogress, tasks,
float(i));
2410 (*it)->Save(&subprogress);
2418 __divide_progress(pProgress, &subprogress, tasks, nExtFiles);
2423 __divide_progress(&subprogress, &subsubprogress, 1.f, 0.f, 0.05f);
2424 subsubprogress.
activity =
"Updating chunks ...";
2425 __notify_progress(&subsubprogress, 0.f);
2434 __divide_progress(&subprogress, &subsubprogress, 1.f, 0.05f, 0.98f);
2435 subsubprogress.
activity =
"Writing file ...";
2436 __notify_progress(&subsubprogress, 0.f);
2438 pRIFF->
Save(&subsubprogress);
2443 pProgress->
activity =
"Updating file offsets ...";
2444 __notify_progress(pProgress, 0.98);
2449 __notify_progress(pProgress, 1.0);
2463 __UpdateWavePoolTableChunk();
2474 if (!lstInstruments) pRIFF->
AddSubList(LIST_TYPE_LINS);
2478 const int iOffsetSize = (b64BitWavePoolOffsets) ? 8 : 4;
2479 ptbl = pRIFF->
AddSubChunk(CHUNK_ID_PTBL, WavePoolHeaderSize + iOffsetSize);
2483 if (!wvpl) pRIFF->
AddSubList(LIST_TYPE_WVPL);
2495 void File::__UpdateWavePoolTableChunk() {
2496 __UpdateWavePoolTable();
2498 const int iOffsetSize = (b64BitWavePoolOffsets) ? 8 : 4;
2500 WavePoolCount = (pSamples) ? uint32_t(pSamples->size()) : 0;
2501 const file_offset_t ulRequiredSize = WavePoolHeaderSize + iOffsetSize * WavePoolCount;
2502 if (ptbl->
GetSize() < ulRequiredSize)
throw Exception(
"Fatal error, 'ptbl' chunk too small");
2504 file_offset_t ullOriginalPos = ptbl->
GetPos();
2507 uint32_t tmp = WavePoolHeaderSize;
2509 tmp = WavePoolCount;
2512 ptbl->
SetPos(WavePoolHeaderSize);
2513 if (b64BitWavePoolOffsets) {
2514 for (
int i = 0 ; i < WavePoolCount ; i++) {
2515 tmp = pWavePoolTableHi[i];
2517 tmp = pWavePoolTable[i];
2521 for (
int i = 0 ; i < WavePoolCount ; i++) {
2522 tmp = pWavePoolTable[i];
2527 ptbl->
SetPos(ullOriginalPos);
2535 void File::__UpdateWavePoolTable() {
2536 WavePoolCount = (pSamples) ? uint32_t(pSamples->size()) : 0;
2538 if (pWavePoolTable)
delete[] pWavePoolTable;
2539 if (pWavePoolTableHi)
delete[] pWavePoolTableHi;
2540 pWavePoolTable =
new uint32_t[WavePoolCount];
2541 pWavePoolTableHi =
new uint32_t[WavePoolCount];
2542 if (!pSamples)
return;
2545 uint64_t wvplFileOffset = wvpl->
GetFilePos() -
2547 if (!b64BitWavePoolOffsets) {
2548 SampleList::iterator iter = pSamples->begin();
2549 SampleList::iterator end = pSamples->end();
2550 for (
int i = 0 ; iter != end ; ++iter, i++) {
2551 uint64_t _64BitOffset =
2552 (*iter)->pWaveList->GetFilePos() -
2553 (*iter)->pWaveList->GetPos() -
2556 (*iter)->ullWavePoolOffset = _64BitOffset;
2557 pWavePoolTable[i] = (uint32_t) _64BitOffset;
2560 if (ExtensionFiles.empty()) {
2561 SampleList::iterator iter = pSamples->begin();
2562 SampleList::iterator end = pSamples->end();
2563 for (
int i = 0 ; iter != end ; ++iter, i++) {
2564 uint64_t _64BitOffset =
2565 (*iter)->pWaveList->GetFilePos() -
2566 (*iter)->pWaveList->GetPos() -
2569 (*iter)->ullWavePoolOffset = _64BitOffset;
2570 pWavePoolTableHi[i] = (uint32_t) (_64BitOffset >> 32);
2571 pWavePoolTable[i] = (uint32_t) _64BitOffset;
2575 std::vector<RIFF::File*> poolFiles;
2576 poolFiles.push_back(pRIFF);
2577 poolFiles.insert(poolFiles.end(), ExtensionFiles.begin(), ExtensionFiles.end());
2582 SampleList::iterator iter = pSamples->begin();
2583 SampleList::iterator end = pSamples->end();
2584 for (
int i = 0 ; iter != end ; ++iter, i++) {
2588 if (pPoolFile != pCurPoolFile) {
2589 pCurPoolFile = pPoolFile;
2591 std::vector<RIFF::File*>::iterator sIter;
2592 sIter = std::find(poolFiles.begin(), poolFiles.end(), pPoolFile);
2593 if (sIter != poolFiles.end())
2594 fileNo = std::distance(poolFiles.begin(), sIter);
2600 throw DLS::Exception(
"Fatal error, pool file has no 'wvpl' list chunk");
2606 uint64_t _64BitOffset =
2607 (*iter)->pWaveList->GetFilePos() -
2608 (*iter)->pWaveList->GetPos() -
2611 pWavePoolTableHi[i] = (uint32_t) fileNo;
2612 pWavePoolTable[i] = (uint32_t) _64BitOffset;
2613 (*iter)->ullWavePoolOffset = _64BitOffset;
2623 Exception::Exception() :
RIFF::Exception() {
2626 Exception::Exception(String format, ...) :
RIFF::Exception() {
2628 va_start(arg, format);
2629 Message = assemble(format, arg);
2633 Exception::Exception(String format, va_list arg) :
RIFF::Exception() {
2634 Message = assemble(format, arg);
2637 void Exception::PrintMessage()
const {
2638 std::cout <<
"DLS::Exception: " << Message << std::endl;
Provides access to the defined connections used for the synthesis model.
Connection * pConnections
Points to the beginning of a Connection array.
virtual void DeleteChunks()
Remove all RIFF chunks associated with this Articulation object.
virtual void UpdateChunks(progress_t *pProgress)
Apply articulation connections to the respective RIFF chunks.
uint32_t Connections
Reflects the number of Connections.
Articulation(RIFF::Chunk *artl)
Constructor.
Abstract base class for classes that provide articulation information (thus for Instrument and Region...
virtual void UpdateChunks(progress_t *pProgress)
Apply all articulations to the respective RIFF chunks.
Articulation * GetNextArticulation()
Returns the next Articulation from the list of articulations.
Articulation * GetFirstArticulation()
Returns the first Articulation in the list of articulations.
Articulation * GetArticulation(size_t pos)
Returns Articulation at supplied pos position within the articulation list.
virtual void CopyAssign(const Articulator *orig)
Not yet implemented in this version, since the .gig format does not need to copy DLS articulators and...
virtual void DeleteChunks()
Remove all RIFF chunks associated with this Articulator object.
Defines a connection within the synthesis model.
Will be thrown whenever a DLS specific error occurs while trying to access a DLS File.
Parses DLS Level 1 and 2 compliant files and provides abstract access to the data.
version_t * pVersion
Points to a version_t structure if the file provided a version number else is set to NULL.
Instrument * AddInstrument()
Add a new instrument definition.
virtual void UpdateChunks(progress_t *pProgress)
Apply all the DLS file's current instruments, samples and settings to the respective RIFF chunks.
void __ensureMandatoryChunksExist()
Checks if all (for DLS) mandatory chunks exist, if not they will be created.
Instrument * GetNextInstrument()
Returns a pointer to the next Instrument object of the file, NULL otherwise.
Sample * GetSample(size_t index)
Returns Sample object of index.
Sample * GetNextSample()
Returns a pointer to the next Sample object of the file, NULL otherwise.
void SetFileName(const String &name)
You may call this method store a future file name, so you don't have to to pass it to the Save() call...
virtual void UpdateFileOffsets()
Updates all file offsets stored all over the file.
void DeleteInstrument(Instrument *pInstrument)
Delete an instrument.
uint32_t Instruments
Reflects the number of available Instrument objects.
virtual void Save(const String &Path, progress_t *pProgress=NULL)
Save changes to another file.
Instrument * GetInstrument(size_t index)
Returns the instrument with the given index from the list of instruments of this file.
bool bOwningRiff
If true then pRIFF was implicitly allocated by this class and hence pRIFF will automatically be freed...
size_t CountSamples()
Returns the total amount of samples of this DLS file.
void DeleteSample(Sample *pSample)
Delete a sample.
RIFF::File * GetRiffFile()
Returns the underlying RIFF::File used for persistency of this DLS::File object.
Sample * GetFirstSample()
Returns a pointer to the first Sample object of the file, NULL otherwise.
Instrument * GetFirstInstrument()
Returns a pointer to the first Instrument object of the file, NULL otherwise.
Sample * AddSample()
Add a new sample.
RIFF::File * GetExtensionFile(int index)
Returns extension file of given index.
String GetFileName()
File name of this DLS file.
Optional information for DLS files, instruments, samples, etc.
String Subject
<ISBJ-ck>. Describes the contents of the file.
String Genre
<IGNR-ck>. Descirbes the original work, such as, Jazz, Classic, Rock, Techno, Rave,...
String Keywords
<IKEY-ck>. Provides a list of keywords that refer to the file or subject of the file....
String SourceForm
<ISRF-ck>. Identifies the original form of the material that was digitized, such as record,...
String Comments
<ICMT-ck>. Provides general comments about the file or the subject of the file. Sentences might end w...
String Medium
<IMED-ck>. Describes the original subject of the file, such as, record, CD, and so forth.
void SetFixedStringLengths(const string_length_t *lengths)
Forces specific Info fields to be of a fixed length when being saved to a file.
virtual void DeleteChunks()
Remove all RIFF chunks associated with this Info object.
Info(RIFF::List *list)
Constructor.
String Software
<ISFT-ck>. Identifies the name of the sofware package used to create the file.
String Artists
<IART-ck>. Lists the artist of the original subject of the file.
String Product
<IPRD-ck>. Specifies the name of the title the file was originally intended for, such as World Ruler ...
virtual void CopyAssign(const Info *orig)
Make a deep copy of the Info object given by orig and assign it to this object.
String Name
<INAM-ck>. Stores the title of the subject of the file, such as, Seattle From Above.
String CreationDate
<ICRD-ck>. Specifies the date the subject of the file was created. List dates in yyyy-mm-dd format.
String ArchivalLocation
<IARL-ck>. Indicates where the subject of the file is stored.
String Engineer
<IENG-ck>. Stores the name of the engineer who worked on the file. Multiple engineer names are separa...
virtual void UpdateChunks(progress_t *pProgress)
Update chunks with current info values.
String Commissioned
<ICMS-ck>. Lists the name of the person or organization that commissioned the subject of the file,...
String Copyright
<ICOP-ck>. Records the copyright information for the file.
String Source
<ISRC-ck>. Identifies the name of the person or organization who supplied the original subject of the...
String Technician
<ITCH-ck>. Identifies the technician who sampled the subject file.
Provides all neccessary information for the synthesis of a DLS Instrument.
virtual ~Instrument()
Destructor.
virtual void CopyAssign(const Instrument *orig)
Make a (semi) deep copy of the Instrument object given by orig and assign it to this object.
uint8_t MIDIBankFine
Reflects the MIDI Bank number for MIDI Control Change 32 (bank 1 - 128).
virtual void DeleteChunks()
Remove all RIFF chunks associated with this Instrument object.
Region * GetFirstRegion()
Returns the first Region of the instrument.
Region * GetNextRegion()
Returns the next Region of the instrument.
uint8_t MIDIBankCoarse
Reflects the MIDI Bank number for MIDI Control Change 0 (bank 1 - 128).
bool IsDrum
Indicates if the Instrument is a drum type, as they differ in the synthesis model of DLS from melodic...
uint32_t Regions
Reflects the number of Region defintions this Instrument has.
uint16_t MIDIBank
Reflects combination of MIDIBankCoarse and MIDIBankFine (bank 1 - bank 16384). Do not change this val...
Instrument(File *pFile, RIFF::List *insList)
Constructor.
uint32_t MIDIProgram
Specifies the MIDI Program Change Number this Instrument should be assigned to.
Region * GetRegionAt(size_t pos)
Returns Region at supplied pos position within the region list of this instrument.
size_t CountRegions()
Returns the amount of regions of this instrument.
virtual void UpdateChunks(progress_t *pProgress)
Apply Instrument with all its Regions to the respective RIFF chunks.
Defines Region information of an Instrument.
virtual void CopyAssign(const Region *orig)
Make a (semi) deep copy of the Region object given by orig and assign it to this object.
virtual ~Region()
Destructor.
void SetSample(Sample *pSample)
Assign another sample to this Region.
virtual void UpdateChunks(progress_t *pProgress)
Apply Region settings to the respective RIFF chunks.
virtual void SetKeyRange(uint16_t Low, uint16_t High)
Modifies the key range of this Region and makes sure the respective chunks are in correct order.
virtual void DeleteChunks()
Remove all RIFF chunks associated with this Region object.
Abstract base class which encapsulates data structures which all DLS resources are able to provide.
virtual void DeleteChunks()
Remove all RIFF chunks associated with this Resource object.
Resource(Resource *Parent, RIFF::List *lstResource)
Constructor.
Info * pInfo
Points (in any case) to an Info object, providing additional, optional infos and comments.
dlsid_t * pDLSID
Points to a dlsid_t structure if the file provided a DLS ID else is NULL.
virtual void UpdateChunks(progress_t *pProgress)
Update chunks with current Resource data.
void GenerateDLSID()
Generates a new DLSID for the resource.
virtual void CopyAssign(const Resource *orig)
Make a deep copy of the Resource object given by orig and assign it to this object.
Encapsulates sample waves used for playback.
file_offset_t Read(void *pBuffer, file_offset_t SampleCount)
Reads SampleCount number of sample points from the current position into the buffer pointed by pBuffe...
void ReleaseSampleData()
Free sample data from RAM.
void CopyAssignCore(const Sample *orig)
Make a deep copy of the Sample object given by orig (without the actual sample waveform data however)...
uint16_t BlockAlign
The block alignment (in bytes) of the waveform data. Playback software needs to process a multiple of...
virtual void UpdateChunks(progress_t *pProgress)
Apply sample and its settings to the respective RIFF chunks.
void Resize(file_offset_t NewSize)
Resize sample.
file_offset_t SetPos(file_offset_t SampleCount, RIFF::stream_whence_t Whence=RIFF::stream_start)
Sets the position within the sample (in sample points, not in bytes).
uint16_t BitDepth
Size of each sample per channel (only if known sample data format is used, 0 otherwise).
virtual void CopyAssign(const Sample *orig)
Make a deep copy of the Sample object given by orig and assign it to this object.
void * LoadSampleData()
Load sample data into RAM.
uint16_t Channels
Number of channels represented in the waveform data, e.g. 1 for mono, 2 for stereo (defaults to 1=mon...
file_offset_t GetSize() const
Returns sample size.
uint32_t SamplesPerSecond
Sampling rate at which each channel should be played (defaults to 44100 if Sample was created with In...
file_offset_t SamplesTotal
Reflects total number of sample points (only if known sample data format is used, 0 otherwise),...
virtual void DeleteChunks()
Remove all RIFF chunks associated with this Sample object.
uint16_t FormatTag
Format ID of the waveform data (should be DLS_WAVE_FORMAT_PCM for DLS1 compliant files,...
uint FrameSize
Reflects the size (in bytes) of one single sample point (only if known sample data format is used,...
uint32_t AverageBytesPerSecond
The average number of bytes per second at which the waveform data should be transferred (Playback sof...
virtual ~Sample()
Destructor.
Sample(File *pFile, RIFF::List *waveList, file_offset_t WavePoolOffset)
Constructor.
file_offset_t Write(void *pBuffer, file_offset_t SampleCount)
Write sample wave data.
Abstract base class which provides mandatory informations about sample players in general.
virtual void DeleteChunks()
Remove all RIFF chunks associated with this Sampler object.
virtual void UpdateChunks(progress_t *pProgress)
Apply all sample player options to the respective RIFF chunk.
virtual void CopyAssign(const Sampler *orig)
Make a deep copy of the Sampler object given by orig and assign it to this object.
void AddSampleLoop(sample_loop_t *pLoopDef)
Adds a new sample loop with the provided loop definition.
uint32_t SampleLoops
Reflects the number of sample loops.
sample_loop_t * pSampleLoops
Points to the beginning of a sample loop array, or is NULL if there are no loops defined.
void DeleteSampleLoop(sample_loop_t *pLoopDef)
Deletes an existing sample loop.
void Resize(file_offset_t NewSize)
Resize chunk.
file_offset_t SetPos(file_offset_t Where, stream_whence_t Whence=stream_start)
Sets the position within the chunk body, thus within the data portion of the chunk (in bytes).
file_offset_t GetFilePos() const
Current, actual offset in file of current chunk data body read/write position.
void ReleaseChunkData()
Free loaded chunk body from RAM.
file_offset_t Write(void *pData, file_offset_t WordCount, file_offset_t WordSize)
Writes WordCount number of data words with given WordSize from the buffer pointed by pData.
file_offset_t RemainingBytes() const
Returns the number of bytes left to read in the chunk body.
file_offset_t ReadUint32(uint32_t *pData, file_offset_t WordCount=1)
Reads WordCount number of 32 Bit unsigned integer words and copies it into the buffer pointed by pDat...
file_offset_t GetPos() const
Current read/write position within the chunk data body (starting with 0).
file_offset_t ReadUint16(uint16_t *pData, file_offset_t WordCount=1)
Reads WordCount number of 16 Bit unsigned integer words and copies it into the buffer pointed by pDat...
file_offset_t Read(void *pData, file_offset_t WordCount, file_offset_t WordSize)
Reads WordCount number of data words with given WordSize and copies it into a buffer pointed by pData...
file_offset_t ReadInt16(int16_t *pData, file_offset_t WordCount=1)
Reads WordCount number of 16 Bit signed integer words and copies it into the buffer pointed by pData.
uint32_t GetChunkID() const
Chunk ID in unsigned integer representation.
void * LoadChunkData()
Load chunk body into RAM.
file_offset_t ReadInt32(int32_t *pData, file_offset_t WordCount=1)
Reads WordCount number of 32 Bit signed integer words and copies it into the buffer pointed by pData.
List * GetParent() const
Returns pointer to the chunk's parent list chunk.
file_offset_t WriteUint32(uint32_t *pData, file_offset_t WordCount=1)
Writes WordCount number of 32 Bit unsigned integer words from the buffer pointed by pData to the chun...
file_offset_t GetSize() const
Chunk size in bytes (without header, thus the chunk data body)
File * GetFile() const
Returns pointer to the chunk's File object.
bool SetMode(stream_mode_t NewMode)
Change file access mode.
int GetFileOffsetSize() const
Returns the current size (in bytes) of file offsets stored in the headers of all chunks of this file.
void SetByteOrder(endian_t Endian)
Set the byte order to be used when saving.
bool IsNew() const
Returns true if this file has been created new from scratch and has not been stored to disk yet.
file_offset_t GetRequiredFileSize()
Returns the required size (in bytes) for this RIFF File to be saved to disk.
stream_mode_t GetMode() const
Returns the file I/O mode currently being available for the calling thread for this RIFF file (either...
virtual void Save(progress_t *pProgress=NULL)
Save changes to same file.
Chunk * GetSubChunk(uint32_t ChunkID)
Returns subchunk with chunk ID ChunkID within this chunk list.
void MoveSubChunk(Chunk *pSrc, Chunk *pDst)
Moves a sub chunk witin this list.
List * AddSubList(uint32_t uiListType)
Creates a new list sub chunk.
void DeleteSubChunk(Chunk *pSubChunk)
Removes a sub chunk.
List * GetSubListAt(size_t pos)
Returns sublist chunk with list type ListType at supplied pos position among all subchunks of type Li...
List * GetSubList(uint32_t ListType)
Returns sublist chunk with list type ListType within this chunk list.
uint32_t GetListType() const
Returns unsigned integer representation of the list's ID.
Chunk * AddSubChunk(uint32_t uiChunkID, file_offset_t ullBodySize)
Creates a new sub chunk.
Chunk * GetSubChunkAt(size_t pos)
Returns subchunk at supplied pos position within this chunk list.
DLS specific classes and definitions.
String libraryName()
Returns the name of this C++ library.
String libraryVersion()
Returns version of this C++ library.
conn_src_t
Connection Sources.
conn_dst_t
Connection Destinations.
conn_trn_t
Connection Transforms.
RIFF specific classes and definitions.
stream_whence_t
File stream position dependent to these relations.
uint64_t file_offset_t
Type used by libgig for handling file positioning during file I/O tasks.
Every subject of an DLS file and the file itself can have an unique, computer generated ID.
uint16_t low
Low value of range.
uint16_t high
High value of range.
Defines Sample Loop Points.
uint32_t Size
For internal usage only: usually reflects exactly sizeof(sample_loop_t), otherwise if the value is la...
Quadtuple version number ("major.minor.release.build").
Used for indicating the progress of a certain task.
const char * activity
Text which describes current ongoing action (e.g. to be displayed along a progress bar).