libgig 3.3.0
|
00001 /*************************************************************************** 00002 * * 00003 * libgig - C++ cross-platform Gigasampler format file access library * 00004 * * 00005 * Copyright (C) 2003-2009 by Christian Schoenebeck * 00006 * <cuse@users.sourceforge.net> * 00007 * * 00008 * This library is free software; you can redistribute it and/or modify * 00009 * it under the terms of the GNU General Public License as published by * 00010 * the Free Software Foundation; either version 2 of the License, or * 00011 * (at your option) any later version. * 00012 * * 00013 * This library is distributed in the hope that it will be useful, * 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00016 * GNU General Public License for more details. * 00017 * * 00018 * You should have received a copy of the GNU General Public License * 00019 * along with this library; if not, write to the Free Software * 00020 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * 00021 * MA 02111-1307 USA * 00022 ***************************************************************************/ 00023 00024 #ifndef __DLS_H__ 00025 #define __DLS_H__ 00026 00027 #include "RIFF.h" 00028 00029 #if WORDS_BIGENDIAN 00030 # define RIFF_TYPE_DLS 0x444C5320 00031 # define LIST_TYPE_INFO 0x494E464F 00032 # define LIST_TYPE_WVPL 0x7776706C 00033 # define LIST_TYPE_DWPL 0x6477706C ///< Seen on some files instead of a wvpl list chunk. 00034 # define LIST_TYPE_WAVE 0x77617665 00035 # define LIST_TYPE_LINS 0X6C696E73 00036 # define LIST_TYPE_INS 0X696E7320 00037 # define LIST_TYPE_LRGN 0x6C72676E 00038 # define LIST_TYPE_LART 0x6C617274 00039 # define LIST_TYPE_LAR2 0x6C617232 00040 # define LIST_TYPE_RGN 0x72676E20 00041 # define LIST_TYPE_RGN2 0x72676E32 00042 # define CHUNK_ID_IARL 0x4941524C 00043 # define CHUNK_ID_IART 0x49415254 00044 # define CHUNK_ID_ICMS 0x49434D53 00045 # define CHUNK_ID_ICMT 0x49434D54 00046 # define CHUNK_ID_ICOP 0x49434F50 00047 # define CHUNK_ID_ICRD 0x49435244 00048 # define CHUNK_ID_IENG 0x49454E47 00049 # define CHUNK_ID_IGNR 0x49474E52 00050 # define CHUNK_ID_IKEY 0x494B4559 00051 # define CHUNK_ID_IMED 0x494D4544 00052 # define CHUNK_ID_INAM 0x494E414D 00053 # define CHUNK_ID_IPRD 0x49505244 00054 # define CHUNK_ID_ISBJ 0x4953424A 00055 # define CHUNK_ID_ISFT 0x49534654 00056 # define CHUNK_ID_ISRC 0x49535243 00057 # define CHUNK_ID_ISRF 0x49535246 00058 # define CHUNK_ID_ITCH 0x49544348 00059 # define CHUNK_ID_VERS 0x76657273 00060 # define CHUNK_ID_DLID 0x646C6964 00061 # define CHUNK_ID_FMT 0x666D7420 00062 # define CHUNK_ID_DATA 0x64617461 00063 # define CHUNK_ID_INSH 0x696E7368 00064 # define CHUNK_ID_RGNH 0x72676E68 00065 # define CHUNK_ID_WLNK 0x776C6E6B 00066 # define CHUNK_ID_PTBL 0x7074626C 00067 # define CHUNK_ID_WSMP 0x77736D70 00068 # define CHUNK_ID_COLH 0x636F6C68 00069 # define CHUNK_ID_ARTL 0x6172746C 00070 # define CHUNK_ID_ART2 0x61727432 00071 #else // little endian 00072 # define RIFF_TYPE_DLS 0x20534C44 00073 # define LIST_TYPE_INFO 0x4F464E49 00074 # define LIST_TYPE_WVPL 0x6C707677 00075 # define LIST_TYPE_DWPL 0x6C707764 ///< Seen on some files instead of a wvpl list chunk. 00076 # define LIST_TYPE_WAVE 0x65766177 00077 # define LIST_TYPE_LINS 0X736E696C 00078 # define LIST_TYPE_INS 0X20736E69 00079 # define LIST_TYPE_LRGN 0x6E67726C 00080 # define LIST_TYPE_LART 0x7472616C 00081 # define LIST_TYPE_LAR2 0x3272616C 00082 # define LIST_TYPE_RGN 0x206E6772 00083 # define LIST_TYPE_RGN2 0x326E6772 00084 # define CHUNK_ID_IARL 0x4C524149 00085 # define CHUNK_ID_IART 0x54524149 00086 # define CHUNK_ID_ICMS 0x534D4349 00087 # define CHUNK_ID_ICMT 0x544D4349 00088 # define CHUNK_ID_ICOP 0x504F4349 00089 # define CHUNK_ID_ICRD 0x44524349 00090 # define CHUNK_ID_IENG 0x474E4549 00091 # define CHUNK_ID_IGNR 0x524E4749 00092 # define CHUNK_ID_IKEY 0x59454B49 00093 # define CHUNK_ID_IMED 0x44454D49 00094 # define CHUNK_ID_INAM 0x4D414E49 00095 # define CHUNK_ID_IPRD 0x44525049 00096 # define CHUNK_ID_ISBJ 0x4A425349 00097 # define CHUNK_ID_ISFT 0x54465349 00098 # define CHUNK_ID_ISRC 0x43525349 00099 # define CHUNK_ID_ISRF 0x46525349 00100 # define CHUNK_ID_ITCH 0x48435449 00101 # define CHUNK_ID_VERS 0x73726576 00102 # define CHUNK_ID_DLID 0x64696C64 00103 # define CHUNK_ID_FMT 0x20746D66 00104 # define CHUNK_ID_DATA 0x61746164 00105 # define CHUNK_ID_INSH 0x68736E69 00106 # define CHUNK_ID_RGNH 0x686E6772 00107 # define CHUNK_ID_WLNK 0x6B6E6C77 00108 # define CHUNK_ID_PTBL 0x6C627470 00109 # define CHUNK_ID_WSMP 0x706D7377 00110 # define CHUNK_ID_COLH 0x686C6F63 00111 # define CHUNK_ID_ARTL 0x6C747261 00112 # define CHUNK_ID_ART2 0x32747261 00113 #endif // WORDS_BIGENDIAN 00114 00115 #define DLS_WAVE_FORMAT_PCM 0x0001 00116 00117 //TODO: no support for conditional chunks <cdl> yet 00118 00120 namespace DLS { 00121 00122 typedef std::string String; 00123 00125 struct version_t { 00126 uint16_t minor; 00127 uint16_t major; 00128 uint16_t build; 00129 uint16_t release; 00130 }; 00131 00133 struct dlsid_t { 00134 uint32_t ulData1; 00135 uint16_t usData2; 00136 uint16_t usData3; 00137 uint8_t abData[8]; 00138 }; 00139 00141 typedef enum { 00142 // Modulator Sources 00143 conn_src_none = 0x0000, 00144 conn_src_lfo = 0x0001, 00145 conn_src_keyonvelocity = 0x0002, 00146 conn_src_keynumber = 0x0003, 00147 conn_src_eg1 = 0x0004, 00148 conn_src_eg2 = 0x0005, 00149 conn_src_pitchwheel = 0x0006, 00150 conn_src_polypressure = 0x0007, 00151 conn_src_channelpressure = 0x0008, 00152 conn_src_vibrato = 0x0009, 00153 // MIDI Controller Sources 00154 conn_src_cc1 = 0x0081, 00155 conn_src_cc7 = 0x0087, 00156 conn_src_cc10 = 0x008A, 00157 conn_src_cc11 = 0x008B, 00158 conn_src_cc91 = 0x00DB, 00159 conn_src_cc93 = 0x00DD, 00160 // Registered Parameter Numbers 00161 conn_src_rpn0 = 0x0100, 00162 conn_src_rpn1 = 0x0101, 00163 conn_src_rpn2 = 0x0102 00164 } conn_src_t; 00165 00167 typedef enum { 00168 // Generic Destinations 00169 conn_dst_none = 0x0000, 00170 conn_dst_gain = 0x0001, 00171 conn_dst_reserved = 0x0002, 00172 conn_dst_pitch = 0x0003, 00173 conn_dst_pan = 0x0004, 00174 conn_dst_keynumber = 0x0005, 00175 // Channel Output Destinations 00176 conn_dst_left = 0x0010, 00177 conn_dst_right = 0x0011, 00178 conn_dst_center = 0x0012, 00179 conn_dst_lfe_channel = 0x0013, 00180 conn_dst_leftrear = 0x0014, 00181 conn_dst_rightrear = 0x0015, 00182 conn_dst_chorus = 0x0080, 00183 conn_dst_reverb = 0x0081, 00184 // Modulator LFO Destinations 00185 conn_dst_lfo_frequency = 0x0104, 00186 conn_dst_lfo_startdelay = 0x0105, 00187 // Vibrato LFO Destinations 00188 conn_dst_vib_frequency = 0x0114, 00189 conn_dst_vib_startdelay = 0x0115, 00190 // EG Destinations 00191 conn_dst_eg1_attacktime = 0x0206, 00192 conn_dst_eg1_decaytime = 0x0207, 00193 conn_dst_eg1_reserved = 0x0208, 00194 conn_dst_eg1_releasetime = 0x0209, 00195 conn_dst_eg1_sustainlevel = 0x020A, 00196 conn_dst_eg1_delaytime = 0x020B, 00197 conn_dst_eg1_holdtime = 0x020C, 00198 conn_dst_eg1_shutdowntime = 0x020D, 00199 conn_dst_eg2_attacktime = 0x030A, 00200 conn_dst_eg2_decaytime = 0x030B, 00201 conn_dst_eg2_reserved = 0x030C, 00202 conn_dst_eg2_releasetime = 0x030D, 00203 conn_dst_eg2_sustainlevel = 0x030E, 00204 conn_dst_eg2_delaytime = 0x030F, 00205 conn_dst_eg2_holdtime = 0x0310, 00206 // Filter Destinations 00207 conn_dst_filter_cutoff = 0x0500, 00208 conn_dst_filter_q = 0x0501 00209 } conn_dst_t; 00210 00212 typedef enum { 00213 conn_trn_none = 0x0000, 00214 conn_trn_concave = 0x0001, 00215 conn_trn_convex = 0x0002, 00216 conn_trn_switch = 0x0003 00217 } conn_trn_t; 00218 00220 struct range_t { 00221 uint16_t low; 00222 uint16_t high; 00223 }; 00224 00226 struct sample_loop_t { 00227 uint32_t Size; 00228 uint32_t LoopType; 00229 uint32_t LoopStart; 00230 uint32_t LoopLength; 00231 }; 00232 00233 // just symbol prototyping 00234 class File; 00235 class Instrument; 00236 class Region; 00237 class Sample; 00238 00240 class Connection { 00241 public: 00242 conn_src_t Source; 00243 conn_trn_t SourceTransform; 00244 bool SourceInvert; 00245 bool SourceBipolar; 00246 conn_src_t Control; 00247 conn_trn_t ControlTransform; 00248 bool ControlInvert; 00249 bool ControlBipolar; 00250 conn_dst_t Destination; 00251 conn_trn_t DestinationTransform; 00252 uint32_t Scale; 00253 protected: 00254 struct conn_block_t { 00255 uint16_t source; 00256 uint16_t control; 00257 uint16_t destination; 00258 uint16_t transform; 00259 uint32_t scale; 00260 }; 00261 Connection() {} 00262 void Init(conn_block_t* Header); 00263 conn_block_t ToConnBlock(); 00264 virtual ~Connection() {} 00265 friend class Articulation; 00266 }; 00267 00269 class Articulation { 00270 public: 00271 Connection* pConnections; 00272 uint32_t Connections; 00273 00274 Articulation(RIFF::Chunk* artl); 00275 virtual ~Articulation(); 00276 virtual void UpdateChunks(); 00277 protected: 00278 RIFF::Chunk* pArticulationCk; 00279 uint32_t HeaderSize; 00280 }; 00281 00283 class Articulator { 00284 public: 00285 Articulator(RIFF::List* ParentList); 00286 Articulation* GetFirstArticulation(); 00287 Articulation* GetNextArticulation(); 00288 virtual void UpdateChunks(); 00289 protected: 00290 typedef std::list<Articulation*> ArticulationList; 00291 RIFF::List* pParentList; 00292 ArticulationList* pArticulations; 00293 ArticulationList::iterator ArticulationsIterator; 00294 00295 void LoadArticulations(); 00296 virtual ~Articulator(); 00297 }; 00298 00300 class Info { 00301 public: 00302 String Name; 00303 String ArchivalLocation; 00304 String CreationDate; 00305 String Comments; 00306 String Product; 00307 String Copyright; 00308 String Artists; 00309 String Genre; 00310 String Keywords; 00311 String Engineer; 00312 String Technician; 00313 String Software; 00314 String Medium; 00315 String Source; 00316 String SourceForm; 00317 String Commissioned; 00318 String Subject; 00319 bool UseFixedLengthStrings; 00320 00321 struct string_length_t { 00322 uint32_t chunkId; 00323 int length; 00324 }; 00325 00326 Info(RIFF::List* list); 00327 void SetFixedStringLengths(const string_length_t* lengths); 00328 virtual ~Info(); 00329 virtual void UpdateChunks(); 00330 private: 00331 RIFF::List* pResourceListChunk; 00332 const string_length_t* pFixedStringLengths; 00333 00334 static void LoadString(uint32_t ChunkID, RIFF::List* lstINFO, String& s); 00335 void SaveString(uint32_t ChunkID, RIFF::List* lstINFO, const String& s, const String& sDefault); 00336 }; 00337 00339 class Resource { 00340 public: 00341 Info* pInfo; 00342 dlsid_t* pDLSID; 00343 00344 Resource* GetParent() { return pParent; } 00345 virtual void UpdateChunks(); 00346 void GenerateDLSID(); 00347 protected: 00348 Resource* pParent; 00349 RIFF::List* pResourceList; 00350 00351 Resource(Resource* Parent, RIFF::List* lstResource); 00352 virtual ~Resource(); 00353 }; 00354 00356 class Sampler { 00357 public: 00358 uint8_t UnityNote; 00359 int16_t FineTune; 00360 int32_t Gain; 00361 bool NoSampleDepthTruncation; 00362 bool NoSampleCompression; 00363 uint32_t SampleLoops; 00364 sample_loop_t* pSampleLoops; 00365 00366 void AddSampleLoop(sample_loop_t* pLoopDef); 00367 void DeleteSampleLoop(sample_loop_t* pLoopDef); 00368 virtual void SetGain(int32_t gain); 00369 virtual void UpdateChunks(); 00370 protected: 00371 RIFF::List* pParentList; 00372 uint32_t uiHeaderSize; 00373 uint32_t SamplerOptions; 00374 Sampler(RIFF::List* ParentList); 00375 virtual ~Sampler(); 00376 }; 00377 00386 class Sample : public Resource { 00387 public: 00388 uint16_t FormatTag; 00389 uint16_t Channels; 00390 uint32_t SamplesPerSecond; 00391 uint32_t AverageBytesPerSecond; 00392 uint16_t BlockAlign; 00393 uint16_t BitDepth; 00394 unsigned long SamplesTotal; 00395 uint FrameSize; 00396 00397 void* LoadSampleData(); 00398 void ReleaseSampleData(); 00399 unsigned long GetSize(); 00400 void Resize(int iNewSize); 00401 unsigned long SetPos(unsigned long SampleCount, RIFF::stream_whence_t Whence = RIFF::stream_start); 00402 unsigned long Read(void* pBuffer, unsigned long SampleCount); 00403 unsigned long Write(void* pBuffer, unsigned long SampleCount); 00404 virtual void UpdateChunks(); 00405 protected: 00406 RIFF::List* pWaveList; 00407 RIFF::Chunk* pCkData; 00408 RIFF::Chunk* pCkFormat; 00409 unsigned long ulWavePoolOffset; // needed for comparison with the wave pool link table, thus the link to instruments 00410 00411 Sample(File* pFile, RIFF::List* waveList, unsigned long WavePoolOffset); 00412 virtual ~Sample(); 00413 friend class File; 00414 friend class Region; // Region has to compare the wave pool offset to get its sample 00415 }; 00416 00418 class Region : public Resource, public Articulator, public Sampler { 00419 public: 00420 range_t KeyRange; 00421 range_t VelocityRange; 00422 uint16_t KeyGroup; 00423 uint16_t Layer; 00424 bool SelfNonExclusive; 00425 bool PhaseMaster; 00426 uint16_t PhaseGroup; 00427 bool MultiChannel; 00428 uint32_t Channel; 00429 00430 Sample* GetSample(); 00431 void SetSample(Sample* pSample); 00432 virtual void SetKeyRange(uint16_t Low, uint16_t High); 00433 virtual void UpdateChunks(); 00434 protected: 00435 RIFF::List* pCkRegion; 00436 uint32_t WavePoolTableIndex; // index in the wave pool table to the sample wave this region is linked to 00437 Sample* pSample; // every region refers to exactly one sample 00438 uint16_t FormatOptionFlags; 00439 uint16_t WaveLinkOptionFlags; 00440 00441 Region(Instrument* pInstrument, RIFF::List* rgnList); 00442 virtual ~Region(); 00443 friend class Instrument; 00444 }; 00445 00447 class Instrument : public Resource, public Articulator { 00448 public: 00449 bool IsDrum; 00450 uint16_t MIDIBank; 00451 uint8_t MIDIBankCoarse; 00452 uint8_t MIDIBankFine; 00453 uint32_t MIDIProgram; 00454 uint32_t Regions; 00455 00456 Region* GetFirstRegion(); 00457 Region* GetNextRegion(); 00458 Region* AddRegion(); 00459 void DeleteRegion(Region* pRegion); 00460 virtual void UpdateChunks(); 00461 protected: 00462 typedef std::list<Region*> RegionList; 00463 struct midi_locale_t { 00464 uint32_t bank; 00465 uint32_t instrument; 00466 }; 00467 00468 RIFF::List* pCkInstrument; 00469 RegionList* pRegions; 00470 RegionList::iterator RegionsIterator; 00471 00472 Instrument(File* pFile, RIFF::List* insList); 00473 virtual void LoadRegions(); 00474 virtual ~Instrument(); 00475 friend class File; 00476 friend class Region; 00477 private: 00478 void MoveRegion(Region* pSrc, Region* pDst); 00479 }; 00480 00482 class File : public Resource { 00483 public: 00484 version_t* pVersion; 00485 uint32_t Instruments; 00486 00487 File(); 00488 File(RIFF::File* pRIFF); 00489 Sample* GetFirstSample(); 00490 Sample* GetNextSample(); 00491 Sample* AddSample(); 00492 void DeleteSample(Sample* pSample); 00493 Instrument* GetFirstInstrument(); 00494 Instrument* GetNextInstrument(); 00495 Instrument* AddInstrument(); 00496 void DeleteInstrument(Instrument* pInstrument); 00497 virtual void UpdateChunks(); 00498 virtual void Save(const String& Path); 00499 virtual void Save(); 00500 virtual ~File(); 00501 protected: 00502 typedef std::list<Sample*> SampleList; 00503 typedef std::list<Instrument*> InstrumentList; 00504 00505 RIFF::File* pRIFF; 00506 std::list<RIFF::File*> ExtensionFiles; 00507 SampleList* pSamples; 00508 SampleList::iterator SamplesIterator; 00509 InstrumentList* pInstruments; 00510 InstrumentList::iterator InstrumentsIterator; 00511 uint32_t WavePoolHeaderSize; 00512 uint32_t WavePoolCount; 00513 uint32_t* pWavePoolTable; 00514 uint32_t* pWavePoolTableHi; 00515 bool b64BitWavePoolOffsets; 00516 00517 virtual void LoadSamples(); 00518 virtual void LoadInstruments(); 00519 void __ensureMandatoryChunksExist(); 00520 friend class Region; // Region has to look in the wave pool table to get its sample 00521 private: 00522 void __UpdateWavePoolTableChunk(); 00523 void __UpdateWavePoolTable(); 00524 }; 00525 00533 class Exception : public RIFF::Exception { 00534 public: 00535 Exception(String Message); 00536 void PrintMessage(); 00537 }; 00538 00539 String libraryName(); 00540 String libraryVersion(); 00541 00542 } // namespace DLS 00543 00544 #endif // __DLS_H__