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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2780 - (show annotations) (download) (as text)
Thu Jul 2 20:04:16 2015 UTC (8 years, 9 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 20378 byte(s)
* src/SF.cpp, src/SF.h:
- Added new method Sample::ReadNoClear().
* Added new command line tool "sf2extract" (and a man page for it).
* Bumped version (3.3.0.svn29).

1 /***************************************************************************
2 * *
3 * libsf2 - C++ cross-platform SF2 format file access library *
4 * *
5 * Copyright (C) 2009-2010 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 #define RIFF_ID(x) (*((uint32_t*) x))
32
33
34 #define RIFF_TYPE_SF2 RIFF_ID("sfbk")
35
36 // Level 0
37 #define LIST_TYPE_SDTA RIFF_ID("sdta")
38 #define LIST_TYPE_PDTA RIFF_ID("pdta")
39
40 // Level 1
41 //<INFO-list>
42 #define CHUNK_ID_IFIL RIFF_ID("ifil")
43 #define CHUNK_ID_ISNG RIFF_ID("isng")
44 #define CHUNK_ID_IROM RIFF_ID("irom")
45 #define CHUNK_ID_IVER RIFF_ID("iver")
46
47 //<sdta-list>
48 #define CHUNK_ID_SM24 RIFF_ID("sm24")
49
50 //<pdta-list>
51 #define CHUNK_ID_PHDR RIFF_ID("phdr")
52 #define CHUNK_ID_PBAG RIFF_ID("pbag")
53 #define CHUNK_ID_PMOD RIFF_ID("pmod")
54 #define CHUNK_ID_PGEN RIFF_ID("pgen")
55 #define CHUNK_ID_INST RIFF_ID("inst")
56 #define CHUNK_ID_IBAG RIFF_ID("ibag")
57 #define CHUNK_ID_IMOD RIFF_ID("imod")
58 #define CHUNK_ID_IGEN RIFF_ID("igen")
59 #define CHUNK_ID_SHDR RIFF_ID("shdr")
60
61 /** SoundFont specific classes and definitions */
62 namespace sf2 {
63
64 static uint NONE = 0x1ffffff;
65
66 double ToSeconds(int Timecents);
67 double ToRatio(int Centibels);
68 double ToHz(int cents);
69
70 typedef struct _PresetBag {
71 uint16_t GenNdx;
72 uint16_t ModNdx;
73 } PresetBag;
74
75 typedef uint16_t SFModulator;
76 typedef uint16_t SFGenerator;
77 typedef uint16_t SFTransform;
78
79 typedef struct _ModList {
80 SFModulator ModSrcOper;
81 SFGenerator ModDestOper;
82 uint16_t ModAmount;
83 SFModulator ModAmtSrcOper;
84 SFTransform ModTransOper;
85 } ModList;
86
87 typedef struct _RangesType {
88 #if WORDS_BIGENDIAN
89 uint8_t byHi;
90 uint8_t byLo;
91 #else
92 uint8_t byLo;
93 uint8_t byHi;
94 #endif
95 } RangesType;
96
97 typedef union _GenAmountType {
98 RangesType ranges;
99 short shAmount;
100 uint16_t wAmount;
101 } GenAmountType;
102
103 typedef struct _GenList {
104 SFGenerator GenOper;
105 GenAmountType GenAmount;
106 } GenList;
107
108 typedef struct _InstBag {
109 uint16_t InstGenNdx;
110 uint16_t InstModNdx;
111 } InstBag;
112
113 typedef enum {
114 START_ADDRS_OFFSET = 0,
115 END_ADDRS_OFFSET,
116 STARTLOOP_ADDRS_OFFSET,
117 ENDLOOP_ADDRS_OFFSET ,
118 START_ADDRS_COARSE_OFFSET,
119 MOD_LFO_TO_PITCH,
120 VIB_LFO_TO_PITCH,
121 MOD_ENV_TO_PITCH,
122 INITIAL_FILTER_FC,
123 INITIAL_FILTER_Q,
124 MOD_LFO_TO_FILTER_FC, // 10
125 MOD_ENV_TO_FILTER_FC,
126 END_ADDRS_COARSE_OFFSET,
127 MOD_LFO_TO_VOLUME,
128 UNUSED1,
129 CHORUS_EFFECTS_SEND,
130 REVERB_EFFECTS_SEND,
131 PAN,
132 UNUSED2,
133 UNUSED3,
134 UNUSED4, //20
135 DELAY_MOD_LFO,
136 FREQ_MOD_LFO,
137 DELAY_VIB_LFO,
138 FREQ_VIB_LFO,
139 DELAY_MOD_ENV,
140 ATTACK_MOD_ENV,
141 HOLD_MOD_ENV,
142 DECAY_MOD_ENV,
143 SUSTAIN_MOD_ENV,
144 RELEASE_MOD_ENV, // 30
145 KEYNUM_TO_MOD_ENV_HOLD,
146 KEYNUM_TO_MOD_ENV_DECAY,
147 DELAY_VOL_ENV,
148 ATTACK_VOL_ENV,
149 HOLD_VOL_ENV,
150 DECAY_VOL_ENV,
151 SUSTAIN_VOL_ENV,
152 RELEASE_VOL_ENV,
153 KEYNUM_TO_VOL_ENV_HOLD,
154 KEYNUM_TO_VOL_ENV_DECAY, //40
155 INSTRUMENT,
156 RESERVED1,
157 KEY_RANGE,
158 VEL_RANGE,
159 STARTLOOP_ADDRS_COARSE_OFFSET,
160 KEYNUM,
161 VELOCITY,
162 INITIAL_ATTENUATION,
163 RESERVED2,
164 ENDLOOP_ADDRS_COARSE_OFFSET, // 50
165 COARSE_TUNE,
166 FINE_TUNE,
167 SAMPLE_ID,
168 SAMPLE_MODES,
169 RESERVED3,
170 SCALE_TUNING,
171 EXCLUSIVE_CLASS,
172 OVERRIDING_ROOT_KEY,
173 UNUSED5,
174 END_OPER
175 } SFGeneratorType;
176
177 class Modulator {
178 public:
179
180 /**
181 * General Controller palette of controllers.
182 * Controller sources.
183 */
184 enum {
185 NO_CONTROLLER = 0,
186 NOTE_ON_VELOCITY = 2,
187 NOTE_ON_KEY_NUMBER = 3,
188 POLY_PRESSURE = 10,
189 CHANNEL_PRESSURE = 13,
190 PITCH_WHEEL = 14,
191 PITCH_WHEEL_SENSITIVITY = 16,
192 LINK = 127
193 };
194
195 /**
196 * Controller type
197 */
198 enum {
199 LINEAR = 0,
200 CONCAVE,
201 CONVEX,
202 SWITCH
203 };
204
205 int Type;
206 bool MidiPalete;
207 bool Direction;
208 bool Polarity;
209 int Index;
210
211 Modulator(SFModulator mod);
212 };
213
214 class ModulatorItem {
215 public:
216 Modulator ModSrcOper;
217 SFGenerator ModDestOper;
218 uint16_t ModAmount;
219 Modulator ModAmtSrcOper;
220 SFTransform ModTransOper;
221
222 ModulatorItem(ModList& mod);
223 };
224
225
226 typedef std::string String;
227
228 class Exception : public RIFF::Exception {
229 public: Exception(String Message) : RIFF::Exception(Message) { }
230 };
231
232 class Version {
233 public:
234 int Major;
235 int Minor;
236
237 Version(RIFF::Chunk* ck);
238 };
239
240 class Info {
241 public:
242 Version* pVer; ///< <ifil-ck> ; Refers to the version of the Sound Font RIFF file
243 String SoundEngine; ///< <isng-ck> ; Refers to the target Sound Engine
244 String BankName; ///< <INAM-ck> ; Refers to the Sound Font Bank Name
245 String RomName; ///< [<irom-ck>] ; Refers to the Sound ROM Name
246 Version* pRomVer; ///< [<iver-ck>] ; Refers to the Sound ROM Version
247 String CreationDate; ///< [<ICRD-ck>] ; Refers to the Date of Creation of the Bank
248 String Engineers; ///< [<IENG-ck>] ; Sound Designers and Engineers for the Bank
249 String Product; ///< [<IPRD-ck>] ; Product for which the Bank was intended
250 String Copyright; ///< [<ICOP-ck>] ; Contains any Copyright message
251 String Comments; ///< [<ICMT-ck>] ; Contains any Comments on the Bank
252 String Software; ///< [<ISFT-ck>] ; The SoundFont tools used to create and alter the bank
253
254 Info(RIFF::List* list);
255 ~Info();
256 private:
257 static void LoadString(uint32_t ChunkID, RIFF::List* lstINFO, String& s);
258 };
259
260 class Region;
261
262 class Sample {
263 public:
264
265 typedef enum {
266 MONO_SAMPLE = 1,
267 RIGHT_SAMPLE = 2,
268 LEFT_SAMPLE = 4,
269 LINKED_SAMPLE = 8,
270 ROM_MONO_SAMPLE = 0x8001,
271 ROM_RIGHT_SAMPLE = 0x8002,
272 ROM_LEFT_SAMPLE = 0x8004,
273 ROM_LINKED_SAMPLE = 0x8008
274 } Link;
275
276 /** Reflects the current playback state for a sample. */
277 class PlaybackState {
278 public:
279 unsigned long position; ///< Current position within the sample.
280 bool reverse; ///< If playback direction is currently backwards (in case there is a pingpong or reverse loop defined).
281 unsigned long loop_cycles_left; ///< How many times the loop has still to be passed, this value will be decremented with each loop cycle.
282 };
283
284 /** Pointer address and size of a buffer. */
285 struct buffer_t {
286 void* pStart; ///< Points to the beginning of the buffer.
287 unsigned long Size; ///< Size of the actual data in the buffer in bytes.
288 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. :)
289 buffer_t() {
290 pStart = NULL;
291 Size = 0;
292 NullExtensionSize = 0;
293 }
294 };
295
296 String Name;
297
298 Sample(RIFF::Chunk* ck, RIFF::Chunk* pCkSmpl, RIFF::Chunk* pCkSm24);
299
300 String GetName() { return Name; }
301 int GetChannelCount();
302 long GetTotalFrameCount();
303 int GetFrameSize();
304 bool HasLoops();
305 bool IsUnpitched() { return OriginalPitch == 255; }
306
307 buffer_t LoadSampleData();
308 buffer_t LoadSampleData(unsigned long SampleCount);
309 buffer_t LoadSampleDataWithNullSamplesExtension(uint NullSamplesCount);
310 buffer_t LoadSampleDataWithNullSamplesExtension(unsigned long SampleCount, uint NullSamplesCount);
311 buffer_t GetCache();
312 void ReleaseSampleData();
313 unsigned long SetPos(unsigned long SampleCount);
314 unsigned long GetPos();
315 unsigned long Read(void* pBuffer, unsigned long SampleCount);
316 unsigned long ReadNoClear(void* pBuffer, unsigned long SampleCount, buffer_t& tempBuffer);
317
318 unsigned long ReadAndLoop (
319 void* pBuffer,
320 unsigned long FrameCount,
321 PlaybackState* pPlaybackState,
322 Region* pRegion
323 );
324
325 //protected:
326 buffer_t RAMCache; ///< Buffers samples (already uncompressed) in RAM.
327 RIFF::Chunk* pCkSmpl;
328 RIFF::Chunk* pCkSm24;
329
330 //private:
331 int ChannelCount; // 2 for left and right samples
332
333 uint32_t Start; // in sample data points (frames) from the begining of the sample data field
334 uint32_t End; // in sample data points (frames) from the begining of the sample data field
335 uint32_t StartLoop; // in sample data points (frames) from the begining of the sample data field
336 uint32_t EndLoop; // in sample data points (frames) from the begining of the sample data field
337 uint32_t SampleRate;
338 uint8_t OriginalPitch;
339 uint8_t PitchCorrection;
340 uint16_t SampleLink; /* If sfSampleType indicates a left or right sample, the
341 * sample header index of the associated right or left stereo
342 * sample respectively; zero otherwise. */
343 uint16_t SampleType;
344 };
345
346 class File;
347 class Instrument;
348
349 /**
350 * Instrument zone
351 */
352 class Region {
353 public:
354 int loKey, hiKey;
355 int minVel, maxVel;
356 int pan; // -64 - +63
357 int fineTune; // -99 - +99
358 int coarseTune; // TODO:
359 int overridingRootKey; // represents the MIDI key number at which the sample is to be played back at its original sample rate.
360 int startAddrsOffset, startAddrsCoarseOffset, endAddrsOffset, endAddrsCoarseOffset;
361 int startloopAddrsOffset, startloopAddrsCoarseOffset, endloopAddrsOffset, endloopAddrsCoarseOffset;
362
363 int modEnvToPitch , modLfoToPitch, modEnvToFilterFc, modLfoToFilterFc; // in cents
364 int modLfoToVolume /* in centibels */, freqModLfo /* in absolute cents */;
365 int delayModLfo; // in absolute timecents
366 int vibLfoToPitch, freqVibLfo /* in absolute cents */;
367 int delayVibLfo; // in absolute timecents
368 int initialFilterFc /* in absolute cents */, initialFilterQ /* in centibels */;
369
370 uint exclusiveClass; // exclusive group
371
372 Sample* pSample;
373 bool HasLoop;
374 uint LoopStart; // index (in frames) from the beginning of the sample
375 uint LoopEnd; // index (in frames) from the beginning of the sample
376 Instrument* pInstrument; // used when the region belongs to preset
377
378 Region();
379 Sample* GetSample() { return pSample; }
380 Region* GetParent() { return this; }
381
382 int GetUnityNote();
383
384 /**
385 * @returns The instrument to which this region belongs, or
386 * NULL if it's preset region.
387 */
388 Instrument* GetParentInstrument() { return pParentInstrument; }
389
390 std::vector<ModulatorItem> modulators;
391
392
393 // Instrument can be referenced by more than one presets so we need to calculate values on the fly
394 int GetPan(Region* pPresetRegion = NULL); // -64 - +63
395 int GetFineTune(Region* pPresetRegion = NULL); // -99 - +99
396 int GetCoarseTune(Region* pPresetRegion = NULL); // -120 - +120
397 double GetEG1PreAttackDelay(Region* pPresetRegion = NULL); // in seconds
398 double GetEG1Attack(Region* pPresetRegion = NULL); // in seconds
399 double GetEG1Hold(Region* pPresetRegion = NULL); // in seconds
400 double GetEG1Decay(Region* pPresetRegion = NULL); // in seconds
401 int GetEG1Sustain(Region* pPresetRegion = NULL); // Sustain value of the sample amplitude EG (the decrease in level, expressed in centibels)
402 double GetEG1Release(Region* pPresetRegion = NULL); // in seconds
403
404 double GetEG2PreAttackDelay(Region* pPresetRegion = NULL); // in seconds
405 double GetEG2Attack(Region* pPresetRegion = NULL); // in seconds
406 double GetEG2Hold(Region* pPresetRegion = NULL); // in seconds
407 double GetEG2Decay(Region* pPresetRegion = NULL); // in seconds
408 int GetEG2Sustain(Region* pPresetRegion = NULL); // Sustain value of the filter cutoff EG (in permilles)
409 double GetEG2Release(Region* pPresetRegion = NULL); // in seconds
410
411 int GetModEnvToPitch(Region* pPresetRegion = NULL); // in cents
412 int GetModLfoToPitch(Region* pPresetRegion = NULL); // in cents
413 int GetModEnvToFilterFc(Region* pPresetRegion = NULL); // in cents
414 int GetModLfoToFilterFc(Region* pPresetRegion = NULL); // in cents
415 double GetModLfoToVolume(Region* pPresetRegion = NULL); // in centibels
416 double GetFreqModLfo(Region* pPresetRegion = NULL); // in Hz
417 double GetDelayModLfo(Region* pPresetRegion = NULL); // in seconds
418 int GetVibLfoToPitch(Region* pPresetRegion = NULL); // in cents
419 double GetFreqVibLfo(Region* pPresetRegion = NULL); // in Hz
420 double GetDelayVibLfo(Region* pPresetRegion = NULL); // in seconds
421 int GetInitialFilterFc(Region* pPresetRegion); // in absolute cents
422 int GetInitialFilterQ(Region* pPresetRegion); // in centibels
423
424 friend class Instrument;
425 friend class Preset;
426
427 private:
428 int EG1PreAttackDelay; // in timecents
429 int EG1Attack; // in timecents
430 int EG1Hold; // in timecents
431 int EG1Decay; // in timecents
432 int EG1Sustain; // Sustain value (the decrease in level, expressed in centibels)
433 int EG1Release; // in timecents
434
435 int EG2PreAttackDelay; // in timecents
436 int EG2Attack; // in timecents
437 int EG2Hold; // in timecents
438 int EG2Decay; // in timecents
439 int EG2Sustain; // Sustain value of the filter cutoff EG (in permilles)
440 int EG2Release; // in timecents
441
442 Instrument* pParentInstrument;
443
444 void SetGenerator(sf2::File* pFile, GenList& Gen);
445 void SetModulator(sf2::File* pFile, ModList& Mod);
446 };
447
448 class InstrumentBase {
449 public:
450 String Name;
451 Region* pGlobalRegion;
452
453 InstrumentBase(sf2::File* pFile);
454 virtual ~InstrumentBase();
455
456 sf2::File* GetFile() { return pFile; }
457 String GetName() { return Name; }
458
459 int GetRegionCount();
460 Region* GetRegion(int idx);
461
462 protected:
463 std::vector<Region*> regions;
464 sf2::File* pFile;
465 };
466
467 class Query {
468 public:
469 int key;
470 uint8_t vel;
471
472 Query(InstrumentBase& instrument);
473 Region* next();
474
475 private:
476 InstrumentBase& instrument;
477 int i;
478 };
479
480 class Instrument : public InstrumentBase {
481 public:
482 Instrument(sf2::File* pFile, RIFF::Chunk* ck);
483 ~Instrument();
484
485 void DeleteRegion(Region* pRegion);
486 //private:
487 uint16_t InstBagNdx;
488
489 /**
490 * Load all regions (zones, bags) in the range idx1 - idx2
491 */
492 void LoadRegions(int idx1, int idx2);
493
494 Region* CreateRegion();
495 };
496
497 class Preset : public InstrumentBase {
498 public:
499 uint16_t PresetNum;
500 uint16_t Bank;
501 uint32_t Library;
502 uint32_t Genre;
503 uint32_t Morphology;
504
505 Preset(sf2::File* pFile, RIFF::Chunk* ck);
506 ~Preset();
507
508 //private:
509 sf2::File* pFile;
510 uint16_t PresetBagNdx;
511
512 /**
513 * Load all regions (zones, bags) in the range idx1 - idx2
514 */
515 void LoadRegions(int idx1, int idx2);
516
517 Region* CreateRegion();
518 };
519
520 class File {
521 public:
522 Info* pInfo;
523
524 File(RIFF::File* pRIFF);
525 ~File();
526
527 int GetPresetCount();
528 Preset* GetPreset(int idx);
529 int GetInstrumentCount();
530 Instrument* GetInstrument(int idx);
531 void DeleteInstrument(Instrument* pInstrument);
532 int GetSampleCount();
533 Sample* GetSample(int idx);
534 void DeleteSample(Sample* pSample);
535 bool HasSamples();
536
537 friend class Region;
538 friend class Instrument;
539 friend class Preset;
540
541 protected:
542 RIFF::File* pRIFF;
543 std::vector<PresetBag> PresetBags;
544 std::vector<ModList> PresetModLists;
545 std::vector<GenList> PresetGenLists;
546 std::vector<InstBag> InstBags;
547 std::vector<ModList> InstModLists;
548 std::vector<GenList> InstGenLists;
549
550 private:
551 std::vector<Preset*> Presets;
552 std::vector<Instrument*> Instruments;
553 std::vector<Sample*> Samples;
554 };
555
556 String libraryName();
557 String libraryVersion();
558
559 } // namespace sf2
560 #endif // __SF2_SF_H__

  ViewVC Help
Powered by ViewVC