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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2206 - (hide annotations) (download) (as text)
Fri Jul 15 14:48:40 2011 UTC (12 years, 9 months ago) by iliev
File MIME type: text/x-c++hdr
File size: 20275 byte(s)
* sf2: generators' values are now ensured to be in the allowed range
* sf2: GetEG2Sustain() now returns the decrease in the level
* sf2: removed ToPermilles() and added ToRatio() function
* sf2: added GetInitialFilterFc() and GetInitialFilterQ()

1 iliev 2016 /***************************************************************************
2     * *
3     * libsf2 - C++ cross-platform SF2 format file access library *
4     * *
5 persson 2044 * Copyright (C) 2009-2010 by Grigor Iliev <grigor@grigoriliev.com> *
6 iliev 2016 * *
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 persson 2044 #define RIFF_ID(x) (*((uint32_t*) x))
32 iliev 2016
33    
34 persson 2044 #define RIFF_TYPE_SF2 RIFF_ID("sfbk")
35 iliev 2016
36     // Level 0
37 persson 2044 #define LIST_TYPE_SDTA RIFF_ID("sdta")
38     #define LIST_TYPE_PDTA RIFF_ID("pdta")
39 iliev 2016
40     // Level 1
41     //<INFO-list>
42 persson 2044 #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 iliev 2016
47     //<sdta-list>
48 persson 2044 #define CHUNK_ID_SM24 RIFF_ID("sm24")
49 iliev 2016
50     //<pdta-list>
51 persson 2044 #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 iliev 2016
61 schoenebeck 2022 /** SoundFont specific classes and definitions */
62 iliev 2016 namespace sf2 {
63 persson 2044
64 iliev 2026 static uint NONE = 0x1ffffff;
65    
66 iliev 2204 double ToSeconds(int Timecents);
67 iliev 2206 double ToRatio(int Centibels);
68 iliev 2204 double ToHz(int cents);
69    
70 iliev 2016 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 persson 2044 #if WORDS_BIGENDIAN
89     uint8_t byHi;
90 iliev 2016 uint8_t byLo;
91 persson 2044 #else
92     uint8_t byLo;
93 iliev 2016 uint8_t byHi;
94 persson 2044 #endif
95 iliev 2016 } 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 iliev 2206 RELEASE_MOD_ENV, // 30
145 iliev 2016 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 persson 2044 SFGenerator ModDestOper;
218     uint16_t ModAmount;
219     Modulator ModAmtSrcOper;
220     SFTransform ModTransOper;
221 iliev 2016
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 iliev 2020 class Region;
261    
262 iliev 2016 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    
317     unsigned long ReadAndLoop (
318     void* pBuffer,
319     unsigned long FrameCount,
320 iliev 2020 PlaybackState* pPlaybackState,
321     Region* pRegion
322 iliev 2016 );
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 iliev 2020 uint32_t Start; // in sample data points (frames) from the begining of the sample data field
333     uint32_t End; // in sample data points (frames) from the begining of the sample data field
334     uint32_t StartLoop; // in sample data points (frames) from the begining of the sample data field
335     uint32_t EndLoop; // in sample data points (frames) from the begining of the sample data field
336 iliev 2016 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 iliev 2020 int coarseTune; // TODO:
358     int overridingRootKey; // represents the MIDI key number at which the sample is to be played back at its original sample rate.
359     int startAddrsOffset, startAddrsCoarseOffset, endAddrsOffset, endAddrsCoarseOffset;
360     int startloopAddrsOffset, startloopAddrsCoarseOffset, endloopAddrsOffset, endloopAddrsCoarseOffset;
361 iliev 2016
362 iliev 2204 int modEnvToPitch , modLfoToPitch, modEnvToFilterFc, modLfoToFilterFc; // in cents
363 iliev 2206 int modLfoToVolume /* in centibels */, freqModLfo /* in absolute cents */;
364 iliev 2204 int delayModLfo; // in absolute timecents
365 iliev 2206 int vibLfoToPitch, freqVibLfo /* in absolute cents */;
366 iliev 2204 int delayVibLfo; // in absolute timecents
367 iliev 2206 int initialFilterFc /* in absolute cents */, initialFilterQ /* in centibels */;
368 iliev 2016
369 iliev 2026 uint exclusiveClass; // exclusive group
370 iliev 2016
371     Sample* pSample;
372 iliev 2020 bool HasLoop;
373     uint LoopStart; // index (in frames) from the beginning of the sample
374     uint LoopEnd; // index (in frames) from the beginning of the sample
375 iliev 2016 Instrument* pInstrument; // used when the region belongs to preset
376    
377     Region();
378     Sample* GetSample() { return pSample; }
379     Region* GetParent() { return this; }
380    
381 iliev 2020 int GetUnityNote();
382    
383 iliev 2026 /**
384     * @returns The instrument to which this region belongs, or
385     * NULL if it's preset region.
386     */
387     Instrument* GetParentInstrument() { return pParentInstrument; }
388    
389 iliev 2016 std::vector<ModulatorItem> modulators;
390    
391 iliev 2026
392     // Instrument can be referenced by more than one presets so we need to calculate values on the fly
393     int GetPan(Region* pPresetRegion = NULL); // -64 - +63
394     int GetFineTune(Region* pPresetRegion = NULL); // -99 - +99
395     int GetCoarseTune(Region* pPresetRegion = NULL); // -120 - +120
396     double GetEG1PreAttackDelay(Region* pPresetRegion = NULL); // in seconds
397     double GetEG1Attack(Region* pPresetRegion = NULL); // in seconds
398     double GetEG1Hold(Region* pPresetRegion = NULL); // in seconds
399     double GetEG1Decay(Region* pPresetRegion = NULL); // in seconds
400 iliev 2206 int GetEG1Sustain(Region* pPresetRegion = NULL); // Sustain value of the sample amplitude EG (the decrease in level, expressed in centibels)
401 iliev 2026 double GetEG1Release(Region* pPresetRegion = NULL); // in seconds
402    
403     double GetEG2PreAttackDelay(Region* pPresetRegion = NULL); // in seconds
404     double GetEG2Attack(Region* pPresetRegion = NULL); // in seconds
405     double GetEG2Hold(Region* pPresetRegion = NULL); // in seconds
406     double GetEG2Decay(Region* pPresetRegion = NULL); // in seconds
407 iliev 2206 int GetEG2Sustain(Region* pPresetRegion = NULL); // Sustain value of the filter cutoff EG (in permilles)
408 iliev 2026 double GetEG2Release(Region* pPresetRegion = NULL); // in seconds
409    
410 iliev 2206 int GetModEnvToPitch(Region* pPresetRegion = NULL); // in cents
411     int GetModLfoToPitch(Region* pPresetRegion = NULL); // in cents
412     int GetModEnvToFilterFc(Region* pPresetRegion = NULL); // in cents
413     int GetModLfoToFilterFc(Region* pPresetRegion = NULL); // in cents
414     double GetModLfoToVolume(Region* pPresetRegion = NULL); // in centibels
415 iliev 2026 double GetFreqModLfo(Region* pPresetRegion = NULL); // in Hz
416     double GetDelayModLfo(Region* pPresetRegion = NULL); // in seconds
417 iliev 2204 int GetVibLfoToPitch(Region* pPresetRegion = NULL); // in cents
418 iliev 2026 double GetFreqVibLfo(Region* pPresetRegion = NULL); // in Hz
419     double GetDelayVibLfo(Region* pPresetRegion = NULL); // in seconds
420 iliev 2206 int GetInitialFilterFc(Region* pPresetRegion); // in absolute cents
421     int GetInitialFilterQ(Region* pPresetRegion); // in centibels
422 iliev 2026
423 iliev 2016 friend class Instrument;
424     friend class Preset;
425    
426     private:
427 persson 2044 int EG1PreAttackDelay; // in timecents
428     int EG1Attack; // in timecents
429     int EG1Hold; // in timecents
430     int EG1Decay; // in timecents
431 iliev 2206 int EG1Sustain; // Sustain value (the decrease in level, expressed in centibels)
432 persson 2044 int EG1Release; // in timecents
433 iliev 2026
434 persson 2044 int EG2PreAttackDelay; // in timecents
435     int EG2Attack; // in timecents
436     int EG2Hold; // in timecents
437     int EG2Decay; // in timecents
438     int EG2Sustain; // Sustain value of the filter cutoff EG (in permilles)
439     int EG2Release; // in timecents
440 iliev 2026
441     Instrument* pParentInstrument;
442    
443 iliev 2016 void SetGenerator(sf2::File* pFile, GenList& Gen);
444     void SetModulator(sf2::File* pFile, ModList& Mod);
445     };
446    
447     class InstrumentBase {
448     public:
449     String Name;
450     Region* pGlobalRegion;
451    
452     InstrumentBase(sf2::File* pFile);
453     virtual ~InstrumentBase();
454    
455     sf2::File* GetFile() { return pFile; }
456     String GetName() { return Name; }
457 persson 2044
458 iliev 2016 int GetRegionCount();
459     Region* GetRegion(int idx);
460    
461     protected:
462     std::vector<Region*> regions;
463     sf2::File* pFile;
464     };
465    
466 persson 2100 class Query {
467     public:
468     int key;
469     uint8_t vel;
470    
471     Query(InstrumentBase& instrument);
472     Region* next();
473    
474     private:
475     InstrumentBase& instrument;
476     int i;
477     };
478    
479 iliev 2016 class Instrument : public InstrumentBase {
480     public:
481     Instrument(sf2::File* pFile, RIFF::Chunk* ck);
482     ~Instrument();
483 iliev 2020
484     void DeleteRegion(Region* pRegion);
485 iliev 2016 //private:
486     uint16_t InstBagNdx;
487 persson 2044
488 iliev 2016 /**
489     * Load all regions (zones, bags) in the range idx1 - idx2
490     */
491     void LoadRegions(int idx1, int idx2);
492 iliev 2020
493     Region* CreateRegion();
494 iliev 2016 };
495    
496     class Preset : public InstrumentBase {
497     public:
498     uint16_t PresetNum;
499     uint16_t Bank;
500     uint32_t Library;
501     uint32_t Genre;
502     uint32_t Morphology;
503    
504     Preset(sf2::File* pFile, RIFF::Chunk* ck);
505     ~Preset();
506    
507     //private:
508     sf2::File* pFile;
509     uint16_t PresetBagNdx;
510    
511     /**
512     * Load all regions (zones, bags) in the range idx1 - idx2
513     */
514     void LoadRegions(int idx1, int idx2);
515 iliev 2026
516     Region* CreateRegion();
517 iliev 2016 };
518    
519     class File {
520     public:
521     Info* pInfo;
522    
523     File(RIFF::File* pRIFF);
524     ~File();
525    
526     int GetPresetCount();
527     Preset* GetPreset(int idx);
528     int GetInstrumentCount();
529     Instrument* GetInstrument(int idx);
530 iliev 2020 void DeleteInstrument(Instrument* pInstrument);
531 iliev 2016 int GetSampleCount();
532     Sample* GetSample(int idx);
533     void DeleteSample(Sample* pSample);
534     bool HasSamples();
535    
536     friend class Region;
537     friend class Instrument;
538     friend class Preset;
539    
540     protected:
541     RIFF::File* pRIFF;
542     std::vector<PresetBag> PresetBags;
543     std::vector<ModList> PresetModLists;
544     std::vector<GenList> PresetGenLists;
545     std::vector<InstBag> InstBags;
546     std::vector<ModList> InstModLists;
547     std::vector<GenList> InstGenLists;
548    
549     private:
550     std::vector<Preset*> Presets;
551     std::vector<Instrument*> Instruments;
552     std::vector<Sample*> Samples;
553     };
554    
555     String libraryName();
556     String libraryVersion();
557    
558     } // namespace sf2
559     #endif // __SF2_SF_H__

  ViewVC Help
Powered by ViewVC