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;
121 if (artl->GetChunkID() != CHUNK_ID_ART2 &&
122 artl->GetChunkID() != CHUNK_ID_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
214 if (art->GetChunkID() == artCkType) {
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)
559 #if defined(WIN32) || defined(__APPLE__) || defined(HAVE_UUID_GENERATE)
563 pDLSID->ulData1 = uuid.Data1;
564 pDLSID->usData2 = uuid.Data2;
565 pDLSID->usData3 = uuid.Data3;
566 memcpy(
pDLSID->abData, uuid.Data4, 8);
568 #elif defined(__APPLE__)
570 CFUUIDRef uuidRef = CFUUIDCreate(NULL);
571 CFUUIDBytes uuid = CFUUIDGetUUIDBytes(uuidRef);
573 pDLSID->ulData1 = uuid.byte0 | uuid.byte1 << 8 | uuid.byte2 << 16 | uuid.byte3 << 24;
574 pDLSID->usData2 = uuid.byte4 | uuid.byte5 << 8;
575 pDLSID->usData3 = uuid.byte6 | uuid.byte7 << 8;
576 pDLSID->abData[0] = uuid.byte8;
577 pDLSID->abData[1] = uuid.byte9;
578 pDLSID->abData[2] = uuid.byte10;
579 pDLSID->abData[3] = uuid.byte11;
580 pDLSID->abData[4] = uuid.byte12;
581 pDLSID->abData[5] = uuid.byte13;
582 pDLSID->abData[6] = uuid.byte14;
583 pDLSID->abData[7] = uuid.byte15;
587 pDLSID->ulData1 = uuid[0] | uuid[1] << 8 | uuid[2] << 16 | uuid[3] << 24;
588 pDLSID->usData2 = uuid[4] | uuid[5] << 8;
589 pDLSID->usData3 = uuid[6] | uuid[7] << 8;
590 memcpy(
pDLSID->abData, &uuid[8], 8);
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;
789 ullWavePoolOffset = WavePoolOffset - LIST_HEADER_SIZE(waveList->GetFile()->GetFileOffsetSize());
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;
952 return (pCkData) ? pCkData->GetSize() /
FrameSize : 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;
1156 RIFF::List* pParent = pCkRegion->GetParent();
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;
1380 if (rgn->GetListType() == regionCkType) {
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) {
1496 RIFF::List* pParent = pCkInstrument->GetParent();
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() -
1684 if (wave->GetListType() == LIST_TYPE_WAVE) {
1685 file_offset_t waveFileOffset = wave->GetFilePos() -
1687 pSamples->push_back(
new Sample(
this, wave, waveFileOffset - wvplFileOffset));
1699 if (wave->GetListType() == LIST_TYPE_WAVE) {
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) {
1763 if (lstInstr->GetListType() == LIST_TYPE_INS) {
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++) {
2348 RIFF::File* pPoolFile = (*iter)->pWaveList->GetFile();
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");
2365 extWvpl->GetFilePos() -
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;