/[svn]/libsf2/trunk/src/SF.h
ViewVC logotype

Contents of /libsf2/trunk/src/SF.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2008 - (show annotations) (download) (as text)
Fri Oct 23 16:56:16 2009 UTC (14 years, 5 months ago) by iliev
File MIME type: text/x-c++hdr
File size: 15765 byte(s)
* Initial CVS Import

1 /***************************************************************************
2 * *
3 * libsf2 - C++ cross-platform SF2 format file access library *
4 * *
5 * Copyright (C) 2009 by Grigor Iliev <grigor@grigoriliev.com> *
6 * *
7 * This library is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This library is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this library; if not, write to the Free Software *
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
20 * MA 02111-1307 USA *
21 ***************************************************************************/
22
23 #ifndef __SF2_SF_H__
24 #define __SF2_SF_H__
25
26 #include "RIFF.h"
27
28 #include <vector>
29
30
31 #if WORDS_BIGENDIAN
32 #define ENDIAN_SWAP(x) \
33 ( (x>>24) | ((x<<8) & 0x00FF0000) | ((x>>8) & 0x0000FF00) | (x<<24) )
34 #else
35 #define ENDIAN_SWAP(x) (x)
36 #endif
37
38 #define RIFF_ID(x) ENDIAN_SWAP( (*((uint32_t*) x)) )
39
40
41 #define RIFF_TYPE_SF2 RIFF_ID("sfbk")
42
43 // Level 0
44 #define LIST_TYPE_INFO RIFF_ID("INFO")
45 #define LIST_TYPE_SDTA RIFF_ID("sdta")
46 #define LIST_TYPE_PDTA RIFF_ID("pdta")
47
48 // Level 1
49 //<INFO-list>
50 #define CHUNK_ID_IFIL RIFF_ID("ifil")
51 #define CHUNK_ID_ISNG RIFF_ID("isng")
52 #define CHUNK_ID_INAM RIFF_ID("INAM")
53 #define CHUNK_ID_IROM RIFF_ID("irom")
54 #define CHUNK_ID_IVER RIFF_ID("iver")
55 #define CHUNK_ID_ICRD RIFF_ID("ICRD")
56 #define CHUNK_ID_IENG RIFF_ID("IENG")
57 #define CHUNK_ID_IPRD RIFF_ID("IPRD")
58 #define CHUNK_ID_ICOP RIFF_ID("ICOP")
59 #define CHUNK_ID_ICMT RIFF_ID("ICMT")
60 #define CHUNK_ID_ISFT RIFF_ID("ISFT")
61
62 //<sdta-list>
63 #define CHUNK_ID_SMPL RIFF_ID("smpl")
64 #define CHUNK_ID_SM24 RIFF_ID("sm24")
65
66 //<pdta-list>
67 #define CHUNK_ID_PHDR RIFF_ID("phdr")
68 #define CHUNK_ID_PBAG RIFF_ID("pbag")
69 #define CHUNK_ID_PMOD RIFF_ID("pmod")
70 #define CHUNK_ID_PGEN RIFF_ID("pgen")
71 #define CHUNK_ID_INST RIFF_ID("inst")
72 #define CHUNK_ID_IBAG RIFF_ID("ibag")
73 #define CHUNK_ID_IMOD RIFF_ID("imod")
74 #define CHUNK_ID_IGEN RIFF_ID("igen")
75 #define CHUNK_ID_SHDR RIFF_ID("shdr")
76
77 #define NONE 0x1ffffff
78
79 namespace sf2 {
80 typedef struct _PresetBag {
81 uint16_t GenNdx;
82 uint16_t ModNdx;
83 } PresetBag;
84
85 typedef uint16_t SFModulator;
86 typedef uint16_t SFGenerator;
87 typedef uint16_t SFTransform;
88
89 typedef struct _ModList {
90 SFModulator ModSrcOper;
91 SFGenerator ModDestOper;
92 uint16_t ModAmount;
93 SFModulator ModAmtSrcOper;
94 SFTransform ModTransOper;
95 } ModList;
96
97 typedef struct _RangesType {
98 uint8_t byLo;
99 uint8_t byHi;
100 } RangesType;
101
102 typedef union _GenAmountType {
103 RangesType ranges;
104 short shAmount;
105 uint16_t wAmount;
106 } GenAmountType;
107
108 typedef struct _GenList {
109 SFGenerator GenOper;
110 GenAmountType GenAmount;
111 } GenList;
112
113 typedef struct _InstBag {
114 uint16_t InstGenNdx;
115 uint16_t InstModNdx;
116 } InstBag;
117
118 typedef enum {
119 START_ADDRS_OFFSET = 0,
120 END_ADDRS_OFFSET,
121 STARTLOOP_ADDRS_OFFSET,
122 ENDLOOP_ADDRS_OFFSET ,
123 START_ADDRS_COARSE_OFFSET,
124 MOD_LFO_TO_PITCH,
125 VIB_LFO_TO_PITCH,
126 MOD_ENV_TO_PITCH,
127 INITIAL_FILTER_FC,
128 INITIAL_FILTER_Q,
129 MOD_LFO_TO_FILTER_FC, // 10
130 MOD_ENV_TO_FILTER_FC,
131 END_ADDRS_COARSE_OFFSET,
132 MOD_LFO_TO_VOLUME,
133 UNUSED1,
134 CHORUS_EFFECTS_SEND,
135 REVERB_EFFECTS_SEND,
136 PAN,
137 UNUSED2,
138 UNUSED3,
139 UNUSED4, //20
140 DELAY_MOD_LFO,
141 FREQ_MOD_LFO,
142 DELAY_VIB_LFO,
143 FREQ_VIB_LFO,
144 DELAY_MOD_ENV,
145 ATTACK_MOD_ENV,
146 HOLD_MOD_ENV,
147 DECAY_MOD_ENV,
148 SUSTAIN_MOD_ENV,
149 RELEASEMODENV, // 30
150 KEYNUM_TO_MOD_ENV_HOLD,
151 KEYNUM_TO_MOD_ENV_DECAY,
152 DELAY_VOL_ENV,
153 ATTACK_VOL_ENV,
154 HOLD_VOL_ENV,
155 DECAY_VOL_ENV,
156 SUSTAIN_VOL_ENV,
157 RELEASE_VOL_ENV,
158 KEYNUM_TO_VOL_ENV_HOLD,
159 KEYNUM_TO_VOL_ENV_DECAY, //40
160 INSTRUMENT,
161 RESERVED1,
162 KEY_RANGE,
163 VEL_RANGE,
164 STARTLOOP_ADDRS_COARSE_OFFSET,
165 KEYNUM,
166 VELOCITY,
167 INITIAL_ATTENUATION,
168 RESERVED2,
169 ENDLOOP_ADDRS_COARSE_OFFSET, // 50
170 COARSE_TUNE,
171 FINE_TUNE,
172 SAMPLE_ID,
173 SAMPLE_MODES,
174 RESERVED3,
175 SCALE_TUNING,
176 EXCLUSIVE_CLASS,
177 OVERRIDING_ROOT_KEY,
178 UNUSED5,
179 END_OPER
180 } SFGeneratorType;
181
182 class Modulator {
183 public:
184
185 /**
186 * General Controller palette of controllers.
187 * Controller sources.
188 */
189 enum {
190 NO_CONTROLLER = 0,
191 NOTE_ON_VELOCITY = 2,
192 NOTE_ON_KEY_NUMBER = 3,
193 POLY_PRESSURE = 10,
194 CHANNEL_PRESSURE = 13,
195 PITCH_WHEEL = 14,
196 PITCH_WHEEL_SENSITIVITY = 16,
197 LINK = 127
198 };
199
200 /**
201 * Controller type
202 */
203 enum {
204 LINEAR = 0,
205 CONCAVE,
206 CONVEX,
207 SWITCH
208 };
209
210 int Type;
211 bool MidiPalete;
212 bool Direction;
213 bool Polarity;
214 int Index;
215
216 Modulator(SFModulator mod);
217 };
218
219 class ModulatorItem {
220 public:
221 Modulator ModSrcOper;
222 SFGenerator ModDestOper;
223 uint16_t ModAmount;
224 Modulator ModAmtSrcOper;
225 SFTransform ModTransOper;
226
227 ModulatorItem(ModList& mod);
228 };
229
230
231 typedef std::string String;
232
233 class Exception : public RIFF::Exception {
234 public: Exception(String Message) : RIFF::Exception(Message) { }
235 };
236
237 class Version {
238 public:
239 int Major;
240 int Minor;
241
242 Version(RIFF::Chunk* ck);
243 };
244
245 class Info {
246 public:
247 Version* pVer; ///< <ifil-ck> ; Refers to the version of the Sound Font RIFF file
248 String SoundEngine; ///< <isng-ck> ; Refers to the target Sound Engine
249 String BankName; ///< <INAM-ck> ; Refers to the Sound Font Bank Name
250 String RomName; ///< [<irom-ck>] ; Refers to the Sound ROM Name
251 Version* pRomVer; ///< [<iver-ck>] ; Refers to the Sound ROM Version
252 String CreationDate; ///< [<ICRD-ck>] ; Refers to the Date of Creation of the Bank
253 String Engineers; ///< [<IENG-ck>] ; Sound Designers and Engineers for the Bank
254 String Product; ///< [<IPRD-ck>] ; Product for which the Bank was intended
255 String Copyright; ///< [<ICOP-ck>] ; Contains any Copyright message
256 String Comments; ///< [<ICMT-ck>] ; Contains any Comments on the Bank
257 String Software; ///< [<ISFT-ck>] ; The SoundFont tools used to create and alter the bank
258
259 Info(RIFF::List* list);
260 ~Info();
261 private:
262 static void LoadString(uint32_t ChunkID, RIFF::List* lstINFO, String& s);
263 };
264
265 class Sample {
266 public:
267
268 typedef enum {
269 MONO_SAMPLE = 1,
270 RIGHT_SAMPLE = 2,
271 LEFT_SAMPLE = 4,
272 LINKED_SAMPLE = 8,
273 ROM_MONO_SAMPLE = 0x8001,
274 ROM_RIGHT_SAMPLE = 0x8002,
275 ROM_LEFT_SAMPLE = 0x8004,
276 ROM_LINKED_SAMPLE = 0x8008
277 } Link;
278
279 /** Reflects the current playback state for a sample. */
280 class PlaybackState {
281 public:
282 unsigned long position; ///< Current position within the sample.
283 bool reverse; ///< If playback direction is currently backwards (in case there is a pingpong or reverse loop defined).
284 unsigned long loop_cycles_left; ///< How many times the loop has still to be passed, this value will be decremented with each loop cycle.
285 };
286
287 /** Pointer address and size of a buffer. */
288 struct buffer_t {
289 void* pStart; ///< Points to the beginning of the buffer.
290 unsigned long Size; ///< Size of the actual data in the buffer in bytes.
291 unsigned long NullExtensionSize; ///< The buffer might be bigger than the actual data, if that's the case that unused space at the end of the buffer is filled with NULLs and NullExtensionSize reflects that unused buffer space in bytes. Those NULL extensions are mandatory for differential algorithms that have to take the following data words into account, thus have to access past the buffer's boundary. If you don't know what I'm talking about, just forget this variable. :)
292 buffer_t() {
293 pStart = NULL;
294 Size = 0;
295 NullExtensionSize = 0;
296 }
297 };
298
299 String Name;
300
301 Sample(RIFF::Chunk* ck, RIFF::Chunk* pCkSmpl, RIFF::Chunk* pCkSm24);
302
303 String GetName() { return Name; }
304 int GetChannelCount();
305 long GetTotalFrameCount();
306 int GetFrameSize();
307
308 buffer_t LoadSampleData();
309 buffer_t LoadSampleData(unsigned long SampleCount);
310 buffer_t LoadSampleDataWithNullSamplesExtension(uint NullSamplesCount);
311 buffer_t LoadSampleDataWithNullSamplesExtension(unsigned long SampleCount, uint NullSamplesCount);
312 buffer_t GetCache();
313 void ReleaseSampleData();
314 unsigned long SetPos(unsigned long SampleCount);
315 unsigned long GetPos();
316 unsigned long Read(void* pBuffer, unsigned long SampleCount);
317
318 unsigned long ReadAndLoop (
319 void* pBuffer,
320 unsigned long FrameCount,
321 PlaybackState* pPlaybackState
322 );
323
324 //protected:
325 buffer_t RAMCache; ///< Buffers samples (already uncompressed) in RAM.
326 RIFF::Chunk* pCkSmpl;
327 RIFF::Chunk* pCkSm24;
328
329 //private:
330 int ChannelCount; // 2 for left and right samples
331
332 uint32_t Start; // in sample data points (frames)
333 uint32_t End; // in sample data points (frames)
334 uint32_t StartLoop; // in sample data points (frames)
335 uint32_t EndLoop; // in sample data points (frames)
336 uint32_t SampleRate;
337 uint8_t OriginalPitch;
338 uint8_t PitchCorrection;
339 uint16_t SampleLink; /* If sfSampleType indicates a left or right sample, the
340 * sample header index of the associated right or left stereo
341 * sample respectively; zero otherwise. */
342 uint16_t SampleType;
343 };
344
345 class File;
346 class Instrument;
347
348 /**
349 * Instrument zone
350 */
351 class Region {
352 public:
353 int loKey, hiKey;
354 int minVel, maxVel;
355 int pan; // -64 - +63
356 int fineTune; // -99 - +99
357 int startAddrsOffset, startAddrsCoarseOffset, endAddrsOffset;
358 int startloopAddrsOffset, endloopAddrsOffset;
359
360 double EG1PreAttack;
361 double EG1Attack;
362 double EG1Hold;
363 double EG1Decay;
364 double EG1Sustain;
365 double EG1Release;
366
367 Sample* pSample;
368 Instrument* pInstrument; // used when the region belongs to preset
369
370 Region();
371 Sample* GetSample() { return pSample; }
372 Region* GetParent() { return this; }
373
374 std::vector<ModulatorItem> modulators;
375
376 friend class Instrument;
377 friend class Preset;
378
379 private:
380 void SetGenerator(sf2::File* pFile, GenList& Gen);
381 void SetModulator(sf2::File* pFile, ModList& Mod);
382 };
383
384 class InstrumentBase {
385 public:
386 String Name;
387 Region* pGlobalRegion;
388
389 InstrumentBase(sf2::File* pFile);
390 virtual ~InstrumentBase();
391
392 sf2::File* GetFile() { return pFile; }
393 String GetName() { return Name; }
394
395 int GetRegionCount();
396 Region* GetRegion(int idx);
397
398 std::vector<Region*> GetRegionsOnKey(int key, uint8_t vel);
399
400 protected:
401 std::vector<Region*> regions;
402 sf2::File* pFile;
403 };
404
405 class Instrument : public InstrumentBase {
406 public:
407 Instrument(sf2::File* pFile, RIFF::Chunk* ck);
408 ~Instrument();
409 //private:
410 uint16_t InstBagNdx;
411
412 /**
413 * Load all regions (zones, bags) in the range idx1 - idx2
414 */
415 void LoadRegions(int idx1, int idx2);
416 };
417
418 class Preset : public InstrumentBase {
419 public:
420 uint16_t PresetNum;
421 uint16_t Bank;
422 uint32_t Library;
423 uint32_t Genre;
424 uint32_t Morphology;
425
426 Preset(sf2::File* pFile, RIFF::Chunk* ck);
427 ~Preset();
428
429 //private:
430 sf2::File* pFile;
431 uint16_t PresetBagNdx;
432
433 /**
434 * Load all regions (zones, bags) in the range idx1 - idx2
435 */
436 void LoadRegions(int idx1, int idx2);
437 };
438
439 class File {
440 public:
441 Info* pInfo;
442
443 File(RIFF::File* pRIFF);
444 ~File();
445
446 int GetPresetCount();
447 Preset* GetPreset(int idx);
448 int GetInstrumentCount();
449 Instrument* GetInstrument(int idx);
450 int GetSampleCount();
451 Sample* GetSample(int idx);
452 void DeleteSample(Sample* pSample);
453 bool HasSamples();
454
455 friend class Region;
456 friend class Instrument;
457 friend class Preset;
458
459 protected:
460 RIFF::File* pRIFF;
461 std::vector<PresetBag> PresetBags;
462 std::vector<ModList> PresetModLists;
463 std::vector<GenList> PresetGenLists;
464 std::vector<InstBag> InstBags;
465 std::vector<ModList> InstModLists;
466 std::vector<GenList> InstGenLists;
467
468 private:
469 std::vector<Preset*> Presets;
470 std::vector<Instrument*> Instruments;
471 std::vector<Sample*> Samples;
472 };
473
474 String libraryName();
475 String libraryVersion();
476
477 } // namespace sf2
478 #endif // __SF2_SF_H__

  ViewVC Help
Powered by ViewVC