--- libgig/trunk/src/DLS.h 2016/05/17 14:30:10 2912 +++ libgig/trunk/src/DLS.h 2019/02/22 12:12:50 3481 @@ -2,7 +2,7 @@ * * * libgig - C++ cross-platform Gigasampler format file access library * * * - * Copyright (C) 2003-2016 by Christian Schoenebeck * + * Copyright (C) 2003-2019 by Christian Schoenebeck * * * * * * This library is free software; you can redistribute it and/or modify * @@ -60,6 +60,8 @@ # define CHUNK_ID_COLH 0x636F6C68 # define CHUNK_ID_ARTL 0x6172746C # define CHUNK_ID_ART2 0x61727432 +# define CHUNK_ID_XFIL 0x7866696C +# define CHUNK_ID_DOXF 0x646F7866 #else // little endian # define RIFF_TYPE_DLS 0x20534C44 # define LIST_TYPE_WVPL 0x6C707677 @@ -94,6 +96,8 @@ # define CHUNK_ID_COLH 0x686C6F63 # define CHUNK_ID_ARTL 0x6C747261 # define CHUNK_ID_ART2 0x32747261 +# define CHUNK_ID_XFIL 0x6C696678 +# define CHUNK_ID_DOXF 0x66786F64 #endif // WORDS_BIGENDIAN #define DLS_WAVE_FORMAT_PCM 0x0001 @@ -124,7 +128,7 @@ }; /** Connection Sources */ - typedef enum { + enum conn_src_t { // Modulator Sources conn_src_none = 0x0000, conn_src_lfo = 0x0001, @@ -147,10 +151,10 @@ conn_src_rpn0 = 0x0100, conn_src_rpn1 = 0x0101, conn_src_rpn2 = 0x0102 - } conn_src_t; + }; /** Connection Destinations */ - typedef enum { + enum conn_dst_t { // Generic Destinations conn_dst_none = 0x0000, conn_dst_gain = 0x0001, @@ -192,16 +196,16 @@ // Filter Destinations conn_dst_filter_cutoff = 0x0500, conn_dst_filter_q = 0x0501 - } conn_dst_t; + }; /** Connection Transforms */ - typedef enum { + enum conn_trn_t { conn_trn_none = 0x0000, conn_trn_concave = 0x0001, conn_trn_convex = 0x0002, conn_trn_switch = 0x0003 - } conn_trn_t; - + }; + /** Lower and upper limit of a range. */ struct range_t { uint16_t low; ///< Low value of range. @@ -270,27 +274,79 @@ friend class Articulation; }; + /** @brief Abstract base class for all classes using RIFF::Chunks for persistency. + * + * This abstract base class defines the general interface for all classes + * which are using RIFF::Chunks to actually load and store their data + * persistently from/to disk. + */ + class Storage { + public: + /** @brief Apply object's changes to the respective RIF::Chunks. + * + * This abstract interface method is intended to be implemented by the + * deriving classes by updating the respective RIFF chunks associated + * with the object such that those RIFF chunks reflect the object's + * current data (i.e. object's current member variables). So the purpose + * of this method is to prepare for saving the object's current state + * persistently to the actual RIFF file. + * + * After returning from this method the changes are just scheduled to be + * saved to the RIFF file, it is required to call File::Save() + * subsequently to make the changes actually persistent on file level. + * + * Usually there is no need to call this method directly from an + * application. This method is called automatically by libgig if one of + * the respective API methods is called to save the file persistently + * to disk (i.e. DLS::File::Save() or gig::File::Save()). + * + * @param pProgress - callback function for progress notification + */ + virtual void UpdateChunks(progress_t* pProgress) = 0; + + /** @brief Remove all RIFF chunks associated with this object. + * + * This abstract interface method is intended to be implemented by the + * deriving classes by removing every RIFF::Chunk the deriving overall + * object is using to store the object in the final RIFF::File. In other + * words: the intention is to remove the deriving class(es)'s object + * persistently from the currently open file. + * + * Note that the RIFF::Chunks deletions is just scheduled after + * returning from this method. You have to call File::Save() to make + * these changes persistent on file level. + * + * Usually there is no need to call this method directly from an + * application. This method is called automatically by libgig if one of + * the respective API methods is called to remove the respective object + * persistently (i.e. File::DeleteInstrument() or File::DeleteSample()). + */ + virtual void DeleteChunks() = 0; + }; + /** Provides access to the defined connections used for the synthesis model. */ - class Articulation { + class Articulation : public Storage { public: Connection* pConnections; ///< Points to the beginning of a Connection array. uint32_t Connections; ///< Reflects the number of Connections. Articulation(RIFF::Chunk* artl); virtual ~Articulation(); - virtual void UpdateChunks(progress_t* pProgress); + virtual void UpdateChunks(progress_t* pProgress) OVERRIDE; + virtual void DeleteChunks() OVERRIDE; protected: RIFF::Chunk* pArticulationCk; uint32_t HeaderSize; }; /** Abstract base class for classes that provide articulation information (thus for Instrument and Region class). */ - class Articulator { + class Articulator : public Storage { public: Articulator(RIFF::List* ParentList); Articulation* GetFirstArticulation(); Articulation* GetNextArticulation(); - virtual void UpdateChunks(progress_t* pProgress); + virtual void UpdateChunks(progress_t* pProgress) OVERRIDE; + virtual void DeleteChunks() OVERRIDE; virtual void CopyAssign(const Articulator* orig); protected: typedef std::list ArticulationList; @@ -303,7 +359,7 @@ }; /** Optional information for DLS files, instruments, samples, etc. */ - class Info { + class Info : public Storage { public: String Name; ///< . Stores the title of the subject of the file, such as, Seattle From Above. String ArchivalLocation; ///< . Indicates where the subject of the file is stored. @@ -332,7 +388,8 @@ Info(RIFF::List* list); void SetFixedStringLengths(const string_length_t* lengths); virtual ~Info(); - virtual void UpdateChunks(progress_t* pProgress); + virtual void UpdateChunks(progress_t* pProgress) OVERRIDE; + virtual void DeleteChunks() OVERRIDE; virtual void CopyAssign(const Info* orig); private: RIFF::List* pResourceListChunk; @@ -343,15 +400,17 @@ }; /** Abstract base class which encapsulates data structures which all DLS resources are able to provide. */ - class Resource { + class Resource : public Storage { public: Info* pInfo; ///< Points (in any case) to an Info object, providing additional, optional infos and comments. dlsid_t* pDLSID; ///< Points to a dlsid_t structure if the file provided a DLS ID else is NULL. Resource* GetParent() { return pParent; } const Resource* GetParent() const { return pParent; } - virtual void UpdateChunks(progress_t* pProgress); + virtual void UpdateChunks(progress_t* pProgress) OVERRIDE; + virtual void DeleteChunks() OVERRIDE; void GenerateDLSID(); + static void GenerateDLSID(dlsid_t* pDLSID); virtual void CopyAssign(const Resource* orig); protected: Resource* pParent; @@ -362,7 +421,7 @@ }; /** Abstract base class which provides mandatory informations about sample players in general. */ - class Sampler { + class Sampler : public Storage { public: uint8_t UnityNote; int16_t FineTune; @@ -375,7 +434,8 @@ void AddSampleLoop(sample_loop_t* pLoopDef); void DeleteSampleLoop(sample_loop_t* pLoopDef); virtual void SetGain(int32_t gain); - virtual void UpdateChunks(progress_t* pProgress); + virtual void UpdateChunks(progress_t* pProgress) OVERRIDE; + virtual void DeleteChunks() OVERRIDE; virtual void CopyAssign(const Sampler* orig); protected: RIFF::List* pParentList; @@ -407,11 +467,12 @@ void* LoadSampleData(); void ReleaseSampleData(); file_offset_t GetSize() const; - void Resize(int iNewSize); + void Resize(file_offset_t NewSize); file_offset_t SetPos(file_offset_t SampleCount, RIFF::stream_whence_t Whence = RIFF::stream_start); file_offset_t Read(void* pBuffer, file_offset_t SampleCount); file_offset_t Write(void* pBuffer, file_offset_t SampleCount); - virtual void UpdateChunks(progress_t* pProgress); + virtual void UpdateChunks(progress_t* pProgress) OVERRIDE; + virtual void DeleteChunks() OVERRIDE; virtual void CopyAssign(const Sample* orig); protected: @@ -443,7 +504,8 @@ Sample* GetSample(); void SetSample(Sample* pSample); virtual void SetKeyRange(uint16_t Low, uint16_t High); - virtual void UpdateChunks(progress_t* pProgress); + virtual void UpdateChunks(progress_t* pProgress) OVERRIDE; + virtual void DeleteChunks() OVERRIDE; virtual void CopyAssign(const Region* orig); protected: RIFF::List* pCkRegion; @@ -471,7 +533,8 @@ Region* GetNextRegion(); Region* AddRegion(); void DeleteRegion(Region* pRegion); - virtual void UpdateChunks(progress_t* pProgress); + virtual void UpdateChunks(progress_t* pProgress) OVERRIDE; + virtual void DeleteChunks() OVERRIDE; virtual void CopyAssign(const Instrument* orig); protected: typedef std::list RegionList; @@ -512,8 +575,9 @@ Instrument* GetNextInstrument(); ///< Returns a pointer to the next Instrument object of the file, NULL otherwise. Instrument* AddInstrument(); void DeleteInstrument(Instrument* pInstrument); + RIFF::File* GetRiffFile(); RIFF::File* GetExtensionFile(int index); - virtual void UpdateChunks(progress_t* pProgress); + virtual void UpdateChunks(progress_t* pProgress) OVERRIDE; virtual void Save(const String& Path, progress_t* pProgress = NULL); virtual void Save(progress_t* pProgress = NULL); virtual ~File(); @@ -522,7 +586,7 @@ typedef std::list InstrumentList; RIFF::File* pRIFF; - std::list ExtensionFiles; + std::list ExtensionFiles; //FIXME: These should automatically be freed, since implicitly allocated. SampleList* pSamples; SampleList::iterator SamplesIterator; InstrumentList* pInstruments; @@ -532,6 +596,7 @@ uint32_t* pWavePoolTable; uint32_t* pWavePoolTableHi; bool b64BitWavePoolOffsets; + bool bOwningRiff; ///< If @c true then @c pRIFF was implicitly allocated by this class and hence pRIFF will automatically be freed by the @c DLS::File destructor in that case. virtual void LoadSamples(); virtual void LoadInstruments(); @@ -552,8 +617,11 @@ */ class Exception : public RIFF::Exception { public: - Exception(String Message); + Exception(String format, ...); + Exception(String format, va_list arg); void PrintMessage(); + protected: + Exception(); }; String libraryName();