2 |
* * |
* * |
3 |
* libsf2 - C++ cross-platform SF2 format file access library * |
* libsf2 - C++ cross-platform SF2 format file access library * |
4 |
* * |
* * |
5 |
* Copyright (C) 2009 by Grigor Iliev <grigor@grigoriliev.com> * |
* Copyright (C) 2009-2010 by Grigor Iliev <grigor@grigoriliev.com> * |
6 |
* * |
* * |
7 |
* This library is free software; you can redistribute it and/or modify * |
* 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 * |
* it under the terms of the GNU General Public License as published by * |
28 |
#include <vector> |
#include <vector> |
29 |
|
|
30 |
|
|
31 |
#if WORDS_BIGENDIAN |
#define RIFF_ID(x) (*((uint32_t*) x)) |
|
#define ENDIAN_SWAP(x) \ |
|
|
( (x>>24) | ((x<<8) & 0x00FF0000) | ((x>>8) & 0x0000FF00) | (x<<24) ) |
|
|
#else |
|
|
#define ENDIAN_SWAP(x) (x) |
|
|
#endif |
|
32 |
|
|
|
#define RIFF_ID(x) ENDIAN_SWAP( (*((uint32_t*) x)) ) |
|
33 |
|
|
34 |
|
#define RIFF_TYPE_SF2 RIFF_ID("sfbk") |
|
#define RIFF_TYPE_SF2 RIFF_ID("sfbk") |
|
35 |
|
|
36 |
// Level 0 |
// Level 0 |
37 |
#define LIST_TYPE_INFO RIFF_ID("INFO") |
#define LIST_TYPE_SDTA RIFF_ID("sdta") |
38 |
#define LIST_TYPE_SDTA RIFF_ID("sdta") |
#define LIST_TYPE_PDTA RIFF_ID("pdta") |
|
#define LIST_TYPE_PDTA RIFF_ID("pdta") |
|
39 |
|
|
40 |
// Level 1 |
// Level 1 |
41 |
//<INFO-list> |
//<INFO-list> |
42 |
#define CHUNK_ID_IFIL RIFF_ID("ifil") |
#define CHUNK_ID_IFIL RIFF_ID("ifil") |
43 |
#define CHUNK_ID_ISNG RIFF_ID("isng") |
#define CHUNK_ID_ISNG RIFF_ID("isng") |
44 |
#define CHUNK_ID_INAM RIFF_ID("INAM") |
#define CHUNK_ID_IROM RIFF_ID("irom") |
45 |
#define CHUNK_ID_IROM RIFF_ID("irom") |
#define CHUNK_ID_IVER RIFF_ID("iver") |
|
#define CHUNK_ID_IVER RIFF_ID("iver") |
|
|
#define CHUNK_ID_ICRD RIFF_ID("ICRD") |
|
|
#define CHUNK_ID_IENG RIFF_ID("IENG") |
|
|
#define CHUNK_ID_IPRD RIFF_ID("IPRD") |
|
|
#define CHUNK_ID_ICOP RIFF_ID("ICOP") |
|
|
#define CHUNK_ID_ICMT RIFF_ID("ICMT") |
|
|
#define CHUNK_ID_ISFT RIFF_ID("ISFT") |
|
46 |
|
|
47 |
//<sdta-list> |
//<sdta-list> |
48 |
#define CHUNK_ID_SMPL RIFF_ID("smpl") |
#define CHUNK_ID_SM24 RIFF_ID("sm24") |
|
#define CHUNK_ID_SM24 RIFF_ID("sm24") |
|
49 |
|
|
50 |
//<pdta-list> |
//<pdta-list> |
51 |
#define CHUNK_ID_PHDR RIFF_ID("phdr") |
#define CHUNK_ID_PHDR RIFF_ID("phdr") |
52 |
#define CHUNK_ID_PBAG RIFF_ID("pbag") |
#define CHUNK_ID_PBAG RIFF_ID("pbag") |
53 |
#define CHUNK_ID_PMOD RIFF_ID("pmod") |
#define CHUNK_ID_PMOD RIFF_ID("pmod") |
54 |
#define CHUNK_ID_PGEN RIFF_ID("pgen") |
#define CHUNK_ID_PGEN RIFF_ID("pgen") |
55 |
#define CHUNK_ID_INST RIFF_ID("inst") |
#define CHUNK_ID_INST RIFF_ID("inst") |
56 |
#define CHUNK_ID_IBAG RIFF_ID("ibag") |
#define CHUNK_ID_IBAG RIFF_ID("ibag") |
57 |
#define CHUNK_ID_IMOD RIFF_ID("imod") |
#define CHUNK_ID_IMOD RIFF_ID("imod") |
58 |
#define CHUNK_ID_IGEN RIFF_ID("igen") |
#define CHUNK_ID_IGEN RIFF_ID("igen") |
59 |
#define CHUNK_ID_SHDR RIFF_ID("shdr") |
#define CHUNK_ID_SHDR RIFF_ID("shdr") |
|
|
|
|
#define NONE 0x1ffffff |
|
60 |
|
|
61 |
/** SoundFont specific classes and definitions */ |
/** SoundFont specific classes and definitions */ |
62 |
namespace sf2 { |
namespace sf2 { |
63 |
|
|
64 |
|
static uint NONE = 0x1ffffff; |
65 |
|
|
66 |
typedef struct _PresetBag { |
typedef struct _PresetBag { |
67 |
uint16_t GenNdx; |
uint16_t GenNdx; |
68 |
uint16_t ModNdx; |
uint16_t ModNdx; |
81 |
} ModList; |
} ModList; |
82 |
|
|
83 |
typedef struct _RangesType { |
typedef struct _RangesType { |
84 |
|
#if WORDS_BIGENDIAN |
85 |
|
uint8_t byHi; |
86 |
|
uint8_t byLo; |
87 |
|
#else |
88 |
uint8_t byLo; |
uint8_t byLo; |
89 |
uint8_t byHi; |
uint8_t byHi; |
90 |
|
#endif |
91 |
} RangesType; |
} RangesType; |
92 |
|
|
93 |
typedef union _GenAmountType { |
typedef union _GenAmountType { |
210 |
class ModulatorItem { |
class ModulatorItem { |
211 |
public: |
public: |
212 |
Modulator ModSrcOper; |
Modulator ModSrcOper; |
213 |
SFGenerator ModDestOper; |
SFGenerator ModDestOper; |
214 |
uint16_t ModAmount; |
uint16_t ModAmount; |
215 |
Modulator ModAmtSrcOper; |
Modulator ModAmtSrcOper; |
216 |
SFTransform ModTransOper; |
SFTransform ModTransOper; |
217 |
|
|
218 |
ModulatorItem(ModList& mod); |
ModulatorItem(ModList& mod); |
219 |
}; |
}; |
355 |
int startAddrsOffset, startAddrsCoarseOffset, endAddrsOffset, endAddrsCoarseOffset; |
int startAddrsOffset, startAddrsCoarseOffset, endAddrsOffset, endAddrsCoarseOffset; |
356 |
int startloopAddrsOffset, startloopAddrsCoarseOffset, endloopAddrsOffset, endloopAddrsCoarseOffset; |
int startloopAddrsOffset, startloopAddrsCoarseOffset, endloopAddrsOffset, endloopAddrsCoarseOffset; |
357 |
|
|
358 |
double EG1PreAttackDelay; |
int modEnvToPitch, modLfoToPitch, modEnvToFilterFc, modLfoToFilterFc, modLfoToVolume, freqModLfo; |
359 |
double EG1Attack; |
int delayModLfo; |
360 |
double EG1Hold; |
int vibLfoToPitch, freqVibLfo; |
361 |
double EG1Decay; |
int delayVibLfo; |
362 |
double EG1Sustain; // Sustain value of the sample amplitude EG (in permilles) |
|
363 |
double EG1Release; |
uint exclusiveClass; // exclusive group |
|
|
|
|
double EG2PreAttackDelay; |
|
|
double EG2Attack; |
|
|
double EG2Hold; |
|
|
double EG2Decay; |
|
|
double EG2Sustain; // Sustain value of the filter cutoff EG (in permilles) |
|
|
double EG2Release; |
|
364 |
|
|
365 |
Sample* pSample; |
Sample* pSample; |
366 |
bool HasLoop; |
bool HasLoop; |
374 |
|
|
375 |
int GetUnityNote(); |
int GetUnityNote(); |
376 |
|
|
377 |
|
/** |
378 |
|
* @returns The instrument to which this region belongs, or |
379 |
|
* NULL if it's preset region. |
380 |
|
*/ |
381 |
|
Instrument* GetParentInstrument() { return pParentInstrument; } |
382 |
|
|
383 |
std::vector<ModulatorItem> modulators; |
std::vector<ModulatorItem> modulators; |
384 |
|
|
385 |
|
|
386 |
|
// Instrument can be referenced by more than one presets so we need to calculate values on the fly |
387 |
|
int GetPan(Region* pPresetRegion = NULL); // -64 - +63 |
388 |
|
int GetFineTune(Region* pPresetRegion = NULL); // -99 - +99 |
389 |
|
int GetCoarseTune(Region* pPresetRegion = NULL); // -120 - +120 |
390 |
|
double GetEG1PreAttackDelay(Region* pPresetRegion = NULL); // in seconds |
391 |
|
double GetEG1Attack(Region* pPresetRegion = NULL); // in seconds |
392 |
|
double GetEG1Hold(Region* pPresetRegion = NULL); // in seconds |
393 |
|
double GetEG1Decay(Region* pPresetRegion = NULL); // in seconds |
394 |
|
double GetEG1Sustain(Region* pPresetRegion = NULL); // Sustain value of the sample amplitude EG (in permilles) |
395 |
|
double GetEG1Release(Region* pPresetRegion = NULL); // in seconds |
396 |
|
|
397 |
|
double GetEG2PreAttackDelay(Region* pPresetRegion = NULL); // in seconds |
398 |
|
double GetEG2Attack(Region* pPresetRegion = NULL); // in seconds |
399 |
|
double GetEG2Hold(Region* pPresetRegion = NULL); // in seconds |
400 |
|
double GetEG2Decay(Region* pPresetRegion = NULL); // in seconds |
401 |
|
double GetEG2Sustain(Region* pPresetRegion = NULL); // Sustain value of the filter cutoff EG (in permilles) |
402 |
|
double GetEG2Release(Region* pPresetRegion = NULL); // in seconds |
403 |
|
|
404 |
|
int GetModEnvToPitch(Region* pPresetRegion = NULL); |
405 |
|
int GetModLfoToPitch(Region* pPresetRegion = NULL); |
406 |
|
int GetModEnvToFilterFc(Region* pPresetRegion = NULL); |
407 |
|
int GetModLfoToFilterFc(Region* pPresetRegion = NULL); |
408 |
|
double GetModLfoToVolume(Region* pPresetRegion = NULL); // in permilles |
409 |
|
double GetFreqModLfo(Region* pPresetRegion = NULL); // in Hz |
410 |
|
double GetDelayModLfo(Region* pPresetRegion = NULL); // in seconds |
411 |
|
int GetVibLfoToPitch(Region* pPresetRegion = NULL); |
412 |
|
double GetFreqVibLfo(Region* pPresetRegion = NULL); // in Hz |
413 |
|
double GetDelayVibLfo(Region* pPresetRegion = NULL); // in seconds |
414 |
|
|
415 |
friend class Instrument; |
friend class Instrument; |
416 |
friend class Preset; |
friend class Preset; |
417 |
|
|
418 |
private: |
private: |
419 |
|
int EG1PreAttackDelay; // in timecents |
420 |
|
int EG1Attack; // in timecents |
421 |
|
int EG1Hold; // in timecents |
422 |
|
int EG1Decay; // in timecents |
423 |
|
int EG1Sustain; // Sustain value of the sample amplitude EG (in permilles) |
424 |
|
int EG1Release; // in timecents |
425 |
|
|
426 |
|
int EG2PreAttackDelay; // in timecents |
427 |
|
int EG2Attack; // in timecents |
428 |
|
int EG2Hold; // in timecents |
429 |
|
int EG2Decay; // in timecents |
430 |
|
int EG2Sustain; // Sustain value of the filter cutoff EG (in permilles) |
431 |
|
int EG2Release; // in timecents |
432 |
|
|
433 |
|
Instrument* pParentInstrument; |
434 |
|
|
435 |
void SetGenerator(sf2::File* pFile, GenList& Gen); |
void SetGenerator(sf2::File* pFile, GenList& Gen); |
436 |
void SetModulator(sf2::File* pFile, ModList& Mod); |
void SetModulator(sf2::File* pFile, ModList& Mod); |
437 |
}; |
}; |
446 |
|
|
447 |
sf2::File* GetFile() { return pFile; } |
sf2::File* GetFile() { return pFile; } |
448 |
String GetName() { return Name; } |
String GetName() { return Name; } |
449 |
|
|
450 |
int GetRegionCount(); |
int GetRegionCount(); |
451 |
Region* GetRegion(int idx); |
Region* GetRegion(int idx); |
452 |
|
|
465 |
void DeleteRegion(Region* pRegion); |
void DeleteRegion(Region* pRegion); |
466 |
//private: |
//private: |
467 |
uint16_t InstBagNdx; |
uint16_t InstBagNdx; |
468 |
|
|
469 |
/** |
/** |
470 |
* Load all regions (zones, bags) in the range idx1 - idx2 |
* Load all regions (zones, bags) in the range idx1 - idx2 |
471 |
*/ |
*/ |
493 |
* Load all regions (zones, bags) in the range idx1 - idx2 |
* Load all regions (zones, bags) in the range idx1 - idx2 |
494 |
*/ |
*/ |
495 |
void LoadRegions(int idx1, int idx2); |
void LoadRegions(int idx1, int idx2); |
496 |
|
|
497 |
|
Region* CreateRegion(); |
498 |
}; |
}; |
499 |
|
|
500 |
class File { |
class File { |