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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2204 - (hide annotations) (download) (as text)
Mon Jul 11 17:23:54 2011 UTC (12 years, 9 months ago) by iliev
File MIME type: text/x-c++hdr
File size: 19935 byte(s)
* sf2: some fixes to sf2dump
* sf2: ToSeconds(), ToPermilles(), ToHz() are now exposed to the C++ API

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     double ToPermilles(int Centibels);
68     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     RELEASEMODENV, // 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 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     int modLfoToVolume /* in centibels */, freqModLfo /* in absolute cents*/;
364     int delayModLfo; // in absolute timecents
365     int vibLfoToPitch, freqVibLfo /* in absolute cents*/;
366     int delayVibLfo; // in absolute timecents
367 iliev 2016
368 iliev 2026 uint exclusiveClass; // exclusive group
369 iliev 2016
370     Sample* pSample;
371 iliev 2020 bool HasLoop;
372     uint LoopStart; // index (in frames) from the beginning of the sample
373     uint LoopEnd; // index (in frames) from the beginning of the sample
374 iliev 2016 Instrument* pInstrument; // used when the region belongs to preset
375    
376     Region();
377     Sample* GetSample() { return pSample; }
378     Region* GetParent() { return this; }
379    
380 iliev 2020 int GetUnityNote();
381    
382 iliev 2026 /**
383     * @returns The instrument to which this region belongs, or
384     * NULL if it's preset region.
385     */
386     Instrument* GetParentInstrument() { return pParentInstrument; }
387    
388 iliev 2016 std::vector<ModulatorItem> modulators;
389    
390 iliev 2026
391     // Instrument can be referenced by more than one presets so we need to calculate values on the fly
392     int GetPan(Region* pPresetRegion = NULL); // -64 - +63
393     int GetFineTune(Region* pPresetRegion = NULL); // -99 - +99
394     int GetCoarseTune(Region* pPresetRegion = NULL); // -120 - +120
395     double GetEG1PreAttackDelay(Region* pPresetRegion = NULL); // in seconds
396     double GetEG1Attack(Region* pPresetRegion = NULL); // in seconds
397     double GetEG1Hold(Region* pPresetRegion = NULL); // in seconds
398     double GetEG1Decay(Region* pPresetRegion = NULL); // in seconds
399     double GetEG1Sustain(Region* pPresetRegion = NULL); // Sustain value of the sample amplitude EG (in permilles)
400     double GetEG1Release(Region* pPresetRegion = NULL); // in seconds
401    
402     double GetEG2PreAttackDelay(Region* pPresetRegion = NULL); // in seconds
403     double GetEG2Attack(Region* pPresetRegion = NULL); // in seconds
404     double GetEG2Hold(Region* pPresetRegion = NULL); // in seconds
405     double GetEG2Decay(Region* pPresetRegion = NULL); // in seconds
406     double GetEG2Sustain(Region* pPresetRegion = NULL); // Sustain value of the filter cutoff EG (in permilles)
407     double GetEG2Release(Region* pPresetRegion = NULL); // in seconds
408    
409     int GetModEnvToPitch(Region* pPresetRegion = NULL);
410     int GetModLfoToPitch(Region* pPresetRegion = NULL);
411     int GetModEnvToFilterFc(Region* pPresetRegion = NULL);
412     int GetModLfoToFilterFc(Region* pPresetRegion = NULL);
413     double GetModLfoToVolume(Region* pPresetRegion = NULL); // in permilles
414     double GetFreqModLfo(Region* pPresetRegion = NULL); // in Hz
415     double GetDelayModLfo(Region* pPresetRegion = NULL); // in seconds
416 iliev 2204 int GetVibLfoToPitch(Region* pPresetRegion = NULL); // in cents
417 iliev 2026 double GetFreqVibLfo(Region* pPresetRegion = NULL); // in Hz
418     double GetDelayVibLfo(Region* pPresetRegion = NULL); // in seconds
419    
420 iliev 2016 friend class Instrument;
421     friend class Preset;
422    
423     private:
424 persson 2044 int EG1PreAttackDelay; // in timecents
425     int EG1Attack; // in timecents
426     int EG1Hold; // in timecents
427     int EG1Decay; // in timecents
428     int EG1Sustain; // Sustain value of the sample amplitude EG (in permilles)
429     int EG1Release; // in timecents
430 iliev 2026
431 persson 2044 int EG2PreAttackDelay; // in timecents
432     int EG2Attack; // in timecents
433     int EG2Hold; // in timecents
434     int EG2Decay; // in timecents
435     int EG2Sustain; // Sustain value of the filter cutoff EG (in permilles)
436     int EG2Release; // in timecents
437 iliev 2026
438     Instrument* pParentInstrument;
439    
440 iliev 2016 void SetGenerator(sf2::File* pFile, GenList& Gen);
441     void SetModulator(sf2::File* pFile, ModList& Mod);
442     };
443    
444     class InstrumentBase {
445     public:
446     String Name;
447     Region* pGlobalRegion;
448    
449     InstrumentBase(sf2::File* pFile);
450     virtual ~InstrumentBase();
451    
452     sf2::File* GetFile() { return pFile; }
453     String GetName() { return Name; }
454 persson 2044
455 iliev 2016 int GetRegionCount();
456     Region* GetRegion(int idx);
457    
458     protected:
459     std::vector<Region*> regions;
460     sf2::File* pFile;
461     };
462    
463 persson 2100 class Query {
464     public:
465     int key;
466     uint8_t vel;
467    
468     Query(InstrumentBase& instrument);
469     Region* next();
470    
471     private:
472     InstrumentBase& instrument;
473     int i;
474     };
475    
476 iliev 2016 class Instrument : public InstrumentBase {
477     public:
478     Instrument(sf2::File* pFile, RIFF::Chunk* ck);
479     ~Instrument();
480 iliev 2020
481     void DeleteRegion(Region* pRegion);
482 iliev 2016 //private:
483     uint16_t InstBagNdx;
484 persson 2044
485 iliev 2016 /**
486     * Load all regions (zones, bags) in the range idx1 - idx2
487     */
488     void LoadRegions(int idx1, int idx2);
489 iliev 2020
490     Region* CreateRegion();
491 iliev 2016 };
492    
493     class Preset : public InstrumentBase {
494     public:
495     uint16_t PresetNum;
496     uint16_t Bank;
497     uint32_t Library;
498     uint32_t Genre;
499     uint32_t Morphology;
500    
501     Preset(sf2::File* pFile, RIFF::Chunk* ck);
502     ~Preset();
503    
504     //private:
505     sf2::File* pFile;
506     uint16_t PresetBagNdx;
507    
508     /**
509     * Load all regions (zones, bags) in the range idx1 - idx2
510     */
511     void LoadRegions(int idx1, int idx2);
512 iliev 2026
513     Region* CreateRegion();
514 iliev 2016 };
515    
516     class File {
517     public:
518     Info* pInfo;
519    
520     File(RIFF::File* pRIFF);
521     ~File();
522    
523     int GetPresetCount();
524     Preset* GetPreset(int idx);
525     int GetInstrumentCount();
526     Instrument* GetInstrument(int idx);
527 iliev 2020 void DeleteInstrument(Instrument* pInstrument);
528 iliev 2016 int GetSampleCount();
529     Sample* GetSample(int idx);
530     void DeleteSample(Sample* pSample);
531     bool HasSamples();
532    
533     friend class Region;
534     friend class Instrument;
535     friend class Preset;
536    
537     protected:
538     RIFF::File* pRIFF;
539     std::vector<PresetBag> PresetBags;
540     std::vector<ModList> PresetModLists;
541     std::vector<GenList> PresetGenLists;
542     std::vector<InstBag> InstBags;
543     std::vector<ModList> InstModLists;
544     std::vector<GenList> InstGenLists;
545    
546     private:
547     std::vector<Preset*> Presets;
548     std::vector<Instrument*> Instruments;
549     std::vector<Sample*> Samples;
550     };
551    
552     String libraryName();
553     String libraryVersion();
554    
555     } // namespace sf2
556     #endif // __SF2_SF_H__

  ViewVC Help
Powered by ViewVC