1 //=============================================================================
2 //  MuseScore
3 //  Linux Music Score Editor
4 //  $Id:$
5 //
6 //  Copyright (C) 2010 Werner Schweer and others
7 //
8 //  This program is free software; you can redistribute it and/or modify
9 //  it under the terms of the GNU General Public License version 2.
10 //
11 //  This program is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 //  GNU General Public License for more details.
15 //
16 //  You should have received a copy of the GNU General Public License
17 //  along with this program; if not, write to the Free Software
18 //  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 //=============================================================================
20 
21 #ifndef SFONT_H
22 #define SFONT_H
23 
24 #include <QtCore/QString>
25 #include <QtCore/QList>
26 
27 class Xml;
28 class QFile;
29 
30 namespace SfTools {
31 
32 //---------------------------------------------------------
33 //   sfVersionTag
34 //---------------------------------------------------------
35 
36 struct sfVersionTag {
37       int major;
38       int minor;
39       };
40 
41 enum Modulator {
42       };
43 enum Generator {
44       Gen_StartAddrOfs, Gen_EndAddrOfs, Gen_StartLoopAddrOfs,
45       Gen_EndLoopAddrOfs, Gen_StartAddrCoarseOfs, Gen_ModLFO2Pitch,
46       Gen_VibLFO2Pitch, Gen_ModEnv2Pitch, Gen_FilterFc, Gen_FilterQ,
47       Gen_ModLFO2FilterFc, Gen_ModEnv2FilterFc, Gen_EndAddrCoarseOfs,
48       Gen_ModLFO2Vol, Gen_Unused1, Gen_ChorusSend, Gen_ReverbSend, Gen_Pan,
49       Gen_Unused2, Gen_Unused3, Gen_Unused4,
50       Gen_ModLFODelay, Gen_ModLFOFreq, Gen_VibLFODelay, Gen_VibLFOFreq,
51       Gen_ModEnvDelay, Gen_ModEnvAttack, Gen_ModEnvHold, Gen_ModEnvDecay,
52       Gen_ModEnvSustain, Gen_ModEnvRelease, Gen_Key2ModEnvHold,
53       Gen_Key2ModEnvDecay, Gen_VolEnvDelay, Gen_VolEnvAttack,
54       Gen_VolEnvHold, Gen_VolEnvDecay, Gen_VolEnvSustain, Gen_VolEnvRelease,
55       Gen_Key2VolEnvHold, Gen_Key2VolEnvDecay, Gen_Instrument,
56       Gen_Reserved1, Gen_KeyRange, Gen_VelRange,
57       Gen_StartLoopAddrCoarseOfs, Gen_Keynum, Gen_Velocity,
58       Gen_Attenuation, Gen_Reserved2, Gen_EndLoopAddrCoarseOfs,
59       Gen_CoarseTune, Gen_FineTune, Gen_SampleId, Gen_SampleModes,
60       Gen_Reserved3, Gen_ScaleTune, Gen_ExclusiveClass, Gen_OverrideRootKey,
61       Gen_Dummy
62       };
63 
64 enum Transform { Linear };
65 
66 //---------------------------------------------------------
67 //   ModulatorList
68 //---------------------------------------------------------
69 
70 struct ModulatorList {
71       Modulator src;
72       Generator dst;
73       int amount;
74       Modulator amtSrc;
75       Transform transform;
76       };
77 
78 //---------------------------------------------------------
79 //   GeneratorList
80 //---------------------------------------------------------
81 
82 union GeneratorAmount {
83       short sword;
84       ushort uword;
85       struct {
86             uchar lo, hi;
87             };
88       };
89 
90 struct GeneratorList {
91       Generator gen;
92       GeneratorAmount amount;
93       };
94 
95 //---------------------------------------------------------
96 //   Zone
97 //---------------------------------------------------------
98 
99 struct Zone {
100       QList<GeneratorList*> generators;
101       QList<ModulatorList*> modulators;
102       int instrumentIndex;
103       };
104 
105 //---------------------------------------------------------
106 //   Preset
107 //---------------------------------------------------------
108 
109 struct Preset {
110       char* name;
111       int preset;
112       int bank;
113       int presetBagNdx; // used only for read
114       int library;
115       int genre;
116       int morphology;
117       QList<Zone*> zones;
118 
119       Preset():name(nullptr), preset(0), bank(0), presetBagNdx(0), library(0), genre(0), morphology(0) {}
120       };
121 
122 //---------------------------------------------------------
123 //   Instrument
124 //---------------------------------------------------------
125 
126 struct Instrument {
127       char* name;
128       int index;        // used only for read
129       QList<Zone*> zones;
130 
131       Instrument();
132       ~Instrument();
133       };
134 
135 //---------------------------------------------------------
136 //   Sample
137 //---------------------------------------------------------
138 
139 struct Sample {
140       char* name;
141       uint start;
142       uint end;
143       uint loopstart;
144       uint loopend;
145       uint samplerate;
146 
147       int origpitch;
148       int pitchadj;
149       int sampleLink;
150       int sampletype;
151 
152       Sample();
153       ~Sample();
154       };
155 
156 //---------------------------------------------------------
157 //   SoundFont
158 //---------------------------------------------------------
159 
160 class SoundFont {
161       QString path;
162       sfVersionTag version;
163       char* engine;
164       char* name;
165       char* date;
166       char* comment;
167       char* tools;
168       char* creator;
169       char* product;
170       char* copyright;
171       char* irom;
172       sfVersionTag iver;
173 
174       int samplePos;
175       int sampleLen;
176 
177       QList<Preset*> presets;
178       QList<Instrument*> instruments;
179 
180       QList<Zone*> pZones;
181       QList<Zone*> iZones;
182       QList<Sample*> samples;
183 
184       QFile* file;
185       FILE* f;
186 
187       bool _compress;
188       double _oggQuality;
189       double _oggAmp;
190       qint64 _oggSerial;
191 
192       // Extra option
193       bool _smallSf;
194 
195       unsigned readDword();
196       int readWord();
197       int readShort();
198       int readByte();
199       int readChar();
200       int readFourcc(const char*);
201       int readFourcc(char*);
202       void readSignature(const char* signature);
203       void readSignature(char* signature);
204       void skip(int);
205       void readSection(const char* fourcc, int len);
206       void readVersion(sfVersionTag* v);
207       char* readString(int);
208       void readPhdr(int);
209       void readBag(int, QList<Zone*>*);
210       void readMod(int, QList<Zone*>*);
211       void readGen(int, QList<Zone*>*);
212       void readInst(int);
213       void readShdr(int);
214 
215       void writeDword(int);
216       void writeWord(unsigned short int);
217       void writeByte(unsigned char);
218       void writeChar(char);
219       void writeShort(short);
220       void write(const char* p, int n);
221       void writeSample(const Sample*);
222       void writeStringSection(const char* fourcc, char* s);
223       void writePreset(int zoneIdx, const Preset*);
224       void writeModulator(const ModulatorList*);
225       void writeGenerator(const GeneratorList*);
226       void writeInstrument(int zoneIdx, const Instrument*);
227 
228       void writeIfil();
229       void writeIver();
230       void writeSmpl();
231       void writePhdr();
232       void writeBag(const char* fourcc, QList<Zone*>*);
233       void writeMod(const char* fourcc, const QList<Zone*>*);
234       void writeGen(const char* fourcc, QList<Zone*>*);
235       void writeInst();
236       void writeShdr();
237 
238       int writeCompressedSample(Sample*);
239       int writeUncompressedSample(Sample* s);
240       bool writeCSample(Sample*, int);
241       bool write();
242 
243    public:
244       SoundFont(const QString&);
245       ~SoundFont();
246       bool read();
247       bool compress(QFile* f, double oggQuality, double oggAmp, qint64 oggSerial = rand());
248       bool uncompress(QFile* f);
249       bool writeCode(QList<int>);
250       bool writeCode();
251       void dumpPresets();
252 
253 #ifndef SFTOOLS_NOXML
254     private:
255       void write(Xml&, Zone*);
256       bool writeSampleFile(Sample*, QString);
257 
258     public:
259       bool readXml(QFile*);
260       bool writeXml(QFile*);
261 #endif
262 };
263 }
264 #endif
265 
266