Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/fluidsynth/src/sfloader/fluid_sffile.c
4396 views
1
/* FluidSynth - A Software Synthesizer
2
*
3
* Copyright (C) 2003 Peter Hanappe and others.
4
*
5
* SoundFont file loading code borrowed from Smurf SoundFont Editor
6
* Copyright (C) 1999-2001 Josh Green
7
*
8
* This library is free software; you can redistribute it and/or
9
* modify it under the terms of the GNU Lesser General Public License
10
* as published by the Free Software Foundation; either version 2.1 of
11
* the License, or (at your option) any later version.
12
*
13
* This library is distributed in the hope that it will be useful, but
14
* WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
* Lesser General Public License for more details.
17
*
18
* You should have received a copy of the GNU Lesser General Public
19
* License along with this library; if not, write to the Free
20
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21
* 02110-1301, USA
22
*/
23
24
25
#include "fluid_sffile.h"
26
#include "fluid_sfont.h"
27
#include "fluid_sys.h"
28
29
#if LIBSNDFILE_SUPPORT
30
#include <sndfile.h>
31
#endif
32
33
#if LIBINSTPATCH_SUPPORT
34
#include <libinstpatch/libinstpatch.h>
35
#endif
36
37
/*=================================sfload.c========================
38
Borrowed from Smurf SoundFont Editor by Josh Green
39
=================================================================*/
40
41
/* FOURCC definitions */
42
#define RIFF_FCC FLUID_FOURCC('R','I','F','F')
43
#define LIST_FCC FLUID_FOURCC('L','I','S','T')
44
#define SFBK_FCC FLUID_FOURCC('s','f','b','k')
45
#define INFO_FCC FLUID_FOURCC('I','N','F','O')
46
#define SDTA_FCC FLUID_FOURCC('s','d','t','a')
47
#define PDTA_FCC FLUID_FOURCC('p','d','t','a') /* info/sample/preset */
48
49
#define IFIL_FCC FLUID_FOURCC('i','f','i','l')
50
#define ISNG_FCC FLUID_FOURCC('i','s','n','g')
51
#define INAM_FCC FLUID_FOURCC('I','N','A','M')
52
#define IROM_FCC FLUID_FOURCC('i','r','o','m') /* info ids (1st byte of info strings) */
53
#define IVER_FCC FLUID_FOURCC('i','v','e','r')
54
#define ICRD_FCC FLUID_FOURCC('I','C','R','D')
55
#define IENG_FCC FLUID_FOURCC('I','E','N','G')
56
#define IPRD_FCC FLUID_FOURCC('I','P','R','D') /* more info ids */
57
#define ICOP_FCC FLUID_FOURCC('I','C','O','P')
58
#define ICMT_FCC FLUID_FOURCC('I','C','M','T')
59
#define ISFT_FCC FLUID_FOURCC('I','S','F','T') /* and yet more info ids */
60
61
#define SNAM_FCC FLUID_FOURCC('s','n','a','m')
62
#define SMPL_FCC FLUID_FOURCC('s','m','p','l') /* sample ids */
63
#define PHDR_FCC FLUID_FOURCC('p','h','d','r')
64
#define PBAG_FCC FLUID_FOURCC('p','b','a','g')
65
#define PMOD_FCC FLUID_FOURCC('p','m','o','d')
66
#define PGEN_FCC FLUID_FOURCC('p','g','e','n') /* preset ids */
67
#define IHDR_FCC FLUID_FOURCC('i','n','s','t')
68
#define IBAG_FCC FLUID_FOURCC('i','b','a','g')
69
#define IMOD_FCC FLUID_FOURCC('i','m','o','d')
70
#define IGEN_FCC FLUID_FOURCC('i','g','e','n') /* instrument ids */
71
#define SHDR_FCC FLUID_FOURCC('s','h','d','r') /* sample info */
72
#define SM24_FCC FLUID_FOURCC('s','m','2','4')
73
74
/* Set when the FCC code is unknown */
75
#define UNKN_ID FLUID_N_ELEMENTS(idlist)
76
77
/*
78
* This declares a uint32_t array containing the SF2 chunk identifiers.
79
*/
80
static const uint32_t idlist[] =
81
{
82
RIFF_FCC,
83
LIST_FCC,
84
SFBK_FCC,
85
INFO_FCC,
86
SDTA_FCC,
87
PDTA_FCC,
88
89
IFIL_FCC,
90
ISNG_FCC,
91
INAM_FCC,
92
IROM_FCC,
93
IVER_FCC,
94
ICRD_FCC,
95
IENG_FCC,
96
IPRD_FCC,
97
ICOP_FCC,
98
ICMT_FCC,
99
ISFT_FCC,
100
101
SNAM_FCC,
102
SMPL_FCC,
103
PHDR_FCC,
104
PBAG_FCC,
105
PMOD_FCC,
106
PGEN_FCC,
107
IHDR_FCC,
108
IBAG_FCC,
109
IMOD_FCC,
110
IGEN_FCC,
111
SHDR_FCC,
112
SM24_FCC
113
};
114
115
static const unsigned short invalid_inst_gen[] =
116
{
117
GEN_UNUSED1,
118
GEN_UNUSED2,
119
GEN_UNUSED3,
120
GEN_UNUSED4,
121
GEN_RESERVED1,
122
GEN_RESERVED2,
123
GEN_RESERVED3,
124
GEN_INSTRUMENT,
125
};
126
127
static const unsigned short invalid_preset_gen[] =
128
{
129
GEN_STARTADDROFS,
130
GEN_ENDADDROFS,
131
GEN_STARTLOOPADDROFS,
132
GEN_ENDLOOPADDROFS,
133
GEN_STARTADDRCOARSEOFS,
134
GEN_ENDADDRCOARSEOFS,
135
GEN_STARTLOOPADDRCOARSEOFS,
136
GEN_KEYNUM,
137
GEN_VELOCITY,
138
GEN_ENDLOOPADDRCOARSEOFS,
139
GEN_SAMPLEMODE,
140
GEN_EXCLUSIVECLASS,
141
GEN_OVERRIDEROOTKEY,
142
GEN_SAMPLEID,
143
};
144
145
146
/* sfont file chunk sizes */
147
#define SF_PHDR_SIZE (38)
148
#define SF_BAG_SIZE (4)
149
#define SF_MOD_SIZE (10)
150
#define SF_GEN_SIZE (4)
151
#define SF_IHDR_SIZE (22)
152
#define SF_SHDR_SIZE (46)
153
154
155
#define READCHUNK(sf, var) \
156
do \
157
{ \
158
if (sf->fcbs->fread(var, 8, sf->sffd) == FLUID_FAILED) \
159
return FALSE; \
160
((SFChunk *)(var))->size = FLUID_LE32TOH(((SFChunk *)(var))->size); \
161
} while (0)
162
163
#define READD(sf, var) \
164
do \
165
{ \
166
uint32_t _temp; \
167
if (sf->fcbs->fread(&_temp, 4, sf->sffd) == FLUID_FAILED) \
168
return FALSE; \
169
var = FLUID_LE32TOH(_temp); \
170
} while (0)
171
172
#define READW(sf, var) \
173
do \
174
{ \
175
uint16_t _temp; \
176
if (sf->fcbs->fread(&_temp, 2, sf->sffd) == FLUID_FAILED) \
177
return FALSE; \
178
var = FLUID_LE16TOH(_temp); \
179
} while (0)
180
181
#define READID(sf, var) \
182
do \
183
{ \
184
if (sf->fcbs->fread(var, 4, sf->sffd) == FLUID_FAILED) \
185
return FALSE; \
186
} while (0)
187
188
#define READSTR(sf, var) \
189
do \
190
{ \
191
if (sf->fcbs->fread(var, 20, sf->sffd) == FLUID_FAILED) \
192
return FALSE; \
193
(*var)[20] = '\0'; \
194
} while (0)
195
196
#define READB(sf, var) \
197
do \
198
{ \
199
if (sf->fcbs->fread(&var, 1, sf->sffd) == FLUID_FAILED) \
200
return FALSE; \
201
} while (0)
202
203
#define FSKIP(sf, size) \
204
do \
205
{ \
206
if (sf->fcbs->fseek(sf->sffd, size, SEEK_CUR) == FLUID_FAILED) \
207
return FALSE; \
208
} while (0)
209
210
#define FSKIPW(sf) \
211
do \
212
{ \
213
if (sf->fcbs->fseek(sf->sffd, 2, SEEK_CUR) == FLUID_FAILED) \
214
return FALSE; \
215
} while (0)
216
217
/* removes and advances a fluid_list_t pointer */
218
#define SLADVREM(list, item) \
219
do \
220
{ \
221
fluid_list_t *_temp = item; \
222
item = fluid_list_next(item); \
223
list = fluid_list_remove_link(list, _temp); \
224
delete1_fluid_list(_temp); \
225
} while (0)
226
227
228
static int load_header(SFData *sf);
229
static int load_body(SFData *sf);
230
static int process_info(SFData *sf, int size);
231
static int process_sdta(SFData *sf, unsigned int size);
232
static int process_pdta(SFData *sf, int size);
233
static int load_phdr(SFData *sf, unsigned int size);
234
static int load_pbag(SFData *sf, int size);
235
static int load_pmod(SFData *sf, int size);
236
static int load_ihdr(SFData *sf, unsigned int size);
237
static int load_ibag(SFData *sf, int size);
238
static int load_imod(SFData *sf, int size);
239
static int load_shdr(SFData *sf, unsigned int size);
240
241
static int chunkid(uint32_t id);
242
static int read_listchunk(SFData *sf, SFChunk *chunk);
243
static int pdtahelper(SFData *sf, unsigned int expid, unsigned int reclen, SFChunk *chunk, int *size);
244
static int preset_compare_func(const void *a, const void *b);
245
static fluid_list_t *find_gen_by_id(int gen, fluid_list_t *genlist);
246
static int valid_inst_genid(unsigned short genid);
247
static int valid_preset_genid(unsigned short genid);
248
249
static int fluid_sffile_read_vorbis(SFData *sf, unsigned int start_byte, unsigned int end_byte, short **data);
250
static int fluid_sffile_read_wav(SFData *sf, unsigned int start, unsigned int end, short **data, char **data24);
251
252
/**
253
* Check if a file is a SoundFont file.
254
*
255
* @param filename Path to the file to check
256
* @return TRUE if it could be a SF2, SF3 or DLS file, FALSE otherwise
257
*
258
* If fluidsynth was built with DLS support, this function will also identify DLS files.
259
*
260
* @note This function only checks whether header(s) in the RIFF chunk are present.
261
* A call to fluid_synth_sfload() might still fail.
262
*/
263
int fluid_is_soundfont(const char *filename)
264
{
265
FILE *fp;
266
uint32_t fcc;
267
int retcode = FALSE;
268
const char* err_msg;
269
270
do
271
{
272
if((fp = fluid_file_open(filename, &err_msg)) == NULL)
273
{
274
FLUID_LOG(FLUID_ERR, "fluid_is_soundfont(): fopen() failed: '%s'", err_msg);
275
return retcode;
276
}
277
278
if(FLUID_FREAD(&fcc, sizeof(fcc), 1, fp) != 1)
279
{
280
FLUID_LOG(FLUID_ERR, "fluid_is_soundfont(): failed to read RIFF chunk id.");
281
break;
282
}
283
284
if(fcc != RIFF_FCC)
285
{
286
FLUID_LOG(FLUID_ERR, "fluid_is_soundfont(): expected RIFF chunk id '0x%04X' but got '0x%04X'.", (unsigned int) RIFF_FCC, (unsigned int)fcc);
287
break;
288
}
289
290
if(FLUID_FSEEK(fp, 4, SEEK_CUR))
291
{
292
FLUID_LOG(FLUID_ERR, "fluid_is_soundfont(): cannot seek +4 bytes.");
293
break;
294
}
295
296
if(FLUID_FREAD(&fcc, sizeof(fcc), 1, fp) != 1)
297
{
298
FLUID_LOG(FLUID_ERR, "fluid_is_soundfont(): failed to read SFBK chunk id.");
299
break;
300
}
301
302
retcode = (fcc == SFBK_FCC);
303
if(retcode)
304
{
305
break; // seems to be SF2, stop here
306
}
307
#ifdef LIBINSTPATCH_SUPPORT
308
else
309
{
310
IpatchFileHandle *fhandle = ipatch_file_identify_open(filename, NULL);
311
if(fhandle != NULL)
312
{
313
retcode = (ipatch_file_identify(fhandle->file, NULL) == IPATCH_TYPE_DLS_FILE);
314
ipatch_file_close(fhandle);
315
}
316
}
317
#endif
318
}
319
while(0);
320
321
FLUID_FCLOSE(fp);
322
323
return retcode;
324
}
325
326
/*
327
* Open a SoundFont file and parse it's contents into a SFData structure.
328
*
329
* @param fname filename
330
* @param fcbs file callback structure
331
* @return the partially parsed SoundFont as SFData structure or NULL on error
332
*/
333
SFData *fluid_sffile_open(const char *fname, const fluid_file_callbacks_t *fcbs)
334
{
335
SFData *sf;
336
fluid_long_long_t fsize = 0;
337
338
if(!(sf = FLUID_NEW(SFData)))
339
{
340
FLUID_LOG(FLUID_ERR, "Out of memory");
341
return NULL;
342
}
343
344
FLUID_MEMSET(sf, 0, sizeof(SFData));
345
346
fluid_rec_mutex_init(sf->mtx);
347
sf->fcbs = fcbs;
348
349
if((sf->sffd = fcbs->fopen(fname)) == NULL)
350
{
351
FLUID_LOG(FLUID_ERR, "Unable to open file '%s'", fname);
352
goto error_exit;
353
}
354
355
sf->fname = FLUID_STRDUP(fname);
356
357
if(sf->fname == NULL)
358
{
359
FLUID_LOG(FLUID_ERR, "Out of memory");
360
goto error_exit;
361
}
362
363
/* get size of file by seeking to end */
364
if(fcbs->fseek(sf->sffd, 0L, SEEK_END) == FLUID_FAILED)
365
{
366
FLUID_LOG(FLUID_ERR, "Seek to end of file failed");
367
goto error_exit;
368
}
369
370
if((fsize = fcbs->ftell(sf->sffd)) == FLUID_FAILED)
371
{
372
FLUID_LOG(FLUID_ERR, "Get end of file position failed");
373
goto error_exit;
374
}
375
376
sf->filesize = fsize;
377
378
if(fcbs->fseek(sf->sffd, 0, SEEK_SET) == FLUID_FAILED)
379
{
380
FLUID_LOG(FLUID_ERR, "Rewind to start of file failed");
381
goto error_exit;
382
}
383
384
if(!load_header(sf))
385
{
386
goto error_exit;
387
}
388
389
return sf;
390
391
error_exit:
392
fluid_sffile_close(sf);
393
return NULL;
394
}
395
396
/*
397
* Parse all preset information from the soundfont
398
*
399
* @return FLUID_OK on success, otherwise FLUID_FAILED
400
*/
401
int fluid_sffile_parse_presets(SFData *sf)
402
{
403
if(!load_body(sf))
404
{
405
return FLUID_FAILED;
406
}
407
408
return FLUID_OK;
409
}
410
411
/* Load sample data from the soundfont file
412
*
413
* This function will always return the sample data in WAV format. If the sample_type specifies an
414
* Ogg Vorbis compressed sample, it will be decompressed automatically before returning.
415
*
416
* @param sf SFData instance
417
* @param sample_start index of first sample point in Soundfont sample chunk
418
* @param sample_end index of last sample point in Soundfont sample chunk
419
* @param sample_type type of the sample in Soundfont
420
* @param data pointer to sample data pointer, will point to loaded sample data on success
421
* @param data24 pointer to 24-bit sample data pointer if 24-bit data present, will point to loaded
422
* 24-bit sample data on success or NULL if no 24-bit data is present in file
423
*
424
* @return The number of sample words in returned buffers or -1 on failure
425
*/
426
int fluid_sffile_read_sample_data(SFData *sf, unsigned int sample_start, unsigned int sample_end,
427
int sample_type, short **data, char **data24)
428
{
429
int num_samples;
430
431
if(sample_type & FLUID_SAMPLETYPE_OGG_VORBIS)
432
{
433
num_samples = fluid_sffile_read_vorbis(sf, sample_start, sample_end, data);
434
}
435
else
436
{
437
num_samples = fluid_sffile_read_wav(sf, sample_start, sample_end, data, data24);
438
}
439
440
return num_samples;
441
}
442
443
/*
444
* Close a SoundFont file and free the SFData structure.
445
*
446
* @param sf pointer to SFData structure
447
* @param fcbs file callback structure
448
*/
449
void fluid_sffile_close(SFData *sf)
450
{
451
fluid_list_t *entry;
452
SFPreset *preset;
453
SFInst *inst;
454
455
fluid_rec_mutex_destroy(sf->mtx);
456
if(sf->sffd)
457
{
458
sf->fcbs->fclose(sf->sffd);
459
}
460
461
FLUID_FREE(sf->fname);
462
463
entry = sf->info;
464
465
while(entry)
466
{
467
FLUID_FREE(fluid_list_get(entry));
468
entry = fluid_list_next(entry);
469
}
470
471
delete_fluid_list(sf->info);
472
473
entry = sf->preset;
474
475
while(entry)
476
{
477
preset = (SFPreset *)fluid_list_get(entry);
478
delete_preset(preset);
479
entry = fluid_list_next(entry);
480
}
481
482
delete_fluid_list(sf->preset);
483
484
entry = sf->inst;
485
486
while(entry)
487
{
488
inst = (SFInst *)fluid_list_get(entry);
489
delete_inst(inst);
490
entry = fluid_list_next(entry);
491
}
492
493
delete_fluid_list(sf->inst);
494
495
entry = sf->sample;
496
497
while(entry)
498
{
499
FLUID_FREE(fluid_list_get(entry));
500
entry = fluid_list_next(entry);
501
}
502
503
delete_fluid_list(sf->sample);
504
505
FLUID_FREE(sf);
506
}
507
508
509
/*
510
* Private functions
511
*/
512
513
/* sound font file load functions */
514
static int chunkid(uint32_t id)
515
{
516
unsigned int i;
517
518
for(i = 0; i < FLUID_N_ELEMENTS(idlist); i++)
519
{
520
if(idlist[i] == id)
521
{
522
break;
523
}
524
}
525
526
/* Return chunk id or UNKN_ID if not found */
527
return i;
528
}
529
530
static int load_header(SFData *sf)
531
{
532
SFChunk chunk;
533
534
READCHUNK(sf, &chunk); /* load RIFF chunk */
535
536
if(chunk.id != RIFF_FCC)
537
{
538
/* error if not RIFF */
539
FLUID_LOG(FLUID_ERR, "Not a RIFF file");
540
return FALSE;
541
}
542
543
READID(sf, &chunk.id); /* load file ID */
544
545
if(chunk.id != SFBK_FCC)
546
{
547
/* error if not SFBK_ID */
548
FLUID_LOG(FLUID_ERR, "Not a SoundFont file");
549
return FALSE;
550
}
551
552
if(chunk.size != sf->filesize - 8)
553
{
554
FLUID_LOG(FLUID_ERR, "SoundFont file size mismatch");
555
return FALSE;
556
}
557
558
/* Process INFO block */
559
if(!read_listchunk(sf, &chunk))
560
{
561
return FALSE;
562
}
563
564
if(chunk.id != INFO_FCC)
565
{
566
FLUID_LOG(FLUID_ERR, "Invalid ID found when expecting INFO chunk");
567
return FALSE;
568
}
569
570
if(!process_info(sf, chunk.size))
571
{
572
return FALSE;
573
}
574
575
/* Process sample chunk */
576
if(!read_listchunk(sf, &chunk))
577
{
578
return FALSE;
579
}
580
581
if(chunk.id != SDTA_FCC)
582
{
583
FLUID_LOG(FLUID_ERR, "Invalid ID found when expecting SAMPLE chunk");
584
return FALSE;
585
}
586
587
if(!process_sdta(sf, chunk.size))
588
{
589
return FALSE;
590
}
591
592
/* process HYDRA chunk */
593
if(!read_listchunk(sf, &chunk))
594
{
595
return FALSE;
596
}
597
598
if(chunk.id != PDTA_FCC)
599
{
600
FLUID_LOG(FLUID_ERR, "Invalid ID found when expecting HYDRA chunk");
601
return FALSE;
602
}
603
604
sf->hydrapos = sf->fcbs->ftell(sf->sffd);
605
sf->hydrasize = chunk.size;
606
607
return TRUE;
608
}
609
610
static int load_body(SFData *sf)
611
{
612
if(sf->fcbs->fseek(sf->sffd, sf->hydrapos, SEEK_SET) == FLUID_FAILED)
613
{
614
FLUID_LOG(FLUID_ERR, "Failed to seek to HYDRA position");
615
return FALSE;
616
}
617
618
if(!process_pdta(sf, sf->hydrasize))
619
{
620
return FALSE;
621
}
622
623
/* sort preset list by bank, preset # */
624
sf->preset = fluid_list_sort(sf->preset, preset_compare_func);
625
626
return TRUE;
627
}
628
629
static int read_listchunk(SFData *sf, SFChunk *chunk)
630
{
631
READCHUNK(sf, chunk); /* read list chunk */
632
633
if(chunk->id != LIST_FCC) /* error if ! list chunk */
634
{
635
FLUID_LOG(FLUID_ERR, "Invalid chunk id in level 0 parse");
636
return FALSE;
637
}
638
639
READID(sf, &chunk->id); /* read id string */
640
chunk->size -= 4;
641
return TRUE;
642
}
643
644
static int process_info(SFData *sf, int size)
645
{
646
SFChunk chunk;
647
union
648
{
649
char *chr;
650
uint32_t *fcc;
651
} item;
652
unsigned short ver;
653
654
while(size > 0)
655
{
656
READCHUNK(sf, &chunk);
657
size -= 8;
658
659
if(chunk.id == IFIL_FCC)
660
{
661
/* sound font version chunk? */
662
if(chunk.size != 4)
663
{
664
FLUID_LOG(FLUID_ERR, "Sound font version info chunk has invalid size");
665
return FALSE;
666
}
667
668
READW(sf, ver);
669
sf->version.major = ver;
670
READW(sf, ver);
671
sf->version.minor = ver;
672
673
if(sf->version.major < 2)
674
{
675
FLUID_LOG(FLUID_ERR, "Sound font version is %d.%d which is not"
676
" supported, convert to version 2.0x",
677
sf->version.major, sf->version.minor);
678
return FALSE;
679
}
680
681
if(sf->version.major == 3)
682
{
683
#if !LIBSNDFILE_SUPPORT
684
FLUID_LOG(FLUID_WARN,
685
"Sound font version is %d.%d but fluidsynth was compiled without"
686
" support for (v3.x)",
687
sf->version.major, sf->version.minor);
688
return FALSE;
689
#endif
690
}
691
else if(sf->version.major > 2)
692
{
693
FLUID_LOG(FLUID_WARN,
694
"Sound font version is %d.%d which is newer than"
695
" what this version of fluidsynth was designed for (v2.0x)",
696
sf->version.major, sf->version.minor);
697
return FALSE;
698
}
699
}
700
else if(chunk.id == IVER_FCC)
701
{
702
/* ROM version chunk? */
703
if(chunk.size != 4)
704
{
705
FLUID_LOG(FLUID_ERR, "ROM version info chunk has invalid size");
706
return FALSE;
707
}
708
709
READW(sf, ver);
710
sf->romver.major = ver;
711
READW(sf, ver);
712
sf->romver.minor = ver;
713
}
714
else if(chunkid(chunk.id) != UNKN_ID)
715
{
716
if((chunk.id != ICMT_FCC && chunk.size > 256) || (chunk.size > 65536) || (chunk.size % 2))
717
{
718
FLUID_LOG(FLUID_ERR, "INFO sub chunk %.4s has invalid chunk size of %d bytes",
719
(char*)&chunk.id, chunk.size);
720
return FALSE;
721
}
722
723
/* alloc for chunk fcc and da chunk */
724
if(!(item.fcc = FLUID_MALLOC(chunk.size + sizeof(uint32_t) + 1)))
725
{
726
FLUID_LOG(FLUID_ERR, "Out of memory");
727
return FALSE;
728
}
729
730
/* attach to INFO list, fluid_sffile_close will cleanup if FAIL occurs */
731
sf->info = fluid_list_append(sf->info, item.fcc);
732
733
/* save chunk fcc and update pointer to data value */
734
*item.fcc++ = chunk.id;
735
736
if(sf->fcbs->fread(item.chr, chunk.size, sf->sffd) == FLUID_FAILED)
737
{
738
return FALSE;
739
}
740
741
/* force terminate info item */
742
item.chr[chunk.size] = '\0';
743
}
744
else
745
{
746
FLUID_LOG(FLUID_ERR, "Invalid chunk id in INFO chunk");
747
return FALSE;
748
}
749
750
size -= chunk.size;
751
}
752
753
if(size < 0)
754
{
755
FLUID_LOG(FLUID_ERR, "INFO chunk size mismatch");
756
return FALSE;
757
}
758
759
return TRUE;
760
}
761
762
static int process_sdta(SFData *sf, unsigned int size)
763
{
764
SFChunk chunk;
765
766
if(size == 0)
767
{
768
return TRUE; /* no sample data? */
769
}
770
771
/* read sub chunk */
772
READCHUNK(sf, &chunk);
773
size -= 8;
774
775
if(chunk.id != SMPL_FCC)
776
{
777
FLUID_LOG(FLUID_ERR, "Expected SMPL chunk found invalid id instead");
778
return FALSE;
779
}
780
781
/* SDTA chunk may also contain sm24 chunk for 24 bit samples
782
* (not yet supported), only an error if SMPL chunk size is
783
* greater than SDTA. */
784
if(chunk.size > size)
785
{
786
FLUID_LOG(FLUID_ERR, "SDTA chunk size mismatch");
787
return FALSE;
788
}
789
790
/* sample data follows */
791
sf->samplepos = sf->fcbs->ftell(sf->sffd);
792
793
/* used to check validity of sample headers */
794
sf->samplesize = chunk.size;
795
796
FSKIP(sf, chunk.size);
797
size -= chunk.size;
798
799
if(sf->version.major >= 2 && sf->version.minor >= 4)
800
{
801
/* any chance to find another chunk here? */
802
if(size > 8)
803
{
804
/* read sub chunk */
805
READCHUNK(sf, &chunk);
806
size -= 8;
807
808
if(chunk.id == SM24_FCC)
809
{
810
int sm24size, sdtahalfsize;
811
812
FLUID_LOG(FLUID_DBG, "Found SM24 chunk");
813
814
if(chunk.size > size)
815
{
816
FLUID_LOG(FLUID_WARN, "SM24 exceeds SDTA chunk, ignoring SM24");
817
goto ret; // no error
818
}
819
820
sdtahalfsize = sf->samplesize / 2;
821
/* + 1 byte in the case that half the size of smpl chunk is an odd value */
822
sdtahalfsize += sdtahalfsize % 2;
823
sm24size = chunk.size;
824
825
if(sdtahalfsize != sm24size)
826
{
827
FLUID_LOG(FLUID_WARN, "SM24 not equal to half the size of SMPL chunk (0x%X != "
828
"0x%X), ignoring SM24",
829
sm24size, sdtahalfsize);
830
goto ret; // no error
831
}
832
833
/* sample data24 follows */
834
sf->sample24pos = sf->fcbs->ftell(sf->sffd);
835
sf->sample24size = sm24size;
836
}
837
}
838
}
839
840
ret:
841
FSKIP(sf, size);
842
843
return TRUE;
844
}
845
846
static int pdtahelper(SFData *sf, unsigned int expid, unsigned int reclen, SFChunk *chunk, int *size)
847
{
848
READCHUNK(sf, chunk);
849
*size -= 8;
850
851
if(chunk->id != expid)
852
{
853
FLUID_LOG(FLUID_ERR, "Expected PDTA sub-chunk '%.4s' found invalid id instead", (char*)&expid);
854
return FALSE;
855
}
856
857
if(chunk->size % reclen) /* valid chunk size? */
858
{
859
FLUID_LOG(FLUID_ERR, "'%.4s' chunk size is not a multiple of %d bytes", (char*)&expid, reclen);
860
return FALSE;
861
}
862
863
if((*size -= chunk->size) < 0)
864
{
865
FLUID_LOG(FLUID_ERR, "'%.4s' chunk size exceeds remaining PDTA chunk size", (char*)&expid);
866
return FALSE;
867
}
868
869
return TRUE;
870
}
871
872
static int process_pdta(SFData *sf, int size)
873
{
874
SFChunk chunk;
875
876
if(!pdtahelper(sf, PHDR_FCC, SF_PHDR_SIZE, &chunk, &size))
877
{
878
return FALSE;
879
}
880
881
if(!load_phdr(sf, chunk.size))
882
{
883
return FALSE;
884
}
885
886
if(!pdtahelper(sf, PBAG_FCC, SF_BAG_SIZE, &chunk, &size))
887
{
888
return FALSE;
889
}
890
891
if(!load_pbag(sf, chunk.size))
892
{
893
return FALSE;
894
}
895
896
if(!pdtahelper(sf, PMOD_FCC, SF_MOD_SIZE, &chunk, &size))
897
{
898
return FALSE;
899
}
900
901
if(!load_pmod(sf, chunk.size))
902
{
903
return FALSE;
904
}
905
906
if(!pdtahelper(sf, PGEN_FCC, SF_GEN_SIZE, &chunk, &size))
907
{
908
return FALSE;
909
}
910
911
if(!load_pgen(sf, chunk.size))
912
{
913
return FALSE;
914
}
915
916
if(!pdtahelper(sf, IHDR_FCC, SF_IHDR_SIZE, &chunk, &size))
917
{
918
return FALSE;
919
}
920
921
if(!load_ihdr(sf, chunk.size))
922
{
923
return FALSE;
924
}
925
926
if(!pdtahelper(sf, IBAG_FCC, SF_BAG_SIZE, &chunk, &size))
927
{
928
return FALSE;
929
}
930
931
if(!load_ibag(sf, chunk.size))
932
{
933
return FALSE;
934
}
935
936
if(!pdtahelper(sf, IMOD_FCC, SF_MOD_SIZE, &chunk, &size))
937
{
938
return FALSE;
939
}
940
941
if(!load_imod(sf, chunk.size))
942
{
943
return FALSE;
944
}
945
946
if(!pdtahelper(sf, IGEN_FCC, SF_GEN_SIZE, &chunk, &size))
947
{
948
return FALSE;
949
}
950
951
if(!load_igen(sf, chunk.size))
952
{
953
return FALSE;
954
}
955
956
if(!pdtahelper(sf, SHDR_FCC, SF_SHDR_SIZE, &chunk, &size))
957
{
958
return FALSE;
959
}
960
961
if(!load_shdr(sf, chunk.size))
962
{
963
return FALSE;
964
}
965
966
return TRUE;
967
}
968
969
/* preset header loader */
970
static int load_phdr(SFData *sf, unsigned int size)
971
{
972
unsigned int i;
973
int i2;
974
SFPreset *preset, *prev_preset = NULL;
975
unsigned short pbag_idx, prev_pbag_idx = 0;
976
977
if(size % SF_PHDR_SIZE || size == 0)
978
{
979
FLUID_LOG(FLUID_ERR, "Preset header chunk size is invalid");
980
return FALSE;
981
}
982
983
i = size / SF_PHDR_SIZE - 1;
984
985
if(i == 0)
986
{
987
/* at least one preset + term record */
988
FLUID_LOG(FLUID_WARN, "File contains no presets");
989
FSKIP(sf, SF_PHDR_SIZE);
990
return TRUE;
991
}
992
993
for(; i > 0; i--)
994
{
995
/* load all preset headers */
996
if((preset = FLUID_NEW(SFPreset)) == NULL)
997
{
998
FLUID_LOG(FLUID_ERR, "Out of memory");
999
return FALSE;
1000
}
1001
1002
sf->preset = fluid_list_append(sf->preset, preset);
1003
preset->zone = NULL; /* In case of failure, fluid_sffile_close can cleanup */
1004
READSTR(sf, &preset->name); /* possible read failure ^ */
1005
READW(sf, preset->prenum);
1006
READW(sf, preset->bank);
1007
READW(sf, pbag_idx);
1008
FSKIP(sf, 4); /* library ignored */
1009
FSKIP(sf, 4); /* genre ignored */
1010
FSKIP(sf, 4); /* morphology ignored */
1011
1012
if(prev_preset)
1013
{
1014
/* not first preset? */
1015
if(pbag_idx < prev_pbag_idx)
1016
{
1017
FLUID_LOG(FLUID_ERR, "Preset header indices not monotonic");
1018
return FALSE;
1019
}
1020
1021
i2 = pbag_idx - prev_pbag_idx;
1022
1023
while(i2--)
1024
{
1025
prev_preset->zone = fluid_list_prepend(prev_preset->zone, NULL);
1026
}
1027
}
1028
else if(pbag_idx > 0) /* 1st preset, warn if ofs >0 */
1029
{
1030
FLUID_LOG(FLUID_WARN, "%d preset zones not referenced, discarding", pbag_idx);
1031
}
1032
1033
prev_preset = preset; /* update preset ptr */
1034
prev_pbag_idx = pbag_idx;
1035
}
1036
1037
FSKIP(sf, 24);
1038
READW(sf, pbag_idx); /* Read terminal generator index */
1039
FSKIP(sf, 12);
1040
1041
if(pbag_idx < prev_pbag_idx)
1042
{
1043
FLUID_LOG(FLUID_ERR, "Preset header indices not monotonic");
1044
return FALSE;
1045
}
1046
1047
i2 = pbag_idx - prev_pbag_idx;
1048
1049
while(i2--)
1050
{
1051
prev_preset->zone = fluid_list_prepend(prev_preset->zone, NULL);
1052
}
1053
1054
return TRUE;
1055
}
1056
1057
/* preset bag loader */
1058
static int load_pbag(SFData *sf, int size)
1059
{
1060
fluid_list_t *preset_list;
1061
fluid_list_t *zone_list;
1062
SFZone *z, *pz = NULL;
1063
unsigned short genndx, modndx;
1064
unsigned short pgenndx = 0, pmodndx = 0;
1065
unsigned short i;
1066
1067
if(size % SF_BAG_SIZE || size == 0) /* size is multiple of SF_BAG_SIZE? */
1068
{
1069
FLUID_LOG(FLUID_ERR, "Preset bag chunk size is invalid");
1070
return FALSE;
1071
}
1072
1073
preset_list = sf->preset;
1074
1075
/* traverse through presets */
1076
while(preset_list)
1077
{
1078
zone_list = ((SFPreset *)(preset_list->data))->zone;
1079
1080
/* traverse preset's zones */
1081
while(zone_list)
1082
{
1083
if((size -= SF_BAG_SIZE) < 0)
1084
{
1085
FLUID_LOG(FLUID_ERR, "Preset bag chunk size mismatch");
1086
return FALSE;
1087
}
1088
1089
if((z = FLUID_NEW(SFZone)) == NULL)
1090
{
1091
FLUID_LOG(FLUID_ERR, "Out of memory");
1092
return FALSE;
1093
}
1094
1095
zone_list->data = z;
1096
z->gen = NULL; /* Init gen and mod before possible failure, */
1097
z->mod = NULL; /* to ensure proper cleanup (fluid_sffile_close) */
1098
READW(sf, genndx); /* possible read failure ^ */
1099
READW(sf, modndx);
1100
1101
if(pz)
1102
{
1103
/* if not first zone */
1104
if(genndx < pgenndx)
1105
{
1106
FLUID_LOG(FLUID_ERR, "Preset bag generator indices not monotonic");
1107
return FALSE;
1108
}
1109
1110
if(modndx < pmodndx)
1111
{
1112
FLUID_LOG(FLUID_ERR, "Preset bag modulator indices not monotonic");
1113
return FALSE;
1114
}
1115
1116
i = genndx - pgenndx;
1117
1118
while(i--)
1119
{
1120
pz->gen = fluid_list_prepend(pz->gen, NULL);
1121
}
1122
1123
i = modndx - pmodndx;
1124
1125
while(i--)
1126
{
1127
pz->mod = fluid_list_prepend(pz->mod, NULL);
1128
}
1129
}
1130
1131
pz = z; /* update previous zone ptr */
1132
pgenndx = genndx; /* update previous zone gen index */
1133
pmodndx = modndx; /* update previous zone mod index */
1134
zone_list = fluid_list_next(zone_list);
1135
}
1136
1137
preset_list = fluid_list_next(preset_list);
1138
}
1139
1140
size -= SF_BAG_SIZE;
1141
1142
if(size != 0)
1143
{
1144
FLUID_LOG(FLUID_ERR, "Preset bag chunk size mismatch");
1145
return FALSE;
1146
}
1147
1148
READW(sf, genndx);
1149
READW(sf, modndx);
1150
1151
if(!pz)
1152
{
1153
if(genndx > 0)
1154
{
1155
FLUID_LOG(FLUID_WARN, "No preset generators and terminal index not 0");
1156
}
1157
1158
if(modndx > 0)
1159
{
1160
FLUID_LOG(FLUID_WARN, "No preset modulators and terminal index not 0");
1161
}
1162
1163
return TRUE;
1164
}
1165
1166
if(genndx < pgenndx)
1167
{
1168
FLUID_LOG(FLUID_ERR, "Preset bag generator indices not monotonic");
1169
return FALSE;
1170
}
1171
1172
if(modndx < pmodndx)
1173
{
1174
FLUID_LOG(FLUID_ERR, "Preset bag modulator indices not monotonic");
1175
return FALSE;
1176
}
1177
1178
i = genndx - pgenndx;
1179
1180
while(i--)
1181
{
1182
pz->gen = fluid_list_prepend(pz->gen, NULL);
1183
}
1184
1185
i = modndx - pmodndx;
1186
1187
while(i--)
1188
{
1189
pz->mod = fluid_list_prepend(pz->mod, NULL);
1190
}
1191
1192
return TRUE;
1193
}
1194
1195
/* preset modulator loader */
1196
static int load_pmod(SFData *sf, int size)
1197
{
1198
fluid_list_t *preset_list;
1199
fluid_list_t *zone_list;
1200
fluid_list_t *mod_list;
1201
SFMod *m;
1202
1203
preset_list = sf->preset;
1204
1205
while(preset_list)
1206
{
1207
/* traverse through all presets */
1208
zone_list = ((SFPreset *)(preset_list->data))->zone;
1209
1210
while(zone_list)
1211
{
1212
/* traverse this preset's zones */
1213
mod_list = ((SFZone *)(zone_list->data))->mod;
1214
1215
while(mod_list)
1216
{
1217
/* load zone's modulators */
1218
if((size -= SF_MOD_SIZE) < 0)
1219
{
1220
FLUID_LOG(FLUID_ERR, "Preset modulator chunk size mismatch");
1221
return FALSE;
1222
}
1223
1224
if((m = FLUID_NEW(SFMod)) == NULL)
1225
{
1226
FLUID_LOG(FLUID_ERR, "Out of memory");
1227
return FALSE;
1228
}
1229
1230
mod_list->data = m;
1231
READW(sf, m->src);
1232
READW(sf, m->dest);
1233
READW(sf, m->amount);
1234
READW(sf, m->amtsrc);
1235
READW(sf, m->trans);
1236
mod_list = fluid_list_next(mod_list);
1237
}
1238
1239
zone_list = fluid_list_next(zone_list);
1240
}
1241
1242
preset_list = fluid_list_next(preset_list);
1243
}
1244
1245
/*
1246
If there isn't even a terminal record
1247
Hmmm, the specs say there should be one, but..
1248
*/
1249
if(size == 0)
1250
{
1251
return TRUE;
1252
}
1253
1254
size -= SF_MOD_SIZE;
1255
1256
if(size != 0)
1257
{
1258
FLUID_LOG(FLUID_ERR, "Preset modulator chunk size mismatch");
1259
return FALSE;
1260
}
1261
1262
FSKIP(sf, SF_MOD_SIZE); /* terminal mod */
1263
1264
return TRUE;
1265
}
1266
1267
/* -------------------------------------------------------------------
1268
* preset generator loader
1269
* generator (per preset) loading rules:
1270
* Zones with no generators or modulators shall be annihilated
1271
* Global zone must be 1st zone, discard additional ones (instrumentless zones)
1272
*
1273
* generator (per zone) loading rules (in order of decreasing precedence):
1274
* KeyRange is 1st in list (if exists), else discard
1275
* if a VelRange exists only preceded by a KeyRange, else discard
1276
* if a generator follows an instrument discard it
1277
* if a duplicate generator exists replace previous one
1278
* ------------------------------------------------------------------- */
1279
int load_pgen(SFData *sf, int size)
1280
{
1281
fluid_list_t *dup;
1282
fluid_list_t *preset_list;
1283
fluid_list_t *zone_list;
1284
fluid_list_t *gen_list;
1285
SFZone *zone;
1286
SFGen *g;
1287
SFPreset *preset;
1288
SFGenAmount genval;
1289
unsigned short genid;
1290
int level, skip, drop, discarded;
1291
1292
preset_list = sf->preset;
1293
1294
while(preset_list)
1295
{
1296
preset = fluid_list_get(preset_list);
1297
1298
/* traverse through all presets */
1299
discarded = FALSE;
1300
zone_list = preset->zone;
1301
1302
/* traverse preset's zones */
1303
while(zone_list)
1304
{
1305
zone = fluid_list_get(zone_list);
1306
level = 0;
1307
gen_list = zone->gen;
1308
1309
while(gen_list)
1310
{
1311
/* load zone's generators */
1312
dup = NULL;
1313
skip = FALSE;
1314
drop = FALSE;
1315
1316
if((size -= SF_GEN_SIZE) < 0)
1317
{
1318
FLUID_LOG(FLUID_ERR, "Preset generator chunk size mismatch");
1319
return FALSE;
1320
}
1321
1322
READW(sf, genid);
1323
1324
if(genid == GEN_KEYRANGE)
1325
{
1326
/* nothing precedes */
1327
if(level == 0)
1328
{
1329
level = 1;
1330
READB(sf, genval.range.lo);
1331
READB(sf, genval.range.hi);
1332
}
1333
else
1334
{
1335
skip = TRUE;
1336
}
1337
}
1338
else if(genid == GEN_VELRANGE)
1339
{
1340
/* only KeyRange precedes */
1341
if(level <= 1)
1342
{
1343
level = 2;
1344
READB(sf, genval.range.lo);
1345
READB(sf, genval.range.hi);
1346
}
1347
else
1348
{
1349
skip = TRUE;
1350
}
1351
}
1352
else if(genid == GEN_INSTRUMENT)
1353
{
1354
/* inst is last gen */
1355
level = 3;
1356
READW(sf, genval.uword);
1357
}
1358
else
1359
{
1360
level = 2;
1361
1362
if(valid_preset_genid(genid))
1363
{
1364
/* generator valid? */
1365
READW(sf, genval.sword);
1366
dup = find_gen_by_id(genid, zone->gen);
1367
}
1368
else
1369
{
1370
skip = TRUE;
1371
}
1372
}
1373
1374
if(!skip)
1375
{
1376
if(!dup)
1377
{
1378
/* if gen ! dup alloc new */
1379
if((g = FLUID_NEW(SFGen)) == NULL)
1380
{
1381
FLUID_LOG(FLUID_ERR, "Out of memory");
1382
return FALSE;
1383
}
1384
1385
gen_list->data = g;
1386
g->id = genid;
1387
}
1388
else
1389
{
1390
g = (SFGen *)(dup->data); /* ptr to orig gen */
1391
drop = TRUE;
1392
}
1393
1394
g->amount = genval;
1395
}
1396
else
1397
{
1398
/* Skip this generator */
1399
discarded = TRUE;
1400
drop = TRUE;
1401
FSKIPW(sf);
1402
}
1403
1404
if(!drop)
1405
{
1406
gen_list = fluid_list_next(gen_list); /* next gen */
1407
}
1408
else
1409
{
1410
SLADVREM(zone->gen, gen_list); /* drop place holder */
1411
}
1412
1413
/* GEN_INSTRUMENT should be the last generator */
1414
if (level == 3)
1415
{
1416
break;
1417
}
1418
1419
} /* generator loop */
1420
1421
/* Anything below level 3 means it's a global zone. The global zone
1422
* should always be the first zone in the list, so discard any
1423
* other global zones we encounter */
1424
if(level < 3 && (zone_list != preset->zone))
1425
{
1426
/* advance to next zone before deleting the current list element */
1427
zone_list = fluid_list_next(zone_list);
1428
1429
FLUID_LOG(FLUID_WARN, "Preset '%s': Discarding invalid global zone",
1430
preset->name);
1431
preset->zone = fluid_list_remove(preset->zone, zone);
1432
delete_zone(zone);
1433
1434
/* we have already advanced the zone_list pointer, so continue with next zone */
1435
continue;
1436
}
1437
1438
/* All remaining generators are invalid and should be discarded
1439
* (because they come after an instrument generator) */
1440
while(gen_list)
1441
{
1442
discarded = TRUE;
1443
1444
if((size -= SF_GEN_SIZE) < 0)
1445
{
1446
FLUID_LOG(FLUID_ERR, "Preset generator chunk size mismatch");
1447
return FALSE;
1448
}
1449
1450
FSKIP(sf, SF_GEN_SIZE);
1451
SLADVREM(zone->gen, gen_list);
1452
}
1453
1454
zone_list = fluid_list_next(zone_list);
1455
}
1456
1457
if(discarded)
1458
{
1459
FLUID_LOG(FLUID_WARN,
1460
"Preset '%s': Some invalid generators were discarded",
1461
preset->name);
1462
}
1463
1464
preset_list = fluid_list_next(preset_list);
1465
}
1466
1467
/* in case there isn't a terminal record */
1468
if(size == 0)
1469
{
1470
return TRUE;
1471
}
1472
1473
size -= SF_GEN_SIZE;
1474
1475
if(size != 0)
1476
{
1477
FLUID_LOG(FLUID_ERR, "Preset generator chunk size mismatch");
1478
return FALSE;
1479
}
1480
1481
FSKIP(sf, SF_GEN_SIZE); /* terminal gen */
1482
1483
return TRUE;
1484
}
1485
1486
/* instrument header loader */
1487
static int load_ihdr(SFData *sf, unsigned int size)
1488
{
1489
unsigned int i;
1490
int i2;
1491
SFInst *inst, *prev_inst = NULL; /* ptr to current & previous instrument */
1492
unsigned short zndx, pzndx = 0;
1493
1494
if(size % SF_IHDR_SIZE || size == 0) /* chunk size is valid? */
1495
{
1496
FLUID_LOG(FLUID_ERR, "Instrument header has invalid size");
1497
return FALSE;
1498
}
1499
1500
size = size / SF_IHDR_SIZE - 1;
1501
1502
if(size == 0)
1503
{
1504
/* at least one preset + term record */
1505
FLUID_LOG(FLUID_WARN, "File contains no instruments");
1506
FSKIP(sf, SF_IHDR_SIZE);
1507
return TRUE;
1508
}
1509
1510
for(i = 0; i < size; i++)
1511
{
1512
/* load all instrument headers */
1513
if((inst = FLUID_NEW(SFInst)) == NULL)
1514
{
1515
FLUID_LOG(FLUID_ERR, "Out of memory");
1516
return FALSE;
1517
}
1518
1519
sf->inst = fluid_list_append(sf->inst, inst);
1520
inst->zone = NULL; /* For proper cleanup if fail (fluid_sffile_close) */
1521
inst->idx = i;
1522
READSTR(sf, &inst->name); /* Possible read failure ^ */
1523
READW(sf, zndx);
1524
1525
if(prev_inst)
1526
{
1527
/* not first instrument? */
1528
if(zndx < pzndx)
1529
{
1530
FLUID_LOG(FLUID_ERR, "Instrument header indices not monotonic");
1531
return FALSE;
1532
}
1533
1534
i2 = zndx - pzndx;
1535
1536
while(i2--)
1537
{
1538
prev_inst->zone = fluid_list_prepend(prev_inst->zone, NULL);
1539
}
1540
}
1541
else if(zndx > 0) /* 1st inst, warn if ofs >0 */
1542
{
1543
FLUID_LOG(FLUID_WARN, "%d instrument zones not referenced, discarding", zndx);
1544
}
1545
1546
pzndx = zndx;
1547
prev_inst = inst; /* update instrument ptr */
1548
}
1549
1550
FSKIP(sf, 20);
1551
READW(sf, zndx);
1552
1553
if(zndx < pzndx)
1554
{
1555
FLUID_LOG(FLUID_ERR, "Instrument header indices not monotonic");
1556
return FALSE;
1557
}
1558
1559
i2 = zndx - pzndx;
1560
1561
while(i2--)
1562
{
1563
prev_inst->zone = fluid_list_prepend(prev_inst->zone, NULL);
1564
}
1565
1566
return TRUE;
1567
}
1568
1569
/* instrument bag loader */
1570
static int load_ibag(SFData *sf, int size)
1571
{
1572
fluid_list_t *inst_list;
1573
fluid_list_t *zone_list;
1574
SFZone *z, *pz = NULL;
1575
unsigned short genndx, modndx, pgenndx = 0, pmodndx = 0;
1576
int i;
1577
1578
if(size % SF_BAG_SIZE || size == 0) /* size is multiple of SF_BAG_SIZE? */
1579
{
1580
FLUID_LOG(FLUID_ERR, "Instrument bag chunk size is invalid");
1581
return FALSE;
1582
}
1583
1584
inst_list = sf->inst;
1585
1586
while(inst_list)
1587
{
1588
/* traverse through inst */
1589
zone_list = ((SFInst *)(inst_list->data))->zone;
1590
1591
while(zone_list)
1592
{
1593
/* load this inst's zones */
1594
if((size -= SF_BAG_SIZE) < 0)
1595
{
1596
FLUID_LOG(FLUID_ERR, "Instrument bag chunk size mismatch");
1597
return FALSE;
1598
}
1599
1600
if((z = FLUID_NEW(SFZone)) == NULL)
1601
{
1602
FLUID_LOG(FLUID_ERR, "Out of memory");
1603
return FALSE;
1604
}
1605
1606
zone_list->data = z;
1607
z->gen = NULL; /* In case of failure, */
1608
z->mod = NULL; /* fluid_sffile_close can clean up */
1609
READW(sf, genndx); /* READW = possible read failure */
1610
READW(sf, modndx);
1611
1612
if(pz)
1613
{
1614
/* if not first zone */
1615
if(genndx < pgenndx)
1616
{
1617
FLUID_LOG(FLUID_ERR, "Instrument generator indices not monotonic");
1618
return FALSE;
1619
}
1620
1621
if(modndx < pmodndx)
1622
{
1623
FLUID_LOG(FLUID_ERR, "Instrument modulator indices not monotonic");
1624
return FALSE;
1625
}
1626
1627
i = genndx - pgenndx;
1628
1629
while(i--)
1630
{
1631
pz->gen = fluid_list_prepend(pz->gen, NULL);
1632
}
1633
1634
i = modndx - pmodndx;
1635
1636
while(i--)
1637
{
1638
pz->mod = fluid_list_prepend(pz->mod, NULL);
1639
}
1640
}
1641
1642
pz = z; /* update previous zone ptr */
1643
pgenndx = genndx;
1644
pmodndx = modndx;
1645
zone_list = fluid_list_next(zone_list);
1646
}
1647
1648
inst_list = fluid_list_next(inst_list);
1649
}
1650
1651
size -= SF_BAG_SIZE;
1652
1653
if(size != 0)
1654
{
1655
FLUID_LOG(FLUID_ERR, "Instrument chunk size mismatch");
1656
return FALSE;
1657
}
1658
1659
READW(sf, genndx);
1660
READW(sf, modndx);
1661
1662
if(!pz)
1663
{
1664
/* in case that all are no zoners */
1665
if(genndx > 0)
1666
{
1667
FLUID_LOG(FLUID_WARN, "No instrument generators and terminal index not 0");
1668
}
1669
1670
if(modndx > 0)
1671
{
1672
FLUID_LOG(FLUID_WARN, "No instrument modulators and terminal index not 0");
1673
}
1674
1675
return TRUE;
1676
}
1677
1678
if(genndx < pgenndx)
1679
{
1680
FLUID_LOG(FLUID_ERR, "Instrument generator indices not monotonic");
1681
return FALSE;
1682
}
1683
1684
if(modndx < pmodndx)
1685
{
1686
FLUID_LOG(FLUID_ERR, "Instrument modulator indices not monotonic");
1687
return FALSE;
1688
}
1689
1690
i = genndx - pgenndx;
1691
1692
while(i--)
1693
{
1694
pz->gen = fluid_list_prepend(pz->gen, NULL);
1695
}
1696
1697
i = modndx - pmodndx;
1698
1699
while(i--)
1700
{
1701
pz->mod = fluid_list_prepend(pz->mod, NULL);
1702
}
1703
1704
return TRUE;
1705
}
1706
1707
/* instrument modulator loader */
1708
static int load_imod(SFData *sf, int size)
1709
{
1710
fluid_list_t *inst_list;
1711
fluid_list_t *zone_list;
1712
fluid_list_t *mod_list;
1713
SFMod *m;
1714
1715
inst_list = sf->inst;
1716
1717
while(inst_list)
1718
{
1719
/* traverse through all inst */
1720
zone_list = ((SFInst *)(inst_list->data))->zone;
1721
1722
while(zone_list)
1723
{
1724
/* traverse this inst's zones */
1725
mod_list = ((SFZone *)(zone_list->data))->mod;
1726
1727
while(mod_list)
1728
{
1729
/* load zone's modulators */
1730
if((size -= SF_MOD_SIZE) < 0)
1731
{
1732
FLUID_LOG(FLUID_ERR, "Instrument modulator chunk size mismatch");
1733
return FALSE;
1734
}
1735
1736
if((m = FLUID_NEW(SFMod)) == NULL)
1737
{
1738
FLUID_LOG(FLUID_ERR, "Out of memory");
1739
return FALSE;
1740
}
1741
1742
mod_list->data = m;
1743
READW(sf, m->src);
1744
READW(sf, m->dest);
1745
READW(sf, m->amount);
1746
READW(sf, m->amtsrc);
1747
READW(sf, m->trans);
1748
mod_list = fluid_list_next(mod_list);
1749
}
1750
1751
zone_list = fluid_list_next(zone_list);
1752
}
1753
1754
inst_list = fluid_list_next(inst_list);
1755
}
1756
1757
/*
1758
If there isn't even a terminal record
1759
Hmmm, the specs say there should be one, but..
1760
*/
1761
if(size == 0)
1762
{
1763
return TRUE;
1764
}
1765
1766
size -= SF_MOD_SIZE;
1767
1768
if(size != 0)
1769
{
1770
FLUID_LOG(FLUID_ERR, "Instrument modulator chunk size mismatch");
1771
return FALSE;
1772
}
1773
1774
FSKIP(sf, SF_MOD_SIZE); /* terminal mod */
1775
1776
return TRUE;
1777
}
1778
1779
/* load instrument generators (see load_pgen for loading rules) */
1780
int load_igen(SFData *sf, int size)
1781
{
1782
fluid_list_t *dup;
1783
fluid_list_t *inst_list;
1784
fluid_list_t *zone_list;
1785
fluid_list_t *gen_list;
1786
SFZone *zone;
1787
SFGen *g;
1788
SFInst *inst;
1789
SFGenAmount genval;
1790
unsigned short genid;
1791
int level, skip, drop, discarded;
1792
1793
inst_list = sf->inst;
1794
1795
/* traverse through all instruments */
1796
while(inst_list)
1797
{
1798
inst = fluid_list_get(inst_list);
1799
1800
discarded = FALSE;
1801
zone_list = inst->zone;
1802
1803
/* traverse this instrument's zones */
1804
while(zone_list)
1805
{
1806
zone = fluid_list_get(zone_list);
1807
1808
level = 0;
1809
gen_list = zone->gen;
1810
1811
while(gen_list)
1812
{
1813
/* load zone's generators */
1814
dup = NULL;
1815
skip = FALSE;
1816
drop = FALSE;
1817
1818
if((size -= SF_GEN_SIZE) < 0)
1819
{
1820
FLUID_LOG(FLUID_ERR, "IGEN chunk size mismatch");
1821
return FALSE;
1822
}
1823
1824
READW(sf, genid);
1825
1826
if(genid == GEN_KEYRANGE)
1827
{
1828
/* nothing precedes */
1829
if(level == 0)
1830
{
1831
level = 1;
1832
READB(sf, genval.range.lo);
1833
READB(sf, genval.range.hi);
1834
}
1835
else
1836
{
1837
skip = TRUE;
1838
}
1839
}
1840
else if(genid == GEN_VELRANGE)
1841
{
1842
/* only KeyRange precedes */
1843
if(level <= 1)
1844
{
1845
level = 2;
1846
READB(sf, genval.range.lo);
1847
READB(sf, genval.range.hi);
1848
}
1849
else
1850
{
1851
skip = TRUE;
1852
}
1853
}
1854
else if(genid == GEN_SAMPLEID)
1855
{
1856
/* sample is last gen */
1857
level = 3;
1858
READW(sf, genval.uword);
1859
}
1860
else
1861
{
1862
level = 2;
1863
1864
if(valid_inst_genid(genid))
1865
{
1866
/* gen valid? */
1867
READW(sf, genval.sword);
1868
dup = find_gen_by_id(genid, zone->gen);
1869
}
1870
else
1871
{
1872
skip = TRUE;
1873
}
1874
}
1875
1876
if(!skip)
1877
{
1878
if(!dup)
1879
{
1880
/* if gen ! dup alloc new */
1881
if((g = FLUID_NEW(SFGen)) == NULL)
1882
{
1883
FLUID_LOG(FLUID_ERR, "Out of memory");
1884
return FALSE;
1885
}
1886
1887
gen_list->data = g;
1888
g->id = genid;
1889
}
1890
else
1891
{
1892
g = (SFGen *)(dup->data);
1893
drop = TRUE;
1894
}
1895
1896
g->amount = genval;
1897
}
1898
else
1899
{
1900
/* skip this generator */
1901
discarded = TRUE;
1902
drop = TRUE;
1903
FSKIPW(sf);
1904
}
1905
1906
if(!drop)
1907
{
1908
gen_list = fluid_list_next(gen_list); /* next gen */
1909
}
1910
else
1911
{
1912
SLADVREM(zone->gen, gen_list);
1913
}
1914
1915
/* GEN_SAMPLEID should be last generator */
1916
if (level == 3)
1917
{
1918
break;
1919
}
1920
1921
} /* generator loop */
1922
1923
/* Anything below level 3 means it's a global zone. The global zone
1924
* should always be the first zone in the list, so discard any
1925
* other global zones we encounter */
1926
if(level < 3 && (zone_list != inst->zone))
1927
{
1928
/* advance to next zone before deleting the current list element */
1929
zone_list = fluid_list_next(zone_list);
1930
1931
FLUID_LOG(FLUID_WARN, "Instrument '%s': Discarding invalid global zone",
1932
inst->name);
1933
inst->zone = fluid_list_remove(inst->zone, zone);
1934
delete_zone(zone);
1935
1936
/* we have already advanced the zone_list pointer, so continue with next zone */
1937
continue;
1938
}
1939
1940
/* All remaining generators must be invalid and should be discarded
1941
* (because they come after a sampleid generator) */
1942
while(gen_list)
1943
{
1944
discarded = TRUE;
1945
1946
if((size -= SF_GEN_SIZE) < 0)
1947
{
1948
FLUID_LOG(FLUID_ERR, "Instrument generator chunk size mismatch");
1949
return FALSE;
1950
}
1951
1952
FSKIP(sf, SF_GEN_SIZE);
1953
SLADVREM(zone->gen, gen_list);
1954
}
1955
1956
zone_list = fluid_list_next(zone_list); /* next zone */
1957
}
1958
1959
if(discarded)
1960
{
1961
FLUID_LOG(FLUID_WARN,
1962
"Instrument '%s': Some invalid generators were discarded",
1963
inst->name);
1964
}
1965
1966
inst_list = fluid_list_next(inst_list);
1967
}
1968
1969
/* for those non-terminal record cases, grr! */
1970
if(size == 0)
1971
{
1972
return TRUE;
1973
}
1974
1975
size -= SF_GEN_SIZE;
1976
1977
if(size != 0)
1978
{
1979
FLUID_LOG(FLUID_ERR, "IGEN chunk size mismatch");
1980
return FALSE;
1981
}
1982
1983
FSKIP(sf, SF_GEN_SIZE); /* terminal gen */
1984
1985
return TRUE;
1986
}
1987
1988
/* sample header loader */
1989
static int load_shdr(SFData *sf, unsigned int size)
1990
{
1991
unsigned int i;
1992
SFSample *p;
1993
1994
if(size % SF_SHDR_SIZE || size == 0) /* size is multiple of SHDR size? */
1995
{
1996
FLUID_LOG(FLUID_ERR, "Sample header has invalid size");
1997
return FALSE;
1998
}
1999
2000
size = size / SF_SHDR_SIZE - 1;
2001
2002
if(size == 0)
2003
{
2004
/* at least one sample + term record? */
2005
FLUID_LOG(FLUID_WARN, "File contains no samples");
2006
FSKIP(sf, SF_SHDR_SIZE);
2007
return TRUE;
2008
}
2009
2010
/* load all sample headers */
2011
for(i = 0; i < size; i++)
2012
{
2013
if((p = FLUID_NEW(SFSample)) == NULL)
2014
{
2015
FLUID_LOG(FLUID_ERR, "Out of memory");
2016
return FALSE;
2017
}
2018
p->idx = i;
2019
2020
sf->sample = fluid_list_prepend(sf->sample, p);
2021
READSTR(sf, &p->name);
2022
READD(sf, p->start);
2023
READD(sf, p->end);
2024
READD(sf, p->loopstart);
2025
READD(sf, p->loopend);
2026
READD(sf, p->samplerate);
2027
READB(sf, p->origpitch);
2028
READB(sf, p->pitchadj);
2029
FSKIPW(sf); /* skip sample link */
2030
READW(sf, p->sampletype);
2031
}
2032
2033
FSKIP(sf, SF_SHDR_SIZE); /* skip terminal shdr */
2034
2035
return TRUE;
2036
}
2037
2038
void delete_preset(SFPreset *preset)
2039
{
2040
fluid_list_t *entry;
2041
SFZone *zone;
2042
2043
if(!preset)
2044
{
2045
return;
2046
}
2047
2048
entry = preset->zone;
2049
2050
while(entry)
2051
{
2052
zone = (SFZone *)fluid_list_get(entry);
2053
delete_zone(zone);
2054
entry = fluid_list_next(entry);
2055
}
2056
2057
delete_fluid_list(preset->zone);
2058
2059
FLUID_FREE(preset);
2060
}
2061
2062
void delete_inst(SFInst *inst)
2063
{
2064
fluid_list_t *entry;
2065
SFZone *zone;
2066
2067
if(!inst)
2068
{
2069
return;
2070
}
2071
2072
entry = inst->zone;
2073
2074
while(entry)
2075
{
2076
zone = (SFZone *)fluid_list_get(entry);
2077
delete_zone(zone);
2078
entry = fluid_list_next(entry);
2079
}
2080
2081
delete_fluid_list(inst->zone);
2082
2083
FLUID_FREE(inst);
2084
}
2085
2086
2087
/* Free all elements of a zone (Preset or Instrument) */
2088
void delete_zone(SFZone *zone)
2089
{
2090
fluid_list_t *entry;
2091
2092
if(!zone)
2093
{
2094
return;
2095
}
2096
2097
entry = zone->gen;
2098
2099
while(entry)
2100
{
2101
FLUID_FREE(fluid_list_get(entry));
2102
entry = fluid_list_next(entry);
2103
}
2104
2105
delete_fluid_list(zone->gen);
2106
2107
entry = zone->mod;
2108
2109
while(entry)
2110
{
2111
FLUID_FREE(fluid_list_get(entry));
2112
entry = fluid_list_next(entry);
2113
}
2114
2115
delete_fluid_list(zone->mod);
2116
2117
FLUID_FREE(zone);
2118
}
2119
2120
/* preset sort function, first by bank, then by preset # */
2121
static int preset_compare_func(const void *a, const void *b)
2122
{
2123
int aval, bval;
2124
2125
aval = (int)(((const SFPreset *)a)->bank) << 16 | ((const SFPreset *)a)->prenum;
2126
bval = (int)(((const SFPreset *)b)->bank) << 16 | ((const SFPreset *)b)->prenum;
2127
2128
return (aval - bval);
2129
}
2130
2131
/* Find a generator by its id in the passed in list.
2132
*
2133
* @return pointer to SFGen if found, otherwise NULL
2134
*/
2135
static fluid_list_t *find_gen_by_id(int gen, fluid_list_t *genlist)
2136
{
2137
/* is generator in gen list? */
2138
fluid_list_t *p;
2139
2140
p = genlist;
2141
2142
while(p)
2143
{
2144
if(p->data == NULL)
2145
{
2146
return NULL;
2147
}
2148
2149
if(gen == ((SFGen *)p->data)->id)
2150
{
2151
break;
2152
}
2153
2154
p = fluid_list_next(p);
2155
}
2156
2157
return p;
2158
}
2159
2160
/* check validity of instrument generator */
2161
static int valid_inst_genid(unsigned short genid)
2162
{
2163
size_t i;
2164
2165
/* OVERRIDEROOTKEY is the last official generator, everything
2166
* following it are generators internal to FluidSynth and will
2167
* never appear in a SoundFont file. */
2168
if(genid > GEN_OVERRIDEROOTKEY)
2169
{
2170
return FALSE;
2171
}
2172
2173
for(i = 0; i < FLUID_N_ELEMENTS(invalid_inst_gen); i++)
2174
{
2175
if (invalid_inst_gen[i] == genid)
2176
{
2177
return FALSE;
2178
}
2179
}
2180
2181
return TRUE;
2182
}
2183
2184
/* check validity of preset generator */
2185
static int valid_preset_genid(unsigned short genid)
2186
{
2187
size_t i;
2188
2189
if(!valid_inst_genid(genid))
2190
{
2191
return FALSE;
2192
}
2193
2194
for(i = 0; i < FLUID_N_ELEMENTS(invalid_preset_gen); i++)
2195
{
2196
if (invalid_preset_gen[i] == genid)
2197
{
2198
return FALSE;
2199
}
2200
}
2201
2202
return TRUE;
2203
}
2204
2205
2206
static int fluid_sffile_read_wav(SFData *sf, unsigned int start, unsigned int end, short **data, char **data24)
2207
{
2208
short *loaded_data = NULL;
2209
char *loaded_data24 = NULL;
2210
unsigned int num_samples;
2211
2212
fluid_return_val_if_fail((end + 1) > start , -1);
2213
2214
num_samples = (end + 1) - start;
2215
2216
if((start * sizeof(short) > sf->samplesize) || (end * sizeof(short) > sf->samplesize))
2217
{
2218
FLUID_LOG(FLUID_ERR, "Sample offsets exceed sample data chunk");
2219
goto error_exit;
2220
}
2221
2222
/* Load 16-bit sample data */
2223
if(sf->fcbs->fseek(sf->sffd, sf->samplepos + (start * sizeof(short)), SEEK_SET) == FLUID_FAILED)
2224
{
2225
FLUID_LOG(FLUID_ERR, "Failed to seek to sample position");
2226
goto error_exit;
2227
}
2228
2229
loaded_data = FLUID_ARRAY(short, num_samples);
2230
2231
if(loaded_data == NULL)
2232
{
2233
FLUID_LOG(FLUID_ERR, "Out of memory");
2234
goto error_exit;
2235
}
2236
2237
if(sf->fcbs->fread(loaded_data, num_samples * sizeof(short), sf->sffd) == FLUID_FAILED)
2238
{
2239
#if FLUID_VERSION_CHECK(FLUIDSYNTH_VERSION_MAJOR, FLUIDSYNTH_VERSION_MINOR, FLUIDSYNTH_VERSION_MICRO) < FLUID_VERSION_CHECK(2,2,0)
2240
if((int)(num_samples * sizeof(short)) < 0)
2241
{
2242
FLUID_LOG(FLUID_INFO,
2243
"This SoundFont seems to be bigger than 2GB, which is not supported in this version of fluidsynth. "
2244
"You need to use at least fluidsynth 2.2.0");
2245
}
2246
#endif
2247
FLUID_LOG(FLUID_ERR, "Failed to read sample data");
2248
goto error_exit;
2249
}
2250
2251
/* If this machine is big endian, byte swap the 16 bit samples */
2252
if(FLUID_IS_BIG_ENDIAN)
2253
{
2254
unsigned int i;
2255
2256
for(i = 0; i < num_samples; i++)
2257
{
2258
loaded_data[i] = FLUID_LE16TOH(loaded_data[i]);
2259
}
2260
}
2261
2262
*data = loaded_data;
2263
2264
/* Optionally load additional 8 bit sample data for 24-bit support. Any failures while loading
2265
* the 24-bit sample data will be logged as errors but won't prevent the sample reading to
2266
* fail, as sound output is still possible with the 16-bit sample data. */
2267
if(sf->sample24pos)
2268
{
2269
if((start > sf->sample24size) || (end > sf->sample24size))
2270
{
2271
FLUID_LOG(FLUID_ERR, "Sample offsets exceed 24-bit sample data chunk");
2272
goto error24_exit;
2273
}
2274
2275
if(sf->fcbs->fseek(sf->sffd, sf->sample24pos + start, SEEK_SET) == FLUID_FAILED)
2276
{
2277
FLUID_LOG(FLUID_ERR, "Failed to seek position for 24-bit sample data in data file");
2278
goto error24_exit;
2279
}
2280
2281
loaded_data24 = FLUID_ARRAY(char, num_samples);
2282
2283
if(loaded_data24 == NULL)
2284
{
2285
FLUID_LOG(FLUID_ERR, "Out of memory reading 24-bit sample data");
2286
goto error24_exit;
2287
}
2288
2289
if(sf->fcbs->fread(loaded_data24, num_samples, sf->sffd) == FLUID_FAILED)
2290
{
2291
FLUID_LOG(FLUID_ERR, "Failed to read 24-bit sample data");
2292
goto error24_exit;
2293
}
2294
}
2295
2296
*data24 = loaded_data24;
2297
2298
return num_samples;
2299
2300
error24_exit:
2301
FLUID_LOG(FLUID_WARN, "Ignoring 24-bit sample data, sound quality might suffer");
2302
FLUID_FREE(loaded_data24);
2303
*data24 = NULL;
2304
return num_samples;
2305
2306
error_exit:
2307
FLUID_FREE(loaded_data);
2308
FLUID_FREE(loaded_data24);
2309
return -1;
2310
}
2311
2312
2313
/* Ogg Vorbis loading and decompression */
2314
#if LIBSNDFILE_SUPPORT
2315
2316
/* Virtual file access routines to allow loading individually compressed
2317
* samples from the Soundfont sample data chunk using the file callbacks
2318
* passing in during opening of the file */
2319
typedef struct _sfvio_data_t
2320
{
2321
SFData *sffile;
2322
sf_count_t start; /* start byte offset of compressed data */
2323
sf_count_t end; /* end byte offset of compressed data */
2324
sf_count_t offset; /* current virtual file offset from start byte offset */
2325
2326
} sfvio_data_t;
2327
2328
static sf_count_t sfvio_get_filelen(void *user_data)
2329
{
2330
sfvio_data_t *data = user_data;
2331
2332
return (data->end + 1) - data->start;
2333
}
2334
2335
static sf_count_t sfvio_seek(sf_count_t offset, int whence, void *user_data)
2336
{
2337
sfvio_data_t *data = user_data;
2338
SFData *sf = data->sffile;
2339
sf_count_t new_offset;
2340
2341
switch(whence)
2342
{
2343
case SEEK_SET:
2344
new_offset = offset;
2345
break;
2346
2347
case SEEK_CUR:
2348
new_offset = data->offset + offset;
2349
break;
2350
2351
case SEEK_END:
2352
new_offset = sfvio_get_filelen(user_data) + offset;
2353
break;
2354
2355
default:
2356
goto fail; /* proper error handling not possible?? */
2357
}
2358
2359
new_offset += data->start;
2360
fluid_rec_mutex_lock(sf->mtx);
2361
if (data->start <= new_offset && new_offset <= data->end &&
2362
sf->fcbs->fseek(sf->sffd, new_offset, SEEK_SET) != FLUID_FAILED)
2363
{
2364
data->offset = new_offset - data->start;
2365
}
2366
fluid_rec_mutex_unlock(sf->mtx);
2367
2368
fail:
2369
return data->offset;
2370
}
2371
2372
static sf_count_t sfvio_read(void *ptr, sf_count_t count, void *user_data)
2373
{
2374
sfvio_data_t *data = user_data;
2375
SFData *sf = data->sffile;
2376
sf_count_t remain;
2377
2378
remain = sfvio_get_filelen(user_data) - data->offset;
2379
2380
if(count > remain)
2381
{
2382
count = remain;
2383
}
2384
2385
if(count == 0)
2386
{
2387
return count;
2388
}
2389
2390
fluid_rec_mutex_lock(sf->mtx);
2391
if (sf->fcbs->fseek(sf->sffd, data->start + data->offset, SEEK_SET) == FLUID_FAILED)
2392
{
2393
FLUID_LOG(FLUID_ERR, "This should never happen: fseek failed in sfvoid_read()");
2394
count = 0;
2395
}
2396
else
2397
{
2398
if (sf->fcbs->fread(ptr, count, sf->sffd) == FLUID_FAILED)
2399
{
2400
FLUID_LOG(FLUID_ERR, "Failed to read compressed sample data");
2401
count = 0;
2402
}
2403
}
2404
fluid_rec_mutex_unlock(sf->mtx);
2405
2406
data->offset += count;
2407
2408
return count;
2409
}
2410
2411
static sf_count_t sfvio_tell(void *user_data)
2412
{
2413
sfvio_data_t *data = user_data;
2414
2415
return data->offset;
2416
}
2417
2418
/**
2419
* Read Ogg Vorbis compressed data from the Soundfont and decompress it, returning the number of samples
2420
* in the decompressed WAV. Only 16-bit mono samples are supported.
2421
*
2422
* Note that this function takes byte indices for start and end source data. The sample headers in SF3
2423
* files use byte indices, so those pointers can be passed directly to this function.
2424
*
2425
* This function uses a virtual file structure in order to read the Ogg Vorbis
2426
* data from arbitrary locations in the source file.
2427
*/
2428
static int fluid_sffile_read_vorbis(SFData *sf, unsigned int start_byte, unsigned int end_byte, short **data)
2429
{
2430
SNDFILE *sndfile;
2431
SF_INFO sfinfo;
2432
SF_VIRTUAL_IO sfvio =
2433
{
2434
sfvio_get_filelen,
2435
sfvio_seek,
2436
sfvio_read,
2437
NULL,
2438
sfvio_tell
2439
};
2440
sfvio_data_t sfdata;
2441
short *wav_data = NULL;
2442
2443
if((start_byte > sf->samplesize) || (end_byte > sf->samplesize))
2444
{
2445
FLUID_LOG(FLUID_ERR, "Ogg Vorbis data offsets exceed sample data chunk");
2446
return -1;
2447
}
2448
2449
// Initialize file position indicator and SF_INFO structure
2450
sfdata.sffile = sf;
2451
sfdata.start = sf->samplepos + start_byte;
2452
sfdata.end = sf->samplepos + end_byte;
2453
sfdata.offset = -1;
2454
2455
/* Seek to sfdata.start, the beginning of Ogg Vorbis data in Soundfont */
2456
sfvio_seek(0, SEEK_SET, &sfdata);
2457
if (sfdata.offset != 0)
2458
{
2459
FLUID_LOG(FLUID_ERR, "Failed to seek to compressed sample position");
2460
return -1;
2461
}
2462
2463
FLUID_MEMSET(&sfinfo, 0, sizeof(sfinfo));
2464
2465
// Open sample as a virtual file
2466
sndfile = sf_open_virtual(&sfvio, SFM_READ, &sfinfo, &sfdata);
2467
2468
if(!sndfile)
2469
{
2470
FLUID_LOG(FLUID_ERR, "sf_open_virtual(): %s", sf_strerror(sndfile));
2471
return -1;
2472
}
2473
2474
// Empty sample
2475
if(sfinfo.frames <= 0 || sfinfo.channels <= 0)
2476
{
2477
FLUID_LOG(FLUID_DBG, "Empty decompressed sample");
2478
*data = NULL;
2479
sf_close(sndfile);
2480
return 0;
2481
}
2482
2483
// Mono sample
2484
if(sfinfo.channels != 1)
2485
{
2486
FLUID_LOG(FLUID_DBG, "Unsupported channel count %d in ogg sample", sfinfo.channels);
2487
goto error_exit;
2488
}
2489
2490
if((sfinfo.format & SF_FORMAT_OGG) == 0)
2491
{
2492
FLUID_LOG(FLUID_WARN, "OGG sample is not OGG compressed, this is not officially supported");
2493
}
2494
2495
wav_data = FLUID_ARRAY(short, sfinfo.frames * sfinfo.channels);
2496
2497
if(!wav_data)
2498
{
2499
FLUID_LOG(FLUID_ERR, "Out of memory");
2500
goto error_exit;
2501
}
2502
2503
// Avoid clipping for loud samples, see
2504
// https://github.com/FluidSynth/fluidsynth/issues/1380
2505
// and
2506
// https://github.com/libsndfile/libsndfile/issues/194
2507
sf_command(sndfile, SFC_SET_SCALE_FLOAT_INT_READ, NULL, SF_TRUE);
2508
2509
/* Automatically decompresses the Ogg Vorbis data to 16-bit PCM */
2510
if(sf_readf_short(sndfile, wav_data, sfinfo.frames) < sfinfo.frames)
2511
{
2512
FLUID_LOG(FLUID_DBG, "Decompression failed!");
2513
FLUID_LOG(FLUID_ERR, "sf_readf_short(): %s", sf_strerror(sndfile));
2514
goto error_exit;
2515
}
2516
2517
sf_close(sndfile);
2518
2519
*data = wav_data;
2520
2521
return sfinfo.frames;
2522
2523
error_exit:
2524
FLUID_FREE(wav_data);
2525
sf_close(sndfile);
2526
return -1;
2527
}
2528
#else
2529
static int fluid_sffile_read_vorbis(SFData *sf, unsigned int start_byte, unsigned int end_byte, short **data)
2530
{
2531
return -1;
2532
}
2533
#endif
2534
2535