30 #include <CoreFoundation/CFUUID.h>
31 #elif defined(HAVE_UUID_UUID_H)
32 #include <uuid/uuid.h>
38 #define CONN_TRANSFORM_SRC(x) ((x >> 10) & 0x000F)
39 #define CONN_TRANSFORM_CTL(x) ((x >> 4) & 0x000F)
40 #define CONN_TRANSFORM_DST(x) (x & 0x000F)
41 #define CONN_TRANSFORM_BIPOLAR_SRC(x) (x & 0x4000)
42 #define CONN_TRANSFORM_BIPOLAR_CTL(x) (x & 0x0100)
43 #define CONN_TRANSFORM_INVERT_SRC(x) (x & 0x8000)
44 #define CONN_TRANSFORM_INVERT_CTL(x) (x & 0x0200)
47 #define CONN_TRANSFORM_SRC_ENCODE(x) ((x & 0x000F) << 10)
48 #define CONN_TRANSFORM_CTL_ENCODE(x) ((x & 0x000F) << 4)
49 #define CONN_TRANSFORM_DST_ENCODE(x) (x & 0x000F)
50 #define CONN_TRANSFORM_BIPOLAR_SRC_ENCODE(x) ((x) ? 0x4000 : 0)
51 #define CONN_TRANSFORM_BIPOLAR_CTL_ENCODE(x) ((x) ? 0x0100 : 0)
52 #define CONN_TRANSFORM_INVERT_SRC_ENCODE(x) ((x) ? 0x8000 : 0)
53 #define CONN_TRANSFORM_INVERT_CTL_ENCODE(x) ((x) ? 0x0200 : 0)
55 #define DRUM_TYPE_MASK 0x80000000
57 #define F_RGN_OPTION_SELFNONEXCLUSIVE 0x0001
59 #define F_WAVELINK_PHASE_MASTER 0x0001
60 #define F_WAVELINK_MULTICHANNEL 0x0002
62 #define F_WSMP_NO_TRUNCATION 0x0001
63 #define F_WSMP_NO_COMPRESSION 0x0002
65 #define MIDI_BANK_COARSE(x) ((x & 0x00007F00) >> 8) // CC0
66 #define MIDI_BANK_FINE(x) (x & 0x0000007F) // CC32
67 #define MIDI_BANK_MERGE(coarse, fine) ((((uint16_t) coarse) << 7) | fine) // CC0 + CC32
68 #define MIDI_BANK_ENCODE(coarse, fine) (((coarse & 0x0000007F) << 8) | (fine & 0x0000007F))
149 const int iEntrySize = 12;
209 while (iter != end) {
225 for (; iter != end; ++iter) {
226 (*iter)->UpdateChunks();
243 pFixedStringLengths = NULL;
244 pResourceListChunk = list;
284 pFixedStringLengths = lengths;
314 if (pFixedStringLengths) {
315 for (
int i = 0 ; pFixedStringLengths[i].
length ; i++) {
316 if (pFixedStringLengths[i].chunkId == ChunkID) {
317 size = pFixedStringLengths[i].
length;
323 ::SaveString(ChunkID, ck, lstINFO, s, sDefault, size != 0, size);
332 if (!pResourceListChunk)
return;
338 String defaultCreationDate =
"";
339 String defaultSoftware =
"";
340 String defaultComments =
"";
342 uint32_t resourceType = pResourceListChunk->
GetListType();
348 defaultName =
"NONAME";
352 time_t now = time(NULL);
353 tm* pNowBroken = localtime(&now);
355 strftime(buf, 11,
"%F", pNowBroken);
356 defaultCreationDate = buf;
451 #if defined(WIN32) || defined(__APPLE__) || defined(HAVE_UUID_GENERATE)
464 #elif defined(__APPLE__)
466 CFUUIDRef uuidRef = CFUUIDCreate(NULL);
467 CFUUIDBytes uuid = CFUUIDGetUUIDBytes(uuidRef);
469 pDLSID->
ulData1 = uuid.byte0 | uuid.byte1 << 8 | uuid.byte2 << 16 | uuid.byte3 << 24;
483 pDLSID->
ulData1 = uuid[0] | uuid[1] << 8 | uuid[2] << 16 | uuid[3] << 24;
545 }
else if (wsmp->
GetSize() != wsmpSize) {
558 store32(&pData[8],
Gain);
560 store32(&pData[16], SampleLoops);
603 if (o == SampleLoops - 1)
604 throw Exception(
"Could not delete Sample Loop, because it does not exist");
762 if (iNewSize < 1)
throw Exception(
"Sample size must be at least one sample point");
763 const int iSizeInBytes = iNewSize *
FrameSize;
787 if (!
pCkData)
throw Exception(
"No data chunk created for sample yet, call Sample::Resize() to create one");
788 unsigned long orderedBytes = SampleCount *
FrameSize;
789 unsigned long result =
pCkData->
SetPos(orderedBytes, Whence);
790 return (result == orderedBytes) ? SampleCount
825 if (
GetSize() < SampleCount)
throw Exception(
"Could not write sample data, current sample size to small");
838 throw Exception(
"Could not save sample, only PCM format is supported");
841 throw Exception(
"Could not save sample, there is no sample data to save");
956 Region* prev_region = NULL;
958 Instrument::RegionList::iterator iter = pInstrument->
pRegions->begin();
959 iter != pInstrument->
pRegions->end(); iter++
961 if ((*iter)->KeyRange.low > this->KeyRange.low) {
969 if (prev_region !=
this) pInstrument->MoveRegion(
this, r);
1014 File::SampleList::iterator iter = pFile->
pSamples->begin();
1015 File::SampleList::iterator end = pFile->
pSamples->end();
1016 for (
int i = 0; iter != end; ++iter, i++) {
1056 insh->
Read(&locale, 2, 4);
1111 void Instrument::MoveRegion(
Region* pSrc,
Region* pDst) {
1116 RegionList::iterator iter = find(
pRegions->begin(),
pRegions->end(), pDst);
1122 RegionList::iterator iter = find(
pRegions->begin(),
pRegions->end(), pRegion);
1123 if (iter ==
pRegions->end())
return;
1151 store32(&pData[4], locale.
bank);
1155 RegionList::iterator iter =
pRegions->begin();
1156 RegionList::iterator end =
pRegions->end();
1157 for (; iter != end; ++iter) {
1158 (*iter)->UpdateChunks();
1169 RegionList::iterator iter =
pRegions->begin();
1170 RegionList::iterator end =
pRegions->end();
1171 while (iter != end) {
1223 if (!pRIFF)
throw DLS::Exception(
"NULL pointer reference to RIFF::File object.");
1224 this->pRIFF =
pRIFF;
1234 if (!colh)
throw DLS::Exception(
"Mandatory chunks in RIFF list chunk not found.");
1258 throw DLS::Exception(
"Files larger than 2 GB not yet supported");
1274 while (iter != end) {
1282 SampleList::iterator iter =
pSamples->begin();
1283 SampleList::iterator end =
pSamples->end();
1284 while (iter != end) {
1315 unsigned long wvplFileOffset = wvpl->
GetFilePos();
1319 unsigned long waveFileOffset = wave->
GetFilePos();
1320 pSamples->push_back(
new Sample(
this, wave, waveFileOffset - wvplFileOffset));
1328 unsigned long dwplFileOffset = dwpl->
GetFilePos();
1332 unsigned long waveFileOffset = wave->
GetFilePos();
1333 pSamples->push_back(
new Sample(
this, wave, waveFileOffset - dwplFileOffset));
1368 SampleList::iterator iter = find(
pSamples->begin(),
pSamples->end(), pSample);
1369 if (iter ==
pSamples->end())
return;
1390 if (lstInstruments) {
1466 for (; iter != end; ++iter) {
1467 (*iter)->UpdateChunks();
1486 SampleList::iterator iter =
pSamples->begin();
1487 SampleList::iterator end =
pSamples->end();
1488 for (; iter != end; ++iter) {
1489 (*iter)->UpdateChunks();
1510 __UpdateWavePoolTableChunk();
1525 __UpdateWavePoolTableChunk();
1557 void File::__UpdateWavePoolTableChunk() {
1558 __UpdateWavePoolTable();
1564 if (ptbl->
GetSize() < ulRequiredSize)
throw Exception(
"Fatal error, 'ptbl' chunk too small");
1566 unsigned long ulOriginalPos = ptbl->
GetPos();
1589 ptbl->
SetPos(ulOriginalPos);
1597 void File::__UpdateWavePoolTable() {
1607 uint64_t wvplFileOffset = wvpl->
GetFilePos();
1609 SampleList::iterator iter =
pSamples->begin();
1610 SampleList::iterator end =
pSamples->end();
1611 for (
int i = 0 ; iter != end ; ++iter, i++) {
1612 uint64_t _64BitOffset = (*iter)->pWaveList->GetFilePos() - wvplFileOffset -
LIST_HEADER_SIZE;
1613 (*iter)->ulWavePoolOffset = _64BitOffset;
1618 SampleList::iterator iter =
pSamples->begin();
1619 SampleList::iterator end =
pSamples->end();
1620 for (
int i = 0 ; iter != end ; ++iter, i++) {
1621 uint64_t _64BitOffset = (*iter)->pWaveList->GetFilePos() - wvplFileOffset -
LIST_HEADER_SIZE;
1622 (*iter)->ulWavePoolOffset = _64BitOffset;
1637 std::cout <<
"DLS::Exception: " <<
Message << std::endl;
#define CONN_TRANSFORM_BIPOLAR_CTL_ENCODE(x)
unsigned long WriteUint32(uint32_t *pData, unsigned long WordCount=1)
Writes WordCount number of 32 Bit unsigned integer words from the buffer pointed by pData to the chun...
ArticulationList * pArticulations
uint16_t BlockAlign
The block alignment (in bytes) of the waveform data. Playback software needs to process a multiple of...
#define LIST_TYPE_DWPL
Seen on some files instead of a wvpl list chunk.
sample_loop_t * pSampleLoops
Points to the beginning of a sample loop array, or is NULL if there are no loops defined.
virtual void UpdateChunks()
Update chunks with current info values.
uint32_t Regions
Reflects the number of Region defintions this Instrument has.
virtual void UpdateChunks()
Update chunks with current Resource data.
virtual void UpdateChunks()
Apply Instrument with all its Regions to the respective RIFF chunks.
Parses DLS Level 1 and 2 compliant files and provides abstract access to the data.
stream_whence_t
File stream position dependent to these relations.
unsigned long Read(void *pData, unsigned long WordCount, unsigned long WordSize)
Reads WordCount number of data words with given WordSize and copies it into a buffer pointed by pData...
String CreationDate
<ICRD-ck>. Specifies the date the subject of the file was created. List dates in yyyy-mm-dd format...
Chunk * GetFirstSubChunk()
Returns the first subchunk within the list.
#define F_WAVELINK_PHASE_MASTER
ArticulationList::iterator ArticulationsIterator
virtual void UpdateChunks()
Apply all articulations to the respective RIFF chunks.
uint32_t GetChunkID()
Chunk ID in unsigned integer representation.
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.
Sample * GetFirstSample()
Returns a pointer to the first Sample object of the file, NULL otherwise.
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.
conn_trn_t SourceTransform
Optional information for DLS files, instruments, samples, etc.
unsigned long Read(void *pBuffer, unsigned long SampleCount)
Reads SampleCount number of sample points from the current position into the buffer pointed by pBuffe...
#define CONN_TRANSFORM_INVERT_SRC_ENCODE(x)
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.
#define DLS_WAVE_FORMAT_PCM
#define CONN_TRANSFORM_DST(x)
std::list< Articulation * > ArticulationList
conn_src_t
Connection Sources.
unsigned long SetPos(unsigned long Where, stream_whence_t Whence=stream_start)
Sets the position within the chunk body, thus within the data portion of the chunk (in bytes)...
#define CONN_TRANSFORM_SRC_ENCODE(x)
unsigned long GetSize()
Returns sample size.
uint32_t * pWavePoolTable
uint32_t WavePoolTableIndex
uint16_t Channels
Number of channels represented in the waveform data, e.g. 1 for mono, 2 for stereo (defaults to 1=mon...
#define CONN_TRANSFORM_BIPOLAR_SRC(x)
RIFF::List * pCkInstrument
void GenerateDLSID()
Generates a new DLSID for the resource.
String SourceForm
<ISRF-ck>. Identifies the original form of the material that was digitized, such as record...
Sampler(RIFF::List *ParentList)
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 void UpdateChunks()
Apply articulation connections to the respective RIFF chunks.
unsigned long SetPos(unsigned long SampleCount, RIFF::stream_whence_t Whence=RIFF::stream_start)
Sets the position within the sample (in sample points, not in bytes).
RIFF::List * pResourceList
virtual ~Sample()
Destructor.
virtual void LoadSamples()
uint16_t MIDIBank
Reflects combination of MIDIBankCoarse and MIDIBankFine (bank 1 - bank 16384). Do not change this val...
virtual void SetGain(int32_t gain)
#define CONN_TRANSFORM_BIPOLAR_CTL(x)
unsigned long RemainingBytes()
Returns the number of bytes left to read in the chunk body.
List * GetFirstSubList()
Returns the first sublist within the list (that is a subchunk with chunk ID "LIST").
#define MIDI_BANK_MERGE(coarse, fine)
#define MIDI_BANK_FINE(x)
std::list< Sample * > SampleList
virtual void UpdateChunks()
Apply all the DLS file's current instruments, samples and settings to the respective RIFF chunks...
InstrumentList::iterator InstrumentsIterator
uint8_t MIDIBankCoarse
Reflects the MIDI Bank number for MIDI Control Change 0 (bank 1 - 128).
uint FrameSize
Reflects the size (in bytes) of one single sample point (only if known sample data format is used...
#define MIDI_BANK_COARSE(x)
unsigned long ReadUint32(uint32_t *pData, unsigned long WordCount=1)
Reads WordCount number of 32 Bit unsigned integer words and copies it into the buffer pointed by pDat...
Every subject of an DLS file and the file itself can have an unique, computer generated ID...
unsigned long GetPos()
Position within the chunk data body.
#define F_WAVELINK_MULTICHANNEL
Region * GetFirstRegion()
void DeleteSampleLoop(sample_loop_t *pLoopDef)
Deletes an existing sample loop.
virtual ~Instrument()
Destructor.
uint16_t low
Low value of range.
void SetByteOrder(endian_t Endian)
Set the byte order to be used when saving.
#define CONN_TRANSFORM_BIPOLAR_SRC_ENCODE(x)
bool b64BitWavePoolOffsets
unsigned long GetSize()
Chunk size in bytes (without header, thus the chunk data body)
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()).
void ReleaseSampleData()
Free sample data from RAM.
Abstract base class which provides mandatory informations about sample players in general...
String libraryName()
Returns the name of this C++ library.
Exception(String Message)
#define CONN_TRANSFORM_DST_ENCODE(x)
conn_trn_t
Connection Transforms.
uint32_t SampleLoops
Reflects the number of sample loops.
conn_trn_t DestinationTransform
void Resize(int iNewSize)
Resize sample.
conn_dst_t
Connection Destinations.
bool NoSampleDepthTruncation
void DeleteSample(Sample *pSample)
Delete a sample.
unsigned long ReadInt32(int32_t *pData, unsigned long WordCount=1)
Reads WordCount number of 32 Bit signed integer words and copies it into the buffer pointed by pData...
uint16_t high
High value of range.
virtual void UpdateChunks()
Apply Region settings to the respective RIFF chunks.
Articulation * GetFirstArticulation()
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.
Chunk * GetNextSubChunk()
Returns the next subchunk within the list.
Info(RIFF::List *list)
Constructor.
std::list< Instrument * > InstrumentList
Region(Instrument *pInstrument, RIFF::List *rgnList)
unsigned long SamplesTotal
Reflects total number of sample points (only if known sample data format is used, 0 otherwise)...
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).
uint32_t GetListType()
Returns unsigned integer representation of the list's ID.
unsigned long GetFilePos()
Current, actual offset in file.
#define F_WSMP_NO_COMPRESSION
#define CONN_TRANSFORM_SRC(x)
uint32_t MIDIProgram
Specifies the MIDI Program Change Number this Instrument should be assigned to.
String Commissioned
<ICMS-ck>. Lists the name of the person or organization that commissioned the subject of the file...
unsigned long ReadInt16(int16_t *pData, unsigned long WordCount=1)
Reads WordCount number of 16 Bit signed integer words and copies it into the buffer pointed by pData...
#define F_RGN_OPTION_SELFNONEXCLUSIVE
void SetSample(Sample *pSample)
Assign another sample to this Region.
unsigned long Write(void *pData, unsigned long WordCount, unsigned long WordSize)
Writes WordCount number of data words with given WordSize from the buffer pointed by pData...
SampleList::iterator SamplesIterator
List * GetParent()
Returns pointer to the chunk's parent list chunk.
Articulation * GetNextArticulation()
Chunk * AddSubChunk(uint32_t uiChunkID, uint uiBodySize)
Creates a new sub chunk.
#define CONN_TRANSFORM_INVERT_CTL_ENCODE(x)
uint16_t WaveLinkOptionFlags
#define F_WSMP_NO_TRUNCATION
#define CONN_TRANSFORM_CTL(x)
#define MIDI_BANK_ENCODE(coarse, fine)
#define CONN_TRANSFORM_INVERT_SRC(x)
void DeleteInstrument(Instrument *pInstrument)
Delete an instrument.
unsigned long Write(void *pBuffer, unsigned long SampleCount)
Write sample wave data.
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.
RegionList::iterator RegionsIterator
void * LoadChunkData()
Load chunk body into RAM.
RIFF::Chunk * pArticulationCk
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).
uint32_t WavePoolHeaderSize
Abstract base class which encapsulates data structures which all DLS resources are able to provide...
void Init(conn_block_t *Header)
List * AddSubList(uint32_t uiListType)
Creates a new list sub chunk.
InstrumentList * pInstruments
virtual void LoadInstruments()
virtual void UpdateChunks()
Apply sample and its settings to the respective RIFF chunks.
String Software
<ISFT-ck>. Identifies the name of the sofware package used to create the file.
#define CONN_TRANSFORM_CTL_ENCODE(x)
String ArchivalLocation
<IARL-ck>. Indicates where the subject of the file is stored.
unsigned long ulWavePoolOffset
virtual void Save()
Save changes to same file.
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.
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 ...
Sample(File *pFile, RIFF::List *waveList, unsigned long WavePoolOffset)
Constructor.
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 LoadRegions()
virtual void Save()
Save changes to same file.
unsigned long ReadUint16(uint16_t *pData, unsigned long WordCount=1)
Reads WordCount number of 16 Bit unsigned integer words and copies it into the buffer pointed by pDat...
conn_block_t ToConnBlock()
void ReleaseChunkData()
Free loaded chunk body from RAM.
void DeleteRegion(Region *pRegion)
Abstract base class for classes that provide articulation information (thus for Instrument and Region...
Connection * pConnections
Points to the beginning of a Connection array.
uint32_t Connections
Reflects the number of Connections.
conn_trn_t ControlTransform
Provides access to the defined connections used for the synthesis model.
#define CONN_TRANSFORM_INVERT_CTL(x)
dlsid_t * pDLSID
Points to a dlsid_t structure if the file provided a DLS ID else is NULL.
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.
Quadtuple version number ("major.minor.release.build").
String Copyright
<ICOP-ck>. Records the copyright information for the file.
Sample * AddSample()
Add a new sample.
Info * pInfo
Points (in any case) to an Info object, providing additional, optional infos and comments.
String libraryVersion()
Returns version of this C++ library.
virtual void UpdateChunks()
Apply all sample player options to the respective RIFF chunk.
Defines a connection within the synthesis model.
uint16_t FormatOptionFlags
uint32_t * pWavePoolTableHi
String Comments
<ICMT-ck>. Provides general comments about the file or the subject of the file. Sentences might end w...
void Resize(int iNewSize)
Resize chunk.
Articulator(RIFF::List *ParentList)
List * GetNextSubList()
Returns the next sublist (that is a subchunk with chunk ID "LIST") within the list.
Defines Region information of an Instrument.
std::list< RIFF::File * > ExtensionFiles
Articulation(RIFF::Chunk *artl)
Constructor.
bool IsDrum
Indicates if the Instrument is a drum type, as they differ in the synthesis model of DLS from melodic...
std::list< Region * > RegionList
void * LoadSampleData()
Load sample data into RAM.
void AddSampleLoop(sample_loop_t *pLoopDef)
Adds a new sample loop with the provided loop definition.
Resource(Resource *Parent, RIFF::List *lstResource)
Constructor.