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