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) // CC0 67 #define MIDI_BANK_FINE(x) (x & 0x0000007F) // CC32 68 #define MIDI_BANK_MERGE(coarse, fine) ((((uint16_t) coarse) << 7) | fine) // CC0 + CC32 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;
134 for (uint32_t i = 0; i < Connections; i++) {
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);
140 pConnections[i].Init(&connblock);
144 Articulation::~Articulation() {
145 if (pConnections)
delete[] pConnections;
155 const int iEntrySize = 12;
156 pArticulationCk->Resize(HeaderSize + Connections * iEntrySize);
157 uint8_t* pData = (uint8_t*) pArticulationCk->LoadChunkData();
158 store16(&pData[0], HeaderSize);
159 store16(&pData[2], Connections);
160 for (uint32_t i = 0; i < Connections; i++) {
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();
322 pFixedStringLengths = NULL;
323 pResourceListChunk = list;
327 LoadString(CHUNK_ID_INAM, lstINFO, Name);
328 LoadString(CHUNK_ID_IARL, lstINFO, ArchivalLocation);
329 LoadString(CHUNK_ID_ICRD, lstINFO, CreationDate);
330 LoadString(CHUNK_ID_ICMT, lstINFO, Comments);
331 LoadString(CHUNK_ID_IPRD, lstINFO, Product);
332 LoadString(CHUNK_ID_ICOP, lstINFO, Copyright);
333 LoadString(CHUNK_ID_IART, lstINFO, Artists);
334 LoadString(CHUNK_ID_IGNR, lstINFO, Genre);
335 LoadString(CHUNK_ID_IKEY, lstINFO, Keywords);
336 LoadString(CHUNK_ID_IENG, lstINFO, Engineer);
337 LoadString(CHUNK_ID_ITCH, lstINFO, Technician);
338 LoadString(CHUNK_ID_ISFT, lstINFO, Software);
339 LoadString(CHUNK_ID_IMED, lstINFO, Medium);
340 LoadString(CHUNK_ID_ISRC, lstINFO, Source);
341 LoadString(CHUNK_ID_ISRF, lstINFO, SourceForm);
342 LoadString(CHUNK_ID_ICMS, lstINFO, Commissioned);
343 LoadString(CHUNK_ID_ISBJ, lstINFO, Subject);
363 pFixedStringLengths = lengths;
371 void Info::LoadString(uint32_t ChunkID,
RIFF::List* lstINFO, String& s) {
391 void Info::SaveString(uint32_t ChunkID,
RIFF::List* lstINFO,
const String& s,
const String& sDefault) {
393 if (pFixedStringLengths) {
394 for (
int i = 0 ; pFixedStringLengths[i].length ; i++) {
395 if (pFixedStringLengths[i].chunkId == ChunkID) {
396 size = pFixedStringLengths[i].length;
402 ::SaveString(ChunkID, ck, lstINFO, s, sDefault, size != 0, size);
413 if (!pResourceListChunk)
return;
418 String defaultName =
"";
419 String defaultCreationDate =
"";
420 String defaultSoftware =
"";
421 String defaultComments =
"";
423 uint32_t resourceType = pResourceListChunk->
GetListType();
426 lstINFO = pResourceListChunk->
AddSubList(LIST_TYPE_INFO);
429 defaultName =
"NONAME";
431 if (resourceType == RIFF_TYPE_DLS) {
433 time_t now = time(NULL);
434 tm* pNowBroken = localtime(&now);
436 strftime(buf, 11,
"%F", pNowBroken);
437 defaultCreationDate = buf;
441 if (resourceType == RIFF_TYPE_DLS || resourceType == LIST_TYPE_INS)
449 SaveString(CHUNK_ID_IARL, lstINFO, ArchivalLocation, String(
""));
450 SaveString(CHUNK_ID_IART, lstINFO, Artists, String(
""));
451 SaveString(CHUNK_ID_ICMS, lstINFO, Commissioned, String(
""));
452 SaveString(CHUNK_ID_ICMT, lstINFO, Comments, defaultComments);
453 SaveString(CHUNK_ID_ICOP, lstINFO, Copyright, String(
""));
454 SaveString(CHUNK_ID_ICRD, lstINFO, CreationDate, defaultCreationDate);
455 SaveString(CHUNK_ID_IENG, lstINFO, Engineer, String(
""));
456 SaveString(CHUNK_ID_IGNR, lstINFO, Genre, String(
""));
457 SaveString(CHUNK_ID_IKEY, lstINFO, Keywords, String(
""));
458 SaveString(CHUNK_ID_IMED, lstINFO, Medium, String(
""));
459 SaveString(CHUNK_ID_INAM, lstINFO, Name, defaultName);
460 SaveString(CHUNK_ID_IPRD, lstINFO, Product, String(
""));
461 SaveString(CHUNK_ID_ISBJ, lstINFO, Subject, String(
""));
462 SaveString(CHUNK_ID_ISFT, lstINFO, Software, defaultSoftware);
463 SaveString(CHUNK_ID_ISRC, lstINFO, Source, String(
""));
464 SaveString(CHUNK_ID_ISRF, lstINFO, SourceForm, String(
""));
465 SaveString(CHUNK_ID_ITCH, lstINFO, Technician, String(
""));
505 pFixedStringLengths = orig->pFixedStringLengths;
524 pResourceList = lstResource;
526 pInfo =
new Info(lstResource);
533 ckDLSID->
Read(&pDLSID->ulData1, 1, 4);
534 ckDLSID->
Read(&pDLSID->usData2, 1, 2);
535 ckDLSID->
Read(&pDLSID->usData3, 1, 2);
536 ckDLSID->
Read(pDLSID->abData, 8, 1);
541 Resource::~Resource() {
542 if (pDLSID)
delete pDLSID;
543 if (pInfo)
delete pInfo;
569 pInfo->UpdateChunks(pProgress);
573 RIFF::Chunk* ckDLSID = pResourceList->GetSubChunk(CHUNK_ID_DLID);
574 if (!ckDLSID) ckDLSID = pResourceList->AddSubChunk(CHUNK_ID_DLID, 16);
577 store32(&pData[0], pDLSID->ulData1);
578 store16(&pData[4], pDLSID->usData2);
579 store16(&pData[6], pDLSID->usData3);
580 memcpy(&pData[8], pDLSID->abData, 8);
588 #if defined(WIN32) || defined(__APPLE__) || defined(HAVE_UUID_GENERATE) 589 if (!pDLSID) pDLSID =
new dlsid_t;
590 GenerateDLSID(pDLSID);
598 pDLSID->ulData1 = uuid.Data1;
599 pDLSID->usData2 = uuid.Data2;
600 pDLSID->usData3 = uuid.Data3;
601 memcpy(pDLSID->abData, uuid.Data4, 8);
603 #elif defined(__APPLE__) 605 CFUUIDRef uuidRef = CFUUIDCreate(NULL);
606 CFUUIDBytes uuid = CFUUIDGetUUIDBytes(uuidRef);
608 pDLSID->ulData1 = uuid.byte0 | uuid.byte1 << 8 | uuid.byte2 << 16 | uuid.byte3 << 24;
609 pDLSID->usData2 = uuid.byte4 | uuid.byte5 << 8;
610 pDLSID->usData3 = uuid.byte6 | uuid.byte7 << 8;
611 pDLSID->abData[0] = uuid.byte8;
612 pDLSID->abData[1] = uuid.byte9;
613 pDLSID->abData[2] = uuid.byte10;
614 pDLSID->abData[3] = uuid.byte11;
615 pDLSID->abData[4] = uuid.byte12;
616 pDLSID->abData[5] = uuid.byte13;
617 pDLSID->abData[6] = uuid.byte14;
618 pDLSID->abData[7] = uuid.byte15;
619 #elif defined(HAVE_UUID_GENERATE) 622 pDLSID->ulData1 = uuid[0] | uuid[1] << 8 | uuid[2] << 16 | uuid[3] << 24;
623 pDLSID->usData2 = uuid[4] | uuid[5] << 8;
624 pDLSID->usData3 = uuid[6] | uuid[7] << 8;
625 memcpy(pDLSID->abData, &uuid[8], 8);
627 # error "Missing support for uuid generation" 638 pInfo->CopyAssign(orig->
pInfo);
646 pParentList = ParentList;
662 SamplerOptions = F_WSMP_NO_COMPRESSION;
665 NoSampleDepthTruncation = SamplerOptions & F_WSMP_NO_TRUNCATION;
666 NoSampleCompression = SamplerOptions & F_WSMP_NO_COMPRESSION;
667 pSampleLoops = (SampleLoops) ?
new sample_loop_t[SampleLoops] : NULL;
669 wsmp->
SetPos(uiHeaderSize);
670 for (uint32_t i = 0; i < SampleLoops; i++) {
671 wsmp->
Read(pSampleLoops + i, 4, 4);
679 Sampler::~Sampler() {
680 if (pSampleLoops)
delete[] pSampleLoops;
683 void Sampler::SetGain(int32_t gain) {
695 RIFF::Chunk* wsmp = pParentList->GetSubChunk(CHUNK_ID_WSMP);
696 int wsmpSize = uiHeaderSize + SampleLoops * 16;
698 wsmp = pParentList->AddSubChunk(CHUNK_ID_WSMP, wsmpSize);
699 }
else if (wsmp->
GetSize() != wsmpSize) {
704 store32(&pData[0], uiHeaderSize);
706 SamplerOptions = (NoSampleDepthTruncation) ? SamplerOptions | F_WSMP_NO_TRUNCATION
707 : SamplerOptions & (~F_WSMP_NO_TRUNCATION);
708 SamplerOptions = (NoSampleCompression) ? SamplerOptions | F_WSMP_NO_COMPRESSION
709 : SamplerOptions & (~F_WSMP_NO_COMPRESSION);
710 store16(&pData[4], UnityNote);
711 store16(&pData[6], FineTune);
712 store32(&pData[8], Gain);
713 store32(&pData[12], SamplerOptions);
714 store32(&pData[16], SampleLoops);
716 for (uint32_t i = 0; i < SampleLoops; i++) {
718 store32(&pData[uiHeaderSize + i * 16], pSampleLoops[i].Size);
719 store32(&pData[uiHeaderSize + i * 16 + 4], pSampleLoops[i].LoopType);
720 store32(&pData[uiHeaderSize + i * 16 + 8], pSampleLoops[i].LoopStart);
721 store32(&pData[uiHeaderSize + i * 16 + 12], pSampleLoops[i].LoopLength);
745 for (
int i = 0; i < SampleLoops; i++) {
746 pNewLoops[i] = pSampleLoops[i];
749 pNewLoops[SampleLoops] = *pLoopDef;
753 if (SampleLoops)
delete[] pSampleLoops;
754 pSampleLoops = pNewLoops;
767 for (
int i = 0, o = 0; i < SampleLoops; i++) {
768 if (&pSampleLoops[i] == pLoopDef)
continue;
769 if (o == SampleLoops - 1) {
771 throw Exception(
"Could not delete Sample Loop, because it does not exist");
773 pNewLoops[o] = pSampleLoops[i];
777 if (SampleLoops)
delete[] pSampleLoops;
778 pSampleLoops = pNewLoops;
790 UnityNote = orig->UnityNote;
791 FineTune = orig->FineTune;
793 NoSampleDepthTruncation = orig->NoSampleDepthTruncation;
794 NoSampleCompression = orig->NoSampleCompression;
795 SamplerOptions = orig->SamplerOptions;
798 if (SampleLoops)
delete[] pSampleLoops;
824 pWaveList = waveList;
924 const file_offset_t restorePos = pOrig->pCkData->
GetPos();
926 for (file_offset_t todo = pOrig->
GetSize(), i = 0; todo; ) {
927 const int iReadAtOnce = 64*1024;
928 file_offset_t n = (iReadAtOnce < todo) ? iReadAtOnce : todo;
929 n = pOrig->
Read(&buf[i], n);
934 pOrig->pCkData->
SetPos(restorePos);
987 if (
FormatTag != DLS_WAVE_FORMAT_PCM)
return 0;
1020 if (
FormatTag != DLS_WAVE_FORMAT_PCM)
throw Exception(
"Sample's format is not DLS_WAVE_FORMAT_PCM");
1021 if (NewSize < 1)
throw Exception(
"Sample size must be at least one sample point");
1022 if ((NewSize >> 48) != 0)
1023 throw Exception(
"Unrealistic high DLS sample size detected");
1024 const file_offset_t sizeInBytes = NewSize *
FrameSize;
1026 if (pCkData) pCkData->
Resize(sizeInBytes);
1027 else pCkData = pWaveList->
AddSubChunk(CHUNK_ID_DATA, sizeInBytes);
1047 if (
FormatTag != DLS_WAVE_FORMAT_PCM)
return 0;
1048 if (!pCkData)
throw Exception(
"No data chunk created for sample yet, call Sample::Resize() to create one");
1049 file_offset_t orderedBytes = SampleCount *
FrameSize;
1050 file_offset_t result = pCkData->
SetPos(orderedBytes, Whence);
1051 return (result == orderedBytes) ? SampleCount
1065 if (
FormatTag != DLS_WAVE_FORMAT_PCM)
return 0;
1085 if (
FormatTag != DLS_WAVE_FORMAT_PCM)
return 0;
1086 if (
GetSize() < SampleCount)
throw Exception(
"Could not write sample data, current sample size to small");
1100 throw Exception(
"Could not save sample, only PCM format is supported");
1103 throw Exception(
"Could not save sample, there is no sample data to save");
1108 if (!pCkFormat) pCkFormat = pWaveList->
AddSubChunk(CHUNK_ID_FMT, 16);
1125 pCkRegion = rgnList;
1132 rgnh->
Read(&KeyRange, 2, 2);
1133 rgnh->
Read(&VelocityRange, 2, 2);
1138 rgnh->
Read(&Layer, 1,
sizeof(uint16_t));
1142 KeyRange.high = 127;
1143 VelocityRange.low = 0;
1144 VelocityRange.high = 127;
1145 FormatOptionFlags = F_RGN_OPTION_SELFNONEXCLUSIVE;
1149 SelfNonExclusive = FormatOptionFlags & F_RGN_OPTION_SELFNONEXCLUSIVE;
1161 WaveLinkOptionFlags = 0;
1164 WavePoolTableIndex = 0;
1166 PhaseMaster = WaveLinkOptionFlags & F_WAVELINK_PHASE_MASTER;
1167 MultiChannel = WaveLinkOptionFlags & F_WAVELINK_MULTICHANNEL;
1192 RIFF::List* pParent = pCkRegion->GetParent();
1198 Sample* Region::GetSample() {
1199 if (pSample)
return pSample;
1200 File* file = (
File*) GetParent()->GetParent();
1201 uint64_t soughtoffset = file->pWavePoolTable[WavePoolTableIndex];
1206 if (sample->ullWavePoolOffset == soughtoffset)
return (pSample = sample);
1217 this->pSample = pSample;
1218 WavePoolTableIndex = 0;
1230 KeyRange.high = High;
1234 if (!pInstrument->pRegions) pInstrument->LoadRegions();
1235 if (!pInstrument->pRegions)
return;
1240 Region* prev_region = NULL;
1242 Instrument::RegionList::iterator iter = pInstrument->pRegions->begin();
1243 iter != pInstrument->pRegions->end(); iter++
1245 if ((*iter)->KeyRange.low > this->KeyRange.low) {
1249 prev_region = *iter;
1253 if (prev_region !=
this) pInstrument->MoveRegion(
this, r);
1265 RIFF::Chunk* rgnh = pCkRegion->GetSubChunk(CHUNK_ID_RGNH);
1266 if (!rgnh) rgnh = pCkRegion->AddSubChunk(CHUNK_ID_RGNH, Layer ? 14 : 12);
1268 FormatOptionFlags = (SelfNonExclusive)
1269 ? FormatOptionFlags | F_RGN_OPTION_SELFNONEXCLUSIVE
1270 : FormatOptionFlags & (~F_RGN_OPTION_SELFNONEXCLUSIVE);
1272 store16(&pData[0], KeyRange.low);
1273 store16(&pData[2], KeyRange.high);
1274 store16(&pData[4], VelocityRange.low);
1275 store16(&pData[6], VelocityRange.high);
1276 store16(&pData[8], FormatOptionFlags);
1277 store16(&pData[10], KeyGroup);
1278 if (rgnh->
GetSize() >= 14) store16(&pData[12], Layer);
1286 RIFF::Chunk* wlnk = pCkRegion->GetSubChunk(CHUNK_ID_WLNK);
1287 if (!wlnk) wlnk = pCkRegion->AddSubChunk(CHUNK_ID_WLNK, 12);
1289 WaveLinkOptionFlags = (PhaseMaster)
1290 ? WaveLinkOptionFlags | F_WAVELINK_PHASE_MASTER
1291 : WaveLinkOptionFlags & (~F_WAVELINK_PHASE_MASTER);
1292 WaveLinkOptionFlags = (MultiChannel)
1293 ? WaveLinkOptionFlags | F_WAVELINK_MULTICHANNEL
1294 : WaveLinkOptionFlags & (~F_WAVELINK_MULTICHANNEL);
1297 File* pFile = (
File*) GetParent()->GetParent();
1298 if (pFile->pSamples) {
1299 File::SampleList::iterator iter = pFile->pSamples->begin();
1300 File::SampleList::iterator end = pFile->pSamples->end();
1301 for (
int i = 0; iter != end; ++iter, i++) {
1302 if (*iter == pSample) {
1308 WavePoolTableIndex = index;
1310 store16(&pData[0], WaveLinkOptionFlags);
1311 store16(&pData[2], PhaseGroup);
1312 store32(&pData[4], Channel);
1313 store32(&pData[8], WavePoolTableIndex);
1332 VelocityRange = orig->VelocityRange;
1333 KeyGroup = orig->KeyGroup;
1334 Layer = orig->Layer;
1335 SelfNonExclusive = orig->SelfNonExclusive;
1336 PhaseMaster = orig->PhaseMaster;
1337 PhaseGroup = orig->PhaseGroup;
1338 MultiChannel = orig->MultiChannel;
1339 Channel = orig->Channel;
1342 if (GetParent()->GetParent() == orig->GetParent()->GetParent()) {
1343 WavePoolTableIndex = orig->WavePoolTableIndex;
1344 pSample = orig->pSample;
1346 WavePoolTableIndex = -1;
1349 FormatOptionFlags = orig->FormatOptionFlags;
1350 WaveLinkOptionFlags = orig->WaveLinkOptionFlags;
1373 pCkInstrument = insList;
1375 midi_locale_t locale;
1381 insh->
Read(&locale, 2, 4);
1385 locale.instrument = 0;
1389 IsDrum = locale.bank & DRUM_TYPE_MASK;
1403 if (!pRegions) LoadRegions();
1404 if (!pRegions)
return 0;
1405 return pRegions->size();
1419 if (!pRegions) LoadRegions();
1420 if (!pRegions)
return NULL;
1421 if (pos >= pRegions->size())
return NULL;
1422 return (*pRegions)[pos];
1435 if (!pRegions) LoadRegions();
1436 if (!pRegions)
return NULL;
1437 RegionsIterator = pRegions->begin();
1438 return (RegionsIterator != pRegions->end()) ? *RegionsIterator : NULL;
1452 if (!pRegions)
return NULL;
1454 return (RegionsIterator != pRegions->end()) ? *RegionsIterator : NULL;
1457 void Instrument::LoadRegions() {
1458 if (!pRegions) pRegions =
new RegionList;
1461 uint32_t regionCkType = (lrgn->
GetSubList(LIST_TYPE_RGN2)) ? LIST_TYPE_RGN2 : LIST_TYPE_RGN;
1466 if (rgn->GetListType() == regionCkType) {
1467 pRegions->push_back(
new Region(
this, rgn));
1473 Region* Instrument::AddRegion() {
1474 if (!pRegions) LoadRegions();
1476 if (!lrgn) lrgn = pCkInstrument->
AddSubList(LIST_TYPE_LRGN);
1479 const size_t idxIt = RegionsIterator - pRegions->begin();
1480 pRegions->push_back(pNewRegion);
1481 RegionsIterator = pRegions->begin() + std::min(idxIt, pRegions->size());
1482 Regions = (uint32_t) pRegions->size();
1486 void Instrument::MoveRegion(
Region* pSrc,
Region* pDst) {
1489 for (
size_t i = 0; i < pRegions->size(); ++i) {
1490 if ((*pRegions)[i] == pSrc) {
1491 const size_t idxIt = RegionsIterator - pRegions->begin();
1492 pRegions->erase(pRegions->begin() + i);
1493 RegionList::iterator iter = find(pRegions->begin(), pRegions->end(), pDst);
1494 pRegions->insert(iter, pSrc);
1495 RegionsIterator = pRegions->begin() + std::min(idxIt, pRegions->size());
1500 void Instrument::DeleteRegion(
Region* pRegion) {
1501 if (!pRegions)
return;
1502 RegionList::iterator iter = find(pRegions->begin(), pRegions->end(), pRegion);
1503 if (iter == pRegions->end())
return;
1504 const size_t idxIt = RegionsIterator - pRegions->begin();
1505 pRegions->erase(iter);
1506 RegionsIterator = pRegions->begin() + std::min(idxIt, pRegions->size());
1507 Regions = (uint32_t) pRegions->size();
1525 if (!insh) insh = pCkInstrument->
AddSubChunk(CHUNK_ID_INSH, 12);
1528 Regions = (pRegions) ? uint32_t(pRegions->size()) : 0;
1529 midi_locale_t locale;
1532 locale.bank = (
IsDrum) ? locale.bank | DRUM_TYPE_MASK : locale.bank & (~DRUM_TYPE_MASK);
1535 store32(&pData[4], locale.bank);
1536 store32(&pData[8], locale.instrument);
1538 if (!pRegions)
return;
1539 RegionList::iterator iter = pRegions->begin();
1540 RegionList::iterator end = pRegions->end();
1541 for (
int i = 0; iter != end; ++iter, ++i) {
1545 __divide_progress(pProgress, &subprogress, pRegions->size(), i);
1547 (*iter)->UpdateChunks(&subprogress);
1549 (*iter)->UpdateChunks(NULL);
1552 __notify_progress(pProgress, 1.0);
1561 RegionList::iterator iter = pRegions->begin();
1562 RegionList::iterator end = pRegions->end();
1563 while (iter != end) {
1582 RegionList::iterator it = pRegions->begin();
1583 RegionList::iterator end = pRegions->end();
1584 for (; it != end; ++it)
1585 (*it)->DeleteChunks();
1589 if (pCkInstrument) {
1592 pCkInstrument = NULL;
1596 void Instrument::CopyAssignCore(
const Instrument* orig) {
1619 CopyAssignCore(orig);
1624 RegionList::const_iterator it = orig->pRegions->begin();
1625 for (
int i = 0; i < orig->
Regions; ++i, ++it) {
1626 Region* dstRgn = AddRegion();
1654 pWavePoolTable = NULL;
1655 pWavePoolTableHi = NULL;
1656 WavePoolHeaderSize = 8;
1659 pInstruments = NULL;
1661 b64BitWavePoolOffsets =
false;
1674 if (!pRIFF)
throw DLS::Exception(
"NULL pointer reference to RIFF::File object.");
1675 this->pRIFF = pRIFF;
1687 if (!colh)
throw DLS::Exception(
"Mandatory chunks in RIFF list chunk not found.");
1694 pWavePoolTable = NULL;
1695 pWavePoolTableHi = NULL;
1696 WavePoolHeaderSize = 8;
1697 b64BitWavePoolOffsets =
false;
1703 pWavePoolTable =
new uint32_t[WavePoolCount];
1704 pWavePoolTableHi =
new uint32_t[WavePoolCount];
1705 ptbl->
SetPos(WavePoolHeaderSize);
1708 b64BitWavePoolOffsets = (ptbl->
GetSize() - WavePoolHeaderSize == WavePoolCount * 8);
1709 if (b64BitWavePoolOffsets) {
1710 for (
int i = 0 ; i < WavePoolCount ; i++) {
1718 ptbl->
Read(pWavePoolTable, WavePoolCount,
sizeof(uint32_t));
1719 for (
int i = 0 ; i < WavePoolCount ; i++) pWavePoolTableHi[i] = 0;
1724 pInstruments = NULL;
1729 InstrumentList::iterator iter = pInstruments->begin();
1730 InstrumentList::iterator end = pInstruments->end();
1731 while (iter != end) {
1735 delete pInstruments;
1739 SampleList::iterator iter = pSamples->begin();
1740 SampleList::iterator end = pSamples->end();
1741 while (iter != end) {
1748 if (pWavePoolTable)
delete[] pWavePoolTable;
1749 if (pWavePoolTableHi)
delete[] pWavePoolTableHi;
1751 for (std::list<RIFF::File*>::iterator i = ExtensionFiles.begin() ; i != ExtensionFiles.end() ; i++)
1764 if (!pSamples) LoadSamples();
1765 if (!pSamples)
return NULL;
1766 if (index >= pSamples->size())
return NULL;
1767 return (*pSamples)[index];
1778 if (!pSamples) LoadSamples();
1779 if (!pSamples)
return NULL;
1780 SamplesIterator = pSamples->begin();
1781 return (SamplesIterator != pSamples->end()) ? *SamplesIterator : NULL;
1792 if (!pSamples)
return NULL;
1794 return (SamplesIterator != pSamples->end()) ? *SamplesIterator : NULL;
1797 void File::LoadSamples() {
1798 if (!pSamples) pSamples =
new SampleList;
1801 file_offset_t wvplFileOffset = wvpl->
GetFilePos() -
1807 if (wave->GetListType() == LIST_TYPE_WAVE) {
1808 file_offset_t waveFileOffset = wave->GetFilePos() -
1810 pSamples->push_back(
new Sample(
this, wave, waveFileOffset - wvplFileOffset));
1817 file_offset_t dwplFileOffset = dwpl->
GetFilePos() -
1823 if (wave->GetListType() == LIST_TYPE_WAVE) {
1824 file_offset_t waveFileOffset = wave->GetFilePos() -
1826 pSamples->push_back(
new Sample(
this, wave, waveFileOffset - dwplFileOffset));
1841 if (!pSamples) LoadSamples();
1847 const size_t idxIt = SamplesIterator - pSamples->begin();
1848 pSamples->push_back(pSample);
1849 SamplesIterator = pSamples->begin() + std::min(idxIt, pSamples->size());
1861 if (!pSamples)
return;
1862 SampleList::iterator iter = find(pSamples->begin(), pSamples->end(), pSample);
1863 if (iter == pSamples->end())
return;
1864 const size_t idxIt = SamplesIterator - pSamples->begin();
1865 pSamples->erase(iter);
1866 SamplesIterator = pSamples->begin() + std::min(idxIt, pSamples->size());
1879 if (!pInstruments) LoadInstruments();
1880 if (!pInstruments)
return NULL;
1881 if (index >= pInstruments->size())
return NULL;
1882 return (*pInstruments)[index];
1893 if (!pInstruments) LoadInstruments();
1894 if (!pInstruments)
return NULL;
1895 InstrumentsIterator = pInstruments->begin();
1896 return (InstrumentsIterator != pInstruments->end()) ? *InstrumentsIterator : NULL;
1907 if (!pInstruments)
return NULL;
1908 InstrumentsIterator++;
1909 return (InstrumentsIterator != pInstruments->end()) ? *InstrumentsIterator : NULL;
1912 void File::LoadInstruments() {
1913 if (!pInstruments) pInstruments =
new InstrumentList;
1915 if (lstInstruments) {
1918 lstInstr; lstInstr = lstInstruments->
GetSubListAt(++i))
1920 if (lstInstr->GetListType() == LIST_TYPE_INS) {
1921 pInstruments->push_back(
new Instrument(
this, lstInstr));
1935 if (!pInstruments) LoadInstruments();
1940 const size_t idxIt = InstrumentsIterator - pInstruments->begin();
1941 pInstruments->push_back(pInstrument);
1942 InstrumentsIterator = pInstruments->begin() + std::min(idxIt, pInstruments->size());
1954 if (!pInstruments)
return;
1955 InstrumentList::iterator iter = find(pInstruments->begin(), pInstruments->end(), pInstrument);
1956 if (iter == pInstruments->end())
return;
1957 const size_t idxIt = InstrumentsIterator - pInstruments->begin();
1958 pInstruments->erase(iter);
1959 InstrumentsIterator = pInstruments->begin() + std::min(idxIt, pInstruments->size());
1985 if (index < 0 || index >= ExtensionFiles.size())
return NULL;
1986 std::list<RIFF::File*>::iterator iter = ExtensionFiles.begin();
1987 for (
int i = 0; iter != ExtensionFiles.end(); ++iter, ++i)
1988 if (i == index)
return *iter;
2002 return pRIFF->GetFileName();
2010 pRIFF->SetFileName(name);
2028 if (!ckVersion) ckVersion = pRIFF->
AddSubChunk(CHUNK_ID_VERS, 8);
2030 store16(&pData[0],
pVersion->minor);
2031 store16(&pData[2],
pVersion->major);
2032 store16(&pData[4],
pVersion->build);
2033 store16(&pData[6],
pVersion->release);
2037 Instruments = (pInstruments) ? uint32_t(pInstruments->size()) : 0;
2039 if (!colh) colh = pRIFF->
AddSubChunk(CHUNK_ID_COLH, 4);
2048 __divide_progress(pProgress, &subprogress, 20.f, 0.f);
2051 InstrumentList::iterator iter = pInstruments->begin();
2052 InstrumentList::iterator end = pInstruments->end();
2053 for (
int i = 0; iter != end; ++iter, ++i) {
2056 __divide_progress(&subprogress, &subsubprogress, pInstruments->size(), i);
2058 (*iter)->UpdateChunks(&subsubprogress);
2061 __notify_progress(&subprogress, 1.0);
2063 InstrumentList::iterator iter = pInstruments->begin();
2064 InstrumentList::iterator end = pInstruments->end();
2065 for (
int i = 0; iter != end; ++iter, ++i) {
2066 (*iter)->UpdateChunks(NULL);
2072 const int iSamples = (pSamples) ?
int(pSamples->size()) : 0;
2073 int iPtblOffsetSize = (b64BitWavePoolOffsets) ? 8 : 4;
2075 if (!ptbl) ptbl = pRIFF->
AddSubChunk(CHUNK_ID_PTBL, 1 );
2076 int iPtblSize = WavePoolHeaderSize + iPtblOffsetSize * iSamples;
2079 WavePoolCount = iSamples;
2080 store32(&pData[4], WavePoolCount);
2082 memset(&pData[WavePoolHeaderSize], 0, iPtblSize - WavePoolHeaderSize);
2089 __divide_progress(pProgress, &subprogress, 20.f, 1.f);
2092 SampleList::iterator iter = pSamples->begin();
2093 SampleList::iterator end = pSamples->end();
2094 for (
int i = 0; iter != end; ++iter, ++i) {
2097 __divide_progress(&subprogress, &subsubprogress, pSamples->size(), i);
2099 (*iter)->UpdateChunks(&subsubprogress);
2102 __notify_progress(&subprogress, 1.0);
2104 SampleList::iterator iter = pSamples->begin();
2105 SampleList::iterator end = pSamples->end();
2106 for (
int i = 0; iter != end; ++iter, ++i) {
2107 (*iter)->UpdateChunks(NULL);
2116 std::list<RIFF::File*> poolFiles;
2118 if (!ExtensionFiles.empty()) {
2119 std::list<RIFF::File*>::iterator it = ExtensionFiles.begin();
2120 for (; it != ExtensionFiles.end(); ++it) {
2126 const std::string oldName = (*it)->GetFileName();
2127 const bool isGigaPulseFile = (extensionOfPath(oldName) ==
"gx99");
2128 if (isGigaPulseFile)
2129 pGigaPulseFile = *it;
2131 poolFiles.push_back(*it);
2137 if (!poolFiles.empty()) {
2138 const int n = poolFiles.size();
2139 const int iHeaderSize = 4;
2140 const int iEntrySize = 144;
2145 ckXfil->
Resize(iHeaderSize + n * iEntrySize);
2147 ckXfil = pRIFF->
AddSubChunk(CHUNK_ID_XFIL, iHeaderSize + n * iEntrySize);
2153 std::list<RIFF::File*>::iterator itExtFile = poolFiles.begin();
2154 for (
int i = 0, iOffset = 4; i < n;
2155 ++itExtFile, ++i, iOffset += iEntrySize)
2158 std::string file = lastPathComponent(
2159 (*itExtFile)->GetFileName()
2161 if (file.length() + 6 > 128)
2162 throw Exception(
"Fatal error, extension filename length exceeds 122 byte maximum");
2163 uint8_t* pStrings = &pData[iOffset];
2164 memset(pStrings, 0, 128);
2165 memcpy(pStrings, file.c_str(), file.length());
2166 pStrings += file.length() + 1;
2167 std::string ext = file.substr(file.length()-5);
2168 memcpy(pStrings, ext.c_str(), 5);
2170 uint8_t* pId = &pData[iOffset + 128];
2172 RIFF::Chunk* ckDLSID = (*itExtFile)->GetSubChunk(CHUNK_ID_DLID);
2174 ckDLSID->
Read(&
id.ulData1, 1, 4);
2175 ckDLSID->
Read(&
id.usData2, 1, 2);
2176 ckDLSID->
Read(&
id.usData3, 1, 2);
2177 ckDLSID->
Read(
id.abData, 8, 1);
2179 ckDLSID = (*itExtFile)->AddSubChunk(CHUNK_ID_DLID, 16);
2182 store32(&pData[0],
id.ulData1);
2183 store16(&pData[4],
id.usData2);
2184 store16(&pData[6],
id.usData3);
2185 memcpy(&pData[8],
id.abData, 8);
2187 store32(&pId[0],
id.ulData1);
2188 store16(&pId[4],
id.usData2);
2189 store16(&pId[6],
id.usData3);
2190 memcpy(&pId[8],
id.abData, 8);
2200 if (pGigaPulseFile) {
2202 if (!ckDoxf) ckDoxf = pRIFF->
AddSubChunk(CHUNK_ID_DOXF, 148);
2207 uint8_t* pId = &pData[132];
2210 throw Exception(
"Fatal error, GigaPulse file does not contain a DLS ID chunk");
2215 id.ulData1 = load32(&pData[0]);
2216 id.usData2 = load16(&pData[4]);
2217 id.usData3 = load16(&pData[6]);
2218 memcpy(
id.abData, &pData[8], 8);
2220 store32(&pId[0],
id.ulData1);
2221 store16(&pId[4],
id.usData2);
2222 store16(&pId[6],
id.usData3);
2223 memcpy(&pId[8],
id.abData, 8);
2236 const bool bRequires64Bit = (finalFileSize >> 32) != 0 ||
2237 poolFiles.size() > 0;
2238 if (b64BitWavePoolOffsets != bRequires64Bit) {
2239 b64BitWavePoolOffsets = bRequires64Bit;
2240 iPtblOffsetSize = (b64BitWavePoolOffsets) ? 8 : 4;
2241 iPtblSize = WavePoolHeaderSize + iPtblOffsetSize * iSamples;
2246 __notify_progress(pProgress, 1.0);
2265 const size_t nExtFiles = ExtensionFiles.size();
2266 const float tasks = 2.f + nExtFiles;
2269 if (!ExtensionFiles.empty()) {
2271 const std::string baseName = pathWithoutExtension(Path);
2273 std::list<RIFF::File*>::iterator it = ExtensionFiles.begin();
2274 for (
int i = 0; it != ExtensionFiles.end(); ++i, ++it) {
2280 const std::string oldName = (*it)->GetFileName();
2281 const bool isGigaPulseFile = (extensionOfPath(oldName) ==
"gx99");
2282 std::string ext = (isGigaPulseFile) ?
".gx99" : strPrint(
".gx%02d", i+1);
2283 std::string newPath = baseName + ext;
2288 __divide_progress(pProgress, &subprogress, tasks, 0.f + i);
2290 (*it)->Save(newPath, &subprogress);
2292 (*it)->Save(newPath);
2299 __divide_progress(pProgress, &subprogress, tasks, 1.f + nExtFiles);
2308 __divide_progress(pProgress, &subprogress, tasks, 2.f + nExtFiles);
2310 pRIFF->
Save(Path, &subprogress);
2317 __notify_progress(pProgress, 1.0);
2332 const size_t nExtFiles = ExtensionFiles.size();
2333 const float tasks = 2.f + nExtFiles;
2336 if (!ExtensionFiles.empty()) {
2337 std::list<RIFF::File*>::iterator it = ExtensionFiles.begin();
2338 for (
int i = 0; it != ExtensionFiles.end(); ++i, ++it) {
2343 __divide_progress(pProgress, &subprogress, tasks, 0.f + i);
2345 (*it)->Save(&subprogress);
2354 __divide_progress(pProgress, &subprogress, tasks, 1.f + nExtFiles);
2363 __divide_progress(pProgress, &subprogress, tasks, 2.f + nExtFiles);
2365 pRIFF->
Save(&subprogress);
2372 __notify_progress(pProgress, 1.0);
2386 __UpdateWavePoolTableChunk();
2397 if (!lstInstruments) pRIFF->
AddSubList(LIST_TYPE_LINS);
2401 const int iOffsetSize = (b64BitWavePoolOffsets) ? 8 : 4;
2402 ptbl = pRIFF->
AddSubChunk(CHUNK_ID_PTBL, WavePoolHeaderSize + iOffsetSize);
2406 if (!wvpl) pRIFF->
AddSubList(LIST_TYPE_WVPL);
2418 void File::__UpdateWavePoolTableChunk() {
2419 __UpdateWavePoolTable();
2421 const int iOffsetSize = (b64BitWavePoolOffsets) ? 8 : 4;
2423 WavePoolCount = (pSamples) ? uint32_t(pSamples->size()) : 0;
2424 const file_offset_t ulRequiredSize = WavePoolHeaderSize + iOffsetSize * WavePoolCount;
2425 if (ptbl->
GetSize() < ulRequiredSize)
throw Exception(
"Fatal error, 'ptbl' chunk too small");
2427 file_offset_t ullOriginalPos = ptbl->
GetPos();
2430 uint32_t tmp = WavePoolHeaderSize;
2432 tmp = WavePoolCount;
2435 ptbl->
SetPos(WavePoolHeaderSize);
2436 if (b64BitWavePoolOffsets) {
2437 for (
int i = 0 ; i < WavePoolCount ; i++) {
2438 tmp = pWavePoolTableHi[i];
2440 tmp = pWavePoolTable[i];
2444 for (
int i = 0 ; i < WavePoolCount ; i++) {
2445 tmp = pWavePoolTable[i];
2450 ptbl->
SetPos(ullOriginalPos);
2458 void File::__UpdateWavePoolTable() {
2459 WavePoolCount = (pSamples) ? uint32_t(pSamples->size()) : 0;
2461 if (pWavePoolTable)
delete[] pWavePoolTable;
2462 if (pWavePoolTableHi)
delete[] pWavePoolTableHi;
2463 pWavePoolTable =
new uint32_t[WavePoolCount];
2464 pWavePoolTableHi =
new uint32_t[WavePoolCount];
2465 if (!pSamples)
return;
2468 uint64_t wvplFileOffset = wvpl->
GetFilePos() -
2470 if (!b64BitWavePoolOffsets) {
2471 SampleList::iterator iter = pSamples->begin();
2472 SampleList::iterator end = pSamples->end();
2473 for (
int i = 0 ; iter != end ; ++iter, i++) {
2474 uint64_t _64BitOffset =
2475 (*iter)->pWaveList->GetFilePos() -
2476 (*iter)->pWaveList->GetPos() -
2479 (*iter)->ullWavePoolOffset = _64BitOffset;
2480 pWavePoolTable[i] = (uint32_t) _64BitOffset;
2483 if (ExtensionFiles.empty()) {
2484 SampleList::iterator iter = pSamples->begin();
2485 SampleList::iterator end = pSamples->end();
2486 for (
int i = 0 ; iter != end ; ++iter, i++) {
2487 uint64_t _64BitOffset =
2488 (*iter)->pWaveList->GetFilePos() -
2489 (*iter)->pWaveList->GetPos() -
2492 (*iter)->ullWavePoolOffset = _64BitOffset;
2493 pWavePoolTableHi[i] = (uint32_t) (_64BitOffset >> 32);
2494 pWavePoolTable[i] = (uint32_t) _64BitOffset;
2498 std::vector<RIFF::File*> poolFiles;
2499 poolFiles.push_back(pRIFF);
2500 poolFiles.insert(poolFiles.end(), ExtensionFiles.begin(), ExtensionFiles.end());
2505 SampleList::iterator iter = pSamples->begin();
2506 SampleList::iterator end = pSamples->end();
2507 for (
int i = 0 ; iter != end ; ++iter, i++) {
2511 if (pPoolFile != pCurPoolFile) {
2512 pCurPoolFile = pPoolFile;
2514 std::vector<RIFF::File*>::iterator sIter;
2515 sIter = std::find(poolFiles.begin(), poolFiles.end(), pPoolFile);
2516 if (sIter != poolFiles.end())
2517 fileNo = std::distance(poolFiles.begin(), sIter);
2523 throw DLS::Exception(
"Fatal error, pool file has no 'wvpl' list chunk");
2529 uint64_t _64BitOffset =
2530 (*iter)->pWaveList->GetFilePos() -
2531 (*iter)->pWaveList->GetPos() -
2534 pWavePoolTableHi[i] = (uint32_t) fileNo;
2535 pWavePoolTable[i] = (uint32_t) _64BitOffset;
2536 (*iter)->ullWavePoolOffset = _64BitOffset;
2551 va_start(arg, format);
2552 Message = assemble(format, arg);
2556 Exception::Exception(String format, va_list arg) :
RIFF::Exception() {
2557 Message = assemble(format, arg);
2560 void Exception::PrintMessage() {
2561 std::cout <<
"DLS::Exception: " << Message << std::endl;
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...
virtual void CopyAssign(const Instrument *orig)
Make a (semi) deep copy of the Instrument object given by orig and assign it to this object...
uint16_t BlockAlign
The block alignment (in bytes) of the waveform data. Playback software needs to process a multiple of...
sample_loop_t * pSampleLoops
Points to the beginning of a sample loop array, or is NULL if there are no loops defined.
uint32_t Regions
Reflects the number of Region defintions this Instrument has.
Parses DLS Level 1 and 2 compliant files and provides abstract access to the data.
Articulation * GetArticulation(size_t pos)
Returns Articulation at supplied pos position within the articulation list.
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...
stream_whence_t
File stream position dependent to these relations.
String CreationDate
<ICRD-ck>. Specifies the date the subject of the file was created. List dates in yyyy-mm-dd format...
String Engineer
<IENG-ck>. Stores the name of the engineer who worked on the file. Multiple engineer names are separa...
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...
void __ensureMandatoryChunksExist()
Checks if all (for DLS) mandatory chunks exist, if not they will be created.
String Artists
<IART-ck>. Lists the artist of the original subject of the file.
file_offset_t GetSize() const
Chunk size in bytes (without header, thus the chunk data body)
List * GetSubListAt(size_t pos)
Returns sublist chunk with list type ListType at supplied pos position among all subchunks of type Li...
Sample * GetFirstSample()
Returns a pointer to the first Sample object of the file, NULL otherwise.
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).
Instrument * GetNextInstrument()
Returns a pointer to the next Instrument object of the file, NULL otherwise.
Will be thrown whenever a DLS specific error occurs while trying to access a DLS File.
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...
Optional information for DLS files, instruments, samples, etc.
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 void UpdateChunks(progress_t *pProgress)
Update chunks with current Resource data.
RIFF::File * GetExtensionFile(int index)
Returns extension file of given index.
virtual ~Region()
Destructor.
Instrument * AddInstrument()
Add a new instrument definition.
Instrument * GetFirstInstrument()
Returns a pointer to the first Instrument object of the file, NULL otherwise.
String Keywords
<IKEY-ck>. Provides a list of keywords that refer to the file or subject of the file. Keywords are separated with semicolon and blank, e.g., FX; death; murder.
virtual void DeleteChunks()
Remove all RIFF chunks associated with this Instrument object.
conn_src_t
Connection Sources.
file_offset_t GetSize() const
Returns sample size.
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 SamplesTotal
Reflects total number of sample points (only if known sample data format is used, 0 otherwise)...
String SourceForm
<ISRF-ck>. Identifies the original form of the material that was digitized, such as record...
List * GetSubList(uint32_t ListType)
Returns sublist chunk with list type ListType within this chunk list.
void DeleteSubChunk(Chunk *pSubChunk)
Removes a sub chunk.
Defines Sample Loop Points.
virtual ~Sample()
Destructor.
uint16_t MIDIBank
Reflects combination of MIDIBankCoarse and MIDIBankFine (bank 1 - bank 16384). Do not change this val...
virtual void CopyAssign(const Info *orig)
Make a deep copy of the Info object given by orig and assign it to this object.
uint8_t MIDIBankCoarse
Reflects the MIDI Bank number for MIDI Control Change 0 (bank 1 - 128).
void GenerateDLSID()
Generates a new DLSID for the resource.
uint FrameSize
Reflects the size (in bytes) of one single sample point (only if known sample data format is used...
List * GetParent() const
Returns pointer to the chunk's parent list chunk.
Every subject of an DLS file and the file itself can have an unique, computer generated ID...
virtual void CopyAssign(const Sample *orig)
Make a deep copy of the Sample object given by orig and assign it to this object. ...
Region * GetFirstRegion()
Returns the first Region of the instrument.
size_t CountRegions()
Returns the amount of regions of this instrument.
void DeleteSampleLoop(sample_loop_t *pLoopDef)
Deletes an existing sample loop.
RIFF::File * GetRiffFile()
Returns the underlying RIFF::File used for persistency of this DLS::File object.
virtual ~Instrument()
Destructor.
uint16_t low
Low value of range.
void SetByteOrder(endian_t Endian)
Set the byte order to be used when saving.
void SetFixedStringLengths(const string_length_t *lengths)
Forces specific Info fields to be of a fixed length when being saved to a file.
uint16_t FormatTag
Format ID of the waveform data (should be DLS_WAVE_FORMAT_PCM for DLS1 compliant files, this is also the default value if Sample was created with Instrument::AddSample()).
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...
virtual void CopyAssign(const Sampler *orig)
Make a deep copy of the Sampler object given by orig and assign it to this object.
void ReleaseSampleData()
Free sample data from RAM.
virtual void CopyAssign(const Articulator *orig)
Not yet implemented in this version, since the .gig format does not need to copy DLS articulators and...
Abstract base class which provides mandatory informations about sample players in general...
String libraryName()
Returns the name of this C++ library.
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)...
Region * GetRegionAt(size_t pos)
Returns Region at supplied pos position within the region list of this instrument.
conn_trn_t
Connection Transforms.
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...
uint32_t SampleLoops
Reflects the number of sample loops.
virtual void Save(const String &Path, progress_t *pProgress=NULL)
Save changes to another file.
void Resize(file_offset_t NewSize)
Resize sample.
conn_dst_t
Connection Destinations.
void DeleteSample(Sample *pSample)
Delete a sample.
uint16_t high
High value of range.
Articulation * GetFirstArticulation()
Returns the first Articulation in the list of articulations.
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...
uint32_t Size
For internal usage only: usually reflects exactly sizeof(sample_loop_t), otherwise if the value is la...
Chunk * GetSubChunk(uint32_t ChunkID)
Returns subchunk with chunk ID ChunkID within this chunk list.
Info(RIFF::List *list)
Constructor.
virtual void Save(progress_t *pProgress=NULL)
Save changes to same file.
String Source
<ISRC-ck>. Identifies the name of the person or organization who supplied the original subject of the...
uint16_t BitDepth
Size of each sample per channel (only if known sample data format is used, 0 otherwise).
Sample(File *pFile, RIFF::List *waveList, file_offset_t WavePoolOffset)
Constructor.
uint32_t MIDIProgram
Specifies the MIDI Program Change Number this Instrument should be assigned to.
file_offset_t GetRequiredFileSize()
Returns the required size (in bytes) for this RIFF File to be saved to disk.
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...
int GetFileOffsetSize() const
Returns the current size (in bytes) of file offsets stored in the headers of all chunks of this file...
uint32_t GetChunkID() const
Chunk ID in unsigned integer representation.
void SetSample(Sample *pSample)
Assign another sample to this Region.
virtual void DeleteChunks()
Remove all RIFF chunks associated with this Articulation object.
file_offset_t RemainingBytes() const
Returns the number of bytes left to read in the chunk body.
Used for indicating the progress of a certain task.
Articulation * GetNextArticulation()
Returns the next Articulation from the list of articulations.
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...
uint32_t GetListType() const
Returns unsigned integer representation of the list's ID.
Chunk * GetSubChunkAt(size_t pos)
Returns subchunk at supplied pos position within this chunk list.
virtual void DeleteChunks()
Remove all RIFF chunks associated with this Resource object.
virtual void UpdateChunks(progress_t *pProgress)
Apply Instrument with all its Regions to the respective RIFF chunks.
void DeleteInstrument(Instrument *pInstrument)
Delete an instrument.
version_t * pVersion
Points to a version_t structure if the file provided a version number else is set to NULL...
String Technician
<ITCH-ck>. Identifies the technician who sampled the subject file.
Instrument(File *pFile, RIFF::List *insList)
Constructor.
void * LoadChunkData()
Load chunk body into RAM.
Region * GetNextRegion()
Returns the next Region of the instrument.
uint32_t AverageBytesPerSecond
The average number of bytes per second at which the waveform data should be transferred (Playback sof...
uint8_t MIDIBankFine
Reflects the MIDI Bank number for MIDI Control Change 32 (bank 1 - 128).
Instrument * GetInstrument(size_t index)
Returns the instrument with the given index from the list of instruments of this file.
virtual void UpdateChunks(progress_t *pProgress)
Apply all articulations to the respective RIFF chunks.
Abstract base class which encapsulates data structures which all DLS resources are able to provide...
void Resize(file_offset_t NewSize)
Resize chunk.
Sample * GetSample(size_t index)
Returns Sample object of index.
List * AddSubList(uint32_t uiListType)
Creates a new list sub chunk.
virtual void DeleteChunks()
Remove all RIFF chunks associated with this Articulator object.
RIFF specific classes and definitions.
virtual void UpdateChunks(progress_t *pProgress)
Apply all sample player options to the respective RIFF chunk.
String Software
<ISFT-ck>. Identifies the name of the sofware package used to create the file.
String ArchivalLocation
<IARL-ck>. Indicates where the subject of the file is stored.
Encapsulates sample waves used for playback.
Sample * GetNextSample()
Returns a pointer to the next Sample object of the file, NULL otherwise.
void MoveSubChunk(Chunk *pSrc, Chunk *pDst)
Moves a sub chunk witin this list.
String Name
<INAM-ck>. Stores the title of the subject of the file, such as, Seattle From Above.
uint32_t SamplesPerSecond
Sampling rate at which each channel should be played (defaults to 44100 if Sample was created with In...
String Product
<IPRD-ck>. Specifies the name of the title the file was originally intended for, such as World Ruler ...
File * GetFile() const
Returns pointer to the chunk's File object.
String GetFileName()
File name of this DLS file.
String Medium
<IMED-ck>. Describes the original subject of the file, such as, record, CD, and so forth...
String Subject
<ISBJ-ck>. Describes the contents of the file.
virtual void DeleteChunks()
Remove all RIFF chunks associated with this Info object.
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...
Will be thrown whenever an error occurs while handling a RIFF file.
void CopyAssignCore(const Sample *orig)
Make a deep copy of the Sample object given by orig (without the actual sample waveform data however)...
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.
Abstract base class for classes that provide articulation information (thus for Instrument and Region...
virtual void UpdateChunks(progress_t *pProgress)
Apply sample and its settings to the respective RIFF chunks.
Provides access to the defined connections used for the synthesis model.
virtual void UpdateChunks(progress_t *pProgress)
Apply articulation connections to the respective RIFF chunks.
uint32_t Instruments
Reflects the number of available Instrument objects.
String Genre
<IGNR-ck>. Descirbes the original work, such as, Jazz, Classic, Rock, Techno, Rave, etc.
Provides all neccessary information for the synthesis of a DLS Instrument.
bool bOwningRiff
If true then pRIFF was implicitly allocated by this class and hence pRIFF will automatically be freed...
virtual void DeleteChunks()
Remove all RIFF chunks associated with this Sample object.
Quadtuple version number ("major.minor.release.build").
virtual void CopyAssign(const Resource *orig)
Make a deep copy of the Resource object given by orig and assign it to this object.
String Copyright
<ICOP-ck>. Records the copyright information for the file.
file_offset_t Write(void *pBuffer, file_offset_t SampleCount)
Write sample wave data.
Sample * AddSample()
Add a new sample.
file_offset_t GetPos() const
Current read/write position within the chunk data body (starting with 0).
DLS specific classes and definitions.
Info * pInfo
Points (in any case) to an Info object, providing additional, optional infos and comments.
String libraryVersion()
Returns version of this C++ library.
Defines a connection within the synthesis model.
virtual void DeleteChunks()
Remove all RIFF chunks associated with this Region object.
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...
virtual void UpdateChunks(progress_t *pProgress)
Apply Region settings to the respective RIFF chunks.
String Comments
<ICMT-ck>. Provides general comments about the file or the subject of the file. Sentences might end w...
Defines Region information of an Instrument.
Articulation(RIFF::Chunk *artl)
Constructor.
Chunk * AddSubChunk(uint32_t uiChunkID, file_offset_t ullBodySize)
Creates a new sub chunk.
bool IsDrum
Indicates if the Instrument is a drum type, as they differ in the synthesis model of DLS from melodic...
virtual void DeleteChunks()
Remove all RIFF chunks associated with this Sampler object.
virtual void UpdateChunks(progress_t *pProgress)
Apply all the DLS file's current instruments, samples and settings to the respective RIFF chunks...
void * LoadSampleData()
Load sample data into RAM.
void AddSampleLoop(sample_loop_t *pLoopDef)
Adds a new sample loop with the provided loop definition.
virtual void UpdateFileOffsets()
Updates all file offsets stored all over the file.
Resource(Resource *Parent, RIFF::List *lstResource)
Constructor.