--- libgig/trunk/src/DLS.h 2005/11/09 20:04:11 800 +++ libgig/trunk/src/DLS.h 2007/09/30 18:13:33 1358 @@ -1,8 +1,8 @@ /*************************************************************************** * * - * libgig - C++ cross-platform Gigasampler format file loader library * + * libgig - C++ cross-platform Gigasampler format file access library * * * - * Copyright (C) 2003-2005 by Christian Schoenebeck * + * Copyright (C) 2003-2007 by Christian Schoenebeck * * * * * * This library is free software; you can redistribute it and/or modify * @@ -27,7 +27,7 @@ #include "RIFF.h" #if WORDS_BIGENDIAN -# define RIFF_TYPE_DLS 0x646C7320 +# define RIFF_TYPE_DLS 0x444C5320 # define LIST_TYPE_INFO 0x494E464F # define LIST_TYPE_WVPL 0x7776706C # define LIST_TYPE_DWPL 0x6477706C ///< Seen on some files instead of a wvpl list chunk. @@ -69,7 +69,7 @@ # define CHUNK_ID_ARTL 0x6172746C # define CHUNK_ID_ART2 0x61727432 #else // little endian -# define RIFF_TYPE_DLS 0x20736C64 +# define RIFF_TYPE_DLS 0x20534C44 # define LIST_TYPE_INFO 0x4F464E49 # define LIST_TYPE_WVPL 0x6C707677 # define LIST_TYPE_DWPL 0x6C707764 ///< Seen on some files instead of a wvpl list chunk. @@ -90,7 +90,7 @@ # define CHUNK_ID_IENG 0x474E4549 # define CHUNK_ID_IGNR 0x524E4749 # define CHUNK_ID_IKEY 0x59454B49 -# define CHUNK_ID_IMED 0x44525049 +# define CHUNK_ID_IMED 0x44454D49 # define CHUNK_ID_INAM 0x4D414E49 # define CHUNK_ID_IPRD 0x44525049 # define CHUNK_ID_ISBJ 0x4A425349 @@ -112,7 +112,7 @@ # define CHUNK_ID_ART2 0x32747261 #endif // WORDS_BIGENDIAN -#define WAVE_FORMAT_PCM 0x0001 +#define DLS_WAVE_FORMAT_PCM 0x0001 //TODO: no support for conditional chunks yet @@ -224,10 +224,10 @@ /** Defines Sample Loop Points. */ struct sample_loop_t { - uint32_t Size; - uint32_t LoopType; - uint32_t LoopStart; - uint32_t LoopLength; + uint32_t Size; ///< For internal usage only: usually reflects exactly @c sizeof(sample_loop_t), otherwise if the value is larger then the DLS format was extended! + uint32_t LoopType; ///< Defines how the waveform samples will be looped (appropriate loop types for the gig format are defined by gig::loop_type_t). + uint32_t LoopStart; ///< The start value specifies the offset (in sample points) in the waveform data of the first sample point to be played in the loop. + uint32_t LoopLength; ///< Length of the looping area (in sample points). }; // just symbol prototyping @@ -315,13 +315,21 @@ String Source; ///< . Identifies the name of the person or organization who supplied the original subject of the file. String SourceForm; ///< . Identifies the original form of the material that was digitized, such as record, sampling CD, TV sound track. This is not neccessarily the same as Medium. String Commissioned; ///< . Lists the name of the person or organization that commissioned the subject of the file, e.g., Pope Julian II. + String Subject; ///< . Describes the contents of the file. + bool UseFixedLengthStrings; ///< @deprecated Use #FixedStringLengths instead. + struct FixedStringLength { + uint32_t chunkId; + int length; + }; + const FixedStringLength* FixedStringLengths; ///< List of IDs and string lengths for strings that should be stored in a fixed length format. This is used for gig files, not for ordinary DLS files. Info(RIFF::List* list); + virtual ~Info(); virtual void UpdateChunks(); private: RIFF::List* pResourceListChunk; - void LoadString(uint32_t ChunkID, RIFF::List* lstINFO, String& s); + static void LoadString(uint32_t ChunkID, RIFF::List* lstINFO, String& s); void SaveString(uint32_t ChunkID, RIFF::List* lstINFO, const String& s, const String& sDefault); }; @@ -333,6 +341,7 @@ Resource* GetParent() { return pParent; }; virtual void UpdateChunks(); + void GenerateDLSID(); protected: Resource* pParent; RIFF::List* pResourceList; @@ -346,12 +355,15 @@ public: uint8_t UnityNote; int16_t FineTune; - int32_t Gain; + int32_t Gain; ///< @deprecated Don't alter directly, use SetGain() instead! bool NoSampleDepthTruncation; bool NoSampleCompression; uint32_t SampleLoops; ///< Reflects the number of sample loops. sample_loop_t* pSampleLoops; ///< Points to the beginning of a sample loop array, or is NULL if there are no loops defined. + void AddSampleLoop(sample_loop_t* pLoopDef); + void DeleteSampleLoop(sample_loop_t* pLoopDef); + virtual void SetGain(int32_t gain); virtual void UpdateChunks(); protected: RIFF::List* pParentList; @@ -364,19 +376,21 @@ /** @brief Encapsulates sample waves used for playback. * * In case you created a new sample with File::AddSample(), you should - * first call Resize() with the desired sample size. This will create + * first update all attributes with the desired meta informations + * (amount of channels, bit depth, sample rate, etc.), then call + * Resize() with the desired sample size. The latter will create * the mandatory RIFF chunk which will hold the sample wave data. */ class Sample : public Resource { public: - uint16_t FormatTag; ///< Format ID of the waveform data (should be WAVE_FORMAT_PCM for DLS1 compliant files). - uint16_t Channels; ///< Number of channels represented in the waveform data, e.g. 1 for mono, 2 for stereo (). - uint32_t SamplesPerSecond; ///< Sampling rate at which each channel should be played. + 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()). + uint16_t Channels; ///< Number of channels represented in the waveform data, e.g. 1 for mono, 2 for stereo (defaults to 1=mono if Sample was created with Instrument::AddSample() previously). + uint32_t SamplesPerSecond; ///< Sampling rate at which each channel should be played (defaults to 44100 if Sample was created with Instrument::AddSample() previously). uint32_t AverageBytesPerSecond; ///< The average number of bytes per second at which the waveform data should be transferred (Playback software can estimate the buffer size using this value). uint16_t BlockAlign; ///< The block alignment (in bytes) of the waveform data. Playback software needs to process a multiple of BlockAlign bytes of data at a time, so the value of BlockAlign can be used for buffer alignment. uint16_t BitDepth; ///< Size of each sample per channel (only if known sample data format is used, 0 otherwise). unsigned long SamplesTotal; ///< Reflects total number of sample points (only if known sample data format is used, 0 otherwise), do not bother to change this value, it will not be saved. - uint FrameSize; ///< Reflects the size (in bytes) of one single sample point (only if known sample data format is used, 0 otherwise). + uint FrameSize; ///< Reflects the size (in bytes) of one single sample point (only if known sample data format is used, 0 otherwise). Caution: with the current version of libgig you have to upate this field by yourself whenever you change one of the following fields: Channels, BitDepth ! Ignoring this might lead to undesired behavior when i.e. calling Resize(), SetPos(), Write() or Read(). void* LoadSampleData(); void ReleaseSampleData(); @@ -401,7 +415,7 @@ /** Defines Region information of an Instrument. */ class Region : public Resource, public Articulator, public Sampler { public: - range_t KeyRange; + range_t KeyRange; ///< @deprecated Only read, don't write! Use SetKeyRange() instead. range_t VelocityRange; uint16_t KeyGroup; uint16_t Layer; @@ -413,6 +427,7 @@ Sample* GetSample(); void SetSample(Sample* pSample); + virtual void SetKeyRange(uint16_t Low, uint16_t High); virtual void UpdateChunks(); protected: RIFF::List* pCkRegion; @@ -453,9 +468,12 @@ RegionList::iterator RegionsIterator; Instrument(File* pFile, RIFF::List* insList); - void LoadRegions(); + virtual void LoadRegions(); virtual ~Instrument(); friend class File; + friend class Region; + private: + void MoveRegion(Region* pSrc, Region* pDst); }; /** Parses DLS Level 1 and 2 compliant files and provides abstract access to the data. */ @@ -483,6 +501,7 @@ typedef std::list InstrumentList; RIFF::File* pRIFF; + std::list ExtensionFiles; SampleList* pSamples; SampleList::iterator SamplesIterator; InstrumentList* pInstruments; @@ -493,8 +512,8 @@ uint32_t* pWavePoolTableHi; bool b64BitWavePoolOffsets; - void LoadSamples(); - void LoadInstruments(); + virtual void LoadSamples(); + virtual void LoadInstruments(); void __ensureMandatoryChunksExist(); friend class Region; // Region has to look in the wave pool table to get its sample private: @@ -502,7 +521,13 @@ void __UpdateWavePoolTable(); }; - /** Will be thrown whenever a DLS specific error occurs while trying to access a DLS File. */ + /** + * Will be thrown whenever a DLS specific error occurs while trying to + * access a DLS File. Note: In your application you should better catch + * for RIFF::Exception rather than this one, except you explicitly want + * to catch and handle DLS::Exception and RIFF::Exception independently, + * which usually shouldn't be necessary though. + */ class Exception : public RIFF::Exception { public: Exception(String Message);