1 #include <stdio.h>
2 #include <string.h>
3 #include <errno.h>
4 #include <math.h>
5
6 #include "doomdef.h"
7 #include "m_swap.h"
8 #include "templates.h"
9 #include "timidity.h"
10 #include "sf2.h"
11 #include "files.h"
12
13 using namespace Timidity;
14
15 #define cindex(identifier) (BYTE)(((size_t)&((SFGenComposite *)1)->identifier - 1) / 2)
16
17 class CIOErr {};
18 class CBadForm {};
19 class CBadVer {};
20
21 struct ListHandler
22 {
23 DWORD ID;
24 void (*Parser)(SFFile *sf2, FileReader *f, DWORD chunkid, DWORD chunklen);
25 };
26
27 enum
28 {
29 GENF_InstrOnly = 1, // Only valid at intstrument level
30 GENF_PresetOnly = 2, // Only valid at preset level
31 GENF_Range = 4, // Value is a range,
32 GENF_Index = 8, // Value is an index (aka unsigned)
33 GENF_32768_Ok = 16, // -32768 is a valid value
34 };
35 struct GenDef
36 {
37 short Min;
38 short Max;
39 BYTE StructIndex;
40 BYTE Flags;
41 };
42
43 static const GenDef GenDefs[] =
44 {
45 /* 0 */ { 0, 32767, cindex(startAddrsOffset), GENF_InstrOnly },
46 /* 1 */ { -32768, 0, cindex(endAddrsOffset), GENF_InstrOnly },
47 /* 2 */ { -32768, 32767, cindex(startLoopAddrsOffset), GENF_InstrOnly },
48 /* 3 */ { -32768, 32767, cindex(endLoopAddrsOffset), GENF_InstrOnly },
49 /* 4 */ { 0, 32767, cindex(startAddrsCoarseOffset), GENF_InstrOnly },
50 /* 5 */ { -12000, 12000, cindex(modLfoToPitch), 0 },
51 /* 6 */ { -12000, 12000, cindex(vibLfoToPitch), 0 },
52 /* 7 */ { -12000, 12000, cindex(modEnvToPitch), 0 },
53 /* 8 */ { 1500, 13500, cindex(initialFilterFc), 0 },
54 /* 9 */ { 0, 960, cindex(initialFilterQ), 0 },
55 /* 10 */ { -12000, 12000, cindex(modLfoToFilterFc), 0 },
56 /* 11 */ { -12000, 12000, cindex(modEnvToFilterFc), 0 },
57 /* 12 */ { -32768, 0, cindex(endAddrsCoarseOffset), 0 },
58 /* 13 */ { -960, 960, cindex(modLfoToVolume), 0 },
59 /* 14 */ { 0, 0, 255 /* unused1 */, 0 },
60 /* 15 */ { 0, 1000, cindex(chorusEffectsSend), 0 },
61 /* 16 */ { 0, 1000, cindex(reverbEffectsSend), 0 },
62 /* 17 */ { -500, 500, cindex(pan), 0 },
63 /* 18 */ { 0, 0, 255 /* unused2 */, 0 },
64 /* 19 */ { 0, 0, 255 /* unused3 */, 0 },
65 /* 20 */ { 0, 0, 255 /* unused4 */, 0 },
66 /* 21 */ { -12000, 5000, cindex(delayModLFO), GENF_32768_Ok },
67 /* 22 */ { -16000, 4500, cindex(freqModLFO), 0 },
68 /* 23 */ { -12000, 5000, cindex(delayVibLFO), GENF_32768_Ok },
69 /* 24 */ { -16000, 4500, cindex(freqVibLFO), 0 },
70 /* 25 */ { -12000, 5000, cindex(delayModEnv), GENF_32768_Ok },
71 /* 26 */ { -12000, 8000, cindex(attackModEnv), GENF_32768_Ok },
72 /* 27 */ { -12000, 5000, cindex(holdModEnv), GENF_32768_Ok },
73 /* 28 */ { -12000, 8000, cindex(decayModEnv), 0 },
74 /* 29 */ { 0, 1000, cindex(sustainModEnv), 0 },
75 /* 30 */ { -12000, 8000, cindex(releaseModEnv), 0 },
76 /* 31 */ { -1200, 1200, cindex(keynumToModEnvHold), 0 },
77 /* 32 */ { -1200, 1200, cindex(keynumToModEnvDecay), 0 },
78 /* 33 */ { -12000, 5000, cindex(delayVolEnv), GENF_32768_Ok },
79 /* 34 */ { -12000, 8000, cindex(attackVolEnv), GENF_32768_Ok },
80 /* 35 */ { -12000, 5000, cindex(holdVolEnv), GENF_32768_Ok },
81 /* 36 */ { -12000, 5000, cindex(decayVolEnv), 0 },
82 /* 37 */ { 0, 1440, cindex(sustainVolEnv), 0 },
83 /* 38 */ { -12000, 8000, cindex(releaseVolEnv), 0 },
84 /* 39 */ { -1200, 1200, cindex(keynumToVolEnvHold), 0 },
85 /* 40 */ { -1200, 1200, cindex(keynumToVolEnvDecay), 0 },
86 /* 41 */ { -32768, 32767, 255 /* instrument */, GENF_Index | GENF_PresetOnly },
87 /* 42 */ { 0, 0, 255 /* reserved1 */, 0 },
88 /* 43 */ { 0, 127, 255 /* keyRange */, GENF_Range },
89 /* 44 */ { 0, 127, 255 /* velRange */, GENF_Range },
90 /* 45 */ { -32768, 32767, cindex(startLoopAddrsCoarseOffset), GENF_InstrOnly },
91 /* 46 */ { 0, 127, cindex(keynum), GENF_InstrOnly },
92 /* 47 */ { 1, 127, cindex(velocity), GENF_InstrOnly },
93 /* 48 */ { 0, 1440, cindex(initialAttenuation), 0 },
94 /* 49 */ { 0, 0, 255 /* reserved2 */, 0 },
95 /* 50 */ { -32768, 32767, cindex(endLoopAddrsCoarseOffset), GENF_InstrOnly },
96 /* 51 */ { -120, 120, cindex(coarseTune), 0 },
97 /* 52 */ { -99, 99, cindex(fineTune), 0 },
98 /* 53 */ { -32768, 32767, 255 /* sampleID */, GENF_Index | GENF_InstrOnly },
99 /* 54 */ { -32768, 32767, cindex(sampleModes), GENF_InstrOnly },
100 /* 55 */ { 0, 0, 255 /* reserved3 */, 0 },
101 /* 56 */ { 0, 1200, cindex(scaleTuning), 0 },
102 /* 57 */ { 1, 127, cindex(exclusiveClass), GENF_InstrOnly },
103 /* 58 */ { 0, 127, cindex(overridingRootKey), GENF_InstrOnly },
104 };
105
106 static const SFGenComposite DefaultGenerators =
107 {
108 { { 0, 127 } }, // keyRange
109 { 0, 127 }, // velRange
110 { 0 }, // instrument/sampleID
111 0, // modLfoToPitch
112 0, // vibLfoToPitch
113 0, // modEnvToPitch
114 13500, // initialFilterFc
115 0, // initialFilterQ
116 0, // modLfoToFilterFc
117 0, // modEnvToFilterFc
118 0, // modLfoToVolume
119 0, // chorusEffectsSend
120 0, // reverbEffectsSend
121 0, // pan
122 -12000, // delayModLFO
123 0, // freqModLFO
124 -12000, // delayVibLFO
125 0, // freqVibLFO
126 -12000, // delayModEnv
127 -12000, // attackModEnv
128 -12000, // holdModEnv
129 -12000, // decayModEnv
130 0, // sustainModEnv
131 -12000, // releaseModEnv
132 0, // keynumToModEnvHold
133 0, // keynumToModEnvDecay
134 -12000, // delayVolEnv
135 -12000, // attackVolEnv
136 -12000, // holdVolEnv
137 -12000, // decayVolEnv
138 0, // sustainVolEnv
139 -12000, // releaseVolEnv
140 0, // keynumToVolEnvHold
141 0, // keynumToVolEnvDecay
142 0, // initialAttenuation
143 0, // coarseTune
144 0, // fineTune
145 100, // scaleTuning
146
147 0, 0, // startAddrs(Coarse)Offset
148 0, 0, // endAddrs(Coarse)Offset
149 0, 0, // startLoop(Coarse)Offset
150 0, 0, // endLoop(Coarse)Offset
151 -1, // keynum
152 -1, // velocity
153 0, // sampleModes
154 0, // exclusiveClass
155 -1 // overridingRootKey
156 };
157
158 static void ParseIfil(SFFile *sf2, FileReader *f, DWORD chunkid, DWORD chunklen);
159 static void ParseSmpl(SFFile *sf2, FileReader *f, DWORD chunkid, DWORD chunklen);
160 static void ParseSm24(SFFile *sf2, FileReader *f, DWORD chunkid, DWORD chunklen);
161 static void ParsePhdr(SFFile *sf2, FileReader *f, DWORD chunkid, DWORD chunklen);
162 static void ParseBag(SFFile *sf2, FileReader *f, DWORD chunkid, DWORD chunklen);
163 static void ParseMod(SFFile *sf2, FileReader *f, DWORD chunkid, DWORD chunklen);
164 static void ParseGen(SFFile *sf2, FileReader *f, DWORD chunkid, DWORD chunklen);
165 static void ParseInst(SFFile *sf2, FileReader *f, DWORD chunkid, DWORD chunklen);
166 static void ParseShdr(SFFile *sf2, FileReader *f, DWORD chunkid, DWORD chunklen);
167
168 ListHandler INFOHandlers[] =
169 {
170 { ID_ifil, ParseIfil },
171 { 0, 0 }
172 };
173
174 ListHandler SdtaHandlers[] =
175 {
176 { ID_smpl, ParseSmpl },
177 { ID_sm24, ParseSm24 },
178 { 0, 0 }
179 };
180
181 ListHandler PdtaHandlers[] =
182 {
183 { ID_phdr, ParsePhdr },
184 { ID_pbag, ParseBag },
185 { ID_pmod, ParseMod },
186 { ID_pgen, ParseGen },
187 { ID_inst, ParseInst },
188 { ID_ibag, ParseBag },
189 { ID_imod, ParseMod },
190 { ID_igen, ParseGen },
191 { ID_shdr, ParseShdr },
192 { 0, 0 }
193 };
194
timecent_to_sec(SWORD timecent)195 static double timecent_to_sec(SWORD timecent)
196 {
197 if (timecent == -32768)
198 return 0;
199 return pow(2.0, timecent / 1200.0);
200 }
201
to_offset(int offset)202 static SDWORD to_offset(int offset)
203 {
204 return (SDWORD)offset << (7+15);
205 }
206
calc_rate(Renderer * song,int diff,double sec)207 static SDWORD calc_rate(Renderer *song, int diff, double sec)
208 {
209 double rate;
210
211 if(sec < 0.006)
212 sec = 0.006;
213 if(diff == 0)
214 diff = 255;
215 diff <<= (7+15);
216 rate = ((double)diff / song->rate) * song->control_ratio / sec;
217 return (SDWORD)rate;
218 }
219
220
read_id(FileReader * f)221 static inline DWORD read_id(FileReader *f)
222 {
223 DWORD id;
224 if (f->Read(&id, 4) != 4)
225 {
226 throw CIOErr();
227 }
228 return id;
229 }
230
read_byte(FileReader * f)231 static inline int read_byte(FileReader *f)
232 {
233 BYTE x;
234 if (f->Read(&x, 1) != 1)
235 {
236 throw CIOErr();
237 }
238 return x;
239 }
240
read_char(FileReader * f)241 static inline int read_char(FileReader *f)
242 {
243 SBYTE x;
244 if (f->Read(&x, 1) != 1)
245 {
246 throw CIOErr();
247 }
248 return x;
249 }
250
read_uword(FileReader * f)251 static inline int read_uword(FileReader *f)
252 {
253 WORD x;
254 if (f->Read(&x, 2) != 2)
255 {
256 throw CIOErr();
257 }
258 return LittleShort(x);
259 }
260
read_sword(FileReader * f)261 static inline int read_sword(FileReader *f)
262 {
263 SWORD x;
264 if (f->Read(&x, 2) != 2)
265 {
266 throw CIOErr();
267 }
268 return LittleShort(x);
269 }
270
read_dword(FileReader * f)271 static inline DWORD read_dword(FileReader *f)
272 {
273 DWORD x;
274 if (f->Read(&x, 4) != 4)
275 {
276 throw CIOErr();
277 }
278 return LittleLong(x);
279 }
280
read_name(FileReader * f,char name[21])281 static inline void read_name(FileReader *f, char name[21])
282 {
283 if (f->Read(name, 20) != 20)
284 {
285 throw CIOErr();
286 }
287 name[20] = 0;
288 }
289
skip_chunk(FileReader * f,DWORD len)290 static inline void skip_chunk(FileReader *f, DWORD len)
291 {
292 // RIFF, like IFF, adds an extra pad byte to the end of
293 // odd-sized chunks so that new chunks are always on even
294 // byte boundaries.
295 if (f->Seek(len + (len & 1), SEEK_CUR) != 0)
296 {
297 throw CIOErr();
298 }
299 }
300
check_list(FileReader * f,DWORD id,DWORD filelen,DWORD & chunklen)301 static void check_list(FileReader *f, DWORD id, DWORD filelen, DWORD &chunklen)
302 {
303 if (read_id(f) != ID_LIST)
304 {
305 throw CBadForm();
306 }
307 chunklen = read_dword(f);
308 if (chunklen + 8 > filelen)
309 {
310 throw CBadForm();
311 }
312 if (read_id(f) != id)
313 {
314 throw CBadForm();
315 }
316 }
317
ParseIfil(SFFile * sf2,FileReader * f,DWORD chunkid,DWORD chunklen)318 static void ParseIfil(SFFile *sf2, FileReader *f, DWORD chunkid, DWORD chunklen)
319 {
320 WORD major, minor;
321
322 if (chunklen != 4)
323 {
324 throw CBadForm();
325 }
326
327 major = read_uword(f);
328 minor = read_uword(f);
329
330 if (major != 2)
331 {
332 throw CBadVer();
333 }
334 sf2->MinorVersion = minor;
335 }
336
ParseLIST(SFFile * sf2,FileReader * f,DWORD chunklen,ListHandler * handlers)337 static void ParseLIST(SFFile *sf2, FileReader *f, DWORD chunklen, ListHandler *handlers)
338 {
339 ListHandler *handler;
340 DWORD id;
341 DWORD len;
342
343 chunklen -= 4;
344 while (chunklen > 0)
345 {
346 id = read_id(f);
347 len = read_dword(f);
348
349 if (len + 8 > chunklen)
350 {
351 throw CBadForm();
352 }
353 chunklen -= len + (len & 1) + 8;
354
355 for (handler = handlers; handler->ID != 0; ++handler)
356 {
357 if (handler->ID == id && handler->Parser != NULL)
358 {
359 handler->Parser(sf2, f, id, len);
360 break;
361 }
362 }
363 if (handler->ID == 0)
364 {
365 // Skip unknown chunks
366 skip_chunk(f, len);
367 }
368 }
369 }
370
ParseINFO(SFFile * sf2,FileReader * f,DWORD chunklen)371 static void ParseINFO(SFFile *sf2, FileReader *f, DWORD chunklen)
372 {
373 sf2->MinorVersion = -1;
374
375 ParseLIST(sf2, f, chunklen, INFOHandlers);
376
377 if (sf2->MinorVersion < 0)
378 { // The ifil chunk must be present.
379 throw CBadForm();
380 }
381 }
382
ParseSdta(SFFile * sf2,FileReader * f,DWORD chunklen)383 static void ParseSdta(SFFile *sf2, FileReader *f, DWORD chunklen)
384 {
385 ParseLIST(sf2, f, chunklen, SdtaHandlers);
386 if (sf2->SampleDataOffset == 0)
387 {
388 throw CBadForm();
389 }
390 // Section 6.2, page 20: It is not clear if the extra pad byte for an
391 // odd chunk is supposed to be included in the chunk length field.
392 if (sf2->SizeSampleDataLSB != sf2->SizeSampleData &&
393 sf2->SizeSampleDataLSB != sf2->SizeSampleData + (sf2->SizeSampleData & 1))
394 {
395 sf2->SampleDataLSBOffset = 0;
396 sf2->SizeSampleDataLSB = 0;
397 }
398 }
399
ParseSmpl(SFFile * sf2,FileReader * f,DWORD chunkid,DWORD chunklen)400 static void ParseSmpl(SFFile *sf2, FileReader *f, DWORD chunkid, DWORD chunklen)
401 {
402 // Only use the first smpl chunk. (Or should we reject files with more than one?)
403 if (sf2->SampleDataOffset == 0)
404 {
405 if (chunklen & 1)
406 { // Chunk must be an even number of bytes.
407 throw CBadForm();
408 }
409 sf2->SampleDataOffset = f->Tell();
410 sf2->SizeSampleData = chunklen >> 1;
411 }
412 skip_chunk(f, chunklen);
413 }
414
ParseSm24(SFFile * sf2,FileReader * f,DWORD chunkid,DWORD chunklen)415 static void ParseSm24(SFFile *sf2, FileReader *f, DWORD chunkid, DWORD chunklen)
416 {
417 // The sm24 chunk is ignored if the file version is < 2.04
418 if (sf2->MinorVersion >= 4)
419 {
420 // Only use the first sm24 chunk. (Or should we reject files with more than one?)
421 if (sf2->SampleDataLSBOffset == 0)
422 {
423 sf2->SampleDataLSBOffset = f->Tell();
424 sf2->SizeSampleDataLSB = chunklen;
425 }
426 }
427 skip_chunk(f, chunklen);
428 }
429
ParsePdta(SFFile * sf2,FileReader * f,DWORD chunklen)430 static void ParsePdta(SFFile *sf2, FileReader *f, DWORD chunklen)
431 {
432 ParseLIST(sf2, f, chunklen, PdtaHandlers);
433 }
434
ParsePhdr(SFFile * sf2,FileReader * f,DWORD chunkid,DWORD chunklen)435 static void ParsePhdr(SFFile *sf2, FileReader *f, DWORD chunkid, DWORD chunklen)
436 {
437 SFPreset *preset;
438
439 // Section 7.2, page 22:
440 // If the PHDR sub-chunk is missing, or contains fewer than two records,
441 // or its size is not a multiple of 38 bytes, the file should be rejected
442 // as structurally unsound.
443 if (chunklen < 38*2 || chunklen % 38 != 0)
444 {
445 throw CBadForm();
446 }
447
448 sf2->NumPresets = chunklen / 38;
449 sf2->Presets = new SFPreset[sf2->NumPresets];
450 preset = sf2->Presets;
451
452 for (int i = sf2->NumPresets; i != 0; --i, ++preset)
453 {
454 read_name(f, preset->Name);
455 preset->Program = read_uword(f);
456 preset->Bank = read_uword(f);
457 preset->BagIndex = read_uword(f);
458 skip_chunk(f, 4*3); // Skip library, genre, and morphology
459
460 // Section 7.2, page 22:
461 // The preset bag indices will be monotonically increasing with
462 // increasing preset headers.
463 if (preset != sf2->Presets)
464 {
465 if (preset->BagIndex < (preset - 1)->BagIndex)
466 {
467 throw CBadForm();
468 }
469 }
470 }
471 }
472
ParseBag(SFFile * sf2,FileReader * f,DWORD chunkid,DWORD chunklen)473 static void ParseBag(SFFile *sf2, FileReader *f, DWORD chunkid, DWORD chunklen)
474 {
475 SFBag *bags, *bag;
476 WORD prev_mod = 0;
477 int numbags;
478 int i;
479
480 // Section 7.3, page 22:
481 // It is always a multiple of four bytes in length, and contains one
482 // record for each preset zone plus one record for a terminal zone. ...
483 // If the PBAG sub-chunk is missing, or its size is not a multiple of
484 // four bytes, the file should be rejected as structurally unsound.
485 // Section 7.7: IBAG is the same, but substitute "instrument" for "preset".
486 if (chunklen & 3)
487 {
488 throw CBadForm();
489 }
490
491 numbags = chunklen >> 2;
492
493 if (chunkid == ID_pbag)
494 {
495 if (numbags != sf2->Presets[sf2->NumPresets - 1].BagIndex + 1)
496 {
497 throw CBadForm();
498 }
499 sf2->PresetBags = bags = new SFBag[numbags];
500 sf2->NumPresetBags = numbags;
501 }
502 else
503 {
504 assert(chunkid == ID_ibag);
505 if (numbags != sf2->Instruments[sf2->NumInstruments - 1].BagIndex + 1)
506 {
507 throw CBadForm();
508 }
509 sf2->InstrBags = bags = new SFBag[numbags];
510 sf2->NumInstrBags = numbags;
511 }
512
513 for (bag = bags, i = numbags; i != 0; --i, ++bag)
514 {
515 bag->GenIndex = read_uword(f);
516 WORD mod = read_uword(f);
517 // Section 7.3, page 22:
518 // If the generator or modulator indices are non-monotonic or do not
519 // match the size of the respective PGEN or PMOD sub-chunks, the file
520 // is structurally defective and should be rejected at load time.
521 if (bag != bags)
522 {
523 if (bag->GenIndex < (bag - 1)->GenIndex || mod < prev_mod)
524 {
525 throw CBadForm();
526 }
527 }
528 prev_mod = mod;
529 bag->KeyRange.Lo = bag->VelRange.Lo = 0;
530 bag->KeyRange.Hi = bag->VelRange.Hi = 127;
531 bag->Target = -1;
532 }
533 }
534
ParseMod(SFFile * sf2,FileReader * f,DWORD chunkid,DWORD chunklen)535 static void ParseMod(SFFile *sf2, FileReader *f, DWORD chunkid, DWORD chunklen)
536 {
537 // Section 7.4, page 23:
538 // It [the PMOD sub-chunk] is always a multiple of ten bytes in length,
539 // and contains zero or more modulators plus a terminal record
540 if (chunklen % 10 != 0)
541 {
542 throw CBadForm();
543 }
544 // We've checked the length, now ignore the chunk.
545 skip_chunk(f, chunklen);
546 }
547
ParseGen(SFFile * sf2,FileReader * f,DWORD chunkid,DWORD chunklen)548 static void ParseGen(SFFile *sf2, FileReader *f, DWORD chunkid, DWORD chunklen)
549 {
550 SFGenList *gens, *gen;
551 int numgens;
552 int i;
553
554 // Section 7.5, page 24:
555 // If the PGEN sub-chunk is missing, or its size is not a multiple of
556 // four bytes, the file should be rejected as structurally unsound.
557 if (chunklen & 3)
558 {
559 throw CBadForm();
560 }
561 numgens = chunklen >> 2;
562
563 if (chunkid == ID_pgen)
564 {
565 // Section 7.3, page 22:
566 // the size of the PGEN sub-chunk in bytes will be equal to four
567 // times the terminal preset�s wGenNdx plus four.
568 if (numgens != sf2->PresetBags[sf2->NumPresetBags - 1].GenIndex + 1)
569 {
570 throw CBadForm();
571 }
572 sf2->PresetGenerators = gens = new SFGenList[numgens];
573 sf2->NumPresetGenerators = numgens;
574 }
575 else
576 {
577 assert(chunkid == ID_igen);
578 if (numgens != sf2->InstrBags[sf2->NumInstrBags - 1].GenIndex + 1)
579 {
580 throw CBadForm();
581 }
582 sf2->InstrGenerators = gens = new SFGenList[numgens];
583 sf2->NumInstrGenerators = numgens;
584 }
585
586 for (i = numgens, gen = gens; i != 0; --i, ++gen)
587 {
588 gen->Oper = read_uword(f);
589 gen->uAmount = read_uword(f);
590 #ifdef __BIG_ENDIAN__
591 if (gen->Oper == GEN_keyRange || gen->Oper == GEN_velRange)
592 {
593 // Reswap range generators
594 gen->uAmount = LittleShort(gen->uAmount);
595 }
596 #endif
597 }
598 }
599
ParseInst(SFFile * sf2,FileReader * f,DWORD chunkid,DWORD chunklen)600 static void ParseInst(SFFile *sf2, FileReader *f, DWORD chunkid, DWORD chunklen)
601 {
602 int i;
603 SFInst *inst;
604
605 // Section 7.6, page 25:
606 // If the INST sub-chunk is missing, contains fewer than two records, or its
607 // size is not a multiple of 22 bytes, the file should be rejected as
608 // structurally unsound.
609 if (chunklen < 22*2 || chunklen % 22 != 0)
610 {
611 throw CBadForm();
612 }
613
614 sf2->NumInstruments = chunklen / 22;
615 sf2->Instruments = inst = new SFInst[sf2->NumInstruments];
616 for (i = sf2->NumInstruments; i != 0; --i, ++inst)
617 {
618 read_name(f, inst->Name);
619 inst->BagIndex = read_uword(f);
620
621 // Section 7.6, page 25:
622 // If the instrument bag indices are non-monotonic or if the terminal
623 // instrument�s wInstBagNdx does not match the IBAG sub-chunk size, the
624 // file is structurally defective and should be rejected at load time.
625 if (inst != sf2->Instruments)
626 {
627 if (inst->BagIndex < (inst - 1)->BagIndex)
628 {
629 throw CBadForm();
630 }
631 }
632 }
633 }
634
ParseShdr(SFFile * sf2,FileReader * f,DWORD chunkid,DWORD chunklen)635 static void ParseShdr(SFFile *sf2, FileReader *f, DWORD chunkid, DWORD chunklen)
636 {
637 int i;
638 SFSample *sample;
639
640 // Section 7.10, page 29:
641 // If the SHDR sub-chunk is missing, or its is size is not a multiple of 46
642 // bytes the file should be rejected as structurally unsound.
643 if (chunklen % 46 != 0)
644 {
645 throw CBadForm();
646 }
647
648 sf2->NumSamples = chunklen / 46;
649 sf2->Samples = sample = new SFSample[sf2->NumSamples];
650 for (i = sf2->NumSamples; i != 0; --i, ++sample)
651 {
652 sample->InMemoryData = NULL;
653 read_name(f, sample->Name);
654 sample->Start = read_dword(f);
655 sample->End = read_dword(f);
656 sample->StartLoop = read_dword(f);
657 sample->EndLoop = read_dword(f);
658 sample->SampleRate = read_dword(f);
659 sample->OriginalPitch = read_byte(f);
660 sample->PitchCorrection = read_char(f);
661 sample->SampleLink = read_uword(f);
662 sample->SampleType = read_uword(f);
663
664 if (sample->SampleRate == 0)
665 {
666 // Section 7.10, page 29:
667 // A value of zero is illegal. If an illegal or impractical value is
668 // encountered, the nearest practical value should be used.
669 sample->SampleRate = 400;
670 }
671 if (sample->OriginalPitch > 127)
672 {
673 // Section 7.10, page 29:
674 // For unpitched sounds, a conventional value of 255 should be used
675 // Values between 128 and 254 are illegal. Whenever an illegal value
676 // or a value of 255 is encountered, the value 60 should be used.
677 sample->OriginalPitch = 60;
678 }
679
680 // Clamp sample positions to the available sample data.
681 sample->Start = MIN(sample->Start, sf2->SizeSampleData - 1);
682 sample->End = MIN(sample->End, sf2->SizeSampleData - 1);
683 sample->StartLoop = MIN(sample->StartLoop, sf2->SizeSampleData - 1);
684 sample->EndLoop = MIN(sample->EndLoop, sf2->SizeSampleData - 1);
685
686 if (sample->Start >= sample->End)
687 {
688 sample->SampleType |= SFST_Bad;
689 }
690 }
691 }
692
693
ReadSF2(const char * filename,FileReader * f)694 SFFile *ReadSF2(const char *filename, FileReader *f)
695 {
696 SFFile *sf2 = NULL;
697 DWORD filelen;
698 DWORD chunklen;
699
700 try
701 {
702 // Read RIFF sfbk header
703 if (read_id(f) != ID_RIFF)
704 {
705 return NULL;
706 }
707 filelen = read_dword(f);
708 if (read_id(f) != ID_sfbk)
709 {
710 return NULL;
711 }
712 filelen -= 4;
713
714 // First chunk must be an INFO LIST
715 check_list(f, ID_INFO, filelen, chunklen);
716
717 sf2 = new SFFile(filename);
718
719 ParseINFO(sf2, f, chunklen);
720 filelen -= chunklen + 8;
721
722 // Second chunk must be a sdta LIST
723 check_list(f, ID_sdta, filelen, chunklen);
724 ParseSdta(sf2, f, chunklen);
725
726 // Third chunk must be a pdta LIST
727 check_list(f, ID_pdta, filelen, chunklen);
728 ParsePdta(sf2, f, chunklen);
729
730 // There should be no more chunks. If there are, we'll just ignore them rather than reject the file.
731 if (!sf2->FinalStructureTest())
732 {
733 throw CBadForm();
734 }
735
736 sf2->CheckBags();
737 sf2->TranslatePercussions();
738
739 return sf2;
740 }
741 catch (CIOErr)
742 {
743 Printf("Error reading %s: %s\n", filename, strerror(errno));
744 }
745 catch (CBadForm)
746 {
747 Printf("%s is corrupted.\n", filename);
748 }
749 catch (CBadVer)
750 {
751 Printf("%s is not a SoundFont version 2 file.\n", filename);
752 }
753 if (sf2 != NULL)
754 {
755 delete sf2;
756 }
757 return NULL;
758 }
759
SFFile(FString filename)760 SFFile::SFFile(FString filename)
761 : FontFile(filename)
762 {
763 Presets = NULL;
764 PresetBags = NULL;
765 PresetGenerators = NULL;
766 Instruments = NULL;
767 InstrBags = NULL;
768 InstrGenerators = NULL;
769 Samples = NULL;
770 MinorVersion = 0;
771 SampleDataOffset = 0;
772 SampleDataLSBOffset = 0;
773 SizeSampleData = 0;
774 SizeSampleDataLSB = 0;
775 NumPresets = 0;
776 NumPresetBags = 0;
777 NumPresetGenerators = 0;
778 NumInstruments = 0;
779 NumInstrBags = 0;
780 NumInstrGenerators = 0;
781 NumSamples = 0;
782 }
783
~SFFile()784 SFFile::~SFFile()
785 {
786 if (Presets != NULL)
787 {
788 delete[] Presets;
789 }
790 if (PresetBags != NULL)
791 {
792 delete[] PresetBags;
793 }
794 if (PresetGenerators != NULL)
795 {
796 delete[] PresetGenerators;
797 }
798 if (Instruments != NULL)
799 {
800 delete[] Instruments;
801 }
802 if (InstrBags != NULL)
803 {
804 delete[] InstrBags;
805 }
806 if (InstrGenerators != NULL)
807 {
808 delete[] InstrGenerators;
809 }
810 if (Samples != NULL)
811 {
812 for (int i = 0; i < NumSamples; ++i)
813 {
814 if (Samples[i].InMemoryData != NULL)
815 {
816 delete[] Samples[i].InMemoryData;
817 }
818 }
819 delete[] Samples;
820 }
821 }
822
FinalStructureTest()823 bool SFFile::FinalStructureTest()
824 {
825 // All required chunks must be present.
826 if (Presets == NULL || PresetBags == NULL || PresetGenerators == NULL ||
827 Instruments == NULL || InstrBags == NULL || InstrGenerators == NULL ||
828 Samples == NULL)
829 {
830 return false;
831 }
832 // What good is it if it has no sample data?
833 if (SizeSampleData == 0)
834 {
835 return false;
836 }
837 return true;
838 }
839
SetOrder(int order,int drum,int bank,int program)840 void SFFile::SetOrder(int order, int drum, int bank, int program)
841 {
842 if (drum)
843 {
844 for (int i = 0; i < NumPresets; ++i)
845 {
846 if (Percussion[i].Generators.drumset == bank && Percussion[i].Generators.key == program)
847 {
848 Percussion[i].LoadOrder = order;
849 }
850 }
851 }
852 else
853 {
854 for (int i = 0; i < NumPresets; ++i)
855 {
856 if (Presets[i].Program == program && Presets[i].Bank == bank)
857 {
858 Presets[i].LoadOrder = order;
859 }
860 }
861 }
862 }
863
SetAllOrders(int order)864 void SFFile::SetAllOrders(int order)
865 {
866 for (int i = 0; i < NumPresets; ++i)
867 {
868 Presets[i].LoadOrder = order;
869 }
870 for (unsigned int i = 0; i < Percussion.Size(); ++i)
871 {
872 Percussion[i].LoadOrder = order;
873 }
874 }
875
LoadInstrument(Renderer * song,int drum,int bank,int program)876 Instrument *SFFile::LoadInstrument(Renderer *song, int drum, int bank, int program)
877 {
878 return LoadInstrumentOrder(song, -1, drum, bank, program);
879 }
880
LoadInstrumentOrder(Renderer * song,int order,int drum,int bank,int program)881 Instrument *SFFile::LoadInstrumentOrder(Renderer *song, int order, int drum, int bank, int program)
882 {
883 if (drum)
884 {
885 for (unsigned int i = 0; i < Percussion.Size(); ++i)
886 {
887 if ((order < 0 || Percussion[i].LoadOrder == order) &&
888 Percussion[i].Generators.drumset == bank &&
889 Percussion[i].Generators.key == program)
890 {
891 return LoadPercussion(song, &Percussion[i]);
892 }
893 }
894 }
895 else
896 {
897 for (int i = 0; i < NumPresets - 1; ++i)
898 {
899 if ((order < 0 || Presets[i].LoadOrder == order) &&
900 Presets[i].Bank == bank &&
901 Presets[i].Program == program)
902 {
903 return LoadPreset(song, &Presets[i]);
904 }
905 }
906 }
907 return NULL;
908 }
909
910 //===========================================================================
911 //
912 // SFFile :: CheckBags
913 //
914 // For all preset and instrument zones, extract the velocity and key ranges
915 // and instrument and sample targets.
916 //
917 //===========================================================================
918
CheckBags()919 void SFFile::CheckBags()
920 {
921 int i;
922
923 for (i = 0; i < NumPresets - 1; ++i)
924 {
925 if (Presets[i].BagIndex >= Presets[i + 1].BagIndex)
926 { // Preset is empty.
927 Presets[i].Bank = ~0;
928 }
929 else
930 {
931 CheckZones(Presets[i].BagIndex, Presets[i + 1].BagIndex, 0);
932 Presets[i].bHasGlobalZone = PresetBags[Presets[i].BagIndex].Target < 0;
933 }
934 }
935 for (i = 0; i < NumInstruments - 1; ++i)
936 {
937 if (Instruments[i].BagIndex >= Instruments[i + 1].BagIndex)
938 { // Instrument is empty.
939 }
940 else
941 {
942 CheckZones(Instruments[i].BagIndex, Instruments[i + 1].BagIndex, 1);
943 Instruments[i].bHasGlobalZone = InstrBags[Instruments[i].BagIndex].Target < 0;
944 }
945 }
946 }
947
948 //===========================================================================
949 //
950 // SFFile :: CheckZones
951 //
952 // For every zone in the bag, extract the velocity and key ranges and
953 // instrument and sample targets.
954 //
955 //===========================================================================
956
CheckZones(int start,int stop,bool instr)957 void SFFile::CheckZones(int start, int stop, bool instr)
958 {
959 SFBag *bag;
960 SFGenList *gens;
961 SFGenerator terminal_gen;
962 int zone_start, zone_stop;
963 int i, j;
964
965 if (!instr)
966 {
967 bag = PresetBags;
968 gens = PresetGenerators;
969 terminal_gen = GEN_instrument;
970 }
971 else
972 {
973 bag = InstrBags;
974 gens = InstrGenerators;
975 terminal_gen = GEN_sampleID;
976 }
977 for (i = start; i < stop; ++i)
978 {
979 zone_start = bag[i].GenIndex;
980 zone_stop = bag[i + 1].GenIndex;
981
982 if (zone_start > zone_stop)
983 {
984 // Skip empty zones, and mark them inaccessible.
985 bag[i].KeyRange.Lo = 255;
986 bag[i].KeyRange.Hi = 255;
987 bag[i].VelRange.Lo = 255;
988 bag[i].VelRange.Hi = 255;
989 continue;
990 }
991
992 // According to the specs, if keyRange is present, it must be the first generator.
993 // If velRange is present, it may only be preceded by keyRange. In real life, there
994 // exist Soundfonts that violate this rule, so we need to scan every generator.
995
996 // Preload ranges from the global zone.
997 if (i != start && bag[start].Target < 0)
998 {
999 bag[i].KeyRange = bag[start].KeyRange;
1000 bag[i].VelRange = bag[start].VelRange;
1001 }
1002 for (j = zone_start; j < zone_stop; ++j)
1003 {
1004 if (gens[j].Oper == GEN_keyRange)
1005 {
1006 bag[i].KeyRange = gens[j].Range;
1007 }
1008 else if (gens[j].Oper == GEN_velRange)
1009 {
1010 bag[i].VelRange = gens[j].Range;
1011 }
1012 else if (gens[j].Oper == terminal_gen)
1013 {
1014 if (terminal_gen == GEN_instrument && gens[j].uAmount < NumInstruments - 1)
1015 {
1016 bag[i].Target = gens[j].uAmount;
1017 }
1018 else if (terminal_gen == GEN_sampleID && gens[j].uAmount < NumSamples - 1)
1019 {
1020 bag[i].Target = gens[j].uAmount;
1021 }
1022 break;
1023 }
1024 }
1025 if (bag[i].Target < 0 && i != start)
1026 {
1027 // Only the first zone may be targetless. If any other zones are,
1028 // make them inaccessible.
1029 bag[i].KeyRange.Lo = 255;
1030 bag[i].KeyRange.Hi = 255;
1031 bag[i].VelRange.Lo = 255;
1032 bag[i].VelRange.Hi = 255;
1033 }
1034
1035 // Check for swapped ranges. (Should we fix them or ignore them?)
1036 if (bag[i].KeyRange.Lo > bag[i].KeyRange.Hi)
1037 {
1038 swapvalues(bag[i].KeyRange.Lo, bag[i].KeyRange.Hi);
1039 }
1040 if (bag[i].VelRange.Lo > bag[i].VelRange.Hi)
1041 {
1042 swapvalues(bag[i].VelRange.Lo, bag[i].VelRange.Hi);
1043 }
1044 }
1045 }
1046
1047 //===========================================================================
1048 //
1049 // SFFile :: TranslatePercussions
1050 //
1051 // For every percussion instrument, compile a set of composite generators
1052 // for each key, to make creating TiMidity instruments for individual
1053 // percussion parts easier.
1054 //
1055 //===========================================================================
1056
TranslatePercussions()1057 void SFFile::TranslatePercussions()
1058 {
1059 for (int i = 0; i < NumPresets - 1; ++i)
1060 {
1061 if (Presets[i].Bank == 128 && Presets[i].Program < 128)
1062 {
1063 TranslatePercussionPreset(&Presets[i]);
1064 }
1065 }
1066 }
1067
1068 //===========================================================================
1069 //
1070 // SFFile :: TranslatePercussionPreset
1071 //
1072 // Compile a set of composite generators for each key of this percussion
1073 // instrument. Note that one instrument is actually an entire drumset.
1074 //
1075 //===========================================================================
1076
TranslatePercussionPreset(SFPreset * preset)1077 void SFFile::TranslatePercussionPreset(SFPreset *preset)
1078 {
1079 SFPerc perc;
1080 int i;
1081 bool has_global;
1082
1083 perc.LoadOrder = preset->LoadOrder;
1084 i = preset->BagIndex;
1085 has_global = false;
1086
1087 for (i = preset->BagIndex; i < (preset + 1)->BagIndex; ++i)
1088 {
1089 if (PresetBags[i].Target < 0)
1090 { // This preset zone has no instrument.
1091 continue;
1092 }
1093 if (PresetBags[i].KeyRange.Lo > 127 || PresetBags[i].VelRange.Lo > 127)
1094 { // This preset zone is inaccesible.
1095 continue;
1096 }
1097 TranslatePercussionPresetZone(preset, &PresetBags[i]);
1098 }
1099 }
1100
1101 //===========================================================================
1102 //
1103 // SFFile :: TranslatePercussionPresetZone
1104 //
1105 // Create a composite generator set for all keys and velocity ranges in this
1106 // preset zone that intersect with this zone's instrument.
1107 //
1108 //===========================================================================
1109
TranslatePercussionPresetZone(SFPreset * preset,SFBag * pzone)1110 void SFFile::TranslatePercussionPresetZone(SFPreset *preset, SFBag *pzone)
1111 {
1112 int key, i;
1113
1114 for (key = pzone->KeyRange.Lo; key <= pzone->KeyRange.Hi; ++key)
1115 {
1116 SFInst *inst = &Instruments[pzone->Target];
1117 for (i = inst->BagIndex; i < (inst + 1)->BagIndex; ++i)
1118 {
1119 if (InstrBags[i].Target < 0)
1120 { // This instrument zone has no sample.
1121 continue;
1122 }
1123 if (InstrBags[i].KeyRange.Lo > key || InstrBags[i].KeyRange.Hi < key)
1124 { // This instrument zone does not contain the key we want.
1125 continue;
1126 }
1127 if (InstrBags[i].VelRange.Lo > pzone->VelRange.Hi ||
1128 InstrBags[i].VelRange.Hi < pzone->VelRange.Lo)
1129 { // This instrument zone does not intersect the current velocity range.
1130 continue;
1131 }
1132 // An intersection! Add the composite generator for this key and velocity range.
1133 SFPerc perc;
1134 perc.LoadOrder = preset->LoadOrder;
1135 perc.Preset = preset;
1136 perc.Generators = DefaultGenerators;
1137 if (inst->bHasGlobalZone)
1138 {
1139 SetInstrumentGenerators(&perc.Generators, InstrBags[inst->BagIndex].GenIndex, InstrBags[inst->BagIndex + 1].GenIndex);
1140 }
1141 SetInstrumentGenerators(&perc.Generators, InstrBags[i].GenIndex, InstrBags[i + 1].GenIndex);
1142 AddPresetGenerators(&perc.Generators, pzone->GenIndex, (pzone + 1)->GenIndex, preset);
1143 perc.Generators.drumset = (BYTE)preset->Program;
1144 perc.Generators.key = key;
1145 perc.Generators.velRange.Lo = MAX(pzone->VelRange.Lo, InstrBags[i].VelRange.Lo);
1146 perc.Generators.velRange.Hi = MIN(pzone->VelRange.Hi, InstrBags[i].VelRange.Hi);
1147 perc.Generators.sampleID = InstrBags[i].Target;
1148 Percussion.Push(perc);
1149 }
1150 }
1151 }
1152
SetInstrumentGenerators(SFGenComposite * composite,int start,int stop)1153 void SFFile::SetInstrumentGenerators(SFGenComposite *composite, int start, int stop)
1154 {
1155 // Proceed from first to last; later generators override earlier ones.
1156 SFGenList *gen = &InstrGenerators[start];
1157 for (int i = stop - start; i != 0; --i, ++gen)
1158 {
1159 if (gen->Oper >= GEN_NumGenerators)
1160 { // Unknown generator.
1161 continue;
1162 }
1163 if (GenDefs[gen->Oper].StructIndex >= sizeof(SFGenComposite)/2)
1164 { // Generator is either unused or ignored.
1165 continue;
1166 }
1167 // Set the generator
1168 ((WORD *)composite)[GenDefs[gen->Oper].StructIndex] = gen->uAmount;
1169 if (gen->Oper == GEN_sampleID)
1170 { // Anything past sampleID is ignored.
1171 break;
1172 }
1173 }
1174 }
1175
AddPresetGenerators(SFGenComposite * composite,int start,int stop,SFPreset * preset)1176 void SFFile::AddPresetGenerators(SFGenComposite *composite, int start, int stop, SFPreset *preset)
1177 {
1178 bool gen_set[GEN_NumGenerators] = { false, };
1179 AddPresetGenerators(composite, start, stop, gen_set);
1180 if (preset->bHasGlobalZone)
1181 {
1182 AddPresetGenerators(composite, PresetBags[preset->BagIndex].GenIndex, PresetBags[preset->BagIndex + 1].GenIndex, gen_set);
1183 }
1184 }
1185
AddPresetGenerators(SFGenComposite * composite,int start,int stop,bool gen_set[GEN_NumGenerators])1186 void SFFile::AddPresetGenerators(SFGenComposite *composite, int start, int stop, bool gen_set[GEN_NumGenerators])
1187 {
1188 // Proceed from last to first; later generators override earlier ones.
1189 SFGenList *gen = &PresetGenerators[stop - 1];
1190 const GenDef *def;
1191
1192 for (int i = stop - start; i != 0; --i, --gen)
1193 {
1194 if (gen->Oper >= GEN_NumGenerators)
1195 { // Unknown generator.
1196 continue;
1197 }
1198 if (gen_set[gen->Oper])
1199 { // Generator was already set.
1200 continue;
1201 }
1202 def = &GenDefs[gen->Oper];
1203 if (def->StructIndex >= sizeof(SFGenComposite)/2)
1204 { // Generator is either unused or ignored.
1205 continue;
1206 }
1207 if (def->Flags & GENF_InstrOnly)
1208 { // Generator is not valid at the preset level.
1209 continue;
1210 }
1211 // Add to instrument/default generator.
1212 int added = ((SWORD *)composite)[def->StructIndex] + gen->Amount;
1213 // Clamp to proper range.
1214 if (added <= -32768 && def->Flags & GENF_32768_Ok)
1215 {
1216 added = -32768;
1217 }
1218 else
1219 {
1220 added = clamp<int>(added, def->Min, def->Max);
1221 }
1222 ((SWORD *)composite)[def->StructIndex] = added;
1223 gen_set[gen->Oper] = true;
1224 if (gen->Oper == GEN_instrument)
1225 { // Anything past the instrument generator is ignored.
1226 break;
1227 }
1228 }
1229 }
1230
LoadPercussion(Renderer * song,SFPerc * perc)1231 Instrument *SFFile::LoadPercussion(Renderer *song, SFPerc *perc)
1232 {
1233 unsigned int i;
1234 int drumkey;
1235 int drumset;
1236 int j;
1237
1238 Instrument *ip = new Instrument;
1239 ip->samples = 0;
1240 drumkey = perc->Generators.key;
1241 drumset = perc->Generators.drumset;
1242
1243 // Count all percussion composites that match this one's key and set.
1244 for (i = 0; i < Percussion.Size(); ++i)
1245 {
1246 if (Percussion[i].Generators.key == drumkey &&
1247 Percussion[i].Generators.drumset == drumset &&
1248 Percussion[i].Generators.sampleID < NumSamples)
1249 {
1250 SFSample *sfsamp = &Samples[Percussion[i].Generators.sampleID];
1251 if (sfsamp->InMemoryData == NULL)
1252 {
1253 LoadSample(sfsamp);
1254 }
1255 if (sfsamp->InMemoryData != NULL)
1256 {
1257 ip->samples++;
1258 }
1259 }
1260 }
1261 if (ip->samples == 0)
1262 { // Nothing here to play.
1263 delete ip;
1264 return NULL;
1265 }
1266 ip->sample = (Sample *)safe_malloc(sizeof(Sample) * ip->samples);
1267 memset(ip->sample, 0, sizeof(Sample) * ip->samples);
1268
1269 // Fill in Sample structure for each composite.
1270 for (j = 0, i = 0; i < Percussion.Size(); ++i)
1271 {
1272 SFPerc *zone = &Percussion[i];
1273 SFGenComposite *gen = &zone->Generators;
1274 if (gen->key != drumkey ||
1275 gen->drumset != drumset ||
1276 gen->sampleID >= NumSamples)
1277 {
1278 continue;
1279 }
1280 SFSample *sfsamp = &Samples[gen->sampleID];
1281 if (sfsamp->InMemoryData == NULL)
1282 {
1283 continue;
1284 }
1285 Sample *sp = ip->sample + j++;
1286
1287 // Set velocity range
1288 sp->low_vel = gen->velRange.Lo;
1289 sp->high_vel = gen->velRange.Hi;
1290
1291 // Set frequency range
1292 sp->low_freq = note_to_freq(gen->key);
1293 sp->high_freq = sp->low_freq;
1294
1295 ApplyGeneratorsToRegion(gen, sfsamp, song, sp);
1296 }
1297 assert(j == ip->samples);
1298 return ip;
1299 }
1300
1301 //===========================================================================
1302 //
1303 // SFFile :: LoadPreset
1304 //
1305 //===========================================================================
1306
LoadPreset(Renderer * song,SFPreset * preset)1307 Instrument *SFFile::LoadPreset(Renderer *song, SFPreset *preset)
1308 {
1309 SFInst *inst;
1310 SFSample *sfsamp;
1311 SFGenComposite gen;
1312 int i, j, k;
1313
1314 Instrument *ip = new Instrument;
1315 ip->samples = 0;
1316
1317 // Count the number of regions we'll need.
1318 for (i = preset->BagIndex; i < (preset + 1)->BagIndex; ++i)
1319 {
1320 if (PresetBags[i].Target < 0)
1321 { // Preset zone has no instrument.
1322 continue;
1323 }
1324 inst = &Instruments[PresetBags[i].Target];
1325 for (j = inst->BagIndex; j < (inst + 1)->BagIndex; ++j)
1326 {
1327 if (InstrBags[j].Target < 0)
1328 { // Instrument zone has no sample.
1329 continue;
1330 }
1331 if (InstrBags[j].KeyRange.Lo <= PresetBags[i].KeyRange.Hi &&
1332 InstrBags[j].KeyRange.Hi >= PresetBags[i].KeyRange.Lo &&
1333 InstrBags[j].VelRange.Lo <= PresetBags[i].VelRange.Hi &&
1334 InstrBags[j].VelRange.Hi >= PresetBags[i].VelRange.Lo)
1335 { // The preset and instrument zones intersect!
1336 sfsamp = &Samples[InstrBags[j].Target];
1337 if (sfsamp->InMemoryData == NULL)
1338 {
1339 LoadSample(sfsamp);
1340 }
1341 if (sfsamp->InMemoryData != NULL)
1342 {
1343 ip->samples++;
1344 }
1345 }
1346 }
1347 }
1348 if (ip->samples == 0)
1349 { // Nothing here to play.
1350 delete ip;
1351 return NULL;
1352 }
1353 // Allocate the regions and define them
1354 ip->sample = (Sample *)safe_malloc(sizeof(Sample) * ip->samples);
1355 memset(ip->sample, 0, sizeof(Sample) * ip->samples);
1356 k = 0;
1357 for (i = preset->BagIndex; i < (preset + 1)->BagIndex; ++i)
1358 {
1359 if (PresetBags[i].Target < 0)
1360 { // Preset zone has no instrument.
1361 continue;
1362 }
1363 inst = &Instruments[PresetBags[i].Target];
1364 for (j = inst->BagIndex; j < (inst + 1)->BagIndex; ++j)
1365 {
1366 if (InstrBags[j].Target < 0)
1367 { // Instrument zone has no sample.
1368 continue;
1369 }
1370 if (InstrBags[j].KeyRange.Lo <= PresetBags[i].KeyRange.Hi &&
1371 InstrBags[j].KeyRange.Hi >= PresetBags[i].KeyRange.Lo &&
1372 InstrBags[j].VelRange.Lo <= PresetBags[i].VelRange.Hi &&
1373 InstrBags[j].VelRange.Hi >= PresetBags[i].VelRange.Lo)
1374 { // The preset and instrument zones intersect!
1375 sfsamp = &Samples[InstrBags[j].Target];
1376 if (sfsamp->InMemoryData == NULL)
1377 {
1378 continue;
1379 }
1380 Sample *sp = ip->sample + k++;
1381
1382 // Set velocity range
1383 sp->low_vel = MAX(InstrBags[j].VelRange.Lo, PresetBags[i].VelRange.Lo);
1384 sp->high_vel = MIN(InstrBags[j].VelRange.Hi, PresetBags[i].VelRange.Hi);
1385
1386 // Set frequency range
1387 sp->low_freq = note_to_freq(MAX(InstrBags[j].KeyRange.Lo, PresetBags[i].KeyRange.Lo));
1388 sp->high_freq = note_to_freq(MIN(InstrBags[j].KeyRange.Hi, PresetBags[i].KeyRange.Hi));
1389
1390 gen = DefaultGenerators;
1391 if (inst->bHasGlobalZone)
1392 {
1393 SetInstrumentGenerators(&gen, InstrBags[inst->BagIndex].GenIndex, InstrBags[inst->BagIndex + 1].GenIndex);
1394 }
1395 SetInstrumentGenerators(&gen, InstrBags[j].GenIndex, InstrBags[j + 1].GenIndex);
1396 AddPresetGenerators(&gen, PresetBags[i].GenIndex, PresetBags[i + 1].GenIndex, preset);
1397 ApplyGeneratorsToRegion(&gen, sfsamp, song, sp);
1398 }
1399 }
1400 }
1401 assert(k == ip->samples);
1402 return ip;
1403 }
1404
1405 //===========================================================================
1406 //
1407 // SFFile :: ApplyGeneratorsToRegion
1408 //
1409 // The caller must set the key and velocity ranges. Other information for
1410 // the TiMidity sample will be filled in using the generators given.
1411 //
1412 // FIXME: At least try to do something useful with every parameter.
1413 //
1414 //===========================================================================
1415
ApplyGeneratorsToRegion(SFGenComposite * gen,SFSample * sfsamp,Renderer * song,Sample * sp)1416 void SFFile::ApplyGeneratorsToRegion(SFGenComposite *gen, SFSample *sfsamp, Renderer *song, Sample *sp)
1417 {
1418 sp->type = INST_SF2;
1419
1420 // Set loop and sample points
1421 int start, end;
1422 start = gen->startAddrsOffset + gen->startAddrsCoarseOffset * 32768;
1423 end = gen->endAddrsOffset + gen->endAddrsCoarseOffset * 32768;
1424 start = MAX<int>(sfsamp->Start, sfsamp->Start + start);
1425 end = MIN<int>(sfsamp->End, sfsamp->End + end);
1426 sp->loop_start = MAX<int>(start, sfsamp->StartLoop + gen->startLoopAddrsOffset + gen->startLoopAddrsCoarseOffset * 32768);
1427 sp->loop_end = MIN<int>(end, sfsamp->EndLoop + gen->endLoopAddrsOffset + gen->endLoopAddrsCoarseOffset * 32768);
1428
1429 sp->loop_start = (sp->loop_start - start) << FRACTION_BITS;
1430 sp->loop_end = (sp->loop_end - start) << FRACTION_BITS;
1431 sp->data_length = (end - start) << FRACTION_BITS;
1432 sp->data = sfsamp->InMemoryData + start - sfsamp->Start;
1433 if (gen->overridingRootKey >= 0 && gen->overridingRootKey <= 127)
1434 {
1435 sp->scale_note = gen->overridingRootKey;
1436 }
1437 else
1438 {
1439 sp->scale_note = sfsamp->OriginalPitch;
1440 }
1441 sp->root_freq = note_to_freq(sp->scale_note);
1442 sp->sample_rate = sfsamp->SampleRate;
1443 sp->key_group = gen->exclusiveClass;
1444
1445 // Set key scaling
1446 if (gen->keynum >= 0 && gen->keynum <= 127)
1447 {
1448 sp->scale_note = gen->keynum;
1449 sp->scale_factor = 0;
1450 }
1451 else if (gen->scaleTuning >= 0)
1452 {
1453 sp->scale_factor = gen->scaleTuning * 1024 / 100;
1454 // Does the root key also serve as the scale key? Assuming it does here.
1455 }
1456 else
1457 {
1458 sp->scale_factor = 1024;
1459 sp->scale_note = 60;
1460 }
1461
1462 // Set panning
1463 sp->panning = gen->pan;
1464
1465 // Set volume envelope
1466 sp->envelope.sf2.delay_vol = gen->delayVolEnv;
1467 sp->envelope.sf2.attack_vol = gen->attackVolEnv;
1468 sp->envelope.sf2.hold_vol = gen->holdVolEnv;
1469 sp->envelope.sf2.decay_vol = gen->decayVolEnv;
1470 sp->envelope.sf2.sustain_vol = gen->sustainVolEnv;
1471 sp->envelope.sf2.release_vol = gen->releaseVolEnv;
1472
1473 // Set sample modes
1474 if (gen->sampleModes == 1)
1475 {
1476 sp->modes = PATCH_LOOPEN | PATCH_SUSTAIN | PATCH_NO_SRELEASE;
1477 }
1478 else if (gen->sampleModes == 3)
1479 {
1480 sp->modes = PATCH_LOOPEN | PATCH_SUSTAIN;
1481 }
1482 else
1483 {
1484 sp->modes = PATCH_SUSTAIN;
1485 }
1486
1487 // Set tuning (in cents)
1488 sp->tune = gen->coarseTune * 100 + gen->fineTune;
1489
1490 sp->velocity = (SBYTE)gen->velocity;
1491 sp->initial_attenuation = gen->initialAttenuation;
1492 }
1493
1494 //===========================================================================
1495 //
1496 // SFFile :: LoadSample
1497 //
1498 // Loads a sample's data and converts it from 16/24-bit to floating point.
1499 //
1500 //===========================================================================
1501
LoadSample(SFSample * sample)1502 void SFFile::LoadSample(SFSample *sample)
1503 {
1504 FileReader *fp = pathExpander.openFileReader(Filename, NULL);
1505 DWORD i;
1506
1507 if (fp == NULL)
1508 {
1509 return;
1510 }
1511 sample->InMemoryData = new float[sample->End - sample->Start + 1];
1512 fp->Seek(SampleDataOffset + sample->Start * 2, SEEK_SET);
1513 // Load 16-bit sample data.
1514 for (i = 0; i < sample->End - sample->Start; ++i)
1515 {
1516 SWORD samp;
1517 *fp >> samp;
1518 sample->InMemoryData[i] = samp / 32768.f;
1519 }
1520 if (SampleDataLSBOffset != 0)
1521 { // Load lower 8 bits of 24-bit sample data.
1522 fp->Seek(SampleDataLSBOffset + sample->Start, SEEK_SET);
1523 for (i = 0; i < sample->End - sample->Start; ++i)
1524 {
1525 BYTE samp;
1526 *fp >> samp;
1527 sample->InMemoryData[i] = ((((SDWORD(sample->InMemoryData[i] * 32768) << 8) | samp) << 8) >> 8) / 8388608.f;
1528 }
1529 }
1530 // Final 0 byte is for interpolation.
1531 sample->InMemoryData[i] = 0;
1532 delete fp;
1533 }
1534