/[svn]/libgig/trunk/src/DLS.h
ViewVC logotype

Contents of /libgig/trunk/src/DLS.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3478 - (show annotations) (download) (as text)
Thu Feb 21 20:10:08 2019 UTC (5 years, 1 month ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 31176 byte(s)
* Fix: Don't automatically delete RIFF chunks from DLS/gig classes'
  destructors. Added new virtual method DeleteChunks() to those classes
  for this which must be explicitly called instead to remove their RIFF
  chunks.
* Fix: Many methods of DLS/gig classes assumed a RIFF chunk read position
  of zero; which is unsafe per se.
* Added C++11 "override" keyword where appropriate.
* DLS.cpp, DLS.h: Added new abstract interface base class DLS::Storage
  which is derived by the respective classes for implementing (the old)
  UpdateChunks() and the new DeleteChunks() method.
* RIFF.cpp, RIFF.h: Added new method progress_t::subdivide().
* Bumped version (4.1.0.svn13).

1 /***************************************************************************
2 * *
3 * libgig - C++ cross-platform Gigasampler format file access library *
4 * *
5 * Copyright (C) 2003-2019 by Christian Schoenebeck *
6 * <cuse@users.sourceforge.net> *
7 * *
8 * This library is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This library is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this library; if not, write to the Free Software *
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21 * MA 02111-1307 USA *
22 ***************************************************************************/
23
24 #ifndef __DLS_H__
25 #define __DLS_H__
26
27 #include "RIFF.h"
28
29 #if WORDS_BIGENDIAN
30 # define RIFF_TYPE_DLS 0x444C5320
31 # define LIST_TYPE_WVPL 0x7776706C
32 # define LIST_TYPE_DWPL 0x6477706C ///< Seen on some files instead of a wvpl list chunk.
33 # define LIST_TYPE_WAVE 0x77617665
34 # define LIST_TYPE_LINS 0X6C696E73
35 # define LIST_TYPE_INS 0X696E7320
36 # define LIST_TYPE_LRGN 0x6C72676E
37 # define LIST_TYPE_LART 0x6C617274
38 # define LIST_TYPE_LAR2 0x6C617232
39 # define LIST_TYPE_RGN 0x72676E20
40 # define LIST_TYPE_RGN2 0x72676E32
41 # define CHUNK_ID_IARL 0x4941524C
42 # define CHUNK_ID_IART 0x49415254
43 # define CHUNK_ID_ICMS 0x49434D53
44 # define CHUNK_ID_IGNR 0x49474E52
45 # define CHUNK_ID_IKEY 0x494B4559
46 # define CHUNK_ID_IMED 0x494D4544
47 # define CHUNK_ID_ISBJ 0x4953424A
48 # define CHUNK_ID_ISRC 0x49535243
49 # define CHUNK_ID_ISRF 0x49535246
50 # define CHUNK_ID_ITCH 0x49544348
51 # define CHUNK_ID_VERS 0x76657273
52 # define CHUNK_ID_DLID 0x646C6964
53 # define CHUNK_ID_FMT 0x666D7420
54 # define CHUNK_ID_DATA 0x64617461
55 # define CHUNK_ID_INSH 0x696E7368
56 # define CHUNK_ID_RGNH 0x72676E68
57 # define CHUNK_ID_WLNK 0x776C6E6B
58 # define CHUNK_ID_PTBL 0x7074626C
59 # define CHUNK_ID_WSMP 0x77736D70
60 # define CHUNK_ID_COLH 0x636F6C68
61 # define CHUNK_ID_ARTL 0x6172746C
62 # define CHUNK_ID_ART2 0x61727432
63 # define CHUNK_ID_XFIL 0x7866696C
64 # define CHUNK_ID_DOXF 0x646F7866
65 #else // little endian
66 # define RIFF_TYPE_DLS 0x20534C44
67 # define LIST_TYPE_WVPL 0x6C707677
68 # define LIST_TYPE_DWPL 0x6C707764 ///< Seen on some files instead of a wvpl list chunk.
69 # define LIST_TYPE_WAVE 0x65766177
70 # define LIST_TYPE_LINS 0X736E696C
71 # define LIST_TYPE_INS 0X20736E69
72 # define LIST_TYPE_LRGN 0x6E67726C
73 # define LIST_TYPE_LART 0x7472616C
74 # define LIST_TYPE_LAR2 0x3272616C
75 # define LIST_TYPE_RGN 0x206E6772
76 # define LIST_TYPE_RGN2 0x326E6772
77 # define CHUNK_ID_IARL 0x4C524149
78 # define CHUNK_ID_IART 0x54524149
79 # define CHUNK_ID_ICMS 0x534D4349
80 # define CHUNK_ID_IGNR 0x524E4749
81 # define CHUNK_ID_IKEY 0x59454B49
82 # define CHUNK_ID_IMED 0x44454D49
83 # define CHUNK_ID_ISBJ 0x4A425349
84 # define CHUNK_ID_ISRC 0x43525349
85 # define CHUNK_ID_ISRF 0x46525349
86 # define CHUNK_ID_ITCH 0x48435449
87 # define CHUNK_ID_VERS 0x73726576
88 # define CHUNK_ID_DLID 0x64696C64
89 # define CHUNK_ID_FMT 0x20746D66
90 # define CHUNK_ID_DATA 0x61746164
91 # define CHUNK_ID_INSH 0x68736E69
92 # define CHUNK_ID_RGNH 0x686E6772
93 # define CHUNK_ID_WLNK 0x6B6E6C77
94 # define CHUNK_ID_PTBL 0x6C627470
95 # define CHUNK_ID_WSMP 0x706D7377
96 # define CHUNK_ID_COLH 0x686C6F63
97 # define CHUNK_ID_ARTL 0x6C747261
98 # define CHUNK_ID_ART2 0x32747261
99 # define CHUNK_ID_XFIL 0x6C696678
100 # define CHUNK_ID_DOXF 0x66786F64
101 #endif // WORDS_BIGENDIAN
102
103 #define DLS_WAVE_FORMAT_PCM 0x0001
104
105 //TODO: no support for conditional chunks <cdl> yet
106
107 /** DLS specific classes and definitions */
108 namespace DLS {
109
110 typedef std::string String;
111 typedef RIFF::progress_t progress_t;
112 typedef RIFF::file_offset_t file_offset_t;
113
114 /** Quadtuple version number ("major.minor.release.build"). */
115 struct version_t {
116 uint16_t minor;
117 uint16_t major;
118 uint16_t build;
119 uint16_t release;
120 };
121
122 /** Every subject of an DLS file and the file itself can have an unique, computer generated ID. */
123 struct dlsid_t {
124 uint32_t ulData1;
125 uint16_t usData2;
126 uint16_t usData3;
127 uint8_t abData[8];
128 };
129
130 /** Connection Sources */
131 enum conn_src_t {
132 // Modulator Sources
133 conn_src_none = 0x0000,
134 conn_src_lfo = 0x0001,
135 conn_src_keyonvelocity = 0x0002,
136 conn_src_keynumber = 0x0003,
137 conn_src_eg1 = 0x0004,
138 conn_src_eg2 = 0x0005,
139 conn_src_pitchwheel = 0x0006,
140 conn_src_polypressure = 0x0007,
141 conn_src_channelpressure = 0x0008,
142 conn_src_vibrato = 0x0009,
143 // MIDI Controller Sources
144 conn_src_cc1 = 0x0081,
145 conn_src_cc7 = 0x0087,
146 conn_src_cc10 = 0x008A,
147 conn_src_cc11 = 0x008B,
148 conn_src_cc91 = 0x00DB,
149 conn_src_cc93 = 0x00DD,
150 // Registered Parameter Numbers
151 conn_src_rpn0 = 0x0100,
152 conn_src_rpn1 = 0x0101,
153 conn_src_rpn2 = 0x0102
154 };
155
156 /** Connection Destinations */
157 enum conn_dst_t {
158 // Generic Destinations
159 conn_dst_none = 0x0000,
160 conn_dst_gain = 0x0001,
161 conn_dst_reserved = 0x0002,
162 conn_dst_pitch = 0x0003,
163 conn_dst_pan = 0x0004,
164 conn_dst_keynumber = 0x0005,
165 // Channel Output Destinations
166 conn_dst_left = 0x0010,
167 conn_dst_right = 0x0011,
168 conn_dst_center = 0x0012,
169 conn_dst_lfe_channel = 0x0013,
170 conn_dst_leftrear = 0x0014,
171 conn_dst_rightrear = 0x0015,
172 conn_dst_chorus = 0x0080,
173 conn_dst_reverb = 0x0081,
174 // Modulator LFO Destinations
175 conn_dst_lfo_frequency = 0x0104,
176 conn_dst_lfo_startdelay = 0x0105,
177 // Vibrato LFO Destinations
178 conn_dst_vib_frequency = 0x0114,
179 conn_dst_vib_startdelay = 0x0115,
180 // EG Destinations
181 conn_dst_eg1_attacktime = 0x0206,
182 conn_dst_eg1_decaytime = 0x0207,
183 conn_dst_eg1_reserved = 0x0208,
184 conn_dst_eg1_releasetime = 0x0209,
185 conn_dst_eg1_sustainlevel = 0x020A,
186 conn_dst_eg1_delaytime = 0x020B,
187 conn_dst_eg1_holdtime = 0x020C,
188 conn_dst_eg1_shutdowntime = 0x020D,
189 conn_dst_eg2_attacktime = 0x030A,
190 conn_dst_eg2_decaytime = 0x030B,
191 conn_dst_eg2_reserved = 0x030C,
192 conn_dst_eg2_releasetime = 0x030D,
193 conn_dst_eg2_sustainlevel = 0x030E,
194 conn_dst_eg2_delaytime = 0x030F,
195 conn_dst_eg2_holdtime = 0x0310,
196 // Filter Destinations
197 conn_dst_filter_cutoff = 0x0500,
198 conn_dst_filter_q = 0x0501
199 };
200
201 /** Connection Transforms */
202 enum conn_trn_t {
203 conn_trn_none = 0x0000,
204 conn_trn_concave = 0x0001,
205 conn_trn_convex = 0x0002,
206 conn_trn_switch = 0x0003
207 };
208
209 /** Lower and upper limit of a range. */
210 struct range_t {
211 uint16_t low; ///< Low value of range.
212 uint16_t high; ///< High value of range.
213
214 inline bool operator< (const range_t& other) const {
215 if (low < other.low) return true;
216 if (low > other.low) return false;
217 return high < other.high;
218 }
219
220 inline bool operator== (const range_t& other) const {
221 return low == other.low && high == other.high;
222 }
223
224 inline bool overlaps(uint16_t scalar) const {
225 return low <= scalar && scalar <= high;
226 }
227
228 inline bool overlaps(const range_t& other) const {
229 return overlaps(other.low) || overlaps(other.high) ||
230 other.overlaps(low) || other.overlaps(high);
231 }
232 };
233
234 /** Defines Sample Loop Points. */
235 struct sample_loop_t {
236 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!
237 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).
238 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.
239 uint32_t LoopLength; ///< Length of the looping area (in sample points).
240 };
241
242 // just symbol prototyping
243 class File;
244 class Instrument;
245 class Region;
246 class Sample;
247
248 /** Defines a connection within the synthesis model. */
249 class Connection {
250 public:
251 conn_src_t Source;
252 conn_trn_t SourceTransform;
253 bool SourceInvert;
254 bool SourceBipolar;
255 conn_src_t Control;
256 conn_trn_t ControlTransform;
257 bool ControlInvert;
258 bool ControlBipolar;
259 conn_dst_t Destination;
260 conn_trn_t DestinationTransform;
261 uint32_t Scale;
262 protected:
263 struct conn_block_t {
264 uint16_t source;
265 uint16_t control;
266 uint16_t destination;
267 uint16_t transform;
268 uint32_t scale;
269 };
270 Connection() {}
271 void Init(conn_block_t* Header);
272 conn_block_t ToConnBlock();
273 virtual ~Connection() {}
274 friend class Articulation;
275 };
276
277 /** @brief Abstract base class for all classes using RIFF::Chunks for persistency.
278 *
279 * This abstract base class defines the general interface for all classes
280 * which are using RIFF::Chunks to actually load and store their data
281 * persistently from/to disk.
282 */
283 class Storage {
284 public:
285 /** @brief Apply object's changes to the respective RIF::Chunks.
286 *
287 * This abstract interface method is intended to be implemented by the
288 * deriving classes by updating the respective RIFF chunks associated
289 * with the object such that those RIFF chunks reflect the object's
290 * current data (i.e. object's current member variables). So the purpose
291 * of this method is to prepare for saving the object's current state
292 * persistently to the actual RIFF file.
293 *
294 * After returning from this method the changes are just scheduled to be
295 * saved to the RIFF file, it is required to call File::Save()
296 * subsequently to make the changes actually persistent on file level.
297 *
298 * Usually there is no need to call this method directly from an
299 * application. This method is called automatically by libgig if one of
300 * the respective API methods is called to save the file persistently
301 * to disk (i.e. DLS::File::Save() or gig::File::Save()).
302 *
303 * @param pProgress - callback function for progress notification
304 */
305 virtual void UpdateChunks(progress_t* pProgress) = 0;
306
307 /** @brief Remove all RIFF chunks associated with this object.
308 *
309 * This abstract interface method is intended to be implemented by the
310 * deriving classes by removing every RIFF::Chunk the deriving overall
311 * object is using to store the object in the final RIFF::File. In other
312 * words: the intention is to remove the deriving class(es)'s object
313 * persistently from the currently open file.
314 *
315 * Note that the RIFF::Chunks deletions is just scheduled after
316 * returning from this method. You have to call File::Save() to make
317 * these changes persistent on file level.
318 *
319 * Usually there is no need to call this method directly from an
320 * application. This method is called automatically by libgig if one of
321 * the respective API methods is called to remove the respective object
322 * persistently (i.e. File::DeleteInstrument() or File::DeleteSample()).
323 */
324 virtual void DeleteChunks() = 0;
325 };
326
327 /** Provides access to the defined connections used for the synthesis model. */
328 class Articulation : public Storage {
329 public:
330 Connection* pConnections; ///< Points to the beginning of a <i>Connection</i> array.
331 uint32_t Connections; ///< Reflects the number of Connections.
332
333 Articulation(RIFF::Chunk* artl);
334 virtual ~Articulation();
335 virtual void UpdateChunks(progress_t* pProgress) OVERRIDE;
336 virtual void DeleteChunks() OVERRIDE;
337 protected:
338 RIFF::Chunk* pArticulationCk;
339 uint32_t HeaderSize;
340 };
341
342 /** Abstract base class for classes that provide articulation information (thus for <i>Instrument</i> and <i>Region</i> class). */
343 class Articulator : public Storage {
344 public:
345 Articulator(RIFF::List* ParentList);
346 Articulation* GetFirstArticulation();
347 Articulation* GetNextArticulation();
348 virtual void UpdateChunks(progress_t* pProgress) OVERRIDE;
349 virtual void DeleteChunks() OVERRIDE;
350 virtual void CopyAssign(const Articulator* orig);
351 protected:
352 typedef std::list<Articulation*> ArticulationList;
353 RIFF::List* pParentList;
354 ArticulationList* pArticulations;
355 ArticulationList::iterator ArticulationsIterator;
356
357 void LoadArticulations();
358 virtual ~Articulator();
359 };
360
361 /** Optional information for DLS files, instruments, samples, etc. */
362 class Info : public Storage {
363 public:
364 String Name; ///< <INAM-ck>. Stores the title of the subject of the file, such as, Seattle From Above.
365 String ArchivalLocation; ///< <IARL-ck>. Indicates where the subject of the file is stored.
366 String CreationDate; ///< <ICRD-ck>. Specifies the date the subject of the file was created. List dates in yyyy-mm-dd format.
367 String Comments; ///< <ICMT-ck>. Provides general comments about the file or the subject of the file. Sentences might end with semicolon.
368 String Product; ///< <IPRD-ck>. Specifies the name of the title the file was originally intended for, such as World Ruler V.
369 String Copyright; ///< <ICOP-ck>. Records the copyright information for the file.
370 String Artists; ///< <IART-ck>. Lists the artist of the original subject of the file.
371 String Genre; ///< <IGNR-ck>. Descirbes the original work, such as, Jazz, Classic, Rock, Techno, Rave, etc.
372 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.
373 String Engineer; ///< <IENG-ck>. 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.
374 String Technician; ///< <ITCH-ck>. Identifies the technician who sampled the subject file.
375 String Software; ///< <ISFT-ck>. Identifies the name of the sofware package used to create the file.
376 String Medium; ///< <IMED-ck>. Describes the original subject of the file, such as, record, CD, and so forth.
377 String Source; ///< <ISRC-ck>. Identifies the name of the person or organization who supplied the original subject of the file.
378 String SourceForm; ///< <ISRF-ck>. 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 <i>Medium</i>.
379 String Commissioned; ///< <ICMS-ck>. Lists the name of the person or organization that commissioned the subject of the file, e.g., Pope Julian II.
380 String Subject; ///< <ISBJ-ck>. Describes the contents of the file.
381 bool UseFixedLengthStrings; ///< @deprecated Not used anymore, use SetFixedStringLengths() instead.
382
383 struct string_length_t {
384 uint32_t chunkId;
385 int length;
386 };
387
388 Info(RIFF::List* list);
389 void SetFixedStringLengths(const string_length_t* lengths);
390 virtual ~Info();
391 virtual void UpdateChunks(progress_t* pProgress) OVERRIDE;
392 virtual void DeleteChunks() OVERRIDE;
393 virtual void CopyAssign(const Info* orig);
394 private:
395 RIFF::List* pResourceListChunk;
396 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.
397
398 static void LoadString(uint32_t ChunkID, RIFF::List* lstINFO, String& s);
399 void SaveString(uint32_t ChunkID, RIFF::List* lstINFO, const String& s, const String& sDefault);
400 };
401
402 /** Abstract base class which encapsulates data structures which all DLS resources are able to provide. */
403 class Resource : public Storage {
404 public:
405 Info* pInfo; ///< Points (in any case) to an <i>Info</i> object, providing additional, optional infos and comments.
406 dlsid_t* pDLSID; ///< Points to a <i>dlsid_t</i> structure if the file provided a DLS ID else is <i>NULL</i>.
407
408 Resource* GetParent() { return pParent; }
409 const Resource* GetParent() const { return pParent; }
410 virtual void UpdateChunks(progress_t* pProgress) OVERRIDE;
411 virtual void DeleteChunks() OVERRIDE;
412 void GenerateDLSID();
413 static void GenerateDLSID(dlsid_t* pDLSID);
414 virtual void CopyAssign(const Resource* orig);
415 protected:
416 Resource* pParent;
417 RIFF::List* pResourceList;
418
419 Resource(Resource* Parent, RIFF::List* lstResource);
420 virtual ~Resource();
421 };
422
423 /** Abstract base class which provides mandatory informations about sample players in general. */
424 class Sampler : public Storage {
425 public:
426 uint8_t UnityNote;
427 int16_t FineTune;
428 int32_t Gain; ///< @deprecated Don't alter directly, use SetGain() instead!
429 bool NoSampleDepthTruncation;
430 bool NoSampleCompression;
431 uint32_t SampleLoops; ///< Reflects the number of sample loops.
432 sample_loop_t* pSampleLoops; ///< Points to the beginning of a sample loop array, or is NULL if there are no loops defined.
433
434 void AddSampleLoop(sample_loop_t* pLoopDef);
435 void DeleteSampleLoop(sample_loop_t* pLoopDef);
436 virtual void SetGain(int32_t gain);
437 virtual void UpdateChunks(progress_t* pProgress) OVERRIDE;
438 virtual void DeleteChunks() OVERRIDE;
439 virtual void CopyAssign(const Sampler* orig);
440 protected:
441 RIFF::List* pParentList;
442 uint32_t uiHeaderSize;
443 uint32_t SamplerOptions;
444 Sampler(RIFF::List* ParentList);
445 virtual ~Sampler();
446 };
447
448 /** @brief Encapsulates sample waves used for playback.
449 *
450 * In case you created a new sample with File::AddSample(), you should
451 * first update all attributes with the desired meta informations
452 * (amount of channels, bit depth, sample rate, etc.), then call
453 * Resize() with the desired sample size. The latter will create
454 * the mandatory RIFF chunk which will hold the sample wave data.
455 */
456 class Sample : public Resource {
457 public:
458 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()).
459 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).
460 uint32_t SamplesPerSecond; ///< Sampling rate at which each channel should be played (defaults to 44100 if Sample was created with Instrument::AddSample() previously).
461 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).
462 uint16_t BlockAlign; ///< The block alignment (in bytes) of the waveform data. Playback software needs to process a multiple of <i>BlockAlign</i> bytes of data at a time, so the value of <i>BlockAlign</i> can be used for buffer alignment.
463 uint16_t BitDepth; ///< Size of each sample per channel (only if known sample data format is used, 0 otherwise).
464 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.
465 uint FrameSize; ///< Reflects the size (in bytes) of one single sample point (only if known sample data format is used, 0 otherwise). <b>Caution:</b> 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().
466
467 void* LoadSampleData();
468 void ReleaseSampleData();
469 file_offset_t GetSize() const;
470 void Resize(file_offset_t NewSize);
471 file_offset_t SetPos(file_offset_t SampleCount, RIFF::stream_whence_t Whence = RIFF::stream_start);
472 file_offset_t Read(void* pBuffer, file_offset_t SampleCount);
473 file_offset_t Write(void* pBuffer, file_offset_t SampleCount);
474 virtual void UpdateChunks(progress_t* pProgress) OVERRIDE;
475 virtual void DeleteChunks() OVERRIDE;
476 virtual void CopyAssign(const Sample* orig);
477
478 protected:
479 RIFF::List* pWaveList;
480 RIFF::Chunk* pCkData;
481 RIFF::Chunk* pCkFormat;
482 file_offset_t ullWavePoolOffset; // needed for comparison with the wave pool link table, thus the link to instruments
483
484 Sample(File* pFile, RIFF::List* waveList, file_offset_t WavePoolOffset);
485 virtual ~Sample();
486 void CopyAssignCore(const Sample* orig);
487 friend class File;
488 friend class Region; // Region has to compare the wave pool offset to get its sample
489 };
490
491 /** Defines <i>Region</i> information of an <i>Instrument</i>. */
492 class Region : public Resource, public Articulator, public Sampler {
493 public:
494 range_t KeyRange; ///< @deprecated Only read, don't write! Use SetKeyRange() instead.
495 range_t VelocityRange;
496 uint16_t KeyGroup;
497 uint16_t Layer;
498 bool SelfNonExclusive;
499 bool PhaseMaster;
500 uint16_t PhaseGroup;
501 bool MultiChannel;
502 uint32_t Channel;
503
504 Sample* GetSample();
505 void SetSample(Sample* pSample);
506 virtual void SetKeyRange(uint16_t Low, uint16_t High);
507 virtual void UpdateChunks(progress_t* pProgress) OVERRIDE;
508 virtual void DeleteChunks() OVERRIDE;
509 virtual void CopyAssign(const Region* orig);
510 protected:
511 RIFF::List* pCkRegion;
512 uint32_t WavePoolTableIndex; // index in the wave pool table to the sample wave this region is linked to
513 Sample* pSample; // every region refers to exactly one sample
514 uint16_t FormatOptionFlags;
515 uint16_t WaveLinkOptionFlags;
516
517 Region(Instrument* pInstrument, RIFF::List* rgnList);
518 virtual ~Region();
519 friend class Instrument;
520 };
521
522 /** Provides all neccessary information for the synthesis of a DLS <i>Instrument</i>. */
523 class Instrument : public Resource, public Articulator {
524 public:
525 bool IsDrum; ///< Indicates if the <i>Instrument</i> is a drum type, as they differ in the synthesis model of DLS from melodic instruments.
526 uint16_t MIDIBank; ///< Reflects combination of <i>MIDIBankCoarse</i> and <i>MIDIBankFine</i> (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).
527 uint8_t MIDIBankCoarse; ///< Reflects the MIDI Bank number for MIDI Control Change 0 (bank 1 - 128).
528 uint8_t MIDIBankFine; ///< Reflects the MIDI Bank number for MIDI Control Change 32 (bank 1 - 128).
529 uint32_t MIDIProgram; ///< Specifies the MIDI Program Change Number this Instrument should be assigned to.
530 uint32_t Regions; ///< Reflects the number of <i>Region</i> defintions this Instrument has.
531
532 Region* GetFirstRegion();
533 Region* GetNextRegion();
534 Region* AddRegion();
535 void DeleteRegion(Region* pRegion);
536 virtual void UpdateChunks(progress_t* pProgress) OVERRIDE;
537 virtual void DeleteChunks() OVERRIDE;
538 virtual void CopyAssign(const Instrument* orig);
539 protected:
540 typedef std::list<Region*> RegionList;
541 struct midi_locale_t {
542 uint32_t bank;
543 uint32_t instrument;
544 };
545
546 RIFF::List* pCkInstrument;
547 RegionList* pRegions;
548 RegionList::iterator RegionsIterator;
549
550 Instrument(File* pFile, RIFF::List* insList);
551 void CopyAssignCore(const Instrument* orig);
552 virtual void LoadRegions();
553 virtual ~Instrument();
554 friend class File;
555 friend class Region;
556 private:
557 void MoveRegion(Region* pSrc, Region* pDst);
558 };
559
560 /** Parses DLS Level 1 and 2 compliant files and provides abstract access to the data. */
561 class File : public Resource {
562 public:
563 version_t* pVersion; ///< Points to a <i>version_t</i> structure if the file provided a version number else is set to <i>NULL</i>.
564 uint32_t Instruments; ///< Reflects the number of available <i>Instrument</i> objects.
565
566 File();
567 File(RIFF::File* pRIFF);
568 String GetFileName();
569 void SetFileName(const String& name);
570 Sample* GetFirstSample(); ///< Returns a pointer to the first <i>Sample</i> object of the file, <i>NULL</i> otherwise.
571 Sample* GetNextSample(); ///< Returns a pointer to the next <i>Sample</i> object of the file, <i>NULL</i> otherwise.
572 Sample* AddSample();
573 void DeleteSample(Sample* pSample);
574 Instrument* GetFirstInstrument(); ///< Returns a pointer to the first <i>Instrument</i> object of the file, <i>NULL</i> otherwise.
575 Instrument* GetNextInstrument(); ///< Returns a pointer to the next <i>Instrument</i> object of the file, <i>NULL</i> otherwise.
576 Instrument* AddInstrument();
577 void DeleteInstrument(Instrument* pInstrument);
578 RIFF::File* GetExtensionFile(int index);
579 virtual void UpdateChunks(progress_t* pProgress) OVERRIDE;
580 virtual void Save(const String& Path, progress_t* pProgress = NULL);
581 virtual void Save(progress_t* pProgress = NULL);
582 virtual ~File();
583 protected:
584 typedef std::list<Sample*> SampleList;
585 typedef std::list<Instrument*> InstrumentList;
586
587 RIFF::File* pRIFF;
588 std::list<RIFF::File*> ExtensionFiles; //FIXME: These should automatically be freed, since implicitly allocated.
589 SampleList* pSamples;
590 SampleList::iterator SamplesIterator;
591 InstrumentList* pInstruments;
592 InstrumentList::iterator InstrumentsIterator;
593 uint32_t WavePoolHeaderSize;
594 uint32_t WavePoolCount;
595 uint32_t* pWavePoolTable;
596 uint32_t* pWavePoolTableHi;
597 bool b64BitWavePoolOffsets;
598 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.
599
600 virtual void LoadSamples();
601 virtual void LoadInstruments();
602 virtual void UpdateFileOffsets();
603 void __ensureMandatoryChunksExist();
604 friend class Region; // Region has to look in the wave pool table to get its sample
605 private:
606 void __UpdateWavePoolTableChunk();
607 void __UpdateWavePoolTable();
608 };
609
610 /**
611 * Will be thrown whenever a DLS specific error occurs while trying to
612 * access a DLS File. Note: In your application you should better catch
613 * for RIFF::Exception rather than this one, except you explicitly want
614 * to catch and handle DLS::Exception and RIFF::Exception independently,
615 * which usually shouldn't be necessary though.
616 */
617 class Exception : public RIFF::Exception {
618 public:
619 Exception(String format, ...);
620 Exception(String format, va_list arg);
621 void PrintMessage();
622 protected:
623 Exception();
624 };
625
626 String libraryName();
627 String libraryVersion();
628
629 } // namespace DLS
630
631 #endif // __DLS_H__

  ViewVC Help
Powered by ViewVC