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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2020 - (show annotations) (download) (as text)
Fri Oct 30 16:25:27 2009 UTC (14 years, 3 months ago) by iliev
File MIME type: text/x-c++hdr
File size: 17042 byte(s)
* sf2: 24bit support
* sf2: loop support
* sf2: implemented overridingRootKey
* sf2: implemented instrument global region
* sf2: bugfix: some regions were ignored

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 Region;
266
267 class Sample {
268 public:
269
270 typedef enum {
271 MONO_SAMPLE = 1,
272 RIGHT_SAMPLE = 2,
273 LEFT_SAMPLE = 4,
274 LINKED_SAMPLE = 8,
275 ROM_MONO_SAMPLE = 0x8001,
276 ROM_RIGHT_SAMPLE = 0x8002,
277 ROM_LEFT_SAMPLE = 0x8004,
278 ROM_LINKED_SAMPLE = 0x8008
279 } Link;
280
281 /** Reflects the current playback state for a sample. */
282 class PlaybackState {
283 public:
284 unsigned long position; ///< Current position within the sample.
285 bool reverse; ///< If playback direction is currently backwards (in case there is a pingpong or reverse loop defined).
286 unsigned long loop_cycles_left; ///< How many times the loop has still to be passed, this value will be decremented with each loop cycle.
287 };
288
289 /** Pointer address and size of a buffer. */
290 struct buffer_t {
291 void* pStart; ///< Points to the beginning of the buffer.
292 unsigned long Size; ///< Size of the actual data in the buffer in bytes.
293 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. :)
294 buffer_t() {
295 pStart = NULL;
296 Size = 0;
297 NullExtensionSize = 0;
298 }
299 };
300
301 String Name;
302
303 Sample(RIFF::Chunk* ck, RIFF::Chunk* pCkSmpl, RIFF::Chunk* pCkSm24);
304
305 String GetName() { return Name; }
306 int GetChannelCount();
307 long GetTotalFrameCount();
308 int GetFrameSize();
309 bool HasLoops();
310 bool IsUnpitched() { return OriginalPitch == 255; }
311
312 buffer_t LoadSampleData();
313 buffer_t LoadSampleData(unsigned long SampleCount);
314 buffer_t LoadSampleDataWithNullSamplesExtension(uint NullSamplesCount);
315 buffer_t LoadSampleDataWithNullSamplesExtension(unsigned long SampleCount, uint NullSamplesCount);
316 buffer_t GetCache();
317 void ReleaseSampleData();
318 unsigned long SetPos(unsigned long SampleCount);
319 unsigned long GetPos();
320 unsigned long Read(void* pBuffer, unsigned long SampleCount);
321
322 unsigned long ReadAndLoop (
323 void* pBuffer,
324 unsigned long FrameCount,
325 PlaybackState* pPlaybackState,
326 Region* pRegion
327 );
328
329 //protected:
330 buffer_t RAMCache; ///< Buffers samples (already uncompressed) in RAM.
331 RIFF::Chunk* pCkSmpl;
332 RIFF::Chunk* pCkSm24;
333
334 //private:
335 int ChannelCount; // 2 for left and right samples
336
337 uint32_t Start; // in sample data points (frames) from the begining of the sample data field
338 uint32_t End; // in sample data points (frames) from the begining of the sample data field
339 uint32_t StartLoop; // in sample data points (frames) from the begining of the sample data field
340 uint32_t EndLoop; // in sample data points (frames) from the begining of the sample data field
341 uint32_t SampleRate;
342 uint8_t OriginalPitch;
343 uint8_t PitchCorrection;
344 uint16_t SampleLink; /* If sfSampleType indicates a left or right sample, the
345 * sample header index of the associated right or left stereo
346 * sample respectively; zero otherwise. */
347 uint16_t SampleType;
348 };
349
350 class File;
351 class Instrument;
352
353 /**
354 * Instrument zone
355 */
356 class Region {
357 public:
358 int loKey, hiKey;
359 int minVel, maxVel;
360 int pan; // -64 - +63
361 int fineTune; // -99 - +99
362 int coarseTune; // TODO:
363 int overridingRootKey; // represents the MIDI key number at which the sample is to be played back at its original sample rate.
364 int startAddrsOffset, startAddrsCoarseOffset, endAddrsOffset, endAddrsCoarseOffset;
365 int startloopAddrsOffset, startloopAddrsCoarseOffset, endloopAddrsOffset, endloopAddrsCoarseOffset;
366
367 double EG1PreAttackDelay;
368 double EG1Attack;
369 double EG1Hold;
370 double EG1Decay;
371 double EG1Sustain; // Sustain value of the sample amplitude EG (in permilles)
372 double EG1Release;
373
374 double EG2PreAttackDelay;
375 double EG2Attack;
376 double EG2Hold;
377 double EG2Decay;
378 double EG2Sustain; // Sustain value of the filter cutoff EG (in permilles)
379 double EG2Release;
380
381 Sample* pSample;
382 bool HasLoop;
383 uint LoopStart; // index (in frames) from the beginning of the sample
384 uint LoopEnd; // index (in frames) from the beginning of the sample
385 Instrument* pInstrument; // used when the region belongs to preset
386
387 Region();
388 Sample* GetSample() { return pSample; }
389 Region* GetParent() { return this; }
390
391 int GetUnityNote();
392
393 std::vector<ModulatorItem> modulators;
394
395 friend class Instrument;
396 friend class Preset;
397
398 private:
399 void SetGenerator(sf2::File* pFile, GenList& Gen);
400 void SetModulator(sf2::File* pFile, ModList& Mod);
401 };
402
403 class InstrumentBase {
404 public:
405 String Name;
406 Region* pGlobalRegion;
407
408 InstrumentBase(sf2::File* pFile);
409 virtual ~InstrumentBase();
410
411 sf2::File* GetFile() { return pFile; }
412 String GetName() { return Name; }
413
414 int GetRegionCount();
415 Region* GetRegion(int idx);
416
417 std::vector<Region*> GetRegionsOnKey(int key, uint8_t vel);
418
419 protected:
420 std::vector<Region*> regions;
421 sf2::File* pFile;
422 };
423
424 class Instrument : public InstrumentBase {
425 public:
426 Instrument(sf2::File* pFile, RIFF::Chunk* ck);
427 ~Instrument();
428
429 void DeleteRegion(Region* pRegion);
430 //private:
431 uint16_t InstBagNdx;
432
433 /**
434 * Load all regions (zones, bags) in the range idx1 - idx2
435 */
436 void LoadRegions(int idx1, int idx2);
437
438 Region* CreateRegion();
439 };
440
441 class Preset : public InstrumentBase {
442 public:
443 uint16_t PresetNum;
444 uint16_t Bank;
445 uint32_t Library;
446 uint32_t Genre;
447 uint32_t Morphology;
448
449 Preset(sf2::File* pFile, RIFF::Chunk* ck);
450 ~Preset();
451
452 //private:
453 sf2::File* pFile;
454 uint16_t PresetBagNdx;
455
456 /**
457 * Load all regions (zones, bags) in the range idx1 - idx2
458 */
459 void LoadRegions(int idx1, int idx2);
460 };
461
462 class File {
463 public:
464 Info* pInfo;
465
466 File(RIFF::File* pRIFF);
467 ~File();
468
469 int GetPresetCount();
470 Preset* GetPreset(int idx);
471 int GetInstrumentCount();
472 Instrument* GetInstrument(int idx);
473 void DeleteInstrument(Instrument* pInstrument);
474 int GetSampleCount();
475 Sample* GetSample(int idx);
476 void DeleteSample(Sample* pSample);
477 bool HasSamples();
478
479 friend class Region;
480 friend class Instrument;
481 friend class Preset;
482
483 protected:
484 RIFF::File* pRIFF;
485 std::vector<PresetBag> PresetBags;
486 std::vector<ModList> PresetModLists;
487 std::vector<GenList> PresetGenLists;
488 std::vector<InstBag> InstBags;
489 std::vector<ModList> InstModLists;
490 std::vector<GenList> InstGenLists;
491
492 private:
493 std::vector<Preset*> Presets;
494 std::vector<Instrument*> Instruments;
495 std::vector<Sample*> Samples;
496 };
497
498 String libraryName();
499 String libraryVersion();
500
501 } // namespace sf2
502 #endif // __SF2_SF_H__

  ViewVC Help
Powered by ViewVC