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