/*************************************************************************** * * * libgig - C++ cross-platform Gigasampler format file access library * * * * Copyright (C) 2003-2021 by Christian Schoenebeck * * * * * * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this library; if not, write to the Free Software * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * * MA 02111-1307 USA * ***************************************************************************/ #ifndef __DLS_H__ #define __DLS_H__ #include "RIFF.h" #if WORDS_BIGENDIAN # define RIFF_TYPE_DLS 0x444C5320 # define LIST_TYPE_WVPL 0x7776706C # define LIST_TYPE_DWPL 0x6477706C ///< Seen on some files instead of a wvpl list chunk. # define LIST_TYPE_WAVE 0x77617665 # define LIST_TYPE_LINS 0X6C696E73 # define LIST_TYPE_INS 0X696E7320 # define LIST_TYPE_LRGN 0x6C72676E # define LIST_TYPE_LART 0x6C617274 # define LIST_TYPE_LAR2 0x6C617232 # define LIST_TYPE_RGN 0x72676E20 # define LIST_TYPE_RGN2 0x72676E32 # define CHUNK_ID_IARL 0x4941524C # define CHUNK_ID_IART 0x49415254 # define CHUNK_ID_ICMS 0x49434D53 # define CHUNK_ID_IGNR 0x49474E52 # define CHUNK_ID_IKEY 0x494B4559 # define CHUNK_ID_IMED 0x494D4544 # define CHUNK_ID_ISBJ 0x4953424A # define CHUNK_ID_ISRC 0x49535243 # define CHUNK_ID_ISRF 0x49535246 # define CHUNK_ID_ITCH 0x49544348 # define CHUNK_ID_VERS 0x76657273 # define CHUNK_ID_DLID 0x646C6964 # define CHUNK_ID_FMT 0x666D7420 # define CHUNK_ID_DATA 0x64617461 # define CHUNK_ID_INSH 0x696E7368 # define CHUNK_ID_RGNH 0x72676E68 # define CHUNK_ID_WLNK 0x776C6E6B # define CHUNK_ID_PTBL 0x7074626C # define CHUNK_ID_WSMP 0x77736D70 # 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 # define LIST_TYPE_DWPL 0x6C707764 ///< Seen on some files instead of a wvpl list chunk. # define LIST_TYPE_WAVE 0x65766177 # define LIST_TYPE_LINS 0X736E696C # define LIST_TYPE_INS 0X20736E69 # define LIST_TYPE_LRGN 0x6E67726C # define LIST_TYPE_LART 0x7472616C # define LIST_TYPE_LAR2 0x3272616C # define LIST_TYPE_RGN 0x206E6772 # define LIST_TYPE_RGN2 0x326E6772 # define CHUNK_ID_IARL 0x4C524149 # define CHUNK_ID_IART 0x54524149 # define CHUNK_ID_ICMS 0x534D4349 # define CHUNK_ID_IGNR 0x524E4749 # define CHUNK_ID_IKEY 0x59454B49 # define CHUNK_ID_IMED 0x44454D49 # define CHUNK_ID_ISBJ 0x4A425349 # define CHUNK_ID_ISRC 0x43525349 # define CHUNK_ID_ISRF 0x46525349 # define CHUNK_ID_ITCH 0x48435449 # define CHUNK_ID_VERS 0x73726576 # define CHUNK_ID_DLID 0x64696C64 # define CHUNK_ID_FMT 0x20746D66 # define CHUNK_ID_DATA 0x61746164 # define CHUNK_ID_INSH 0x68736E69 # define CHUNK_ID_RGNH 0x686E6772 # define CHUNK_ID_WLNK 0x6B6E6C77 # define CHUNK_ID_PTBL 0x6C627470 # define CHUNK_ID_WSMP 0x706D7377 # 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 //TODO: no support for conditional chunks yet /** DLS specific classes and definitions */ namespace DLS { typedef std::string String; typedef RIFF::progress_t progress_t; typedef RIFF::file_offset_t file_offset_t; /** Quadtuple version number ("major.minor.release.build"). */ struct version_t { uint16_t minor; uint16_t major; uint16_t build; uint16_t release; }; /** Every subject of an DLS file and the file itself can have an unique, computer generated ID. */ struct dlsid_t { uint32_t ulData1; uint16_t usData2; uint16_t usData3; uint8_t abData[8]; }; /** Connection Sources */ enum conn_src_t { // Modulator Sources conn_src_none = 0x0000, conn_src_lfo = 0x0001, conn_src_keyonvelocity = 0x0002, conn_src_keynumber = 0x0003, conn_src_eg1 = 0x0004, conn_src_eg2 = 0x0005, conn_src_pitchwheel = 0x0006, conn_src_polypressure = 0x0007, conn_src_channelpressure = 0x0008, conn_src_vibrato = 0x0009, // MIDI Controller Sources conn_src_cc1 = 0x0081, conn_src_cc7 = 0x0087, conn_src_cc10 = 0x008A, conn_src_cc11 = 0x008B, conn_src_cc91 = 0x00DB, conn_src_cc93 = 0x00DD, // Registered Parameter Numbers conn_src_rpn0 = 0x0100, conn_src_rpn1 = 0x0101, conn_src_rpn2 = 0x0102 }; /** Connection Destinations */ enum conn_dst_t { // Generic Destinations conn_dst_none = 0x0000, conn_dst_gain = 0x0001, conn_dst_reserved = 0x0002, conn_dst_pitch = 0x0003, conn_dst_pan = 0x0004, conn_dst_keynumber = 0x0005, // Channel Output Destinations conn_dst_left = 0x0010, conn_dst_right = 0x0011, conn_dst_center = 0x0012, conn_dst_lfe_channel = 0x0013, conn_dst_leftrear = 0x0014, conn_dst_rightrear = 0x0015, conn_dst_chorus = 0x0080, conn_dst_reverb = 0x0081, // Modulator LFO Destinations conn_dst_lfo_frequency = 0x0104, conn_dst_lfo_startdelay = 0x0105, // Vibrato LFO Destinations conn_dst_vib_frequency = 0x0114, conn_dst_vib_startdelay = 0x0115, // EG Destinations conn_dst_eg1_attacktime = 0x0206, conn_dst_eg1_decaytime = 0x0207, conn_dst_eg1_reserved = 0x0208, conn_dst_eg1_releasetime = 0x0209, conn_dst_eg1_sustainlevel = 0x020A, conn_dst_eg1_delaytime = 0x020B, conn_dst_eg1_holdtime = 0x020C, conn_dst_eg1_shutdowntime = 0x020D, conn_dst_eg2_attacktime = 0x030A, conn_dst_eg2_decaytime = 0x030B, conn_dst_eg2_reserved = 0x030C, conn_dst_eg2_releasetime = 0x030D, conn_dst_eg2_sustainlevel = 0x030E, conn_dst_eg2_delaytime = 0x030F, conn_dst_eg2_holdtime = 0x0310, // Filter Destinations conn_dst_filter_cutoff = 0x0500, conn_dst_filter_q = 0x0501 }; /** Connection Transforms */ enum conn_trn_t { conn_trn_none = 0x0000, conn_trn_concave = 0x0001, conn_trn_convex = 0x0002, conn_trn_switch = 0x0003 }; /** Lower and upper limit of a range. */ struct range_t { uint16_t low; ///< Low value of range. uint16_t high; ///< High value of range. inline bool operator< (const range_t& other) const { if (low < other.low) return true; if (low > other.low) return false; return high < other.high; } inline bool operator== (const range_t& other) const { return low == other.low && high == other.high; } inline bool overlaps(uint16_t scalar) const { return low <= scalar && scalar <= high; } inline bool overlaps(const range_t& other) const { return overlaps(other.low) || overlaps(other.high) || other.overlaps(low) || other.overlaps(high); } }; /** Defines Sample Loop Points. */ struct sample_loop_t { 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 class File; class Instrument; class Region; class Sample; /** Defines a connection within the synthesis model. */ class Connection { public: conn_src_t Source; conn_trn_t SourceTransform; bool SourceInvert; bool SourceBipolar; conn_src_t Control; conn_trn_t ControlTransform; bool ControlInvert; bool ControlBipolar; conn_dst_t Destination; conn_trn_t DestinationTransform; uint32_t Scale; protected: struct conn_block_t { uint16_t source; uint16_t control; uint16_t destination; uint16_t transform; uint32_t scale; }; Connection() {} void Init(conn_block_t* Header); conn_block_t ToConnBlock(); virtual ~Connection() {} 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 : 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) 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 : public Storage { public: Articulator(RIFF::List* ParentList); Articulation* GetArticulation(size_t pos); Articulation* GetFirstArticulation() LIBGIG_DEPRECATED_API("Use GetArticulation() instead."); Articulation* GetNextArticulation() LIBGIG_DEPRECATED_API("Use GetArticulation() instead."); virtual void UpdateChunks(progress_t* pProgress) OVERRIDE; virtual void DeleteChunks() OVERRIDE; virtual void CopyAssign(const Articulator* orig); protected: typedef std::vector ArticulationList; RIFF::List* pParentList; ArticulationList* pArticulations; ArticulationList::iterator ArticulationsIterator; void LoadArticulations(); virtual ~Articulator(); }; /** Optional information for DLS files, instruments, samples, etc. */ 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. String CreationDate; ///< . Specifies the date the subject of the file was created. List dates in yyyy-mm-dd format. String Comments; ///< . Provides general comments about the file or the subject of the file. Sentences might end with semicolon. String Product; ///< . Specifies the name of the title the file was originally intended for, such as World Ruler V. String Copyright; ///< . Records the copyright information for the file. String Artists; ///< . Lists the artist of the original subject of the file. String Genre; ///< . Descirbes the original work, such as, Jazz, Classic, Rock, Techno, Rave, etc. String Keywords; ///< . 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. String Engineer; ///< . Stores the name of the engineer who worked on the file. Multiple engineer names are separated by semicolon and blank, e.g, Smith, John; Adams, Joe. String Technician; ///< . Identifies the technician who sampled the subject file. String Software; ///< . Identifies the name of the sofware package used to create the file. String Medium; ///< . Describes the original subject of the file, such as, record, CD, and so forth. 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 Not used anymore, use SetFixedStringLengths() instead. struct string_length_t { uint32_t chunkId; int length; }; Info(RIFF::List* list); void SetFixedStringLengths(const string_length_t* lengths); virtual ~Info(); virtual void UpdateChunks(progress_t* pProgress) OVERRIDE; virtual void DeleteChunks() OVERRIDE; virtual void CopyAssign(const Info* orig); private: RIFF::List* pResourceListChunk; const string_length_t* pFixedStringLengths; ///< 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. 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); }; /** Abstract base class which encapsulates data structures which all DLS resources are able to provide. */ 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) OVERRIDE; virtual void DeleteChunks() OVERRIDE; void GenerateDLSID(); static void GenerateDLSID(dlsid_t* pDLSID); virtual void CopyAssign(const Resource* orig); protected: Resource* pParent; RIFF::List* pResourceList; Resource(Resource* Parent, RIFF::List* lstResource); virtual ~Resource(); }; /** Abstract base class which provides mandatory informations about sample players in general. */ class Sampler : public Storage { public: uint8_t UnityNote; int16_t FineTune; 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(progress_t* pProgress) OVERRIDE; virtual void DeleteChunks() OVERRIDE; virtual void CopyAssign(const Sampler* orig); protected: RIFF::List* pParentList; uint32_t uiHeaderSize; uint32_t SamplerOptions; Sampler(RIFF::List* ParentList); virtual ~Sampler(); }; /** @brief Encapsulates sample waves used for playback. * * In case you created a new sample with File::AddSample(), you should * 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 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). file_offset_t 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). 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(); file_offset_t GetSize() const; 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) OVERRIDE; virtual void DeleteChunks() OVERRIDE; virtual void CopyAssign(const Sample* orig); protected: RIFF::List* pWaveList; RIFF::Chunk* pCkData; RIFF::Chunk* pCkFormat; file_offset_t ullWavePoolOffset; // needed for comparison with the wave pool link table, thus the link to instruments Sample(File* pFile, RIFF::List* waveList, file_offset_t WavePoolOffset); virtual ~Sample(); void CopyAssignCore(const Sample* orig); friend class File; friend class Region; // Region has to compare the wave pool offset to get its sample }; /** Defines Region information of an Instrument. */ class Region : public Resource, public Articulator, public Sampler { public: range_t KeyRange; ///< @deprecated Only read, don't write! Use SetKeyRange() instead. range_t VelocityRange; uint16_t KeyGroup; uint16_t Layer; bool SelfNonExclusive; bool PhaseMaster; uint16_t PhaseGroup; bool MultiChannel; uint32_t Channel; Sample* GetSample(); void SetSample(Sample* pSample); virtual void SetKeyRange(uint16_t Low, uint16_t High); virtual void UpdateChunks(progress_t* pProgress) OVERRIDE; virtual void DeleteChunks() OVERRIDE; virtual void CopyAssign(const Region* orig); protected: RIFF::List* pCkRegion; uint32_t WavePoolTableIndex; // index in the wave pool table to the sample wave this region is linked to Sample* pSample; // every region refers to exactly one sample uint16_t FormatOptionFlags; uint16_t WaveLinkOptionFlags; Region(Instrument* pInstrument, RIFF::List* rgnList); virtual ~Region(); friend class Instrument; }; /** Provides all neccessary information for the synthesis of a DLS Instrument. */ class Instrument : public Resource, public Articulator { public: bool IsDrum; ///< Indicates if the Instrument is a drum type, as they differ in the synthesis model of DLS from melodic instruments. uint16_t MIDIBank; ///< Reflects combination of MIDIBankCoarse and MIDIBankFine (bank 1 - bank 16384). Do not change this value, it will not be saved! Change MIDIBankCoarse and MIDIBankFine instead (we might change that in future). uint8_t MIDIBankCoarse; ///< Reflects the MIDI Bank number for MIDI Control Change 0 (bank 1 - 128). uint8_t MIDIBankFine; ///< Reflects the MIDI Bank number for MIDI Control Change 32 (bank 1 - 128). uint32_t MIDIProgram; ///< Specifies the MIDI Program Change Number this Instrument should be assigned to. uint32_t Regions; ///< Reflects the number of Region defintions this Instrument has. size_t CountRegions(); Region* GetRegionAt(size_t pos); Region* GetFirstRegion() LIBGIG_DEPRECATED_API("Use GetRegionAt() instead."); Region* GetNextRegion() LIBGIG_DEPRECATED_API("Use GetRegionAt() instead."); Region* AddRegion(); void DeleteRegion(Region* pRegion); virtual void UpdateChunks(progress_t* pProgress) OVERRIDE; virtual void DeleteChunks() OVERRIDE; virtual void CopyAssign(const Instrument* orig); protected: typedef std::vector RegionList; struct midi_locale_t { uint32_t bank; uint32_t instrument; }; RIFF::List* pCkInstrument; RegionList* pRegions; RegionList::iterator RegionsIterator; Instrument(File* pFile, RIFF::List* insList); void CopyAssignCore(const Instrument* orig); 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. */ class File : public Resource { public: version_t* pVersion; ///< Points to a version_t structure if the file provided a version number else is set to NULL. uint32_t Instruments; ///< Reflects the number of available Instrument objects. File(); File(RIFF::File* pRIFF); String GetFileName(); void SetFileName(const String& name); Sample* GetSample(size_t index); Sample* GetFirstSample() LIBGIG_DEPRECATED_API("Use GetSample() instead."); Sample* GetNextSample() LIBGIG_DEPRECATED_API("Use GetSample() instead."); Sample* AddSample(); void DeleteSample(Sample* pSample); Instrument* GetInstrument(size_t index); Instrument* GetFirstInstrument() LIBGIG_DEPRECATED_API("Use GetInstrument() instead."); Instrument* GetNextInstrument() LIBGIG_DEPRECATED_API("Use GetInstrument() instead."); Instrument* AddInstrument(); void DeleteInstrument(Instrument* pInstrument); RIFF::File* GetRiffFile(); RIFF::File* GetExtensionFile(int index); 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(); protected: typedef std::vector SampleList; typedef std::vector InstrumentList; RIFF::File* pRIFF; std::list ExtensionFiles; SampleList* pSamples; SampleList::iterator SamplesIterator; InstrumentList* pInstruments; InstrumentList::iterator InstrumentsIterator; uint32_t WavePoolHeaderSize; uint32_t WavePoolCount; 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(); virtual void UpdateFileOffsets(); void __ensureMandatoryChunksExist(); friend class Region; // Region has to look in the wave pool table to get its sample private: void __UpdateWavePoolTableChunk(); void __UpdateWavePoolTable(); }; /** * 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 format, ...); Exception(String format, va_list arg); void PrintMessage(); protected: Exception(); }; String libraryName(); String libraryVersion(); } // namespace DLS #endif // __DLS_H__