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;
192 Articulation* Articulator::GetFirstArticulation() {
193 if (!pArticulations) LoadArticulations();
194 if (!pArticulations)
return NULL;
195 ArticulationsIterator = pArticulations->begin();
196 return (ArticulationsIterator != pArticulations->end()) ? *ArticulationsIterator : NULL;
199 Articulation* Articulator::GetNextArticulation() {
200 if (!pArticulations)
return NULL;
201 ArticulationsIterator++;
202 return (ArticulationsIterator != pArticulations->end()) ? *ArticulationsIterator : NULL;
205 void Articulator::LoadArticulations() {
208 if (!lart) lart = pParentList->
GetSubList(LIST_TYPE_LART);
210 uint32_t artCkType = (lart->
GetListType() == LIST_TYPE_LAR2) ? CHUNK_ID_ART2
215 if (!pArticulations) pArticulations =
new ArticulationList;
216 pArticulations->push_back(
new Articulation(art));
223 Articulator::~Articulator() {
224 if (pArticulations) {
225 ArticulationList::iterator iter = pArticulations->begin();
226 ArticulationList::iterator end = pArticulations->end();
227 while (iter != end) {
231 delete pArticulations;
242 if (pArticulations) {
243 ArticulationList::iterator iter = pArticulations->begin();
244 ArticulationList::iterator end = pArticulations->end();
245 for (; iter != end; ++iter) {
246 (*iter)->UpdateChunks(pProgress);
256 if (pArticulations) {
257 ArticulationList::iterator iter = pArticulations->begin();
258 ArticulationList::iterator end = pArticulations->end();
259 for (; iter != end; ++iter) {
260 (*iter)->DeleteChunks();
286 pFixedStringLengths = NULL;
287 pResourceListChunk = list;
291 LoadString(CHUNK_ID_INAM, lstINFO,
Name);
294 LoadString(CHUNK_ID_ICMT, lstINFO,
Comments);
295 LoadString(CHUNK_ID_IPRD, lstINFO,
Product);
296 LoadString(CHUNK_ID_ICOP, lstINFO,
Copyright);
297 LoadString(CHUNK_ID_IART, lstINFO,
Artists);
298 LoadString(CHUNK_ID_IGNR, lstINFO,
Genre);
299 LoadString(CHUNK_ID_IKEY, lstINFO,
Keywords);
300 LoadString(CHUNK_ID_IENG, lstINFO,
Engineer);
301 LoadString(CHUNK_ID_ITCH, lstINFO,
Technician);
302 LoadString(CHUNK_ID_ISFT, lstINFO,
Software);
303 LoadString(CHUNK_ID_IMED, lstINFO,
Medium);
304 LoadString(CHUNK_ID_ISRC, lstINFO,
Source);
305 LoadString(CHUNK_ID_ISRF, lstINFO,
SourceForm);
307 LoadString(CHUNK_ID_ISBJ, lstINFO,
Subject);
327 pFixedStringLengths = lengths;
335 void Info::LoadString(uint32_t ChunkID,
RIFF::List* lstINFO, String& s) {
355 void Info::SaveString(uint32_t ChunkID,
RIFF::List* lstINFO,
const String& s,
const String& sDefault) {
357 if (pFixedStringLengths) {
358 for (
int i = 0 ; pFixedStringLengths[i].length ; i++) {
359 if (pFixedStringLengths[i].chunkId == ChunkID) {
360 size = pFixedStringLengths[i].length;
366 ::SaveString(ChunkID, ck, lstINFO, s, sDefault, size != 0, size);
377 if (!pResourceListChunk)
return;
382 String defaultName =
"";
383 String defaultCreationDate =
"";
384 String defaultSoftware =
"";
385 String defaultComments =
"";
387 uint32_t resourceType = pResourceListChunk->
GetListType();
390 lstINFO = pResourceListChunk->
AddSubList(LIST_TYPE_INFO);
393 defaultName =
"NONAME";
395 if (resourceType == RIFF_TYPE_DLS) {
397 time_t now = time(NULL);
398 tm* pNowBroken = localtime(&now);
400 strftime(buf, 11,
"%F", pNowBroken);
401 defaultCreationDate = buf;
405 if (resourceType == RIFF_TYPE_DLS || resourceType == LIST_TYPE_INS)
414 SaveString(CHUNK_ID_IART, lstINFO,
Artists, String(
""));
415 SaveString(CHUNK_ID_ICMS, lstINFO,
Commissioned, String(
""));
416 SaveString(CHUNK_ID_ICMT, lstINFO,
Comments, defaultComments);
417 SaveString(CHUNK_ID_ICOP, lstINFO,
Copyright, String(
""));
418 SaveString(CHUNK_ID_ICRD, lstINFO,
CreationDate, defaultCreationDate);
419 SaveString(CHUNK_ID_IENG, lstINFO,
Engineer, String(
""));
420 SaveString(CHUNK_ID_IGNR, lstINFO,
Genre, String(
""));
421 SaveString(CHUNK_ID_IKEY, lstINFO,
Keywords, String(
""));
422 SaveString(CHUNK_ID_IMED, lstINFO,
Medium, String(
""));
423 SaveString(CHUNK_ID_INAM, lstINFO,
Name, defaultName);
424 SaveString(CHUNK_ID_IPRD, lstINFO,
Product, String(
""));
425 SaveString(CHUNK_ID_ISBJ, lstINFO,
Subject, String(
""));
426 SaveString(CHUNK_ID_ISFT, lstINFO,
Software, defaultSoftware);
427 SaveString(CHUNK_ID_ISRC, lstINFO,
Source, String(
""));
428 SaveString(CHUNK_ID_ISRF, lstINFO,
SourceForm, String(
""));
429 SaveString(CHUNK_ID_ITCH, lstINFO,
Technician, String(
""));
469 pFixedStringLengths = orig->pFixedStringLengths;
488 pResourceList = lstResource;
505 Resource::~Resource() {
538 if (!ckDLSID) ckDLSID = pResourceList->
AddSubChunk(CHUNK_ID_DLID, 16);
541 store32(&pData[0],
pDLSID->ulData1);
542 store16(&pData[4],
pDLSID->usData2);
543 store16(&pData[6],
pDLSID->usData3);
544 memcpy(&pData[8],
pDLSID->abData, 8);
552 #if defined(WIN32) || defined(__APPLE__) || defined(HAVE_UUID_GENERATE)
562 pDLSID->ulData1 = uuid.Data1;
563 pDLSID->usData2 = uuid.Data2;
564 pDLSID->usData3 = uuid.Data3;
565 memcpy(
pDLSID->abData, uuid.Data4, 8);
567 #elif defined(__APPLE__)
569 CFUUIDRef uuidRef = CFUUIDCreate(NULL);
570 CFUUIDBytes uuid = CFUUIDGetUUIDBytes(uuidRef);
572 pDLSID->ulData1 = uuid.byte0 | uuid.byte1 << 8 | uuid.byte2 << 16 | uuid.byte3 << 24;
573 pDLSID->usData2 = uuid.byte4 | uuid.byte5 << 8;
574 pDLSID->usData3 = uuid.byte6 | uuid.byte7 << 8;
575 pDLSID->abData[0] = uuid.byte8;
576 pDLSID->abData[1] = uuid.byte9;
577 pDLSID->abData[2] = uuid.byte10;
578 pDLSID->abData[3] = uuid.byte11;
579 pDLSID->abData[4] = uuid.byte12;
580 pDLSID->abData[5] = uuid.byte13;
581 pDLSID->abData[6] = uuid.byte14;
582 pDLSID->abData[7] = uuid.byte15;
583 #elif defined(HAVE_UUID_GENERATE)
586 pDLSID->ulData1 = uuid[0] | uuid[1] << 8 | uuid[2] << 16 | uuid[3] << 24;
587 pDLSID->usData2 = uuid[4] | uuid[5] << 8;
588 pDLSID->usData3 = uuid[6] | uuid[7] << 8;
589 memcpy(
pDLSID->abData, &uuid[8], 8);
591 # error "Missing support for uuid generation"
610 pParentList = ParentList;
626 SamplerOptions = F_WSMP_NO_COMPRESSION;
629 NoSampleDepthTruncation = SamplerOptions & F_WSMP_NO_TRUNCATION;
630 NoSampleCompression = SamplerOptions & F_WSMP_NO_COMPRESSION;
633 wsmp->
SetPos(uiHeaderSize);
643 Sampler::~Sampler() {
647 void Sampler::SetGain(int32_t gain) {
662 wsmp = pParentList->
AddSubChunk(CHUNK_ID_WSMP, wsmpSize);
663 }
else if (wsmp->
GetSize() != wsmpSize) {
668 store32(&pData[0], uiHeaderSize);
670 SamplerOptions = (NoSampleDepthTruncation) ? SamplerOptions | F_WSMP_NO_TRUNCATION
671 : SamplerOptions & (~F_WSMP_NO_TRUNCATION);
672 SamplerOptions = (NoSampleCompression) ? SamplerOptions | F_WSMP_NO_COMPRESSION
673 : SamplerOptions & (~F_WSMP_NO_COMPRESSION);
674 store16(&pData[4], UnityNote);
675 store16(&pData[6], FineTune);
676 store32(&pData[8],
Gain);
677 store32(&pData[12], SamplerOptions);
682 store32(&pData[uiHeaderSize + i * 16],
pSampleLoops[i].Size);
683 store32(&pData[uiHeaderSize + i * 16 + 4],
pSampleLoops[i].LoopType);
684 store32(&pData[uiHeaderSize + i * 16 + 8],
pSampleLoops[i].LoopStart);
685 store32(&pData[uiHeaderSize + i * 16 + 12],
pSampleLoops[i].LoopLength);
735 throw Exception(
"Could not delete Sample Loop, because it does not exist");
754 UnityNote = orig->UnityNote;
755 FineTune = orig->FineTune;
757 NoSampleDepthTruncation = orig->NoSampleDepthTruncation;
758 NoSampleCompression = orig->NoSampleCompression;
759 SamplerOptions = orig->SamplerOptions;
788 pWaveList = waveList;
888 const file_offset_t restorePos = pOrig->pCkData->
GetPos();
890 for (file_offset_t todo = pOrig->
GetSize(), i = 0; todo; ) {
891 const int iReadAtOnce = 64*1024;
892 file_offset_t n = (iReadAtOnce < todo) ? iReadAtOnce : todo;
893 n = pOrig->
Read(&buf[i], n);
898 pOrig->pCkData->
SetPos(restorePos);
951 if (
FormatTag != DLS_WAVE_FORMAT_PCM)
return 0;
984 if (
FormatTag != DLS_WAVE_FORMAT_PCM)
throw Exception(
"Sample's format is not DLS_WAVE_FORMAT_PCM");
985 if (NewSize < 1)
throw Exception(
"Sample size must be at least one sample point");
986 if ((NewSize >> 48) != 0)
987 throw Exception(
"Unrealistic high DLS sample size detected");
988 const file_offset_t sizeInBytes = NewSize *
FrameSize;
990 if (pCkData) pCkData->
Resize(sizeInBytes);
991 else pCkData = pWaveList->
AddSubChunk(CHUNK_ID_DATA, sizeInBytes);
1011 if (
FormatTag != DLS_WAVE_FORMAT_PCM)
return 0;
1012 if (!pCkData)
throw Exception(
"No data chunk created for sample yet, call Sample::Resize() to create one");
1013 file_offset_t orderedBytes = SampleCount *
FrameSize;
1014 file_offset_t result = pCkData->
SetPos(orderedBytes, Whence);
1015 return (result == orderedBytes) ? SampleCount
1029 if (
FormatTag != DLS_WAVE_FORMAT_PCM)
return 0;
1049 if (
FormatTag != DLS_WAVE_FORMAT_PCM)
return 0;
1050 if (
GetSize() < SampleCount)
throw Exception(
"Could not write sample data, current sample size to small");
1064 throw Exception(
"Could not save sample, only PCM format is supported");
1067 throw Exception(
"Could not save sample, there is no sample data to save");
1072 if (!pCkFormat) pCkFormat = pWaveList->
AddSubChunk(CHUNK_ID_FMT, 16);
1089 pCkRegion = rgnList;
1096 rgnh->
Read(&KeyRange, 2, 2);
1097 rgnh->
Read(&VelocityRange, 2, 2);
1102 rgnh->
Read(&Layer, 1,
sizeof(uint16_t));
1106 KeyRange.high = 127;
1107 VelocityRange.low = 0;
1108 VelocityRange.high = 127;
1109 FormatOptionFlags = F_RGN_OPTION_SELFNONEXCLUSIVE;
1113 SelfNonExclusive = FormatOptionFlags & F_RGN_OPTION_SELFNONEXCLUSIVE;
1125 WaveLinkOptionFlags = 0;
1128 WavePoolTableIndex = 0;
1130 PhaseMaster = WaveLinkOptionFlags & F_WAVELINK_PHASE_MASTER;
1131 MultiChannel = WaveLinkOptionFlags & F_WAVELINK_MULTICHANNEL;
1162 Sample* Region::GetSample() {
1163 if (pSample)
return pSample;
1164 File* file = (
File*) GetParent()->GetParent();
1165 uint64_t soughtoffset = file->pWavePoolTable[WavePoolTableIndex];
1168 if (sample->ullWavePoolOffset == soughtoffset)
return (pSample = sample);
1180 this->pSample = pSample;
1181 WavePoolTableIndex = 0;
1197 if (!pInstrument->pRegions) pInstrument->LoadRegions();
1198 if (!pInstrument->pRegions)
return;
1203 Region* prev_region = NULL;
1205 Instrument::RegionList::iterator iter = pInstrument->pRegions->begin();
1206 iter != pInstrument->pRegions->end(); iter++
1208 if ((*iter)->KeyRange.low > this->KeyRange.low) {
1212 prev_region = *iter;
1216 if (prev_region !=
this) pInstrument->MoveRegion(
this, r);
1229 if (!rgnh) rgnh = pCkRegion->
AddSubChunk(CHUNK_ID_RGNH, Layer ? 14 : 12);
1231 FormatOptionFlags = (SelfNonExclusive)
1232 ? FormatOptionFlags | F_RGN_OPTION_SELFNONEXCLUSIVE
1233 : FormatOptionFlags & (~F_RGN_OPTION_SELFNONEXCLUSIVE);
1237 store16(&pData[4], VelocityRange.
low);
1238 store16(&pData[6], VelocityRange.
high);
1239 store16(&pData[8], FormatOptionFlags);
1240 store16(&pData[10], KeyGroup);
1241 if (rgnh->
GetSize() >= 14) store16(&pData[12], Layer);
1250 if (!wlnk) wlnk = pCkRegion->
AddSubChunk(CHUNK_ID_WLNK, 12);
1252 WaveLinkOptionFlags = (PhaseMaster)
1253 ? WaveLinkOptionFlags | F_WAVELINK_PHASE_MASTER
1254 : WaveLinkOptionFlags & (~F_WAVELINK_PHASE_MASTER);
1255 WaveLinkOptionFlags = (MultiChannel)
1256 ? WaveLinkOptionFlags | F_WAVELINK_MULTICHANNEL
1257 : WaveLinkOptionFlags & (~F_WAVELINK_MULTICHANNEL);
1260 File* pFile = (
File*) GetParent()->GetParent();
1261 if (pFile->pSamples) {
1262 File::SampleList::iterator iter = pFile->pSamples->begin();
1263 File::SampleList::iterator end = pFile->pSamples->end();
1264 for (
int i = 0; iter != end; ++iter, i++) {
1265 if (*iter == pSample) {
1271 WavePoolTableIndex = index;
1273 store16(&pData[0], WaveLinkOptionFlags);
1274 store16(&pData[2], PhaseGroup);
1275 store32(&pData[4], Channel);
1276 store32(&pData[8], WavePoolTableIndex);
1295 VelocityRange = orig->VelocityRange;
1296 KeyGroup = orig->KeyGroup;
1297 Layer = orig->Layer;
1298 SelfNonExclusive = orig->SelfNonExclusive;
1299 PhaseMaster = orig->PhaseMaster;
1300 PhaseGroup = orig->PhaseGroup;
1301 MultiChannel = orig->MultiChannel;
1302 Channel = orig->Channel;
1305 if (GetParent()->GetParent() == orig->GetParent()->GetParent()) {
1306 WavePoolTableIndex = orig->WavePoolTableIndex;
1307 pSample = orig->pSample;
1309 WavePoolTableIndex = -1;
1312 FormatOptionFlags = orig->FormatOptionFlags;
1313 WaveLinkOptionFlags = orig->WaveLinkOptionFlags;
1336 pCkInstrument = insList;
1338 midi_locale_t locale;
1344 insh->
Read(&locale, 2, 4);
1348 locale.instrument = 0;
1352 IsDrum = locale.bank & DRUM_TYPE_MASK;
1360 Region* Instrument::GetFirstRegion() {
1361 if (!pRegions) LoadRegions();
1362 if (!pRegions)
return NULL;
1363 RegionsIterator = pRegions->begin();
1364 return (RegionsIterator != pRegions->end()) ? *RegionsIterator : NULL;
1367 Region* Instrument::GetNextRegion() {
1368 if (!pRegions)
return NULL;
1370 return (RegionsIterator != pRegions->end()) ? *RegionsIterator : NULL;
1373 void Instrument::LoadRegions() {
1374 if (!pRegions) pRegions =
new RegionList;
1377 uint32_t regionCkType = (lrgn->
GetSubList(LIST_TYPE_RGN2)) ? LIST_TYPE_RGN2 : LIST_TYPE_RGN;
1381 pRegions->push_back(
new Region(
this, rgn));
1388 Region* Instrument::AddRegion() {
1389 if (!pRegions) LoadRegions();
1391 if (!lrgn) lrgn = pCkInstrument->
AddSubList(LIST_TYPE_LRGN);
1393 Region* pNewRegion =
new Region(
this, rgn);
1394 pRegions->push_back(pNewRegion);
1395 Regions = (uint32_t) pRegions->size();
1399 void Instrument::MoveRegion(Region* pSrc, Region* pDst) {
1403 pRegions->remove(pSrc);
1404 RegionList::iterator iter = find(pRegions->begin(), pRegions->end(), pDst);
1405 pRegions->insert(iter, pSrc);
1408 void Instrument::DeleteRegion(Region* pRegion) {
1409 if (!pRegions)
return;
1410 RegionList::iterator iter = find(pRegions->begin(), pRegions->end(), pRegion);
1411 if (iter == pRegions->end())
return;
1412 pRegions->erase(iter);
1413 Regions = (uint32_t) pRegions->size();
1414 pRegion->DeleteChunks();
1431 if (!insh) insh = pCkInstrument->
AddSubChunk(CHUNK_ID_INSH, 12);
1434 Regions = (pRegions) ? uint32_t(pRegions->size()) : 0;
1435 midi_locale_t locale;
1438 locale.bank = (
IsDrum) ? locale.bank | DRUM_TYPE_MASK : locale.bank & (~DRUM_TYPE_MASK);
1441 store32(&pData[4], locale.bank);
1442 store32(&pData[8], locale.instrument);
1444 if (!pRegions)
return;
1445 RegionList::iterator iter = pRegions->begin();
1446 RegionList::iterator end = pRegions->end();
1447 for (
int i = 0; iter != end; ++iter, ++i) {
1451 __divide_progress(pProgress, &subprogress, pRegions->size(), i);
1453 (*iter)->UpdateChunks(&subprogress);
1455 (*iter)->UpdateChunks(NULL);
1458 __notify_progress(pProgress, 1.0);
1467 RegionList::iterator iter = pRegions->begin();
1468 RegionList::iterator end = pRegions->end();
1469 while (iter != end) {
1488 RegionList::iterator it = pRegions->begin();
1489 RegionList::iterator end = pRegions->end();
1490 for (; it != end; ++it)
1491 (*it)->DeleteChunks();
1495 if (pCkInstrument) {
1498 pCkInstrument = NULL;
1502 void Instrument::CopyAssignCore(
const Instrument* orig) {
1525 CopyAssignCore(orig);
1527 while (
Regions) DeleteRegion(GetFirstRegion());
1530 RegionList::const_iterator it = orig->pRegions->begin();
1531 for (
int i = 0; i < orig->
Regions; ++i, ++it) {
1532 Region* dstRgn = AddRegion();
1560 pWavePoolTable = NULL;
1561 pWavePoolTableHi = NULL;
1562 WavePoolHeaderSize = 8;
1565 pInstruments = NULL;
1567 b64BitWavePoolOffsets =
false;
1580 if (!pRIFF)
throw DLS::Exception(
"NULL pointer reference to RIFF::File object.");
1581 this->pRIFF = pRIFF;
1593 if (!colh)
throw DLS::Exception(
"Mandatory chunks in RIFF list chunk not found.");
1600 pWavePoolTable = NULL;
1601 pWavePoolTableHi = NULL;
1602 WavePoolHeaderSize = 8;
1603 b64BitWavePoolOffsets =
false;
1609 pWavePoolTable =
new uint32_t[WavePoolCount];
1610 pWavePoolTableHi =
new uint32_t[WavePoolCount];
1611 ptbl->
SetPos(WavePoolHeaderSize);
1614 b64BitWavePoolOffsets = (ptbl->
GetSize() - WavePoolHeaderSize == WavePoolCount * 8);
1615 if (b64BitWavePoolOffsets) {
1616 for (
int i = 0 ; i < WavePoolCount ; i++) {
1624 ptbl->
Read(pWavePoolTable, WavePoolCount,
sizeof(uint32_t));
1625 for (
int i = 0 ; i < WavePoolCount ; i++) pWavePoolTableHi[i] = 0;
1630 pInstruments = NULL;
1635 InstrumentList::iterator iter = pInstruments->begin();
1636 InstrumentList::iterator end = pInstruments->end();
1637 while (iter != end) {
1641 delete pInstruments;
1645 SampleList::iterator iter = pSamples->begin();
1646 SampleList::iterator end = pSamples->end();
1647 while (iter != end) {
1654 if (pWavePoolTable)
delete[] pWavePoolTable;
1655 if (pWavePoolTableHi)
delete[] pWavePoolTableHi;
1657 for (std::list<RIFF::File*>::iterator i = ExtensionFiles.begin() ; i != ExtensionFiles.end() ; i++)
1664 if (!pSamples) LoadSamples();
1665 if (!pSamples)
return NULL;
1666 SamplesIterator = pSamples->begin();
1667 return (SamplesIterator != pSamples->end()) ? *SamplesIterator : NULL;
1671 if (!pSamples)
return NULL;
1673 return (SamplesIterator != pSamples->end()) ? *SamplesIterator : NULL;
1676 void File::LoadSamples() {
1677 if (!pSamples) pSamples =
new SampleList;
1680 file_offset_t wvplFileOffset = wvpl->
GetFilePos() -
1685 file_offset_t waveFileOffset = wave->
GetFilePos() -
1687 pSamples->push_back(
new Sample(
this, wave, waveFileOffset - wvplFileOffset));
1702 pSamples->push_back(
new Sample(
this, wave, waveFileOffset - dwplFileOffset));
1718 if (!pSamples) LoadSamples();
1724 pSamples->push_back(pSample);
1736 if (!pSamples)
return;
1737 SampleList::iterator iter = find(pSamples->begin(), pSamples->end(), pSample);
1738 if (iter == pSamples->end())
return;
1739 pSamples->erase(iter);
1745 if (!pInstruments) LoadInstruments();
1746 if (!pInstruments)
return NULL;
1747 InstrumentsIterator = pInstruments->begin();
1748 return (InstrumentsIterator != pInstruments->end()) ? *InstrumentsIterator : NULL;
1752 if (!pInstruments)
return NULL;
1753 InstrumentsIterator++;
1754 return (InstrumentsIterator != pInstruments->end()) ? *InstrumentsIterator : NULL;
1757 void File::LoadInstruments() {
1758 if (!pInstruments) pInstruments =
new InstrumentList;
1760 if (lstInstruments) {
1764 pInstruments->push_back(
new Instrument(
this, lstInstr));
1779 if (!pInstruments) LoadInstruments();
1784 pInstruments->push_back(pInstrument);
1796 if (!pInstruments)
return;
1797 InstrumentList::iterator iter = find(pInstruments->begin(), pInstruments->end(), pInstrument);
1798 if (iter == pInstruments->end())
return;
1799 pInstruments->erase(iter);
1825 if (index < 0 || index >= ExtensionFiles.size())
return NULL;
1826 std::list<RIFF::File*>::iterator iter = ExtensionFiles.begin();
1827 for (
int i = 0; iter != ExtensionFiles.end(); ++iter, ++i)
1828 if (i == index)
return *iter;
1842 return pRIFF->GetFileName();
1850 pRIFF->SetFileName(name);
1868 if (!ckVersion) ckVersion = pRIFF->
AddSubChunk(CHUNK_ID_VERS, 8);
1870 store16(&pData[0],
pVersion->minor);
1871 store16(&pData[2],
pVersion->major);
1872 store16(&pData[4],
pVersion->build);
1873 store16(&pData[6],
pVersion->release);
1877 Instruments = (pInstruments) ? uint32_t(pInstruments->size()) : 0;
1879 if (!colh) colh = pRIFF->
AddSubChunk(CHUNK_ID_COLH, 4);
1888 __divide_progress(pProgress, &subprogress, 20.f, 0.f);
1891 InstrumentList::iterator iter = pInstruments->begin();
1892 InstrumentList::iterator end = pInstruments->end();
1893 for (
int i = 0; iter != end; ++iter, ++i) {
1896 __divide_progress(&subprogress, &subsubprogress, pInstruments->size(), i);
1898 (*iter)->UpdateChunks(&subsubprogress);
1901 __notify_progress(&subprogress, 1.0);
1903 InstrumentList::iterator iter = pInstruments->begin();
1904 InstrumentList::iterator end = pInstruments->end();
1905 for (
int i = 0; iter != end; ++iter, ++i) {
1906 (*iter)->UpdateChunks(NULL);
1912 const int iSamples = (pSamples) ?
int(pSamples->size()) : 0;
1913 int iPtblOffsetSize = (b64BitWavePoolOffsets) ? 8 : 4;
1915 if (!ptbl) ptbl = pRIFF->
AddSubChunk(CHUNK_ID_PTBL, 1 );
1916 int iPtblSize = WavePoolHeaderSize + iPtblOffsetSize * iSamples;
1919 WavePoolCount = iSamples;
1920 store32(&pData[4], WavePoolCount);
1922 memset(&pData[WavePoolHeaderSize], 0, iPtblSize - WavePoolHeaderSize);
1929 __divide_progress(pProgress, &subprogress, 20.f, 1.f);
1932 SampleList::iterator iter = pSamples->begin();
1933 SampleList::iterator end = pSamples->end();
1934 for (
int i = 0; iter != end; ++iter, ++i) {
1937 __divide_progress(&subprogress, &subsubprogress, pSamples->size(), i);
1939 (*iter)->UpdateChunks(&subsubprogress);
1942 __notify_progress(&subprogress, 1.0);
1944 SampleList::iterator iter = pSamples->begin();
1945 SampleList::iterator end = pSamples->end();
1946 for (
int i = 0; iter != end; ++iter, ++i) {
1947 (*iter)->UpdateChunks(NULL);
1956 std::list<RIFF::File*> poolFiles;
1958 if (!ExtensionFiles.empty()) {
1959 std::list<RIFF::File*>::iterator it = ExtensionFiles.begin();
1960 for (; it != ExtensionFiles.end(); ++it) {
1966 const std::string oldName = (*it)->GetFileName();
1967 const bool isGigaPulseFile = (extensionOfPath(oldName) ==
"gx99");
1968 if (isGigaPulseFile)
1969 pGigaPulseFile = *it;
1971 poolFiles.push_back(*it);
1977 if (!poolFiles.empty()) {
1978 const int n = poolFiles.size();
1979 const int iHeaderSize = 4;
1980 const int iEntrySize = 144;
1985 ckXfil->
Resize(iHeaderSize + n * iEntrySize);
1987 ckXfil = pRIFF->
AddSubChunk(CHUNK_ID_XFIL, iHeaderSize + n * iEntrySize);
1993 std::list<RIFF::File*>::iterator itExtFile = poolFiles.begin();
1994 for (
int i = 0, iOffset = 4; i < n;
1995 ++itExtFile, ++i, iOffset += iEntrySize)
1998 std::string file = lastPathComponent(
1999 (*itExtFile)->GetFileName()
2001 if (file.length() + 6 > 128)
2002 throw Exception(
"Fatal error, extension filename length exceeds 122 byte maximum");
2003 uint8_t* pStrings = &pData[iOffset];
2004 memset(pStrings, 0, 128);
2005 memcpy(pStrings, file.c_str(), file.length());
2006 pStrings += file.length() + 1;
2007 std::string ext = file.substr(file.length()-5);
2008 memcpy(pStrings, ext.c_str(), 5);
2010 uint8_t* pId = &pData[iOffset + 128];
2012 RIFF::Chunk* ckDLSID = (*itExtFile)->GetSubChunk(CHUNK_ID_DLID);
2014 ckDLSID->
Read(&
id.ulData1, 1, 4);
2015 ckDLSID->
Read(&
id.usData2, 1, 2);
2016 ckDLSID->
Read(&
id.usData3, 1, 2);
2017 ckDLSID->
Read(
id.abData, 8, 1);
2019 ckDLSID = (*itExtFile)->AddSubChunk(CHUNK_ID_DLID, 16);
2022 store32(&pData[0],
id.ulData1);
2023 store16(&pData[4],
id.usData2);
2024 store16(&pData[6],
id.usData3);
2025 memcpy(&pData[8],
id.abData, 8);
2027 store32(&pId[0],
id.ulData1);
2028 store16(&pId[4],
id.usData2);
2029 store16(&pId[6],
id.usData3);
2030 memcpy(&pId[8],
id.abData, 8);
2040 if (pGigaPulseFile) {
2042 if (!ckDoxf) ckDoxf = pRIFF->
AddSubChunk(CHUNK_ID_DOXF, 148);
2047 uint8_t* pId = &pData[132];
2050 throw Exception(
"Fatal error, GigaPulse file does not contain a DLS ID chunk");
2055 id.ulData1 = load32(&pData[0]);
2056 id.usData2 = load16(&pData[4]);
2057 id.usData3 = load16(&pData[6]);
2058 memcpy(
id.abData, &pData[8], 8);
2060 store32(&pId[0],
id.ulData1);
2061 store16(&pId[4],
id.usData2);
2062 store16(&pId[6],
id.usData3);
2063 memcpy(&pId[8],
id.abData, 8);
2076 const bool bRequires64Bit = (finalFileSize >> 32) != 0 ||
2077 poolFiles.size() > 0;
2078 if (b64BitWavePoolOffsets != bRequires64Bit) {
2079 b64BitWavePoolOffsets = bRequires64Bit;
2080 iPtblOffsetSize = (b64BitWavePoolOffsets) ? 8 : 4;
2081 iPtblSize = WavePoolHeaderSize + iPtblOffsetSize * iSamples;
2086 __notify_progress(pProgress, 1.0);
2105 const size_t nExtFiles = ExtensionFiles.size();
2106 const float tasks = 2.f + nExtFiles;
2109 if (!ExtensionFiles.empty()) {
2111 const std::string baseName = pathWithoutExtension(Path);
2113 std::list<RIFF::File*>::iterator it = ExtensionFiles.begin();
2114 for (
int i = 0; it != ExtensionFiles.end(); ++i, ++it) {
2120 const std::string oldName = (*it)->GetFileName();
2121 const bool isGigaPulseFile = (extensionOfPath(oldName) ==
"gx99");
2122 std::string ext = (isGigaPulseFile) ?
".gx99" : strPrint(
".gx%02d", i+1);
2123 std::string newPath = baseName + ext;
2128 __divide_progress(pProgress, &subprogress, tasks, 0.f + i);
2130 (*it)->Save(newPath, &subprogress);
2132 (*it)->Save(newPath);
2139 __divide_progress(pProgress, &subprogress, tasks, 1.f + nExtFiles);
2148 __divide_progress(pProgress, &subprogress, tasks, 2.f + nExtFiles);
2150 pRIFF->
Save(Path, &subprogress);
2157 __notify_progress(pProgress, 1.0);
2172 const size_t nExtFiles = ExtensionFiles.size();
2173 const float tasks = 2.f + nExtFiles;
2176 if (!ExtensionFiles.empty()) {
2177 std::list<RIFF::File*>::iterator it = ExtensionFiles.begin();
2178 for (
int i = 0; it != ExtensionFiles.end(); ++i, ++it) {
2183 __divide_progress(pProgress, &subprogress, tasks, 0.f + i);
2185 (*it)->Save(&subprogress);
2194 __divide_progress(pProgress, &subprogress, tasks, 1.f + nExtFiles);
2203 __divide_progress(pProgress, &subprogress, tasks, 2.f + nExtFiles);
2205 pRIFF->
Save(&subprogress);
2212 __notify_progress(pProgress, 1.0);
2226 __UpdateWavePoolTableChunk();
2237 if (!lstInstruments) pRIFF->
AddSubList(LIST_TYPE_LINS);
2241 const int iOffsetSize = (b64BitWavePoolOffsets) ? 8 : 4;
2242 ptbl = pRIFF->
AddSubChunk(CHUNK_ID_PTBL, WavePoolHeaderSize + iOffsetSize);
2246 if (!wvpl) pRIFF->
AddSubList(LIST_TYPE_WVPL);
2258 void File::__UpdateWavePoolTableChunk() {
2259 __UpdateWavePoolTable();
2261 const int iOffsetSize = (b64BitWavePoolOffsets) ? 8 : 4;
2263 WavePoolCount = (pSamples) ? uint32_t(pSamples->size()) : 0;
2264 const file_offset_t ulRequiredSize = WavePoolHeaderSize + iOffsetSize * WavePoolCount;
2265 if (ptbl->
GetSize() < ulRequiredSize)
throw Exception(
"Fatal error, 'ptbl' chunk too small");
2267 file_offset_t ullOriginalPos = ptbl->
GetPos();
2270 uint32_t tmp = WavePoolHeaderSize;
2272 tmp = WavePoolCount;
2275 ptbl->
SetPos(WavePoolHeaderSize);
2276 if (b64BitWavePoolOffsets) {
2277 for (
int i = 0 ; i < WavePoolCount ; i++) {
2278 tmp = pWavePoolTableHi[i];
2280 tmp = pWavePoolTable[i];
2284 for (
int i = 0 ; i < WavePoolCount ; i++) {
2285 tmp = pWavePoolTable[i];
2290 ptbl->
SetPos(ullOriginalPos);
2298 void File::__UpdateWavePoolTable() {
2299 WavePoolCount = (pSamples) ? uint32_t(pSamples->size()) : 0;
2301 if (pWavePoolTable)
delete[] pWavePoolTable;
2302 if (pWavePoolTableHi)
delete[] pWavePoolTableHi;
2303 pWavePoolTable =
new uint32_t[WavePoolCount];
2304 pWavePoolTableHi =
new uint32_t[WavePoolCount];
2305 if (!pSamples)
return;
2308 uint64_t wvplFileOffset = wvpl->
GetFilePos() -
2310 if (!b64BitWavePoolOffsets) {
2311 SampleList::iterator iter = pSamples->begin();
2312 SampleList::iterator end = pSamples->end();
2313 for (
int i = 0 ; iter != end ; ++iter, i++) {
2314 uint64_t _64BitOffset =
2315 (*iter)->pWaveList->GetFilePos() -
2316 (*iter)->pWaveList->GetPos() -
2319 (*iter)->ullWavePoolOffset = _64BitOffset;
2320 pWavePoolTable[i] = (uint32_t) _64BitOffset;
2323 if (ExtensionFiles.empty()) {
2324 SampleList::iterator iter = pSamples->begin();
2325 SampleList::iterator end = pSamples->end();
2326 for (
int i = 0 ; iter != end ; ++iter, i++) {
2327 uint64_t _64BitOffset =
2328 (*iter)->pWaveList->GetFilePos() -
2329 (*iter)->pWaveList->GetPos() -
2332 (*iter)->ullWavePoolOffset = _64BitOffset;
2333 pWavePoolTableHi[i] = (uint32_t) (_64BitOffset >> 32);
2334 pWavePoolTable[i] = (uint32_t) _64BitOffset;
2338 std::vector<RIFF::File*> poolFiles;
2339 poolFiles.push_back(pRIFF);
2340 poolFiles.insert(poolFiles.end(), ExtensionFiles.begin(), ExtensionFiles.end());
2345 SampleList::iterator iter = pSamples->begin();
2346 SampleList::iterator end = pSamples->end();
2347 for (
int i = 0 ; iter != end ; ++iter, i++) {
2351 if (pPoolFile != pCurPoolFile) {
2352 pCurPoolFile = pPoolFile;
2354 std::vector<RIFF::File*>::iterator sIter;
2355 sIter = std::find(poolFiles.begin(), poolFiles.end(), pPoolFile);
2356 if (sIter != poolFiles.end())
2357 fileNo = std::distance(poolFiles.begin(), sIter);
2363 throw DLS::Exception(
"Fatal error, pool file has no 'wvpl' list chunk");
2369 uint64_t _64BitOffset =
2370 (*iter)->pWaveList->GetFilePos() -
2371 (*iter)->pWaveList->GetPos() -
2374 pWavePoolTableHi[i] = (uint32_t) fileNo;
2375 pWavePoolTable[i] = (uint32_t) _64BitOffset;
2376 (*iter)->ullWavePoolOffset = _64BitOffset;
2386 Exception::Exception() :
RIFF::Exception() {
2389 Exception::Exception(String format, ...) :
RIFF::Exception() {
2391 va_start(arg, format);
2392 Message = assemble(format, arg);
2396 Exception::Exception(String format, va_list arg) :
RIFF::Exception() {
2397 Message = assemble(format, arg);
2400 void Exception::PrintMessage() {
2401 std::cout <<
"DLS::Exception: " << Message << std::endl;
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.
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 * 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.
bool bOwningRiff
If true then pRIFF was implicitly allocated by this class and hence pRIFF will automatically be freed...
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.
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.
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
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.
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.
file_offset_t GetRequiredFileSize()
Returns the required size (in bytes) for this RIFF File to be saved to disk.
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 * GetFirstSubList()
Returns the first sublist within the list (that is a subchunk with chunk ID "LIST").
List * AddSubList(uint32_t uiListType)
Creates a new list sub chunk.
Chunk * GetFirstSubChunk()
Returns the first subchunk within the list (which may be an ordinary chunk as well as a list chunk).
void DeleteSubChunk(Chunk *pSubChunk)
Removes a sub chunk.
List * GetSubList(uint32_t ListType)
Returns sublist chunk with list type ListType within this chunk list.
Chunk * GetNextSubChunk()
Returns the next subchunk within the list (which may be an ordinary chunk as well as a list chunk).
uint32_t GetListType() const
Returns unsigned integer representation of the list's ID.
List * GetNextSubList()
Returns the next sublist (that is a subchunk with chunk ID "LIST") within the list.
Chunk * AddSubChunk(uint32_t uiChunkID, file_offset_t ullBodySize)
Creates a new sub chunk.
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.