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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2026 - (hide annotations) (download) (as text)
Tue Nov 3 19:08:44 2009 UTC (14 years, 4 months ago) by iliev
File MIME type: text/x-c++hdr
File size: 19935 byte(s)
* sf2: better support for preset regions

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

  ViewVC Help
Powered by ViewVC