MuseScore/fluid/sfont.h
alexandr 923b8dbf7d fix #167161 Make Fluid and Zerberus options the same
Make unification for Zerberus and Fluid GUI
Make logic for 'up' and 'down' arrows in Zerberus

Logic of adding SF in fluid are the same as zerberus
Create Progress Bar in Fluid
2018-07-06 15:53:35 +02:00

401 lines
13 KiB
C++

/* FluidSynth - A Software Synthesizer
*
* Copyright (C) 2003 Peter Hanappe and others.
*
* SoundFont loading code borrowed from Smurf SoundFont Editor by Josh Green
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public License
* as published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307, USA
*/
#ifndef _FLUID_DEFSFONT_H
#define _FLUID_DEFSFONT_H
#include "config.h"
#include "fluid.h"
namespace FluidS {
class Preset;
class Sample;
class Instrument;
struct SFGen;
struct SFMod;
struct SFChunk;
//---------------------------------------------------------
// SFVersion
//---------------------------------------------------------
struct SFVersion { // version structure
unsigned short major, minor;
SFVersion();
};
//---------------------------------------------------------
// SFont
//---------------------------------------------------------
class SFont {
Fluid* synth;
QFile f;
unsigned samplepos; // the position in the file at which the sample data starts
unsigned samplesize; // the size of the sample data
QList<Instrument*> instruments;
QList<Preset*> presets;
QList<Sample*> sample;
int _id;
int _bankOffset;
SFVersion _version; // sound font version
SFVersion romver; // ROM version
QList<unsigned char*> infos; // list of info strings (1st byte is ID)
void read_listchunk(SFChunk* chunk);
void process_info(int size);
void process_sdta(unsigned int size);
void pdtahelper(unsigned int expid, unsigned int reclen, SFChunk* chunk, int* size);
void process_pdta(int size);
void load_phdr(int size);
void load_pbag(int size);
void load_pmod(int size);
void load_pgen(int size);
void load_ihdr(int size);
void load_ibag(int size);
void load_imod(int size);
void load_igen(int size);
void load_shdr(int size);
void fixup_pgen();
void fixup_igen();
void fixup_sample();
void readchunk(SFChunk*);
unsigned short READW();
void READD(unsigned int& var);
void FSKIP(int size) { return safe_fseek(size); }
void FSKIPW();
unsigned char READB();
char READC();
void READSTR(char*);
void safe_fread(void *buf, int count);
void safe_fseek(long ofs);
bool load();
public:
SFont(Fluid* f);
virtual ~SFont();
QString get_name() const { return f.fileName(); }
Preset* get_preset(int bank, int prenum);
bool read(const QString& file);
int load_sampledata();
unsigned int samplePos() const { return samplepos; }
int id() const { return _id; }
void setId(int i) { _id = i; }
void setSamplepos(unsigned v) { samplepos = v; }
void setSamplesize(unsigned v) { samplesize = v; }
unsigned getSamplesize() const { return samplesize; }
const QList<Preset*> getPresets() const { return presets; }
SFVersion version() const { return _version; }
int bankOffset() const { return _bankOffset; }
void setBankOffset(int val) { _bankOffset = val; }
friend class Preset;
};
//---------------------------------------------------------
// Sample
//---------------------------------------------------------
class Sample {
bool _valid;
public:
SFont* sf;
unsigned int start;
unsigned int end;
unsigned int loopstart;
unsigned int loopend;
unsigned int samplerate;
int origpitch;
int pitchadj;
int sampletype;
short* data;
/** The amplitude, that will lower the level of the sample's loop to
the noise floor. Needed for note turnoff optimization, will be
filled out automatically */
/* Set this to zero, when submitting a new sample. */
bool amplitude_that_reaches_noise_floor_is_valid;
double amplitude_that_reaches_noise_floor;
Sample(SFont*);
~Sample();
bool inRom() const;
void optimize();
void load();
bool valid() const { return _valid; }
void setValid(bool v) { _valid = v; }
#ifdef SOUNDFONT3
bool decompressOggVorbis(char* p, int size);
#endif
};
//---------------------------------------------------------
// Zone
//---------------------------------------------------------
class Zone {
public:
union {
Sample* sample;
int sampIdx;
Instrument* instrument;
int instIdx;
};
QList<SFGen*> gen;
QList<SFMod*> mod;
int keylo, keyhi, vello, velhi;
Generator genlist[GEN_LAST];
QList<Mod*> modlist; // List of modulators
public:
Zone();
~Zone();
bool importZone();
bool inside_range(int key, int vel) const;
Instrument* get_inst() const { return instrument; }
Sample* get_sample() const { return sample; }
};
//---------------------------------------------------------
// Instrument
//---------------------------------------------------------
class Instrument {
public:
Zone* global_zone;
QList<Zone*> zones;
public:
Instrument();
~Instrument();
Zone* get_global_zone() const { return global_zone; }
QList<Zone*> get_zone() { return zones; }
bool import_sfont();
};
//---------------------------------------------------------
// Preset
//---------------------------------------------------------
class Preset {
public:
QString name; // the name of the preset
SFont* sfont;
int bank; // the bank number
int num; // the preset number
Zone* _global_zone; // the global zone of the preset
QList<Zone*> zones;
public:
Preset(SFont* sfont);
~Preset();
QString get_name() const { return name; }
int get_banknum() const { return bank; }
int get_num() const { return num; }
bool noteon(Fluid*, unsigned id, int chan, int key, int vel, double nt);
void setGlobalZone(Zone* z) { _global_zone = z; }
bool importSfont();
Zone* global_zone() { return _global_zone; }
void loadSamples();
QList<Zone*> getZones() { return zones; }
};
//---------------------------------------------------------
// SFChunk
//---------------------------------------------------------
struct SFChunk { // RIFF file chunk structure
unsigned int id; // chunk id
unsigned int size; // size of the following chunk
};
struct SFMod { /* Modulator structure */
unsigned short src; /* source modulator */
unsigned short dest; /* destination generator */
signed short amount; /* signed, degree of modulation */
unsigned short amtsrc; /* second source controls amnt of first */
unsigned short trans; /* transform applied to source */
};
union SFGenAmount { /* Generator amount structure */
signed short sword; /* signed 16 bit value */
unsigned short uword; /* unsigned 16 bit value */
struct {
unsigned char lo; /* low value for ranges */
unsigned char hi; /* high value for ranges */
} range;
};
struct SFGen { /* Generator structure */
unsigned short id; /* generator ID */
SFGenAmount amount; /* generator value */
};
/* NOTE: sffd is also used to determine if sound font is new (NULL) */
/* sf file chunk IDs */
enum {
UNKN_ID, RIFF_ID, LIST_ID, SFBK_ID,
INFO_ID, SDTA_ID, PDTA_ID, /* info/sample/preset */
IFIL_ID, ISNG_ID, INAM_ID, IROM_ID, /* info ids (1st byte of info strings) */
IVER_ID, ICRD_ID, IENG_ID, IPRD_ID, /* more info ids */
ICOP_ID, ICMT_ID, ISFT_ID, /* and yet more info ids */
SNAM_ID, SMPL_ID, /* sample ids */
PHDR_ID, PBAG_ID, PMOD_ID, PGEN_ID, /* preset ids */
IHDR_ID, IBAG_ID, IMOD_ID, IGEN_ID, /* instrument ids */
SHDR_ID /* sample info */
};
/* generator types */
enum Gen_Type {
Gen_StartAddrOfs, Gen_EndAddrOfs, Gen_StartLoopAddrOfs,
Gen_EndLoopAddrOfs, Gen_StartAddrCoarseOfs, Gen_ModLFO2Pitch,
Gen_VibLFO2Pitch, Gen_ModEnv2Pitch, Gen_FilterFc, Gen_FilterQ,
Gen_ModLFO2FilterFc, Gen_ModEnv2FilterFc, Gen_EndAddrCoarseOfs,
Gen_ModLFO2Vol, Gen_Unused1, Gen_ChorusSend, Gen_ReverbSend, Gen_Pan,
Gen_Unused2, Gen_Unused3, Gen_Unused4,
Gen_ModLFODelay, Gen_ModLFOFreq, Gen_VibLFODelay, Gen_VibLFOFreq,
Gen_ModEnvDelay, Gen_ModEnvAttack, Gen_ModEnvHold, Gen_ModEnvDecay,
Gen_ModEnvSustain, Gen_ModEnvRelease, Gen_Key2ModEnvHold,
Gen_Key2ModEnvDecay, Gen_VolEnvDelay, Gen_VolEnvAttack,
Gen_VolEnvHold, Gen_VolEnvDecay, Gen_VolEnvSustain, Gen_VolEnvRelease,
Gen_Key2VolEnvHold, Gen_Key2VolEnvDecay, Gen_Instrument,
Gen_Reserved1, Gen_KeyRange, Gen_VelRange,
Gen_StartLoopAddrCoarseOfs, Gen_Keynum, Gen_Velocity,
Gen_Attenuation, Gen_Reserved2, Gen_EndLoopAddrCoarseOfs,
Gen_CoarseTune, Gen_FineTune, Gen_SampleId, Gen_SampleModes,
Gen_Reserved3, Gen_ScaleTune, Gen_ExclusiveClass, Gen_OverrideRootKey,
Gen_Dummy
};
#define Gen_MaxValid Gen_Dummy - 1 /* maximum valid generator */
/* generator unit type */
enum Gen_Unit {
None, /* No unit type */
Unit_Smpls, /* in samples */
Unit_32kSmpls, /* in 32k samples */
Unit_Cent, /* in cents (1/100th of a semitone) */
Unit_HzCent, /* in Hz Cents */
Unit_TCent, /* in Time Cents */
Unit_cB, /* in centibels (1/100th of a decibel) */
Unit_Percent, /* in percentage */
Unit_Semitone, /* in semitones */
Unit_Range /* a range of values */
};
/* global data */
#define CHNKIDSTR(id) &idlist[(id - 1) * 4]
/* sfont file chunk sizes */
#define SFPHDRSIZE 38
#define SFBAGSIZE 4
#define SFMODSIZE 10
#define SFGENSIZE 4
#define SFIHDRSIZE 22
#define SFSHDRSIZE 46
/* sfont file data structures */
struct SFPhdr {
unsigned char name[20]; /* preset name */
unsigned short preset; /* preset number */
unsigned short bank; /* bank number */
unsigned short pbagndx; /* index into preset bag */
unsigned int library; /* just for preserving them */
unsigned int genre; /* Not used */
unsigned int morphology; /* Not used */
};
struct SFBag {
unsigned short genndx; /* index into generator list */
unsigned short modndx; /* index into modulator list */
};
struct SFIhdr {
char name[20]; /* Name of instrument */
unsigned short ibagndx; /* Instrument bag index */
};
/* Basic bit swapping functions
*/
#define GUINT16_SWAP_LE_BE_CONSTANT(val) ((unsigned short) ( \
(((unsigned short) (val) & (unsigned short) 0x00ffU) << 8) | \
(((unsigned short) (val) & (unsigned short) 0xff00U) >> 8)))
#define GUINT32_SWAP_LE_BE_CONSTANT(val) ((unsigned int) ( \
(((unsigned int) (val) & (unsigned int) 0x000000ffU) << 24) | \
(((unsigned int) (val) & (unsigned int) 0x0000ff00U) << 8) | \
(((unsigned int) (val) & (unsigned int) 0x00ff0000U) >> 8) | \
(((unsigned int) (val) & (unsigned int) 0xff000000U) >> 24)))
#define GUINT16_SWAP_LE_BE(val) (GUINT16_SWAP_LE_BE_CONSTANT (val))
#define GUINT32_SWAP_LE_BE(val) (GUINT32_SWAP_LE_BE_CONSTANT (val))
#define GINT16_TO_LE(val) ((signed short) (val))
#define GUINT16_TO_LE(val) ((unsigned short) (val))
#define GINT16_TO_BE(val) ((signed short) GUINT16_SWAP_LE_BE (val))
#define GUINT16_TO_BE(val) (GUINT16_SWAP_LE_BE (val))
#define GINT32_TO_LE(val) ((signed int) (val))
#define GUINT32_TO_LE(val) ((unsigned int) (val))
#define GINT32_TO_BE(val) ((signed int) GUINT32_SWAP_LE_BE (val))
#define GUINT32_TO_BE(val) (GUINT32_SWAP_LE_BE (val))
/* The G*_TO_?E() macros are defined in glibconfig.h.
* The transformation is symmetric, so the FROM just maps to the TO.
*/
#define GINT16_FROM_LE(val) (GINT16_TO_LE (val))
#define GUINT16_FROM_LE(val) (GUINT16_TO_LE (val))
#define GINT16_FROM_BE(val) (GINT16_TO_BE (val))
#define GUINT16_FROM_BE(val) (GUINT16_TO_BE (val))
#define GINT32_FROM_LE(val) (GINT32_TO_LE (val))
#define GUINT32_FROM_LE(val) (GUINT32_TO_LE (val))
#define GINT32_FROM_BE(val) (GINT32_TO_BE (val))
#define GUINT32_FROM_BE(val) (GUINT32_TO_BE (val))
}
#endif /* _FLUID_SFONT_H */