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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2780 - (hide 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 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 schoenebeck 2780 unsigned long ReadNoClear(void* pBuffer, unsigned long SampleCount, buffer_t& tempBuffer);
317 iliev 2016
318     unsigned long ReadAndLoop (
319     void* pBuffer,
320     unsigned long FrameCount,
321 iliev 2020 PlaybackState* pPlaybackState,
322     Region* pRegion
323 iliev 2016 );
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 iliev 2020 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 iliev 2016 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 iliev 2020 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 iliev 2016
363 iliev 2204 int modEnvToPitch , modLfoToPitch, modEnvToFilterFc, modLfoToFilterFc; // in cents
364 iliev 2206 int modLfoToVolume /* in centibels */, freqModLfo /* in absolute cents */;
365 iliev 2204 int delayModLfo; // in absolute timecents
366 iliev 2206 int vibLfoToPitch, freqVibLfo /* in absolute cents */;
367 iliev 2204 int delayVibLfo; // in absolute timecents
368 iliev 2206 int initialFilterFc /* in absolute cents */, initialFilterQ /* in centibels */;
369 iliev 2016
370 iliev 2026 uint exclusiveClass; // exclusive group
371 iliev 2016
372     Sample* pSample;
373 iliev 2020 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 iliev 2016 Instrument* pInstrument; // used when the region belongs to preset
377    
378     Region();
379     Sample* GetSample() { return pSample; }
380     Region* GetParent() { return this; }
381    
382 iliev 2020 int GetUnityNote();
383    
384 iliev 2026 /**
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 iliev 2016 std::vector<ModulatorItem> modulators;
391    
392 iliev 2026
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 iliev 2206 int GetEG1Sustain(Region* pPresetRegion = NULL); // Sustain value of the sample amplitude EG (the decrease in level, expressed in centibels)
402 iliev 2026 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 iliev 2206 int GetEG2Sustain(Region* pPresetRegion = NULL); // Sustain value of the filter cutoff EG (in permilles)
409 iliev 2026 double GetEG2Release(Region* pPresetRegion = NULL); // in seconds
410    
411 iliev 2206 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 iliev 2026 double GetFreqModLfo(Region* pPresetRegion = NULL); // in Hz
417     double GetDelayModLfo(Region* pPresetRegion = NULL); // in seconds
418 iliev 2204 int GetVibLfoToPitch(Region* pPresetRegion = NULL); // in cents
419 iliev 2026 double GetFreqVibLfo(Region* pPresetRegion = NULL); // in Hz
420     double GetDelayVibLfo(Region* pPresetRegion = NULL); // in seconds
421 iliev 2206 int GetInitialFilterFc(Region* pPresetRegion); // in absolute cents
422     int GetInitialFilterQ(Region* pPresetRegion); // in centibels
423 iliev 2026
424 iliev 2016 friend class Instrument;
425     friend class Preset;
426    
427     private:
428 persson 2044 int EG1PreAttackDelay; // in timecents
429     int EG1Attack; // in timecents
430     int EG1Hold; // in timecents
431     int EG1Decay; // in timecents
432 iliev 2206 int EG1Sustain; // Sustain value (the decrease in level, expressed in centibels)
433 persson 2044 int EG1Release; // in timecents
434 iliev 2026
435 persson 2044 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 iliev 2026
442     Instrument* pParentInstrument;
443    
444 iliev 2016 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 persson 2044
459 iliev 2016 int GetRegionCount();
460     Region* GetRegion(int idx);
461    
462     protected:
463     std::vector<Region*> regions;
464     sf2::File* pFile;
465     };
466    
467 persson 2100 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 iliev 2016 class Instrument : public InstrumentBase {
481     public:
482     Instrument(sf2::File* pFile, RIFF::Chunk* ck);
483     ~Instrument();
484 iliev 2020
485     void DeleteRegion(Region* pRegion);
486 iliev 2016 //private:
487     uint16_t InstBagNdx;
488 persson 2044
489 iliev 2016 /**
490     * Load all regions (zones, bags) in the range idx1 - idx2
491     */
492     void LoadRegions(int idx1, int idx2);
493 iliev 2020
494     Region* CreateRegion();
495 iliev 2016 };
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 iliev 2026
517     Region* CreateRegion();
518 iliev 2016 };
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 iliev 2020 void DeleteInstrument(Instrument* pInstrument);
532 iliev 2016 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