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 Library General Public License
10  * as published by the Free Software Foundation; either version 2 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  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library 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 #include <retro_endianness.h>
25 
26 #include "fluid_defsfont.h"
27 /* Todo: Get rid of that 'include' */
28 #include "fluid_sys.h"
29 
30 /***************************************************************
31  *
32  *                           SFONT LOADER
33  */
34 
new_fluid_defsfloader(fluid_settings_t * settings)35 fluid_sfloader_t* new_fluid_defsfloader(fluid_settings_t* settings)
36 {
37   fluid_sfloader_t* loader;
38 
39   loader = FLUID_NEW(fluid_sfloader_t);
40   if (loader == NULL) {
41     FLUID_LOG(FLUID_ERR, "Out of memory");
42     return NULL;
43   }
44 
45   loader->data = settings;
46   loader->free = delete_fluid_defsfloader;
47   loader->load = fluid_defsfloader_load;
48 
49   return loader;
50 }
51 
delete_fluid_defsfloader(fluid_sfloader_t * loader)52 int delete_fluid_defsfloader(fluid_sfloader_t* loader)
53 {
54   if (loader) {
55     FLUID_FREE(loader);
56   }
57   return FLUID_OK;
58 }
59 
fluid_defsfloader_load(fluid_sfloader_t * loader,const char * filename)60 fluid_sfont_t* fluid_defsfloader_load(fluid_sfloader_t* loader, const char* filename)
61 {
62   fluid_defsfont_t* defsfont;
63   fluid_sfont_t* sfont;
64 
65   defsfont = new_fluid_defsfont(loader->data);
66 
67   if (defsfont == NULL) {
68     return NULL;
69   }
70 
71   if (fluid_defsfont_load(defsfont, filename) == FLUID_FAILED) {
72     delete_fluid_defsfont(defsfont);
73     return NULL;
74   }
75 
76   sfont = FLUID_NEW(fluid_sfont_t);
77   if (sfont == NULL) {
78     FLUID_LOG(FLUID_ERR, "Out of memory");
79     return NULL;
80   }
81 
82   sfont->data = defsfont;
83   sfont->free = fluid_defsfont_sfont_delete;
84   sfont->get_name = fluid_defsfont_sfont_get_name;
85   sfont->get_preset = fluid_defsfont_sfont_get_preset;
86   sfont->iteration_start = fluid_defsfont_sfont_iteration_start;
87   sfont->iteration_next = fluid_defsfont_sfont_iteration_next;
88 
89   return sfont;
90 }
91 
92 
93 
94 /***************************************************************
95  *
96  *                           PUBLIC INTERFACE
97  */
98 
fluid_defsfont_sfont_delete(fluid_sfont_t * sfont)99 int fluid_defsfont_sfont_delete(fluid_sfont_t* sfont)
100 {
101   if (delete_fluid_defsfont(sfont->data) != 0) {
102     return -1;
103   }
104   FLUID_FREE(sfont);
105   return 0;
106 }
107 
fluid_defsfont_sfont_get_name(fluid_sfont_t * sfont)108 char* fluid_defsfont_sfont_get_name(fluid_sfont_t* sfont)
109 {
110   return fluid_defsfont_get_name((fluid_defsfont_t*) sfont->data);
111 }
112 
fluid_defsfont_get_sample(fluid_defsfont_t * sfont,char * s)113 fluid_sample_t* fluid_defsfont_get_sample(fluid_defsfont_t* sfont, char *s)
114 {
115   /* This function is here just to avoid an ABI/SONAME bump, see ticket #98. Should never be used. */
116   return NULL;
117 }
118 
119 fluid_preset_t*
fluid_defsfont_sfont_get_preset(fluid_sfont_t * sfont,unsigned int bank,unsigned int prenum)120 fluid_defsfont_sfont_get_preset(fluid_sfont_t* sfont, unsigned int bank, unsigned int prenum)
121 {
122   fluid_preset_t* preset = NULL;
123   fluid_defpreset_t* defpreset;
124   fluid_defsfont_t* defsfont = sfont->data;
125 
126   defpreset = fluid_defsfont_get_preset(defsfont, bank, prenum);
127 
128   if (defpreset == NULL) {
129     return NULL;
130   }
131 
132   if (defsfont->preset_stack_size > 0) {
133     defsfont->preset_stack_size--;
134     preset = defsfont->preset_stack[defsfont->preset_stack_size];
135   }
136   if (!preset)
137     preset = FLUID_NEW(fluid_preset_t);
138   if (!preset) {
139     FLUID_LOG(FLUID_ERR, "Out of memory");
140     return NULL;
141   }
142 
143   preset->sfont = sfont;
144   preset->data = defpreset;
145   preset->free = fluid_defpreset_preset_delete;
146   preset->get_name = fluid_defpreset_preset_get_name;
147   preset->get_banknum = fluid_defpreset_preset_get_banknum;
148   preset->get_num = fluid_defpreset_preset_get_num;
149   preset->noteon = fluid_defpreset_preset_noteon;
150   preset->notify = NULL;
151 
152   return preset;
153 }
154 
fluid_defsfont_sfont_iteration_start(fluid_sfont_t * sfont)155 void fluid_defsfont_sfont_iteration_start(fluid_sfont_t* sfont)
156 {
157   fluid_defsfont_iteration_start((fluid_defsfont_t*) sfont->data);
158 }
159 
fluid_defsfont_sfont_iteration_next(fluid_sfont_t * sfont,fluid_preset_t * preset)160 int fluid_defsfont_sfont_iteration_next(fluid_sfont_t* sfont, fluid_preset_t* preset)
161 {
162   preset->free = fluid_defpreset_preset_delete;
163   preset->get_name = fluid_defpreset_preset_get_name;
164   preset->get_banknum = fluid_defpreset_preset_get_banknum;
165   preset->get_num = fluid_defpreset_preset_get_num;
166   preset->noteon = fluid_defpreset_preset_noteon;
167   preset->notify = NULL;
168 
169   return fluid_defsfont_iteration_next((fluid_defsfont_t*) sfont->data, preset);
170 }
171 
fluid_defpreset_preset_delete(fluid_preset_t * preset)172 int fluid_defpreset_preset_delete(fluid_preset_t* preset)
173 {
174   fluid_defpreset_t* defpreset = preset ? preset->data : NULL;
175   fluid_defsfont_t* sfont = defpreset ? defpreset->sfont : NULL;
176 
177   if (sfont && sfont->preset_stack_size < sfont->preset_stack_capacity) {
178      sfont->preset_stack[sfont->preset_stack_size] = preset;
179      sfont->preset_stack_size++;
180   }
181   else
182     FLUID_FREE(preset);
183 
184   return 0;
185 }
186 
fluid_defpreset_preset_get_name(fluid_preset_t * preset)187 char* fluid_defpreset_preset_get_name(fluid_preset_t* preset)
188 {
189   return fluid_defpreset_get_name((fluid_defpreset_t*) preset->data);
190 }
191 
fluid_defpreset_preset_get_banknum(fluid_preset_t * preset)192 int fluid_defpreset_preset_get_banknum(fluid_preset_t* preset)
193 {
194   return fluid_defpreset_get_banknum((fluid_defpreset_t*) preset->data);
195 }
196 
fluid_defpreset_preset_get_num(fluid_preset_t * preset)197 int fluid_defpreset_preset_get_num(fluid_preset_t* preset)
198 {
199   return fluid_defpreset_get_num((fluid_defpreset_t*) preset->data);
200 }
201 
fluid_defpreset_preset_noteon(fluid_preset_t * preset,fluid_synth_t * synth,int chan,int key,int vel)202 int fluid_defpreset_preset_noteon(fluid_preset_t* preset, fluid_synth_t* synth,
203 				 int chan, int key, int vel)
204 {
205   return fluid_defpreset_noteon((fluid_defpreset_t*) preset->data, synth, chan, key, vel);
206 }
207 
208 
209 
210 
211 /***************************************************************
212  *
213  *                    CACHED SAMPLEDATA LOADER
214  */
215 
216 typedef struct _fluid_cached_sampledata_t {
217   struct _fluid_cached_sampledata_t *next;
218 
219   char* filename;
220   time_t modification_time;
221   int num_references;
222   int mlock;
223 
224   const short* sampledata;
225   unsigned int samplesize;
226 } fluid_cached_sampledata_t;
227 
228 static fluid_cached_sampledata_t* all_cached_sampledata = NULL;
229 static fluid_mutex_t cached_sampledata_mutex = FLUID_MUTEX_INIT;
230 
fluid_get_file_modification_time(char * filename,time_t * modification_time)231 static int fluid_get_file_modification_time(char *filename, time_t *modification_time)
232 {
233 #if defined(WIN32) || defined(__OS2__)
234   *modification_time = 0;
235   return FLUID_OK;
236 #else
237   struct stat buf;
238 
239   if (stat(filename, &buf) == -1) {
240     return FLUID_FAILED;
241   }
242 
243   *modification_time = buf.st_mtime;
244   return FLUID_OK;
245 #endif
246 }
247 
fluid_cached_sampledata_load(char * filename,unsigned int samplepos,unsigned int samplesize,short ** sampledata,int try_mlock)248 static int fluid_cached_sampledata_load(char *filename, unsigned int samplepos,
249   unsigned int samplesize, short **sampledata, int try_mlock)
250 {
251   fluid_file fd = NULL;
252   short *loaded_sampledata = NULL;
253   fluid_cached_sampledata_t* cached_sampledata = NULL;
254   time_t modification_time;
255 
256   fluid_mutex_lock(cached_sampledata_mutex);
257 
258   if (fluid_get_file_modification_time(filename, &modification_time) == FLUID_FAILED) {
259     FLUID_LOG(FLUID_WARN, "Unable to read modificaton time of soundfont file.");
260     modification_time = 0;
261   }
262 
263   for (cached_sampledata = all_cached_sampledata; cached_sampledata; cached_sampledata = cached_sampledata->next) {
264     if (strcmp(filename, cached_sampledata->filename))
265       continue;
266     if (cached_sampledata->modification_time != modification_time)
267       continue;
268     if (cached_sampledata->samplesize != samplesize) {
269       FLUID_LOG(FLUID_ERR, "Cached size of soundfont doesn't match actual size of soundfont (cached: %u. actual: %u)",
270         cached_sampledata->samplesize, samplesize);
271       continue;
272     }
273 
274     if (try_mlock && !cached_sampledata->mlock) {
275       if (fluid_mlock(cached_sampledata->sampledata, samplesize) != 0)
276         FLUID_LOG(FLUID_WARN, "Failed to pin the sample data to RAM; swapping is possible.");
277       else
278         cached_sampledata->mlock = try_mlock;
279     }
280 
281     cached_sampledata->num_references++;
282     loaded_sampledata = (short*) cached_sampledata->sampledata;
283     goto success_exit;
284   }
285 
286   fd = FLUID_FOPEN(filename, "rb");
287   if (fd == NULL) {
288     FLUID_LOG(FLUID_ERR, "Can't open soundfont file");
289     goto error_exit;
290   }
291   if (FLUID_FSEEK(fd, samplepos, SEEK_SET) == -1) {
292     perror("error");
293     FLUID_LOG(FLUID_ERR, "Failed to seek position in data file");
294     goto error_exit;
295   }
296 
297 
298   loaded_sampledata = (short*) FLUID_MALLOC(samplesize);
299   if (loaded_sampledata == NULL) {
300     FLUID_LOG(FLUID_ERR, "Out of memory");
301     goto error_exit;
302   }
303   if (FLUID_FREAD(loaded_sampledata, 1, samplesize, fd) < samplesize) {
304     FLUID_LOG(FLUID_ERR, "Failed to read sample data");
305     goto error_exit;
306   }
307 
308   FLUID_FCLOSE(fd);
309   fd = NULL;
310 
311 
312   cached_sampledata = (fluid_cached_sampledata_t*) FLUID_MALLOC(sizeof(fluid_cached_sampledata_t));
313   if (cached_sampledata == NULL) {
314     FLUID_LOG(FLUID_ERR, "Out of memory.");
315     goto error_exit;
316   }
317 
318   /* Lock the memory to disable paging. It's okay if this fails. It
319      probably means that the user doesn't have to required permission.  */
320   cached_sampledata->mlock = 0;
321   if (try_mlock) {
322     if (fluid_mlock(loaded_sampledata, samplesize) != 0)
323       FLUID_LOG(FLUID_WARN, "Failed to pin the sample data to RAM; swapping is possible.");
324     else
325       cached_sampledata->mlock = try_mlock;
326   }
327 
328 #ifdef MSB_FIRST
329   /* If this machine is big endian, the sample have to byte swapped  */
330   {
331      unsigned char* cbuf;
332      unsigned char hi, lo;
333      unsigned int i, j;
334      short s;
335      cbuf = (unsigned char*)loaded_sampledata;
336      for (i = 0, j = 0; j < samplesize; i++) {
337         lo = cbuf[j++];
338         hi = cbuf[j++];
339         s = (hi << 8) | lo;
340         loaded_sampledata[i] = s;
341      }
342   }
343 #endif
344 
345   cached_sampledata->filename = (char*) FLUID_MALLOC(strlen(filename) + 1);
346   if (cached_sampledata->filename == NULL) {
347     FLUID_LOG(FLUID_ERR, "Out of memory.");
348     goto error_exit;
349   }
350 
351   sprintf(cached_sampledata->filename, "%s", filename);
352   cached_sampledata->modification_time = modification_time;
353   cached_sampledata->num_references = 1;
354   cached_sampledata->sampledata = loaded_sampledata;
355   cached_sampledata->samplesize = samplesize;
356 
357   cached_sampledata->next = all_cached_sampledata;
358   all_cached_sampledata = cached_sampledata;
359 
360 
361  success_exit:
362   fluid_mutex_unlock(cached_sampledata_mutex);
363   *sampledata = loaded_sampledata;
364   return FLUID_OK;
365 
366  error_exit:
367   if (fd != NULL) {
368     FLUID_FCLOSE(fd);
369   }
370   if (loaded_sampledata != NULL) {
371     FLUID_FREE(loaded_sampledata);
372   }
373 
374   if (cached_sampledata != NULL) {
375     if (cached_sampledata->filename != NULL) {
376       FLUID_FREE(cached_sampledata->filename);
377     }
378     FLUID_FREE(cached_sampledata);
379   }
380 
381   fluid_mutex_unlock(cached_sampledata_mutex);
382   *sampledata = NULL;
383   return FLUID_FAILED;
384 }
385 
fluid_cached_sampledata_unload(const short * sampledata)386 static int fluid_cached_sampledata_unload(const short *sampledata)
387 {
388   fluid_cached_sampledata_t* prev = NULL;
389   fluid_cached_sampledata_t* cached_sampledata;
390 
391   fluid_mutex_lock(cached_sampledata_mutex);
392   cached_sampledata = all_cached_sampledata;
393 
394   while (cached_sampledata != NULL) {
395     if (sampledata == cached_sampledata->sampledata) {
396 
397       cached_sampledata->num_references--;
398 
399       if (cached_sampledata->num_references == 0) {
400         if (cached_sampledata->mlock)
401           fluid_munlock(cached_sampledata->sampledata, cached_sampledata->samplesize);
402         FLUID_FREE((short*) cached_sampledata->sampledata);
403         FLUID_FREE(cached_sampledata->filename);
404 
405         if (prev != NULL) {
406           prev->next = cached_sampledata->next;
407         } else {
408           all_cached_sampledata = cached_sampledata->next;
409         }
410 
411         FLUID_FREE(cached_sampledata);
412       }
413 
414       goto success_exit;
415     }
416 
417     prev = cached_sampledata;
418     cached_sampledata = cached_sampledata->next;
419   }
420 
421   FLUID_LOG(FLUID_ERR, "Trying to free sampledata not found in cache.");
422   goto error_exit;
423 
424  success_exit:
425   fluid_mutex_unlock(cached_sampledata_mutex);
426   return FLUID_OK;
427 
428  error_exit:
429   fluid_mutex_unlock(cached_sampledata_mutex);
430   return FLUID_FAILED;
431 }
432 
433 
434 
435 
436 /***************************************************************
437  *
438  *                           SFONT
439  */
440 
441 /*
442  * new_fluid_defsfont
443  */
new_fluid_defsfont(fluid_settings_t * settings)444 fluid_defsfont_t* new_fluid_defsfont(fluid_settings_t* settings)
445 {
446   fluid_defsfont_t* sfont;
447   int i;
448 
449   sfont = FLUID_NEW(fluid_defsfont_t);
450   if (sfont == NULL) {
451     FLUID_LOG(FLUID_ERR, "Out of memory");
452     return NULL;
453   }
454 
455   sfont->filename = NULL;
456   sfont->samplepos = 0;
457   sfont->samplesize = 0;
458   sfont->sample = NULL;
459   sfont->sampledata = NULL;
460   sfont->preset = NULL;
461   fluid_settings_getint(settings, "synth.lock-memory", &sfont->mlock);
462 
463   /* Initialise preset cache, so we don't have to call malloc on program changes.
464      Usually, we have at most one preset per channel plus one temporarily used,
465      so optimise for that case. */
466   fluid_settings_getint(settings, "synth.midi-channels", &sfont->preset_stack_capacity);
467   sfont->preset_stack_capacity++;
468   sfont->preset_stack_size = 0;
469   sfont->preset_stack = FLUID_ARRAY(fluid_preset_t*, sfont->preset_stack_capacity);
470   if (!sfont->preset_stack) {
471     FLUID_LOG(FLUID_ERR, "Out of memory");
472     FLUID_FREE(sfont);
473     return NULL;
474   }
475 
476   for (i = 0; i < sfont->preset_stack_capacity; i++) {
477     sfont->preset_stack[i] = FLUID_NEW(fluid_preset_t);
478     if (!sfont->preset_stack[i]) {
479       FLUID_LOG(FLUID_ERR, "Out of memory");
480       delete_fluid_defsfont(sfont);
481       return NULL;
482     }
483     sfont->preset_stack_size++;
484   }
485 
486   return sfont;
487 }
488 
489 /*
490  * delete_fluid_defsfont
491  */
delete_fluid_defsfont(fluid_defsfont_t * sfont)492 int delete_fluid_defsfont(fluid_defsfont_t* sfont)
493 {
494   fluid_list_t *list;
495   fluid_defpreset_t* preset;
496   fluid_sample_t* sample;
497 
498   /* Check that no samples are currently used */
499   for (list = sfont->sample; list; list = fluid_list_next(list)) {
500     sample = (fluid_sample_t*) fluid_list_get(list);
501     if (fluid_sample_refcount(sample) != 0) {
502       return -1;
503     }
504   }
505 
506   if (sfont->filename != NULL) {
507     FLUID_FREE(sfont->filename);
508   }
509 
510   for (list = sfont->sample; list; list = fluid_list_next(list)) {
511     delete_fluid_sample((fluid_sample_t*) fluid_list_get(list));
512   }
513 
514   if (sfont->sample) {
515     delete_fluid_list(sfont->sample);
516   }
517 
518   if (sfont->sampledata != NULL) {
519     fluid_cached_sampledata_unload(sfont->sampledata);
520   }
521 
522   while (sfont->preset_stack_size > 0)
523     FLUID_FREE(sfont->preset_stack[--sfont->preset_stack_size]);
524   FLUID_FREE(sfont->preset_stack);
525 
526   preset = sfont->preset;
527   while (preset != NULL) {
528     sfont->preset = preset->next;
529     delete_fluid_defpreset(preset);
530     preset = sfont->preset;
531   }
532 
533   FLUID_FREE(sfont);
534   return FLUID_OK;
535 }
536 
537 /*
538  * fluid_defsfont_get_name
539  */
fluid_defsfont_get_name(fluid_defsfont_t * sfont)540 char* fluid_defsfont_get_name(fluid_defsfont_t* sfont)
541 {
542   return sfont->filename;
543 }
544 
545 
546 /*
547  * fluid_defsfont_load
548  */
fluid_defsfont_load(fluid_defsfont_t * sfont,const char * file)549 int fluid_defsfont_load(fluid_defsfont_t* sfont, const char* file)
550 {
551   SFData* sfdata;
552   fluid_list_t *p;
553   SFPreset* sfpreset;
554   SFSample* sfsample;
555   fluid_sample_t* sample;
556   fluid_defpreset_t* preset = NULL;
557 
558   sfont->filename = FLUID_MALLOC(1 + FLUID_STRLEN(file));
559   if (sfont->filename == NULL) {
560     FLUID_LOG(FLUID_ERR, "Out of memory");
561     return FLUID_FAILED;
562   }
563   FLUID_STRCPY(sfont->filename, file);
564 
565   /* The actual loading is done in the sfont and sffile files */
566   sfdata = sfload_file(file);
567   if (sfdata == NULL) {
568     FLUID_LOG(FLUID_ERR, "Couldn't load soundfont file");
569     return FLUID_FAILED;
570   }
571 
572   /* Keep track of the position and size of the sample data because
573      it's loaded separately (and might be unoaded/reloaded in future) */
574   sfont->samplepos = sfdata->samplepos;
575   sfont->samplesize = sfdata->samplesize;
576 
577   /* load sample data in one block */
578   if (fluid_defsfont_load_sampledata(sfont) != FLUID_OK)
579     goto err_exit;
580 
581   /* Create all the sample headers */
582   p = sfdata->sample;
583   while (p != NULL) {
584     sfsample = (SFSample *) p->data;
585 
586     sample = new_fluid_sample();
587     if (sample == NULL) goto err_exit;
588 
589     if (fluid_sample_import_sfont(sample, sfsample, sfont) != FLUID_OK)
590       goto err_exit;
591 
592     /* Store reference to FluidSynth sample in SFSample for later IZone fixups */
593     sfsample->fluid_sample = sample;
594 
595     fluid_defsfont_add_sample(sfont, sample);
596     fluid_voice_optimize_sample(sample);
597     p = fluid_list_next(p);
598   }
599 
600   /* Load all the presets */
601   p = sfdata->preset;
602   while (p != NULL) {
603     sfpreset = (SFPreset *) p->data;
604     preset = new_fluid_defpreset(sfont);
605     if (preset == NULL) goto err_exit;
606 
607     if (fluid_defpreset_import_sfont(preset, sfpreset, sfont) != FLUID_OK)
608       goto err_exit;
609 
610     fluid_defsfont_add_preset(sfont, preset);
611     p = fluid_list_next(p);
612   }
613   sfont_close (sfdata);
614 
615   return FLUID_OK;
616 
617 err_exit:
618   sfont_close (sfdata);
619   if (preset != NULL)
620     delete_fluid_defpreset(preset);
621   return FLUID_FAILED;
622 }
623 
624 /* fluid_defsfont_add_sample
625  *
626  * Add a sample to the SoundFont
627  */
fluid_defsfont_add_sample(fluid_defsfont_t * sfont,fluid_sample_t * sample)628 int fluid_defsfont_add_sample(fluid_defsfont_t* sfont, fluid_sample_t* sample)
629 {
630   sfont->sample = fluid_list_append(sfont->sample, sample);
631   return FLUID_OK;
632 }
633 
634 /* fluid_defsfont_add_preset
635  *
636  * Add a preset to the SoundFont
637  */
fluid_defsfont_add_preset(fluid_defsfont_t * sfont,fluid_defpreset_t * preset)638 int fluid_defsfont_add_preset(fluid_defsfont_t* sfont, fluid_defpreset_t* preset)
639 {
640   fluid_defpreset_t *cur, *prev;
641   if (sfont->preset == NULL) {
642     preset->next = NULL;
643     sfont->preset = preset;
644   } else {
645     /* sort them as we go along. very basic sorting trick. */
646     cur = sfont->preset;
647     prev = NULL;
648     while (cur != NULL) {
649       if ((preset->bank < cur->bank)
650 	  || ((preset->bank == cur->bank) && (preset->num < cur->num))) {
651 	if (prev == NULL) {
652 	  preset->next = cur;
653 	  sfont->preset = preset;
654 	} else {
655 	  preset->next = cur;
656 	  prev->next = preset;
657 	}
658 	return FLUID_OK;
659       }
660       prev = cur;
661       cur = cur->next;
662     }
663     preset->next = NULL;
664     prev->next = preset;
665   }
666   return FLUID_OK;
667 }
668 
669 /*
670  * fluid_defsfont_load_sampledata
671  */
672 int
fluid_defsfont_load_sampledata(fluid_defsfont_t * sfont)673 fluid_defsfont_load_sampledata(fluid_defsfont_t* sfont)
674 {
675   return fluid_cached_sampledata_load(sfont->filename, sfont->samplepos,
676     sfont->samplesize, &sfont->sampledata, sfont->mlock);
677 }
678 
679 /*
680  * fluid_defsfont_get_preset
681  */
fluid_defsfont_get_preset(fluid_defsfont_t * sfont,unsigned int bank,unsigned int num)682 fluid_defpreset_t* fluid_defsfont_get_preset(fluid_defsfont_t* sfont, unsigned int bank, unsigned int num)
683 {
684   fluid_defpreset_t* preset = sfont->preset;
685   while (preset != NULL) {
686     if ((preset->bank == bank) && ((preset->num == num))) {
687       return preset;
688     }
689     preset = preset->next;
690   }
691   return NULL;
692 }
693 
694 /*
695  * fluid_defsfont_iteration_start
696  */
fluid_defsfont_iteration_start(fluid_defsfont_t * sfont)697 void fluid_defsfont_iteration_start(fluid_defsfont_t* sfont)
698 {
699   sfont->iter_cur = sfont->preset;
700 }
701 
702 /*
703  * fluid_defsfont_iteration_next
704  */
fluid_defsfont_iteration_next(fluid_defsfont_t * sfont,fluid_preset_t * preset)705 int fluid_defsfont_iteration_next(fluid_defsfont_t* sfont, fluid_preset_t* preset)
706 {
707   if (sfont->iter_cur == NULL) {
708     return 0;
709   }
710 
711   preset->data = (void*) sfont->iter_cur;
712   sfont->iter_cur = fluid_defpreset_next(sfont->iter_cur);
713   return 1;
714 }
715 
716 /***************************************************************
717  *
718  *                           PRESET
719  */
720 
721 /*
722  * new_fluid_defpreset
723  */
724 fluid_defpreset_t*
new_fluid_defpreset(fluid_defsfont_t * sfont)725 new_fluid_defpreset(fluid_defsfont_t* sfont)
726 {
727   fluid_defpreset_t* preset = FLUID_NEW(fluid_defpreset_t);
728   if (preset == NULL) {
729     FLUID_LOG(FLUID_ERR, "Out of memory");
730     return NULL;
731   }
732   preset->next = NULL;
733   preset->sfont = sfont;
734   preset->name[0] = 0;
735   preset->bank = 0;
736   preset->num = 0;
737   preset->global_zone = NULL;
738   preset->zone = NULL;
739   return preset;
740 }
741 
742 /*
743  * delete_fluid_defpreset
744  */
745 int
delete_fluid_defpreset(fluid_defpreset_t * preset)746 delete_fluid_defpreset(fluid_defpreset_t* preset)
747 {
748   int err = FLUID_OK;
749   fluid_preset_zone_t* zone;
750   if (preset->global_zone != NULL) {
751     if (delete_fluid_preset_zone(preset->global_zone) != FLUID_OK) {
752       err = FLUID_FAILED;
753     }
754     preset->global_zone = NULL;
755   }
756   zone = preset->zone;
757   while (zone != NULL) {
758     preset->zone = zone->next;
759     if (delete_fluid_preset_zone(zone) != FLUID_OK) {
760       err = FLUID_FAILED;
761     }
762     zone = preset->zone;
763   }
764   FLUID_FREE(preset);
765   return err;
766 }
767 
768 int
fluid_defpreset_get_banknum(fluid_defpreset_t * preset)769 fluid_defpreset_get_banknum(fluid_defpreset_t* preset)
770 {
771   return preset->bank;
772 }
773 
774 int
fluid_defpreset_get_num(fluid_defpreset_t * preset)775 fluid_defpreset_get_num(fluid_defpreset_t* preset)
776 {
777   return preset->num;
778 }
779 
780 char*
fluid_defpreset_get_name(fluid_defpreset_t * preset)781 fluid_defpreset_get_name(fluid_defpreset_t* preset)
782 {
783   return preset->name;
784 }
785 
786 /*
787  * fluid_defpreset_next
788  */
789 fluid_defpreset_t*
fluid_defpreset_next(fluid_defpreset_t * preset)790 fluid_defpreset_next(fluid_defpreset_t* preset)
791 {
792   return preset->next;
793 }
794 
795 
796 /*
797  * fluid_defpreset_noteon
798  */
799 int
fluid_defpreset_noteon(fluid_defpreset_t * preset,fluid_synth_t * synth,int chan,int key,int vel)800 fluid_defpreset_noteon(fluid_defpreset_t* preset, fluid_synth_t* synth, int chan, int key, int vel)
801 {
802   fluid_preset_zone_t *preset_zone, *global_preset_zone;
803   fluid_inst_t* inst;
804   fluid_inst_zone_t *inst_zone, *global_inst_zone;
805   fluid_sample_t* sample;
806   fluid_voice_t* voice;
807   fluid_mod_t * mod;
808   fluid_mod_t * mod_list[FLUID_NUM_MOD]; /* list for 'sorting' preset modulators */
809   int mod_list_count;
810   int i;
811 
812   global_preset_zone = fluid_defpreset_get_global_zone(preset);
813 
814   /* run thru all the zones of this preset */
815   preset_zone = fluid_defpreset_get_zone(preset);
816   while (preset_zone != NULL) {
817 
818     /* check if the note falls into the key and velocity range of this
819        preset */
820     if (fluid_preset_zone_inside_range(preset_zone, key, vel)) {
821 
822       inst = fluid_preset_zone_get_inst(preset_zone);
823       global_inst_zone = fluid_inst_get_global_zone(inst);
824 
825       /* run thru all the zones of this instrument */
826       inst_zone = fluid_inst_get_zone(inst);
827 	  while (inst_zone != NULL) {
828 
829 	/* make sure this instrument zone has a valid sample */
830 	sample = fluid_inst_zone_get_sample(inst_zone);
831 	if ((sample == NULL) || fluid_sample_in_rom(sample)) {
832 	  inst_zone = fluid_inst_zone_next(inst_zone);
833 	  continue;
834 	}
835 
836 	/* check if the note falls into the key and velocity range of this
837 	   instrument */
838 
839 	if (fluid_inst_zone_inside_range(inst_zone, key, vel) && (sample != NULL)) {
840 
841 	  /* this is a good zone. allocate a new synthesis process and
842              initialize it */
843 
844 	  voice = fluid_synth_alloc_voice(synth, sample, chan, key, vel);
845 	  if (voice == NULL) {
846 	    return FLUID_FAILED;
847 	  }
848 
849 
850 	  /* Instrument level, generators */
851 
852 	  for (i = 0; i < GEN_LAST; i++) {
853 
854 	    /* SF 2.01 section 9.4 'bullet' 4:
855 	     *
856 	     * A generator in a local instrument zone supersedes a
857 	     * global instrument zone generator.  Both cases supersede
858 	     * the default generator -> voice_gen_set */
859 
860 	    if (inst_zone->gen[i].flags){
861 	      fluid_voice_gen_set(voice, i, inst_zone->gen[i].val);
862 
863 	    } else if ((global_inst_zone != NULL) && (global_inst_zone->gen[i].flags)) {
864 	      fluid_voice_gen_set(voice, i, global_inst_zone->gen[i].val);
865 
866 	    } else {
867 	      /* The generator has not been defined in this instrument.
868 	       * Do nothing, leave it at the default.
869 	       */
870 	    }
871 
872 	  } /* for all generators */
873 
874 	  /* global instrument zone, modulators: Put them all into a
875 	   * list. */
876 
877 	  mod_list_count = 0;
878 
879 	  if (global_inst_zone){
880 	    mod = global_inst_zone->mod;
881 	    while (mod){
882 	      mod_list[mod_list_count++] = mod;
883 	      mod = mod->next;
884 	    }
885 	  }
886 
887 	  /* local instrument zone, modulators.
888 	   * Replace modulators with the same definition in the list:
889 	   * SF 2.01 page 69, 'bullet' 8
890 	   */
891 	  mod = inst_zone->mod;
892 
893 	  while (mod){
894 
895 	    /* 'Identical' modulators will be deleted by setting their
896 	     *  list entry to NULL.  The list length is known, NULL
897 	     *  entries will be ignored later.  SF2.01 section 9.5.1
898 	     *  page 69, 'bullet' 3 defines 'identical'.  */
899 
900 	    for (i = 0; i < mod_list_count; i++){
901 	      if (mod_list[i] && fluid_mod_test_identity(mod,mod_list[i])){
902 		mod_list[i] = NULL;
903 	      }
904 	    }
905 
906 	    /* Finally add the new modulator to to the list. */
907 	    mod_list[mod_list_count++] = mod;
908 	    mod = mod->next;
909 	  }
910 
911 	  /* Add instrument modulators (global / local) to the voice. */
912 	  for (i = 0; i < mod_list_count; i++){
913 
914 	    mod = mod_list[i];
915 
916 	    if (mod != NULL){ /* disabled modulators CANNOT be skipped. */
917 
918 	      /* Instrument modulators -supersede- existing (default)
919 	       * modulators.  SF 2.01 page 69, 'bullet' 6 */
920 	      fluid_voice_add_mod(voice, mod, FLUID_VOICE_OVERWRITE);
921 	    }
922 	  }
923 
924 	  /* Preset level, generators */
925 
926 	  for (i = 0; i < GEN_LAST; i++) {
927 
928 	    /* SF 2.01 section 8.5 page 58: If some generators are
929 	     * encountered at preset level, they should be ignored */
930 	    if ((i != GEN_STARTADDROFS)
931 		&& (i != GEN_ENDADDROFS)
932 		&& (i != GEN_STARTLOOPADDROFS)
933 		&& (i != GEN_ENDLOOPADDROFS)
934 		&& (i != GEN_STARTADDRCOARSEOFS)
935 		&& (i != GEN_ENDADDRCOARSEOFS)
936 		&& (i != GEN_STARTLOOPADDRCOARSEOFS)
937 		&& (i != GEN_KEYNUM)
938 		&& (i != GEN_VELOCITY)
939 		&& (i != GEN_ENDLOOPADDRCOARSEOFS)
940 		&& (i != GEN_SAMPLEMODE)
941 		&& (i != GEN_EXCLUSIVECLASS)
942 		&& (i != GEN_OVERRIDEROOTKEY)) {
943 
944 	      /* SF 2.01 section 9.4 'bullet' 9: A generator in a
945 	       * local preset zone supersedes a global preset zone
946 	       * generator.  The effect is -added- to the destination
947 	       * summing node -> voice_gen_incr */
948 
949 	      if (preset_zone->gen[i].flags) {
950 		fluid_voice_gen_incr(voice, i, preset_zone->gen[i].val);
951 	      } else if ((global_preset_zone != NULL) && global_preset_zone->gen[i].flags) {
952 		fluid_voice_gen_incr(voice, i, global_preset_zone->gen[i].val);
953 	      } else {
954 		/* The generator has not been defined in this preset
955 		 * Do nothing, leave it unchanged.
956 		 */
957 	      }
958 	    } /* if available at preset level */
959 	  } /* for all generators */
960 
961 
962 	  /* Global preset zone, modulators: put them all into a
963 	   * list. */
964 	  mod_list_count = 0;
965 	  if (global_preset_zone){
966 	    mod = global_preset_zone->mod;
967 	    while (mod){
968 	      mod_list[mod_list_count++] = mod;
969 	      mod = mod->next;
970 	    }
971 	  }
972 
973 	  /* Process the modulators of the local preset zone.  Kick
974 	   * out all identical modulators from the global preset zone
975 	   * (SF 2.01 page 69, second-last bullet) */
976 
977 	  mod = preset_zone->mod;
978 	  while (mod){
979 	    for (i = 0; i < mod_list_count; i++){
980 	      if (mod_list[i] && fluid_mod_test_identity(mod,mod_list[i])){
981 		mod_list[i] = NULL;
982 	      }
983 	    }
984 
985 	    /* Finally add the new modulator to the list. */
986 	    mod_list[mod_list_count++] = mod;
987 	    mod = mod->next;
988 	  }
989 
990 	  /* Add preset modulators (global / local) to the voice. */
991 	  for (i = 0; i < mod_list_count; i++){
992 	    mod = mod_list[i];
993 	    if ((mod != NULL) && (mod->amount != 0)) { /* disabled modulators can be skipped. */
994 
995 	      /* Preset modulators -add- to existing instrument /
996 	       * default modulators.  SF2.01 page 70 first bullet on
997 	       * page */
998 	      fluid_voice_add_mod(voice, mod, FLUID_VOICE_ADD);
999 	    }
1000 	  }
1001 
1002 	  /* add the synthesis process to the synthesis loop. */
1003 	  fluid_synth_start_voice(synth, voice);
1004 
1005 	  /* Store the ID of the first voice that was created by this noteon event.
1006 	   * Exclusive class may only terminate older voices.
1007 	   * That avoids killing voices, which have just been created.
1008 	   * (a noteon event can create several voice processes with the same exclusive
1009 	   * class - for example when using stereo samples)
1010 	   */
1011 	}
1012 
1013 	inst_zone = fluid_inst_zone_next(inst_zone);
1014       }
1015 	}
1016     preset_zone = fluid_preset_zone_next(preset_zone);
1017   }
1018 
1019   return FLUID_OK;
1020 }
1021 
1022 /*
1023  * fluid_defpreset_set_global_zone
1024  */
1025 int
fluid_defpreset_set_global_zone(fluid_defpreset_t * preset,fluid_preset_zone_t * zone)1026 fluid_defpreset_set_global_zone(fluid_defpreset_t* preset, fluid_preset_zone_t* zone)
1027 {
1028   preset->global_zone = zone;
1029   return FLUID_OK;
1030 }
1031 
1032 /*
1033  * fluid_defpreset_import_sfont
1034  */
1035 int
fluid_defpreset_import_sfont(fluid_defpreset_t * preset,SFPreset * sfpreset,fluid_defsfont_t * sfont)1036 fluid_defpreset_import_sfont(fluid_defpreset_t* preset,
1037 			     SFPreset* sfpreset,
1038 			     fluid_defsfont_t* sfont)
1039 {
1040   fluid_list_t *p;
1041   SFZone* sfzone;
1042   fluid_preset_zone_t* zone;
1043   int count;
1044   char zone_name[256];
1045   if ((sfpreset->name != NULL) && (FLUID_STRLEN(sfpreset->name) > 0)) {
1046     FLUID_STRCPY(preset->name, sfpreset->name);
1047   } else {
1048     FLUID_SPRINTF(preset->name, "Bank%d,Preset%d", sfpreset->bank, sfpreset->prenum);
1049   }
1050   preset->bank = sfpreset->bank;
1051   preset->num = sfpreset->prenum;
1052   p = sfpreset->zone;
1053   count = 0;
1054   while (p != NULL) {
1055     sfzone = (SFZone *) p->data;
1056     FLUID_SPRINTF(zone_name, "%s/%d", preset->name, count);
1057     zone = new_fluid_preset_zone(zone_name);
1058     if (zone == NULL) {
1059       return FLUID_FAILED;
1060     }
1061     if (fluid_preset_zone_import_sfont(zone, sfzone, sfont) != FLUID_OK) {
1062       delete_fluid_preset_zone(zone);
1063       return FLUID_FAILED;
1064     }
1065     if ((count == 0) && (fluid_preset_zone_get_inst(zone) == NULL)) {
1066       fluid_defpreset_set_global_zone(preset, zone);
1067     } else if (fluid_defpreset_add_zone(preset, zone) != FLUID_OK) {
1068       return FLUID_FAILED;
1069     }
1070     p = fluid_list_next(p);
1071     count++;
1072   }
1073   return FLUID_OK;
1074 }
1075 
1076 /*
1077  * fluid_defpreset_add_zone
1078  */
1079 int
fluid_defpreset_add_zone(fluid_defpreset_t * preset,fluid_preset_zone_t * zone)1080 fluid_defpreset_add_zone(fluid_defpreset_t* preset, fluid_preset_zone_t* zone)
1081 {
1082   if (preset->zone == NULL) {
1083     zone->next = NULL;
1084     preset->zone = zone;
1085   } else {
1086     zone->next = preset->zone;
1087     preset->zone = zone;
1088   }
1089   return FLUID_OK;
1090 }
1091 
1092 /*
1093  * fluid_defpreset_get_zone
1094  */
1095 fluid_preset_zone_t*
fluid_defpreset_get_zone(fluid_defpreset_t * preset)1096 fluid_defpreset_get_zone(fluid_defpreset_t* preset)
1097 {
1098   return preset->zone;
1099 }
1100 
1101 /*
1102  * fluid_defpreset_get_global_zone
1103  */
1104 fluid_preset_zone_t*
fluid_defpreset_get_global_zone(fluid_defpreset_t * preset)1105 fluid_defpreset_get_global_zone(fluid_defpreset_t* preset)
1106 {
1107   return preset->global_zone;
1108 }
1109 
1110 /*
1111  * fluid_preset_zone_next
1112  */
1113 fluid_preset_zone_t*
fluid_preset_zone_next(fluid_preset_zone_t * preset)1114 fluid_preset_zone_next(fluid_preset_zone_t* preset)
1115 {
1116   return preset->next;
1117 }
1118 
1119 /*
1120  * new_fluid_preset_zone
1121  */
1122 fluid_preset_zone_t*
new_fluid_preset_zone(char * name)1123 new_fluid_preset_zone(char *name)
1124 {
1125   int size;
1126   fluid_preset_zone_t* zone = NULL;
1127   zone = FLUID_NEW(fluid_preset_zone_t);
1128   if (zone == NULL) {
1129     FLUID_LOG(FLUID_ERR, "Out of memory");
1130     return NULL;
1131   }
1132   zone->next = NULL;
1133   size = 1 + FLUID_STRLEN(name);
1134   zone->name = FLUID_MALLOC(size);
1135   if (zone->name == NULL) {
1136     FLUID_LOG(FLUID_ERR, "Out of memory");
1137     FLUID_FREE(zone);
1138     return NULL;
1139   }
1140   FLUID_STRCPY(zone->name, name);
1141   zone->inst = NULL;
1142   zone->keylo = 0;
1143   zone->keyhi = 128;
1144   zone->vello = 0;
1145   zone->velhi = 128;
1146 
1147   /* Flag all generators as unused (default, they will be set when they are found
1148    * in the sound font).
1149    * This also sets the generator values to default, but that is of no concern here.*/
1150   fluid_gen_set_default_values(&zone->gen[0]);
1151   zone->mod = NULL; /* list of modulators */
1152   return zone;
1153 }
1154 
1155 /***************************************************************
1156  *
1157  *                           PRESET_ZONE
1158  */
1159 
1160 /*
1161  * delete_fluid_preset_zone
1162  */
1163 int
delete_fluid_preset_zone(fluid_preset_zone_t * zone)1164 delete_fluid_preset_zone(fluid_preset_zone_t* zone)
1165 {
1166   fluid_mod_t *mod, *tmp;
1167 
1168   mod = zone->mod;
1169   while (mod)	/* delete the modulators */
1170     {
1171       tmp = mod;
1172       mod = mod->next;
1173       fluid_mod_delete (tmp);
1174     }
1175 
1176   if (zone->name) FLUID_FREE (zone->name);
1177   if (zone->inst) delete_fluid_inst (zone->inst);
1178   FLUID_FREE(zone);
1179   return FLUID_OK;
1180 }
1181 
1182 /*
1183  * fluid_preset_zone_import_sfont
1184  */
1185 int
fluid_preset_zone_import_sfont(fluid_preset_zone_t * zone,SFZone * sfzone,fluid_defsfont_t * sfont)1186 fluid_preset_zone_import_sfont(fluid_preset_zone_t* zone, SFZone *sfzone, fluid_defsfont_t* sfont)
1187 {
1188   fluid_list_t *r;
1189   SFGen* sfgen;
1190   int count;
1191   for (count = 0, r = sfzone->gen; r != NULL; count++) {
1192     sfgen = (SFGen *) r->data;
1193     switch (sfgen->id) {
1194     case GEN_KEYRANGE:
1195       zone->keylo = (int) sfgen->amount.range.lo;
1196       zone->keyhi = (int) sfgen->amount.range.hi;
1197       break;
1198     case GEN_VELRANGE:
1199       zone->vello = (int) sfgen->amount.range.lo;
1200       zone->velhi = (int) sfgen->amount.range.hi;
1201       break;
1202     default:
1203       /* FIXME: some generators have an unsigne word amount value but i don't know which ones */
1204       zone->gen[sfgen->id].val = (fluid_real_t) sfgen->amount.sword;
1205       zone->gen[sfgen->id].flags = GEN_SET;
1206       break;
1207     }
1208     r = fluid_list_next(r);
1209   }
1210   if ((sfzone->instsamp != NULL) && (sfzone->instsamp->data != NULL)) {
1211     zone->inst = (fluid_inst_t*) new_fluid_inst();
1212     if (zone->inst == NULL) {
1213       FLUID_LOG(FLUID_ERR, "Out of memory");
1214       return FLUID_FAILED;
1215     }
1216     if (fluid_inst_import_sfont(zone->inst, (SFInst *) sfzone->instsamp->data, sfont) != FLUID_OK) {
1217       return FLUID_FAILED;
1218     }
1219   }
1220 
1221   /* Import the modulators (only SF2.1 and higher) */
1222   for (count = 0, r = sfzone->mod; r != NULL; count++) {
1223 
1224     SFMod* mod_src = (SFMod *)r->data;
1225     fluid_mod_t * mod_dest = fluid_mod_new();
1226     int type;
1227 
1228     if (mod_dest == NULL){
1229       return FLUID_FAILED;
1230     }
1231     mod_dest->next = NULL; /* pointer to next modulator, this is the end of the list now.*/
1232 
1233     /* *** Amount *** */
1234     mod_dest->amount = mod_src->amount;
1235 
1236     /* *** Source *** */
1237     mod_dest->src1 = mod_src->src & 127; /* index of source 1, seven-bit value, SF2.01 section 8.2, page 50 */
1238     mod_dest->flags1 = 0;
1239 
1240     /* Bit 7: CC flag SF 2.01 section 8.2.1 page 50*/
1241     if (mod_src->src & (1<<7)){
1242       mod_dest->flags1 |= FLUID_MOD_CC;
1243     } else {
1244       mod_dest->flags1 |= FLUID_MOD_GC;
1245     }
1246 
1247     /* Bit 8: D flag SF 2.01 section 8.2.2 page 51*/
1248     if (mod_src->src & (1<<8)){
1249       mod_dest->flags1 |= FLUID_MOD_NEGATIVE;
1250     } else {
1251       mod_dest->flags1 |= FLUID_MOD_POSITIVE;
1252     }
1253 
1254     /* Bit 9: P flag SF 2.01 section 8.2.3 page 51*/
1255     if (mod_src->src & (1<<9)){
1256       mod_dest->flags1 |= FLUID_MOD_BIPOLAR;
1257     } else {
1258       mod_dest->flags1 |= FLUID_MOD_UNIPOLAR;
1259     }
1260 
1261     /* modulator source types: SF2.01 section 8.2.1 page 52 */
1262     type=(mod_src->src) >> 10;
1263     type &= 63; /* type is a 6-bit value */
1264     if (type == 0){
1265       mod_dest->flags1 |= FLUID_MOD_LINEAR;
1266     } else if (type == 1){
1267       mod_dest->flags1 |= FLUID_MOD_CONCAVE;
1268     } else if (type == 2){
1269       mod_dest->flags1 |= FLUID_MOD_CONVEX;
1270     } else if (type == 3){
1271       mod_dest->flags1 |= FLUID_MOD_SWITCH;
1272     } else {
1273       /* This shouldn't happen - unknown type!
1274        * Deactivate the modulator by setting the amount to 0. */
1275       mod_dest->amount=0;
1276     }
1277 
1278     /* *** Dest *** */
1279     mod_dest->dest = mod_src->dest; /* index of controlled generator */
1280 
1281     /* *** Amount source *** */
1282     mod_dest->src2 = mod_src->amtsrc & 127; /* index of source 2, seven-bit value, SF2.01 section 8.2, p.50 */
1283     mod_dest->flags2 = 0;
1284 
1285     /* Bit 7: CC flag SF 2.01 section 8.2.1 page 50*/
1286     if (mod_src->amtsrc & (1<<7)){
1287       mod_dest->flags2 |= FLUID_MOD_CC;
1288     } else {
1289       mod_dest->flags2 |= FLUID_MOD_GC;
1290     }
1291 
1292     /* Bit 8: D flag SF 2.01 section 8.2.2 page 51*/
1293     if (mod_src->amtsrc & (1<<8)){
1294       mod_dest->flags2 |= FLUID_MOD_NEGATIVE;
1295     } else {
1296       mod_dest->flags2 |= FLUID_MOD_POSITIVE;
1297     }
1298 
1299     /* Bit 9: P flag SF 2.01 section 8.2.3 page 51*/
1300     if (mod_src->amtsrc & (1<<9)){
1301       mod_dest->flags2 |= FLUID_MOD_BIPOLAR;
1302     } else {
1303       mod_dest->flags2 |= FLUID_MOD_UNIPOLAR;
1304     }
1305 
1306     /* modulator source types: SF2.01 section 8.2.1 page 52 */
1307     type = (mod_src->amtsrc) >> 10;
1308     type &= 63; /* type is a 6-bit value */
1309     if (type == 0){
1310       mod_dest->flags2 |= FLUID_MOD_LINEAR;
1311     } else if (type == 1){
1312       mod_dest->flags2 |= FLUID_MOD_CONCAVE;
1313     } else if (type == 2){
1314       mod_dest->flags2 |= FLUID_MOD_CONVEX;
1315     } else if (type == 3){
1316       mod_dest->flags2 |= FLUID_MOD_SWITCH;
1317     } else {
1318       /* This shouldn't happen - unknown type!
1319        * Deactivate the modulator by setting the amount to 0. */
1320       mod_dest->amount=0;
1321     }
1322 
1323     /* *** Transform *** */
1324     /* SF2.01 only uses the 'linear' transform (0).
1325      * Deactivate the modulator by setting the amount to 0 in any other case.
1326      */
1327     if (mod_src->trans !=0){
1328       mod_dest->amount = 0;
1329     }
1330 
1331     /* Store the new modulator in the zone The order of modulators
1332      * will make a difference, at least in an instrument context: The
1333      * second modulator overwrites the first one, if they only differ
1334      * in amount. */
1335     if (count == 0){
1336       zone->mod = mod_dest;
1337     } else {
1338       fluid_mod_t * last_mod = zone->mod;
1339 
1340       /* Find the end of the list */
1341       while (last_mod->next != NULL){
1342 	last_mod=last_mod->next;
1343       }
1344 
1345       last_mod->next = mod_dest;
1346     }
1347 
1348     r = fluid_list_next(r);
1349   } /* foreach modulator */
1350 
1351   return FLUID_OK;
1352 }
1353 
1354 /*
1355  * fluid_preset_zone_get_inst
1356  */
1357 fluid_inst_t*
fluid_preset_zone_get_inst(fluid_preset_zone_t * zone)1358 fluid_preset_zone_get_inst(fluid_preset_zone_t* zone)
1359 {
1360   return zone->inst;
1361 }
1362 
1363 /*
1364  * fluid_preset_zone_inside_range
1365  */
1366 int
fluid_preset_zone_inside_range(fluid_preset_zone_t * zone,int key,int vel)1367 fluid_preset_zone_inside_range(fluid_preset_zone_t* zone, int key, int vel)
1368 {
1369   return ((zone->keylo <= key) &&
1370 	  (zone->keyhi >= key) &&
1371 	  (zone->vello <= vel) &&
1372 	  (zone->velhi >= vel));
1373 }
1374 
1375 /***************************************************************
1376  *
1377  *                           INST
1378  */
1379 
1380 /*
1381  * new_fluid_inst
1382  */
1383 fluid_inst_t*
new_fluid_inst()1384 new_fluid_inst()
1385 {
1386   fluid_inst_t* inst = FLUID_NEW(fluid_inst_t);
1387   if (inst == NULL) {
1388     FLUID_LOG(FLUID_ERR, "Out of memory");
1389     return NULL;
1390   }
1391   inst->name[0] = 0;
1392   inst->global_zone = NULL;
1393   inst->zone = NULL;
1394   return inst;
1395 }
1396 
1397 /*
1398  * delete_fluid_inst
1399  */
1400 int
delete_fluid_inst(fluid_inst_t * inst)1401 delete_fluid_inst(fluid_inst_t* inst)
1402 {
1403   fluid_inst_zone_t* zone;
1404   int err = FLUID_OK;
1405   if (inst->global_zone != NULL) {
1406     if (delete_fluid_inst_zone(inst->global_zone) != FLUID_OK) {
1407       err = FLUID_FAILED;
1408     }
1409     inst->global_zone = NULL;
1410   }
1411   zone = inst->zone;
1412   while (zone != NULL) {
1413     inst->zone = zone->next;
1414     if (delete_fluid_inst_zone(zone) != FLUID_OK) {
1415       err = FLUID_FAILED;
1416     }
1417     zone = inst->zone;
1418   }
1419   FLUID_FREE(inst);
1420   return err;
1421 }
1422 
1423 /*
1424  * fluid_inst_set_global_zone
1425  */
1426 int
fluid_inst_set_global_zone(fluid_inst_t * inst,fluid_inst_zone_t * zone)1427 fluid_inst_set_global_zone(fluid_inst_t* inst, fluid_inst_zone_t* zone)
1428 {
1429   inst->global_zone = zone;
1430   return FLUID_OK;
1431 }
1432 
1433 /*
1434  * fluid_inst_import_sfont
1435  */
1436 int
fluid_inst_import_sfont(fluid_inst_t * inst,SFInst * sfinst,fluid_defsfont_t * sfont)1437 fluid_inst_import_sfont(fluid_inst_t* inst, SFInst *sfinst, fluid_defsfont_t* sfont)
1438 {
1439   fluid_list_t *p;
1440   SFZone* sfzone;
1441   fluid_inst_zone_t* zone;
1442   char zone_name[256];
1443   int count;
1444 
1445   p = sfinst->zone;
1446   if ((sfinst->name != NULL) && (FLUID_STRLEN(sfinst->name) > 0)) {
1447     FLUID_STRCPY(inst->name, sfinst->name);
1448   } else {
1449     FLUID_STRCPY(inst->name, "<untitled>");
1450   }
1451 
1452   count = 0;
1453   while (p != NULL) {
1454 
1455     sfzone = (SFZone *) p->data;
1456     FLUID_SPRINTF(zone_name, "%s/%d", inst->name, count);
1457 
1458     zone = new_fluid_inst_zone(zone_name);
1459     if (zone == NULL) {
1460       return FLUID_FAILED;
1461     }
1462 
1463     if (fluid_inst_zone_import_sfont(zone, sfzone, sfont) != FLUID_OK) {
1464       delete_fluid_inst_zone(zone);
1465       return FLUID_FAILED;
1466     }
1467 
1468     if ((count == 0) && (fluid_inst_zone_get_sample(zone) == NULL)) {
1469       fluid_inst_set_global_zone(inst, zone);
1470 
1471     } else if (fluid_inst_add_zone(inst, zone) != FLUID_OK) {
1472       return FLUID_FAILED;
1473     }
1474 
1475     p = fluid_list_next(p);
1476     count++;
1477   }
1478   return FLUID_OK;
1479 }
1480 
1481 /*
1482  * fluid_inst_add_zone
1483  */
1484 int
fluid_inst_add_zone(fluid_inst_t * inst,fluid_inst_zone_t * zone)1485 fluid_inst_add_zone(fluid_inst_t* inst, fluid_inst_zone_t* zone)
1486 {
1487   if (inst->zone == NULL) {
1488     zone->next = NULL;
1489     inst->zone = zone;
1490   } else {
1491     zone->next = inst->zone;
1492     inst->zone = zone;
1493   }
1494   return FLUID_OK;
1495 }
1496 
1497 /*
1498  * fluid_inst_get_zone
1499  */
1500 fluid_inst_zone_t*
fluid_inst_get_zone(fluid_inst_t * inst)1501 fluid_inst_get_zone(fluid_inst_t* inst)
1502 {
1503   return inst->zone;
1504 }
1505 
1506 /*
1507  * fluid_inst_get_global_zone
1508  */
1509 fluid_inst_zone_t*
fluid_inst_get_global_zone(fluid_inst_t * inst)1510 fluid_inst_get_global_zone(fluid_inst_t* inst)
1511 {
1512   return inst->global_zone;
1513 }
1514 
1515 /***************************************************************
1516  *
1517  *                           INST_ZONE
1518  */
1519 
1520 /*
1521  * new_fluid_inst_zone
1522  */
1523 fluid_inst_zone_t*
new_fluid_inst_zone(char * name)1524 new_fluid_inst_zone(char* name)
1525 {
1526   int size;
1527   fluid_inst_zone_t* zone = NULL;
1528   zone = FLUID_NEW(fluid_inst_zone_t);
1529   if (zone == NULL) {
1530     FLUID_LOG(FLUID_ERR, "Out of memory");
1531     return NULL;
1532   }
1533   zone->next = NULL;
1534   size = 1 + FLUID_STRLEN(name);
1535   zone->name = FLUID_MALLOC(size);
1536   if (zone->name == NULL) {
1537     FLUID_LOG(FLUID_ERR, "Out of memory");
1538     FLUID_FREE(zone);
1539     return NULL;
1540   }
1541   FLUID_STRCPY(zone->name, name);
1542   zone->sample = NULL;
1543   zone->keylo = 0;
1544   zone->keyhi = 128;
1545   zone->vello = 0;
1546   zone->velhi = 128;
1547 
1548   /* Flag the generators as unused.
1549    * This also sets the generator values to default, but they will be overwritten anyway, if used.*/
1550   fluid_gen_set_default_values(&zone->gen[0]);
1551   zone->mod=NULL; /* list of modulators */
1552   return zone;
1553 }
1554 
1555 /*
1556  * delete_fluid_inst_zone
1557  */
1558 int
delete_fluid_inst_zone(fluid_inst_zone_t * zone)1559 delete_fluid_inst_zone(fluid_inst_zone_t* zone)
1560 {
1561   fluid_mod_t *mod, *tmp;
1562 
1563   mod = zone->mod;
1564   while (mod)	/* delete the modulators */
1565     {
1566       tmp = mod;
1567       mod = mod->next;
1568       fluid_mod_delete (tmp);
1569     }
1570 
1571   if (zone->name) FLUID_FREE (zone->name);
1572   FLUID_FREE(zone);
1573   return FLUID_OK;
1574 }
1575 
1576 /*
1577  * fluid_inst_zone_next
1578  */
1579 fluid_inst_zone_t*
fluid_inst_zone_next(fluid_inst_zone_t * zone)1580 fluid_inst_zone_next(fluid_inst_zone_t* zone)
1581 {
1582   return zone->next;
1583 }
1584 
1585 /*
1586  * fluid_inst_zone_import_sfont
1587  */
1588 int
fluid_inst_zone_import_sfont(fluid_inst_zone_t * zone,SFZone * sfzone,fluid_defsfont_t * sfont)1589 fluid_inst_zone_import_sfont(fluid_inst_zone_t* zone, SFZone *sfzone, fluid_defsfont_t* sfont)
1590 {
1591   fluid_list_t *r;
1592   SFGen* sfgen;
1593   int count;
1594 
1595   for (count = 0, r = sfzone->gen; r != NULL; count++) {
1596     sfgen = (SFGen *) r->data;
1597     switch (sfgen->id) {
1598     case GEN_KEYRANGE:
1599       zone->keylo = (int) sfgen->amount.range.lo;
1600       zone->keyhi = (int) sfgen->amount.range.hi;
1601       break;
1602     case GEN_VELRANGE:
1603       zone->vello = (int) sfgen->amount.range.lo;
1604       zone->velhi = (int) sfgen->amount.range.hi;
1605       break;
1606     default:
1607       /* FIXME: some generators have an unsigned word amount value but
1608 	 i don't know which ones */
1609       zone->gen[sfgen->id].val = (fluid_real_t) sfgen->amount.sword;
1610       zone->gen[sfgen->id].flags = GEN_SET;
1611       break;
1612     }
1613     r = fluid_list_next(r);
1614   }
1615 
1616   /* FIXME */
1617 /*    if (zone->gen[GEN_EXCLUSIVECLASS].flags == GEN_SET) { */
1618 /*      FLUID_LOG(FLUID_DBG, "ExclusiveClass=%d\n", (int) zone->gen[GEN_EXCLUSIVECLASS].val); */
1619 /*    } */
1620 
1621   /* fixup sample pointer */
1622   if ((sfzone->instsamp != NULL) && (sfzone->instsamp->data != NULL))
1623     zone->sample = ((SFSample *)(sfzone->instsamp->data))->fluid_sample;
1624 
1625   /* Import the modulators (only SF2.1 and higher) */
1626   for (count = 0, r = sfzone->mod; r != NULL; count++) {
1627     SFMod* mod_src = (SFMod *) r->data;
1628     int type;
1629     fluid_mod_t* mod_dest;
1630 
1631     mod_dest = fluid_mod_new();
1632     if (mod_dest == NULL){
1633       return FLUID_FAILED;
1634     }
1635 
1636     mod_dest->next = NULL; /* pointer to next modulator, this is the end of the list now.*/
1637 
1638     /* *** Amount *** */
1639     mod_dest->amount = mod_src->amount;
1640 
1641     /* *** Source *** */
1642     mod_dest->src1 = mod_src->src & 127; /* index of source 1, seven-bit value, SF2.01 section 8.2, page 50 */
1643     mod_dest->flags1 = 0;
1644 
1645     /* Bit 7: CC flag SF 2.01 section 8.2.1 page 50*/
1646     if (mod_src->src & (1<<7)){
1647       mod_dest->flags1 |= FLUID_MOD_CC;
1648     } else {
1649       mod_dest->flags1 |= FLUID_MOD_GC;
1650     }
1651 
1652     /* Bit 8: D flag SF 2.01 section 8.2.2 page 51*/
1653     if (mod_src->src & (1<<8)){
1654       mod_dest->flags1 |= FLUID_MOD_NEGATIVE;
1655     } else {
1656       mod_dest->flags1 |= FLUID_MOD_POSITIVE;
1657     }
1658 
1659     /* Bit 9: P flag SF 2.01 section 8.2.3 page 51*/
1660     if (mod_src->src & (1<<9)){
1661       mod_dest->flags1 |= FLUID_MOD_BIPOLAR;
1662     } else {
1663       mod_dest->flags1 |= FLUID_MOD_UNIPOLAR;
1664     }
1665 
1666     /* modulator source types: SF2.01 section 8.2.1 page 52 */
1667     type = (mod_src->src) >> 10;
1668     type &= 63; /* type is a 6-bit value */
1669     if (type == 0){
1670       mod_dest->flags1 |= FLUID_MOD_LINEAR;
1671     } else if (type == 1){
1672       mod_dest->flags1 |= FLUID_MOD_CONCAVE;
1673     } else if (type == 2){
1674       mod_dest->flags1 |= FLUID_MOD_CONVEX;
1675     } else if (type == 3){
1676       mod_dest->flags1 |= FLUID_MOD_SWITCH;
1677     } else {
1678       /* This shouldn't happen - unknown type!
1679        * Deactivate the modulator by setting the amount to 0. */
1680       mod_dest->amount = 0;
1681     }
1682 
1683     /* *** Dest *** */
1684     mod_dest->dest=mod_src->dest; /* index of controlled generator */
1685 
1686     /* *** Amount source *** */
1687     mod_dest->src2=mod_src->amtsrc & 127; /* index of source 2, seven-bit value, SF2.01 section 8.2, page 50 */
1688     mod_dest->flags2 = 0;
1689 
1690     /* Bit 7: CC flag SF 2.01 section 8.2.1 page 50*/
1691     if (mod_src->amtsrc & (1<<7)){
1692       mod_dest->flags2 |= FLUID_MOD_CC;
1693     } else {
1694       mod_dest->flags2 |= FLUID_MOD_GC;
1695     }
1696 
1697     /* Bit 8: D flag SF 2.01 section 8.2.2 page 51*/
1698     if (mod_src->amtsrc & (1<<8)){
1699       mod_dest->flags2 |= FLUID_MOD_NEGATIVE;
1700     } else {
1701       mod_dest->flags2 |= FLUID_MOD_POSITIVE;
1702     }
1703 
1704     /* Bit 9: P flag SF 2.01 section 8.2.3 page 51*/
1705     if (mod_src->amtsrc & (1<<9)){
1706       mod_dest->flags2 |= FLUID_MOD_BIPOLAR;
1707     } else {
1708       mod_dest->flags2 |= FLUID_MOD_UNIPOLAR;
1709     }
1710 
1711     /* modulator source types: SF2.01 section 8.2.1 page 52 */
1712     type=(mod_src->amtsrc) >> 10;
1713     type &= 63; /* type is a 6-bit value */
1714     if (type == 0){
1715       mod_dest->flags2 |= FLUID_MOD_LINEAR;
1716     } else if (type == 1){
1717       mod_dest->flags2 |= FLUID_MOD_CONCAVE;
1718     } else if (type == 2){
1719       mod_dest->flags2 |= FLUID_MOD_CONVEX;
1720     } else if (type == 3){
1721       mod_dest->flags2 |= FLUID_MOD_SWITCH;
1722     } else {
1723       /* This shouldn't happen - unknown type!
1724        * Deactivate the modulator by setting the amount to 0. */
1725       mod_dest->amount = 0;
1726     }
1727 
1728     /* *** Transform *** */
1729     /* SF2.01 only uses the 'linear' transform (0).
1730      * Deactivate the modulator by setting the amount to 0 in any other case.
1731      */
1732     if (mod_src->trans !=0){
1733       mod_dest->amount = 0;
1734     }
1735 
1736     /* Store the new modulator in the zone
1737      * The order of modulators will make a difference, at least in an instrument context:
1738      * The second modulator overwrites the first one, if they only differ in amount. */
1739     if (count == 0){
1740       zone->mod=mod_dest;
1741     } else {
1742       fluid_mod_t * last_mod=zone->mod;
1743       /* Find the end of the list */
1744       while (last_mod->next != NULL){
1745 	last_mod=last_mod->next;
1746       }
1747       last_mod->next=mod_dest;
1748     }
1749 
1750     r = fluid_list_next(r);
1751   } /* foreach modulator */
1752   return FLUID_OK;
1753 }
1754 
1755 /*
1756  * fluid_inst_zone_get_sample
1757  */
1758 fluid_sample_t*
fluid_inst_zone_get_sample(fluid_inst_zone_t * zone)1759 fluid_inst_zone_get_sample(fluid_inst_zone_t* zone)
1760 {
1761   return zone->sample;
1762 }
1763 
1764 /*
1765  * fluid_inst_zone_inside_range
1766  */
1767 int
fluid_inst_zone_inside_range(fluid_inst_zone_t * zone,int key,int vel)1768 fluid_inst_zone_inside_range(fluid_inst_zone_t* zone, int key, int vel)
1769 {
1770   return ((zone->keylo <= key) &&
1771 	  (zone->keyhi >= key) &&
1772 	  (zone->vello <= vel) &&
1773 	  (zone->velhi >= vel));
1774 }
1775 
1776 /***************************************************************
1777  *
1778  *                           SAMPLE
1779  */
1780 
1781 /*
1782  * new_fluid_sample
1783  */
1784 fluid_sample_t*
new_fluid_sample()1785 new_fluid_sample()
1786 {
1787   fluid_sample_t* sample = NULL;
1788 
1789   sample = FLUID_NEW(fluid_sample_t);
1790   if (sample == NULL) {
1791     FLUID_LOG(FLUID_ERR, "Out of memory");
1792     return NULL;
1793   }
1794 
1795   memset(sample, 0, sizeof(fluid_sample_t));
1796   sample->valid = 1;
1797 
1798   return sample;
1799 }
1800 
1801 /*
1802  * delete_fluid_sample
1803  */
1804 int
delete_fluid_sample(fluid_sample_t * sample)1805 delete_fluid_sample(fluid_sample_t* sample)
1806 {
1807   FLUID_FREE(sample);
1808   return FLUID_OK;
1809 }
1810 
1811 /*
1812  * fluid_sample_in_rom
1813  */
1814 int
fluid_sample_in_rom(fluid_sample_t * sample)1815 fluid_sample_in_rom(fluid_sample_t* sample)
1816 {
1817   return (sample->sampletype & FLUID_SAMPLETYPE_ROM);
1818 }
1819 
1820 /*
1821  * fluid_sample_import_sfont
1822  */
1823 int
fluid_sample_import_sfont(fluid_sample_t * sample,SFSample * sfsample,fluid_defsfont_t * sfont)1824 fluid_sample_import_sfont(fluid_sample_t* sample, SFSample* sfsample, fluid_defsfont_t* sfont)
1825 {
1826   FLUID_STRCPY(sample->name, sfsample->name);
1827   sample->data = sfont->sampledata;
1828   sample->start = sfsample->start;
1829   sample->end = sfsample->start + sfsample->end;
1830   sample->loopstart = sfsample->start + sfsample->loopstart;
1831   sample->loopend = sfsample->start + sfsample->loopend;
1832   sample->samplerate = sfsample->samplerate;
1833   sample->origpitch = sfsample->origpitch;
1834   sample->pitchadj = sfsample->pitchadj;
1835   sample->sampletype = sfsample->sampletype;
1836 
1837   if (sample->sampletype & FLUID_SAMPLETYPE_ROM) {
1838     sample->valid = 0;
1839     FLUID_LOG(FLUID_WARN, "Ignoring sample %s: can't use ROM samples", sample->name);
1840   }
1841   if (sample->end - sample->start < 8) {
1842     sample->valid = 0;
1843     FLUID_LOG(FLUID_WARN, "Ignoring sample %s: too few sample data points", sample->name);
1844   } else {
1845 /*      if (sample->loopstart < sample->start + 8) { */
1846 /*        FLUID_LOG(FLUID_WARN, "Fixing sample %s: at least 8 data points required before loop start", sample->name);     */
1847 /*        sample->loopstart = sample->start + 8; */
1848 /*      } */
1849 /*      if (sample->loopend > sample->end - 8) { */
1850 /*        FLUID_LOG(FLUID_WARN, "Fixing sample %s: at least 8 data points required after loop end", sample->name);     */
1851 /*        sample->loopend = sample->end - 8; */
1852 /*      } */
1853   }
1854   return FLUID_OK;
1855 }
1856 
1857 
1858 
1859 /********************************************************************************/
1860 /********************************************************************************/
1861 /********************************************************************************/
1862 /********************************************************************************/
1863 /********************************************************************************/
1864 
1865 
1866 
1867 /*=================================sfload.c========================
1868   Borrowed from Smurf SoundFont Editor by Josh Green
1869   =================================================================*/
1870 
1871 /*
1872    functions for loading data from sfont files, with appropriate byte swapping
1873    on big endian machines. Sfont IDs are not swapped because the ID read is
1874    equivalent to the matching ID list in memory regardless of LE/BE machine
1875 */
1876 
1877 #ifdef MSB_FIRST
1878 
1879 #define READCHUNK(var,fd)	FLUID_STMT_START {		\
1880 	if (!safe_fread(var, 8, fd))			\
1881 		return(FAIL);				\
1882 	((SFChunk *)(var))->size = GUINT32_FROM_LE(((SFChunk *)(var))->size);  \
1883 } FLUID_STMT_END
1884 
1885 #define READD(var,fd)		FLUID_STMT_START {		\
1886 	unsigned int _temp;				\
1887 	if (!safe_fread(&_temp, 4, fd))			\
1888 		return(FAIL);				\
1889 	var = GINT32_FROM_LE(_temp);			\
1890 } FLUID_STMT_END
1891 
1892 #define READW(var,fd)		FLUID_STMT_START {		\
1893 	unsigned short _temp;				\
1894 	if (!safe_fread(&_temp, 2, fd))			\
1895 		return(FAIL);				\
1896 	var = GINT16_FROM_LE(_temp);			\
1897 } FLUID_STMT_END
1898 
1899 #else
1900 
1901 #define READCHUNK(var,fd)	FLUID_STMT_START {		\
1902     if (!safe_fread(var, 8, fd))			\
1903 	return(FAIL);					\
1904     ((SFChunk *)(var))->size = GUINT32_FROM_LE(((SFChunk *)(var))->size);  \
1905 } FLUID_STMT_END
1906 
1907 #define READD(var,fd)		FLUID_STMT_START {		\
1908     unsigned int _temp;					\
1909     if (!safe_fread(&_temp, 4, fd))			\
1910 	return(FAIL);					\
1911     var = GINT32_FROM_LE(_temp);			\
1912 } FLUID_STMT_END
1913 
1914 #define READW(var,fd)		FLUID_STMT_START {		\
1915     unsigned short _temp;					\
1916     if (!safe_fread(&_temp, 2, fd))			\
1917 	return(FAIL);					\
1918     var = GINT16_FROM_LE(_temp);			\
1919 } FLUID_STMT_END
1920 
1921 #endif
1922 
1923 
1924 #define READID(var,fd)		FLUID_STMT_START {		\
1925     if (!safe_fread(var, 4, fd))			\
1926 	return(FAIL);					\
1927 } FLUID_STMT_END
1928 
1929 #define READSTR(var,fd)		FLUID_STMT_START {		\
1930     if (!safe_fread(var, 20, fd))			\
1931 	return(FAIL);					\
1932     (*var)[20] = '\0';					\
1933 } FLUID_STMT_END
1934 
1935 #define READB(var,fd)		FLUID_STMT_START {		\
1936     if (!safe_fread(&var, 1, fd))			\
1937 	return(FAIL);					\
1938 } FLUID_STMT_END
1939 
1940 #define FSKIP(size,fd)		FLUID_STMT_START {		\
1941     if (!safe_fseek(fd, size, SEEK_CUR))		\
1942 	return(FAIL);					\
1943 } FLUID_STMT_END
1944 
1945 #define FSKIPW(fd)		FLUID_STMT_START {		\
1946     if (!safe_fseek(fd, 2, SEEK_CUR))			\
1947 	return(FAIL);					\
1948 } FLUID_STMT_END
1949 
1950 /* removes and advances a fluid_list_t pointer */
1951 #define SLADVREM(list, item)	FLUID_STMT_START {		\
1952     fluid_list_t *_temp = item;				\
1953     item = fluid_list_next(item);				\
1954     list = fluid_list_remove_link(list, _temp);		\
1955     delete1_fluid_list(_temp);				\
1956 } FLUID_STMT_END
1957 
1958 static int chunkid (unsigned int id);
1959 static int load_body (unsigned int size, SFData * sf, FILE * fd);
1960 static int read_listchunk (SFChunk * chunk, FILE * fd);
1961 static int process_info (int size, SFData * sf, FILE * fd);
1962 static int process_sdta (unsigned int size, SFData * sf, FILE * fd);
1963 static int pdtahelper (unsigned int expid, unsigned int reclen, SFChunk * chunk,
1964   int * size, FILE * fd);
1965 static int process_pdta (int size, SFData * sf, FILE * fd);
1966 static int load_phdr (int size, SFData * sf, FILE * fd);
1967 static int load_pbag (int size, SFData * sf, FILE * fd);
1968 static int load_pmod (int size, SFData * sf, FILE * fd);
1969 static int load_pgen (int size, SFData * sf, FILE * fd);
1970 static int load_ihdr (int size, SFData * sf, FILE * fd);
1971 static int load_ibag (int size, SFData * sf, FILE * fd);
1972 static int load_imod (int size, SFData * sf, FILE * fd);
1973 static int load_igen (int size, SFData * sf, FILE * fd);
1974 static int load_shdr (unsigned int size, SFData * sf, FILE * fd);
1975 static int fixup_pgen (SFData * sf);
1976 static int fixup_igen (SFData * sf);
1977 static int fixup_sample (SFData * sf);
1978 
1979 char idlist[] = {
1980   "RIFFLISTsfbkINFOsdtapdtaifilisngINAMiromiverICRDIENGIPRD"
1981     "ICOPICMTISFTsnamsmplphdrpbagpmodpgeninstibagimodigenshdr"
1982 };
1983 
1984 static unsigned int sdtachunk_size;
1985 
1986 /* sound font file load functions */
1987 static int
chunkid(unsigned int id)1988 chunkid (unsigned int id)
1989 {
1990   unsigned int i;
1991   unsigned int *p;
1992 
1993   p = (unsigned int *) & idlist;
1994   for (i = 0; i < sizeof (idlist) / sizeof (int); i++, p += 1)
1995     if (*p == id)
1996       return (i + 1);
1997 
1998   return (UNKN_ID);
1999 }
2000 
2001 SFData *
sfload_file(const char * fname)2002 sfload_file (const char * fname)
2003 {
2004   SFData *sf = NULL;
2005   FILE *fd;
2006   int fsize = 0;
2007   int err = FALSE;
2008 
2009   if (!(fd = fopen (fname, "rb")))
2010     {
2011       FLUID_LOG (FLUID_ERR, _("Unable to open file \"%s\""), fname);
2012       return (NULL);
2013     }
2014 
2015   if (!(sf = FLUID_NEW (SFData)))
2016     {
2017       FLUID_LOG(FLUID_ERR, "Out of memory");
2018       fclose(fd);
2019       err = TRUE;
2020     }
2021 
2022   if (!err)
2023     {
2024       memset (sf, 0, sizeof (SFData));	/* zero sfdata */
2025       sf->fname = FLUID_STRDUP (fname);	/* copy file name */
2026       sf->sffd = fd;
2027     }
2028 
2029   /* get size of file */
2030   if (!err && fseek (fd, 0L, SEEK_END) == -1)
2031     {				/* seek to end of file */
2032       err = TRUE;
2033       FLUID_LOG (FLUID_ERR, _("Seek to end of file failed"));
2034     }
2035   if (!err && (fsize = ftell (fd)) == -1)
2036     {				/* position = size */
2037       err = TRUE;
2038       FLUID_LOG (FLUID_ERR, _("Get end of file position failed"));
2039     }
2040   if (!err)
2041     rewind (fd);
2042 
2043   if (!err && !load_body (fsize, sf, fd))
2044     err = TRUE;			/* load the sfont */
2045 
2046   if (err)
2047     {
2048       if (sf)
2049 	sfont_close (sf);
2050       return (NULL);
2051     }
2052 
2053   return (sf);
2054 }
2055 
2056 static int
load_body(unsigned int size,SFData * sf,FILE * fd)2057 load_body (unsigned int size, SFData * sf, FILE * fd)
2058 {
2059   SFChunk chunk;
2060 
2061   READCHUNK (&chunk, fd);	/* load RIFF chunk */
2062   if (chunkid (chunk.id) != RIFF_ID) {	/* error if not RIFF */
2063     FLUID_LOG (FLUID_ERR, _("Not a RIFF file"));
2064     return (FAIL);
2065   }
2066 
2067   READID (&chunk.id, fd);	/* load file ID */
2068   if (chunkid (chunk.id) != SFBK_ID) {	/* error if not SFBK_ID */
2069     FLUID_LOG (FLUID_ERR, _("Not a SoundFont file"));
2070     return (FAIL);
2071   }
2072 
2073   if (chunk.size != size - 8) {
2074     gerr (ErrCorr, _("SoundFont file size mismatch"));
2075     return (FAIL);
2076   }
2077 
2078   /* Process INFO block */
2079   if (!read_listchunk (&chunk, fd))
2080     return (FAIL);
2081   if (chunkid (chunk.id) != INFO_ID)
2082     return (gerr (ErrCorr, _("Invalid ID found when expecting INFO chunk")));
2083   if (!process_info (chunk.size, sf, fd))
2084     return (FAIL);
2085 
2086   /* Process sample chunk */
2087   if (!read_listchunk (&chunk, fd))
2088     return (FAIL);
2089   if (chunkid (chunk.id) != SDTA_ID)
2090     return (gerr (ErrCorr,
2091 	_("Invalid ID found when expecting SAMPLE chunk")));
2092   if (!process_sdta (chunk.size, sf, fd))
2093     return (FAIL);
2094 
2095   /* process HYDRA chunk */
2096   if (!read_listchunk (&chunk, fd))
2097     return (FAIL);
2098   if (chunkid (chunk.id) != PDTA_ID)
2099     return (gerr (ErrCorr, _("Invalid ID found when expecting HYDRA chunk")));
2100   if (!process_pdta (chunk.size, sf, fd))
2101     return (FAIL);
2102 
2103   if (!fixup_pgen (sf))
2104     return (FAIL);
2105   if (!fixup_igen (sf))
2106     return (FAIL);
2107   if (!fixup_sample (sf))
2108     return (FAIL);
2109 
2110   /* sort preset list by bank, preset # */
2111   sf->preset = fluid_list_sort (sf->preset,
2112     (fluid_compare_func_t) sfont_preset_compare_func);
2113 
2114   return (OK);
2115 }
2116 
2117 static int
read_listchunk(SFChunk * chunk,FILE * fd)2118 read_listchunk (SFChunk * chunk, FILE * fd)
2119 {
2120   READCHUNK (chunk, fd);	/* read list chunk */
2121   if (chunkid (chunk->id) != LIST_ID)	/* error if ! list chunk */
2122     return (gerr (ErrCorr, _("Invalid chunk id in level 0 parse")));
2123   READID (&chunk->id, fd);	/* read id string */
2124   chunk->size -= 4;
2125   return (OK);
2126 }
2127 
2128 static int
process_info(int size,SFData * sf,FILE * fd)2129 process_info (int size, SFData * sf, FILE * fd)
2130 {
2131   SFChunk chunk;
2132   unsigned char id;
2133   char *item;
2134   unsigned short ver;
2135 
2136   while (size > 0)
2137     {
2138       READCHUNK (&chunk, fd);
2139       size -= 8;
2140 
2141       id = chunkid (chunk.id);
2142 
2143       if (id == IFIL_ID)
2144 	{			/* sound font version chunk? */
2145 	  if (chunk.size != 4)
2146 	    return (gerr (ErrCorr,
2147 		_("Sound font version info chunk has invalid size")));
2148 
2149 	  READW (ver, fd);
2150 	  sf->version.major = ver;
2151 	  READW (ver, fd);
2152 	  sf->version.minor = ver;
2153 
2154 	  if (sf->version.major < 2) {
2155 	    FLUID_LOG (FLUID_ERR,
2156 		      _("Sound font version is %d.%d which is not"
2157 			" supported, convert to version 2.0x"),
2158 		      sf->version.major,
2159 		      sf->version.minor);
2160 	    return (FAIL);
2161 	  }
2162 
2163 	  if (sf->version.major > 2) {
2164 	    FLUID_LOG (FLUID_WARN,
2165 		      _("Sound font version is %d.%d which is newer than"
2166 			" what this version of FLUID Synth was designed for (v2.0x)"),
2167 		      sf->version.major,
2168 		      sf->version.minor);
2169 	    return (FAIL);
2170 	  }
2171 	}
2172       else if (id == IVER_ID)
2173 	{			/* ROM version chunk? */
2174 	  if (chunk.size != 4)
2175 	    return (gerr (ErrCorr,
2176 		_("ROM version info chunk has invalid size")));
2177 
2178 	  READW (ver, fd);
2179 	  sf->romver.major = ver;
2180 	  READW (ver, fd);
2181 	  sf->romver.minor = ver;
2182 	}
2183       else if (id != UNKN_ID)
2184 	{
2185 	  if ((id != ICMT_ID && chunk.size > 256) || (chunk.size > 65536)
2186 	    || (chunk.size % 2))
2187 	    return (gerr (ErrCorr,
2188 		_("INFO sub chunk %.4s has invalid chunk size"
2189 		  " of %d bytes"), &chunk.id, chunk.size));
2190 
2191 	  /* alloc for chunk id and da chunk */
2192 	  if (!(item = FLUID_MALLOC (chunk.size + 1)))
2193 	    {
2194 	      FLUID_LOG(FLUID_ERR, "Out of memory");
2195 	      return (FAIL);
2196 	    }
2197 
2198 	  /* attach to INFO list, sfont_close will cleanup if FAIL occurs */
2199 	  sf->info = fluid_list_append (sf->info, item);
2200 
2201 	  *(unsigned char *) item = id;
2202 	  if (!safe_fread (&item[1], chunk.size, fd))
2203 	    return (FAIL);
2204 
2205 	  /* force terminate info item (don't forget uint8 info ID) */
2206 	  *(item + chunk.size) = '\0';
2207 	}
2208       else
2209 	return (gerr (ErrCorr, _("Invalid chunk id in INFO chunk")));
2210       size -= chunk.size;
2211     }
2212 
2213   if (size < 0)
2214     return (gerr (ErrCorr, _("INFO chunk size mismatch")));
2215 
2216   return (OK);
2217 }
2218 
2219 static int
process_sdta(unsigned int size,SFData * sf,FILE * fd)2220 process_sdta (unsigned int size, SFData * sf, FILE * fd)
2221 {
2222   SFChunk chunk;
2223 
2224   if (size == 0)
2225     return (OK);		/* no sample data? */
2226 
2227   /* read sub chunk */
2228   READCHUNK (&chunk, fd);
2229   size -= 8;
2230 
2231   if (chunkid (chunk.id) != SMPL_ID)
2232     return (gerr (ErrCorr,
2233 	_("Expected SMPL chunk found invalid id instead")));
2234 
2235   /* SDTA chunk may also contain sm24 chunk for 24 bit samples
2236    * (not yet supported), only an error if SMPL chunk size is
2237    * greater than SDTA. */
2238   if (chunk.size > size)
2239     return (gerr (ErrCorr, _("SDTA chunk size mismatch")));
2240 
2241   /* sample data follows */
2242   sf->samplepos = ftell (fd);
2243 
2244   /* used in fixup_sample() to check validity of sample headers */
2245   sdtachunk_size = chunk.size;
2246   sf->samplesize = chunk.size;
2247 
2248   FSKIP (size, fd);
2249 
2250   return (OK);
2251 }
2252 
2253 static int
pdtahelper(unsigned int expid,unsigned int reclen,SFChunk * chunk,int * size,FILE * fd)2254 pdtahelper (unsigned int expid, unsigned int reclen, SFChunk * chunk,
2255   int * size, FILE * fd)
2256 {
2257   unsigned int id;
2258   char *expstr;
2259 
2260   expstr = CHNKIDSTR (expid);	/* in case we need it */
2261 
2262   READCHUNK (chunk, fd);
2263   *size -= 8;
2264 
2265   if ((id = chunkid (chunk->id)) != expid)
2266     return (gerr (ErrCorr, _("Expected"
2267 	  " PDTA sub-chunk \"%.4s\" found invalid id instead"), expstr));
2268 
2269   if (chunk->size % reclen)	/* valid chunk size? */
2270     return (gerr (ErrCorr,
2271 	_("\"%.4s\" chunk size is not a multiple of %d bytes"), expstr,
2272 	reclen));
2273   if ((*size -= chunk->size) < 0)
2274     return (gerr (ErrCorr,
2275 	_("\"%.4s\" chunk size exceeds remaining PDTA chunk size"), expstr));
2276   return (OK);
2277 }
2278 
2279 static int
process_pdta(int size,SFData * sf,FILE * fd)2280 process_pdta (int size, SFData * sf, FILE * fd)
2281 {
2282   SFChunk chunk;
2283 
2284   if (!pdtahelper (PHDR_ID, SFPHDRSIZE, &chunk, &size, fd))
2285     return (FAIL);
2286   if (!load_phdr (chunk.size, sf, fd))
2287     return (FAIL);
2288 
2289   if (!pdtahelper (PBAG_ID, SFBAGSIZE, &chunk, &size, fd))
2290     return (FAIL);
2291   if (!load_pbag (chunk.size, sf, fd))
2292     return (FAIL);
2293 
2294   if (!pdtahelper (PMOD_ID, SFMODSIZE, &chunk, &size, fd))
2295     return (FAIL);
2296   if (!load_pmod (chunk.size, sf, fd))
2297     return (FAIL);
2298 
2299   if (!pdtahelper (PGEN_ID, SFGENSIZE, &chunk, &size, fd))
2300     return (FAIL);
2301   if (!load_pgen (chunk.size, sf, fd))
2302     return (FAIL);
2303 
2304   if (!pdtahelper (IHDR_ID, SFIHDRSIZE, &chunk, &size, fd))
2305     return (FAIL);
2306   if (!load_ihdr (chunk.size, sf, fd))
2307     return (FAIL);
2308 
2309   if (!pdtahelper (IBAG_ID, SFBAGSIZE, &chunk, &size, fd))
2310     return (FAIL);
2311   if (!load_ibag (chunk.size, sf, fd))
2312     return (FAIL);
2313 
2314   if (!pdtahelper (IMOD_ID, SFMODSIZE, &chunk, &size, fd))
2315     return (FAIL);
2316   if (!load_imod (chunk.size, sf, fd))
2317     return (FAIL);
2318 
2319   if (!pdtahelper (IGEN_ID, SFGENSIZE, &chunk, &size, fd))
2320     return (FAIL);
2321   if (!load_igen (chunk.size, sf, fd))
2322     return (FAIL);
2323 
2324   if (!pdtahelper (SHDR_ID, SFSHDRSIZE, &chunk, &size, fd))
2325     return (FAIL);
2326   if (!load_shdr (chunk.size, sf, fd))
2327     return (FAIL);
2328 
2329   return (OK);
2330 }
2331 
2332 /* preset header loader */
2333 static int
load_phdr(int size,SFData * sf,FILE * fd)2334 load_phdr (int size, SFData * sf, FILE * fd)
2335 {
2336   int i, i2;
2337   SFPreset *p, *pr = NULL;	/* ptr to current & previous preset */
2338   unsigned short zndx, pzndx = 0;
2339 
2340   if (size % SFPHDRSIZE || size == 0)
2341     return (gerr (ErrCorr, _("Preset header chunk size is invalid")));
2342 
2343   i = size / SFPHDRSIZE - 1;
2344   if (i == 0)
2345     {				/* at least one preset + term record */
2346       FLUID_LOG (FLUID_WARN, _("File contains no presets"));
2347       FSKIP (SFPHDRSIZE, fd);
2348       return (OK);
2349     }
2350 
2351   for (; i > 0; i--)
2352     {				/* load all preset headers */
2353       p = FLUID_NEW (SFPreset);
2354       sf->preset = fluid_list_append (sf->preset, p);
2355       p->zone = NULL;		/* In case of failure, sfont_close can cleanup */
2356       READSTR (&p->name, fd);	/* possible read failure ^ */
2357       READW (p->prenum, fd);
2358       READW (p->bank, fd);
2359       READW (zndx, fd);
2360       READD (p->libr, fd);
2361       READD (p->genre, fd);
2362       READD (p->morph, fd);
2363 
2364       if (pr)
2365 	{			/* not first preset? */
2366 	  if (zndx < pzndx)
2367 	    return (gerr (ErrCorr, _("Preset header indices not monotonic")));
2368 	  i2 = zndx - pzndx;
2369 	  while (i2--)
2370 	    {
2371 	      pr->zone = fluid_list_prepend (pr->zone, NULL);
2372 	    }
2373 	}
2374       else if (zndx > 0)	/* 1st preset, warn if ofs >0 */
2375 	FLUID_LOG (FLUID_WARN, _("%d preset zones not referenced, discarding"), zndx);
2376       pr = p;			/* update preset ptr */
2377       pzndx = zndx;
2378     }
2379 
2380   FSKIP (24, fd);
2381   READW (zndx, fd);		/* Read terminal generator index */
2382   FSKIP (12, fd);
2383 
2384   if (zndx < pzndx)
2385     return (gerr (ErrCorr, _("Preset header indices not monotonic")));
2386   i2 = zndx - pzndx;
2387   while (i2--)
2388     {
2389       pr->zone = fluid_list_prepend (pr->zone, NULL);
2390     }
2391 
2392   return (OK);
2393 }
2394 
2395 /* preset bag loader */
2396 static int
load_pbag(int size,SFData * sf,FILE * fd)2397 load_pbag (int size, SFData * sf, FILE * fd)
2398 {
2399   fluid_list_t *p, *p2;
2400   SFZone *z, *pz = NULL;
2401   unsigned short genndx, modndx;
2402   unsigned short pgenndx = 0, pmodndx = 0;
2403   unsigned short i;
2404 
2405   if (size % SFBAGSIZE || size == 0)	/* size is multiple of SFBAGSIZE? */
2406     return (gerr (ErrCorr, _("Preset bag chunk size is invalid")));
2407 
2408   p = sf->preset;
2409   while (p)
2410     {				/* traverse through presets */
2411       p2 = ((SFPreset *) (p->data))->zone;
2412       while (p2)
2413 	{			/* traverse preset's zones */
2414 	  if ((size -= SFBAGSIZE) < 0)
2415 	    return (gerr (ErrCorr, _("Preset bag chunk size mismatch")));
2416 	  z = FLUID_NEW (SFZone);
2417 	  p2->data = z;
2418 	  z->gen = NULL;	/* Init gen and mod before possible failure, */
2419 	  z->mod = NULL;	/* to ensure proper cleanup (sfont_close) */
2420 	  READW (genndx, fd);	/* possible read failure ^ */
2421 	  READW (modndx, fd);
2422 	  z->instsamp = NULL;
2423 
2424 	  if (pz)
2425 	    {			/* if not first zone */
2426 	      if (genndx < pgenndx)
2427 		return (gerr (ErrCorr,
2428 		    _("Preset bag generator indices not monotonic")));
2429 	      if (modndx < pmodndx)
2430 		return (gerr (ErrCorr,
2431 		    _("Preset bag modulator indices not monotonic")));
2432 	      i = genndx - pgenndx;
2433 	      while (i--)
2434 		pz->gen = fluid_list_prepend (pz->gen, NULL);
2435 	      i = modndx - pmodndx;
2436 	      while (i--)
2437 		pz->mod = fluid_list_prepend (pz->mod, NULL);
2438 	    }
2439 	  pz = z;		/* update previous zone ptr */
2440 	  pgenndx = genndx;	/* update previous zone gen index */
2441 	  pmodndx = modndx;	/* update previous zone mod index */
2442 	  p2 = fluid_list_next (p2);
2443 	}
2444       p = fluid_list_next (p);
2445     }
2446 
2447   size -= SFBAGSIZE;
2448   if (size != 0)
2449     return (gerr (ErrCorr, _("Preset bag chunk size mismatch")));
2450 
2451   READW (genndx, fd);
2452   READW (modndx, fd);
2453 
2454   if (!pz)
2455     {
2456       if (genndx > 0)
2457 	FLUID_LOG (FLUID_WARN, _("No preset generators and terminal index not 0"));
2458       if (modndx > 0)
2459 	FLUID_LOG (FLUID_WARN, _("No preset modulators and terminal index not 0"));
2460       return (OK);
2461     }
2462 
2463   if (genndx < pgenndx)
2464     return (gerr (ErrCorr, _("Preset bag generator indices not monotonic")));
2465   if (modndx < pmodndx)
2466     return (gerr (ErrCorr, _("Preset bag modulator indices not monotonic")));
2467   i = genndx - pgenndx;
2468   while (i--)
2469     pz->gen = fluid_list_prepend (pz->gen, NULL);
2470   i = modndx - pmodndx;
2471   while (i--)
2472     pz->mod = fluid_list_prepend (pz->mod, NULL);
2473 
2474   return (OK);
2475 }
2476 
2477 /* preset modulator loader */
2478 static int
load_pmod(int size,SFData * sf,FILE * fd)2479 load_pmod (int size, SFData * sf, FILE * fd)
2480 {
2481   fluid_list_t *p, *p2, *p3;
2482   SFMod *m;
2483 
2484   p = sf->preset;
2485   while (p)
2486     {				/* traverse through all presets */
2487       p2 = ((SFPreset *) (p->data))->zone;
2488       while (p2)
2489 	{			/* traverse this preset's zones */
2490 	  p3 = ((SFZone *) (p2->data))->mod;
2491 	  while (p3)
2492 	    {			/* load zone's modulators */
2493 	      if ((size -= SFMODSIZE) < 0)
2494 		return (gerr (ErrCorr,
2495 		    _("Preset modulator chunk size mismatch")));
2496 	      m = FLUID_NEW (SFMod);
2497 	      p3->data = m;
2498 	      READW (m->src, fd);
2499 	      READW (m->dest, fd);
2500 	      READW (m->amount, fd);
2501 	      READW (m->amtsrc, fd);
2502 	      READW (m->trans, fd);
2503 	      p3 = fluid_list_next (p3);
2504 	    }
2505 	  p2 = fluid_list_next (p2);
2506 	}
2507       p = fluid_list_next (p);
2508     }
2509 
2510   /*
2511      If there isn't even a terminal record
2512      Hmmm, the specs say there should be one, but..
2513    */
2514   if (size == 0)
2515     return (OK);
2516 
2517   size -= SFMODSIZE;
2518   if (size != 0)
2519     return (gerr (ErrCorr, _("Preset modulator chunk size mismatch")));
2520   FSKIP (SFMODSIZE, fd);	/* terminal mod */
2521 
2522   return (OK);
2523 }
2524 
2525 /* -------------------------------------------------------------------
2526  * preset generator loader
2527  * generator (per preset) loading rules:
2528  * Zones with no generators or modulators shall be annihilated
2529  * Global zone must be 1st zone, discard additional ones (instrumentless zones)
2530  *
2531  * generator (per zone) loading rules (in order of decreasing precedence):
2532  * KeyRange is 1st in list (if exists), else discard
2533  * if a VelRange exists only preceded by a KeyRange, else discard
2534  * if a generator follows an instrument discard it
2535  * if a duplicate generator exists replace previous one
2536  * ------------------------------------------------------------------- */
2537 static int
load_pgen(int size,SFData * sf,FILE * fd)2538 load_pgen (int size, SFData * sf, FILE * fd)
2539 {
2540   fluid_list_t *p, *p2, *p3, *dup, **hz = NULL;
2541   SFZone *z;
2542   SFGen *g;
2543   SFGenAmount genval;
2544   unsigned short genid;
2545   int level, skip, drop, gzone, discarded;
2546 
2547   p = sf->preset;
2548   while (p)
2549     {				/* traverse through all presets */
2550       gzone = FALSE;
2551       discarded = FALSE;
2552       p2 = ((SFPreset *) (p->data))->zone;
2553       if (p2)
2554 	hz = &p2;
2555       while (p2)
2556 	{			/* traverse preset's zones */
2557 	  level = 0;
2558 	  z = (SFZone *) (p2->data);
2559 	  p3 = z->gen;
2560 	  while (p3)
2561 	    {			/* load zone's generators */
2562 	      dup = NULL;
2563 	      skip = FALSE;
2564 	      drop = FALSE;
2565 	      if ((size -= SFGENSIZE) < 0)
2566 		return (gerr (ErrCorr,
2567 		    _("Preset generator chunk size mismatch")));
2568 
2569 	      READW (genid, fd);
2570 
2571 	      if (genid == Gen_KeyRange)
2572 		{		/* nothing precedes */
2573 		  if (level == 0)
2574 		    {
2575 		      level = 1;
2576 		      READB (genval.range.lo, fd);
2577 		      READB (genval.range.hi, fd);
2578 		    }
2579 		  else
2580 		    skip = TRUE;
2581 		}
2582 	      else if (genid == Gen_VelRange)
2583 		{		/* only KeyRange precedes */
2584 		  if (level <= 1)
2585 		    {
2586 		      level = 2;
2587 		      READB (genval.range.lo, fd);
2588 		      READB (genval.range.hi, fd);
2589 		    }
2590 		  else
2591 		    skip = TRUE;
2592 		}
2593 	      else if (genid == Gen_Instrument)
2594 		{		/* inst is last gen */
2595 		  level = 3;
2596 		  READW (genval.uword, fd);
2597 		  ((SFZone *) (p2->data))->instsamp = GINT_TO_POINTER (genval.uword + 1);
2598 		  break;	/* break out of generator loop */
2599 		}
2600 	      else
2601 		{
2602 		  level = 2;
2603 		  if (gen_validp (genid))
2604 		    {		/* generator valid? */
2605 		      READW (genval.sword, fd);
2606 		      dup = gen_inlist (genid, z->gen);
2607 		    }
2608 		  else
2609 		    skip = TRUE;
2610 		}
2611 
2612 	      if (!skip)
2613 		{
2614 		  if (!dup)
2615 		    {		/* if gen ! dup alloc new */
2616 		      g = FLUID_NEW (SFGen);
2617 		      p3->data = g;
2618 		      g->id = genid;
2619 		    }
2620 		  else
2621 		    {
2622 		      g = (SFGen *) (dup->data);	/* ptr to orig gen */
2623 		      drop = TRUE;
2624 		    }
2625 		  g->amount = genval;
2626 		}
2627 	      else
2628 		{		/* Skip this generator */
2629 		  discarded = TRUE;
2630 		  drop = TRUE;
2631 		  FSKIPW (fd);
2632 		}
2633 
2634 	      if (!drop)
2635 		p3 = fluid_list_next (p3);	/* next gen */
2636 	      else
2637 		SLADVREM (z->gen, p3);	/* drop place holder */
2638 
2639 	    }			/* generator loop */
2640 
2641 	  if (level == 3)
2642 	    SLADVREM (z->gen, p3);	/* zone has inst? */
2643 	  else
2644 	    {			/* congratulations its a global zone */
2645 	      if (!gzone)
2646 		{		/* Prior global zones? */
2647 		  gzone = TRUE;
2648 
2649 		  /* if global zone is not 1st zone, relocate */
2650 		  if (*hz != p2)
2651 		    {
2652 		      void* save = p2->data;
2653 		      FLUID_LOG (FLUID_WARN,
2654 			_("Preset \"%s\": Global zone is not first zone"),
2655 			((SFPreset *) (p->data))->name);
2656 		      SLADVREM (*hz, p2);
2657 		      *hz = fluid_list_prepend (*hz, save);
2658 		      continue;
2659 		    }
2660 		}
2661 	      else
2662 		{		/* previous global zone exists, discard */
2663 		  FLUID_LOG (FLUID_WARN,
2664 		    _("Preset \"%s\": Discarding invalid global zone"),
2665 		    ((SFPreset *) (p->data))->name);
2666 		  sfont_zone_delete (sf, hz, (SFZone *) (p2->data));
2667 		}
2668 	    }
2669 
2670 	  while (p3)
2671 	    {			/* Kill any zones following an instrument */
2672 	      discarded = TRUE;
2673 	      if ((size -= SFGENSIZE) < 0)
2674 		return (gerr (ErrCorr,
2675 		    _("Preset generator chunk size mismatch")));
2676 	      FSKIP (SFGENSIZE, fd);
2677 	      SLADVREM (z->gen, p3);
2678 	    }
2679 
2680 	  p2 = fluid_list_next (p2);	/* next zone */
2681 	}
2682       if (discarded)
2683 	FLUID_LOG(FLUID_WARN,
2684 	  _("Preset \"%s\": Some invalid generators were discarded"),
2685 	  ((SFPreset *) (p->data))->name);
2686       p = fluid_list_next (p);
2687     }
2688 
2689   /* in case there isn't a terminal record */
2690   if (size == 0)
2691     return (OK);
2692 
2693   size -= SFGENSIZE;
2694   if (size != 0)
2695     return (gerr (ErrCorr, _("Preset generator chunk size mismatch")));
2696   FSKIP (SFGENSIZE, fd);	/* terminal gen */
2697 
2698   return (OK);
2699 }
2700 
2701 /* instrument header loader */
2702 static int
load_ihdr(int size,SFData * sf,FILE * fd)2703 load_ihdr (int size, SFData * sf, FILE * fd)
2704 {
2705   int i, i2;
2706   SFInst *p, *pr = NULL;	/* ptr to current & previous instrument */
2707   unsigned short zndx, pzndx = 0;
2708 
2709   if (size % SFIHDRSIZE || size == 0)	/* chunk size is valid? */
2710     return (gerr (ErrCorr, _("Instrument header has invalid size")));
2711 
2712   size = size / SFIHDRSIZE - 1;
2713   if (size == 0)
2714     {				/* at least one preset + term record */
2715       FLUID_LOG (FLUID_WARN, _("File contains no instruments"));
2716       FSKIP (SFIHDRSIZE, fd);
2717       return (OK);
2718     }
2719 
2720   for (i = 0; i < size; i++)
2721     {				/* load all instrument headers */
2722       p = FLUID_NEW (SFInst);
2723       sf->inst = fluid_list_append (sf->inst, p);
2724       p->zone = NULL;		/* For proper cleanup if fail (sfont_close) */
2725       READSTR (&p->name, fd);	/* Possible read failure ^ */
2726       READW (zndx, fd);
2727 
2728       if (pr)
2729 	{			/* not first instrument? */
2730 	  if (zndx < pzndx)
2731 	    return (gerr (ErrCorr,
2732 		_("Instrument header indices not monotonic")));
2733 	  i2 = zndx - pzndx;
2734 	  while (i2--)
2735 	    pr->zone = fluid_list_prepend (pr->zone, NULL);
2736 	}
2737       else if (zndx > 0)	/* 1st inst, warn if ofs >0 */
2738 	FLUID_LOG (FLUID_WARN, _("%d instrument zones not referenced, discarding"),
2739 	  zndx);
2740       pzndx = zndx;
2741       pr = p;			/* update instrument ptr */
2742     }
2743 
2744   FSKIP (20, fd);
2745   READW (zndx, fd);
2746 
2747   if (zndx < pzndx)
2748     return (gerr (ErrCorr, _("Instrument header indices not monotonic")));
2749   i2 = zndx - pzndx;
2750   while (i2--)
2751     pr->zone = fluid_list_prepend (pr->zone, NULL);
2752 
2753   return (OK);
2754 }
2755 
2756 /* instrument bag loader */
2757 static int
load_ibag(int size,SFData * sf,FILE * fd)2758 load_ibag (int size, SFData * sf, FILE * fd)
2759 {
2760   fluid_list_t *p, *p2;
2761   SFZone *z, *pz = NULL;
2762   unsigned short genndx, modndx, pgenndx = 0, pmodndx = 0;
2763   int i;
2764 
2765   if (size % SFBAGSIZE || size == 0)	/* size is multiple of SFBAGSIZE? */
2766     return (gerr (ErrCorr, _("Instrument bag chunk size is invalid")));
2767 
2768   p = sf->inst;
2769   while (p)
2770     {				/* traverse through inst */
2771       p2 = ((SFInst *) (p->data))->zone;
2772       while (p2)
2773 	{			/* load this inst's zones */
2774 	  if ((size -= SFBAGSIZE) < 0)
2775 	    return (gerr (ErrCorr, _("Instrument bag chunk size mismatch")));
2776 	  z = FLUID_NEW (SFZone);
2777 	  p2->data = z;
2778 	  z->gen = NULL;	/* In case of failure, */
2779 	  z->mod = NULL;	/* sfont_close can clean up */
2780 	  READW (genndx, fd);	/* READW = possible read failure */
2781 	  READW (modndx, fd);
2782 	  z->instsamp = NULL;
2783 
2784 	  if (pz)
2785 	    {			/* if not first zone */
2786 	      if (genndx < pgenndx)
2787 		return (gerr (ErrCorr,
2788 		    _("Instrument generator indices not monotonic")));
2789 	      if (modndx < pmodndx)
2790 		return (gerr (ErrCorr,
2791 		    _("Instrument modulator indices not monotonic")));
2792 	      i = genndx - pgenndx;
2793 	      while (i--)
2794 		pz->gen = fluid_list_prepend (pz->gen, NULL);
2795 	      i = modndx - pmodndx;
2796 	      while (i--)
2797 		pz->mod = fluid_list_prepend (pz->mod, NULL);
2798 	    }
2799 	  pz = z;		/* update previous zone ptr */
2800 	  pgenndx = genndx;
2801 	  pmodndx = modndx;
2802 	  p2 = fluid_list_next (p2);
2803 	}
2804       p = fluid_list_next (p);
2805     }
2806 
2807   size -= SFBAGSIZE;
2808   if (size != 0)
2809     return (gerr (ErrCorr, _("Instrument chunk size mismatch")));
2810 
2811   READW (genndx, fd);
2812   READW (modndx, fd);
2813 
2814   if (!pz)
2815     {				/* in case that all are no zoners */
2816       if (genndx > 0)
2817 	FLUID_LOG (FLUID_WARN,
2818 	  _("No instrument generators and terminal index not 0"));
2819       if (modndx > 0)
2820 	FLUID_LOG (FLUID_WARN,
2821 	  _("No instrument modulators and terminal index not 0"));
2822       return (OK);
2823     }
2824 
2825   if (genndx < pgenndx)
2826     return (gerr (ErrCorr, _("Instrument generator indices not monotonic")));
2827   if (modndx < pmodndx)
2828     return (gerr (ErrCorr, _("Instrument modulator indices not monotonic")));
2829   i = genndx - pgenndx;
2830   while (i--)
2831     pz->gen = fluid_list_prepend (pz->gen, NULL);
2832   i = modndx - pmodndx;
2833   while (i--)
2834     pz->mod = fluid_list_prepend (pz->mod, NULL);
2835 
2836   return (OK);
2837 }
2838 
2839 /* instrument modulator loader */
2840 static int
load_imod(int size,SFData * sf,FILE * fd)2841 load_imod (int size, SFData * sf, FILE * fd)
2842 {
2843   fluid_list_t *p, *p2, *p3;
2844   SFMod *m;
2845 
2846   p = sf->inst;
2847   while (p)
2848     {				/* traverse through all inst */
2849       p2 = ((SFInst *) (p->data))->zone;
2850       while (p2)
2851 	{			/* traverse this inst's zones */
2852 	  p3 = ((SFZone *) (p2->data))->mod;
2853 	  while (p3)
2854 	    {			/* load zone's modulators */
2855 	      if ((size -= SFMODSIZE) < 0)
2856 		return (gerr (ErrCorr,
2857 		    _("Instrument modulator chunk size mismatch")));
2858 	      m = FLUID_NEW (SFMod);
2859 	      p3->data = m;
2860 	      READW (m->src, fd);
2861 	      READW (m->dest, fd);
2862 	      READW (m->amount, fd);
2863 	      READW (m->amtsrc, fd);
2864 	      READW (m->trans, fd);
2865 	      p3 = fluid_list_next (p3);
2866 	    }
2867 	  p2 = fluid_list_next (p2);
2868 	}
2869       p = fluid_list_next (p);
2870     }
2871 
2872   /*
2873      If there isn't even a terminal record
2874      Hmmm, the specs say there should be one, but..
2875    */
2876   if (size == 0)
2877     return (OK);
2878 
2879   size -= SFMODSIZE;
2880   if (size != 0)
2881     return (gerr (ErrCorr, _("Instrument modulator chunk size mismatch")));
2882   FSKIP (SFMODSIZE, fd);	/* terminal mod */
2883 
2884   return (OK);
2885 }
2886 
2887 /* load instrument generators (see load_pgen for loading rules) */
2888 static int
load_igen(int size,SFData * sf,FILE * fd)2889 load_igen (int size, SFData * sf, FILE * fd)
2890 {
2891   fluid_list_t *p, *p2, *p3, *dup, **hz = NULL;
2892   SFZone *z;
2893   SFGen *g;
2894   SFGenAmount genval;
2895   unsigned short genid;
2896   int level, skip, drop, gzone, discarded;
2897 
2898   p = sf->inst;
2899   while (p)
2900     {				/* traverse through all instruments */
2901       gzone = FALSE;
2902       discarded = FALSE;
2903       p2 = ((SFInst *) (p->data))->zone;
2904       if (p2)
2905 	hz = &p2;
2906       while (p2)
2907 	{			/* traverse this instrument's zones */
2908 	  level = 0;
2909 	  z = (SFZone *) (p2->data);
2910 	  p3 = z->gen;
2911 	  while (p3)
2912 	    {			/* load zone's generators */
2913 	      dup = NULL;
2914 	      skip = FALSE;
2915 	      drop = FALSE;
2916 	      if ((size -= SFGENSIZE) < 0)
2917 		return (gerr (ErrCorr, _("IGEN chunk size mismatch")));
2918 
2919 	      READW (genid, fd);
2920 
2921 	      if (genid == Gen_KeyRange)
2922 		{		/* nothing precedes */
2923 		  if (level == 0)
2924 		    {
2925 		      level = 1;
2926 		      READB (genval.range.lo, fd);
2927 		      READB (genval.range.hi, fd);
2928 		    }
2929 		  else
2930 		    skip = TRUE;
2931 		}
2932 	      else if (genid == Gen_VelRange)
2933 		{		/* only KeyRange precedes */
2934 		  if (level <= 1)
2935 		    {
2936 		      level = 2;
2937 		      READB (genval.range.lo, fd);
2938 		      READB (genval.range.hi, fd);
2939 		    }
2940 		  else
2941 		    skip = TRUE;
2942 		}
2943 	      else if (genid == Gen_SampleId)
2944 		{		/* sample is last gen */
2945 		  level = 3;
2946 		  READW (genval.uword, fd);
2947 		  ((SFZone *) (p2->data))->instsamp = GINT_TO_POINTER (genval.uword + 1);
2948 		  break;	/* break out of generator loop */
2949 		}
2950 	      else
2951 		{
2952 		  level = 2;
2953 		  if (gen_valid (genid))
2954 		    {		/* gen valid? */
2955 		      READW (genval.sword, fd);
2956 		      dup = gen_inlist (genid, z->gen);
2957 		    }
2958 		  else
2959 		    skip = TRUE;
2960 		}
2961 
2962 	      if (!skip)
2963 		{
2964 		  if (!dup)
2965 		    {		/* if gen ! dup alloc new */
2966 		      g = FLUID_NEW (SFGen);
2967 		      p3->data = g;
2968 		      g->id = genid;
2969 		    }
2970 		  else
2971 		    {
2972 		      g = (SFGen *) (dup->data);
2973 		      drop = TRUE;
2974 		    }
2975 		  g->amount = genval;
2976 		}
2977 	      else
2978 		{		/* skip this generator */
2979 		  discarded = TRUE;
2980 		  drop = TRUE;
2981 		  FSKIPW (fd);
2982 		}
2983 
2984 	      if (!drop)
2985 		p3 = fluid_list_next (p3);	/* next gen */
2986 	      else
2987 		SLADVREM (z->gen, p3);
2988 
2989 	    }			/* generator loop */
2990 
2991 	  if (level == 3)
2992 	    SLADVREM (z->gen, p3);	/* zone has sample? */
2993 	  else
2994 	    {			/* its a global zone */
2995 	      if (!gzone)
2996 		{
2997 		  gzone = TRUE;
2998 
2999 		  /* if global zone is not 1st zone, relocate */
3000 		  if (*hz != p2)
3001 		    {
3002 		      void* save = p2->data;
3003 		      FLUID_LOG (FLUID_WARN,
3004 			_("Instrument \"%s\": Global zone is not first zone"),
3005 			((SFPreset *) (p->data))->name);
3006 		      SLADVREM (*hz, p2);
3007 		      *hz = fluid_list_prepend (*hz, save);
3008 		      continue;
3009 		    }
3010 		}
3011 	      else
3012 		{		/* previous global zone exists, discard */
3013 		  FLUID_LOG (FLUID_WARN,
3014 		    _("Instrument \"%s\": Discarding invalid global zone"),
3015 		    ((SFInst *) (p->data))->name);
3016 		  sfont_zone_delete (sf, hz, (SFZone *) (p2->data));
3017 		}
3018 	    }
3019 
3020 	  while (p3)
3021 	    {			/* Kill any zones following a sample */
3022 	      discarded = TRUE;
3023 	      if ((size -= SFGENSIZE) < 0)
3024 		return (gerr (ErrCorr,
3025 		    _("Instrument generator chunk size mismatch")));
3026 	      FSKIP (SFGENSIZE, fd);
3027 	      SLADVREM (z->gen, p3);
3028 	    }
3029 
3030 	  p2 = fluid_list_next (p2);	/* next zone */
3031 	}
3032       if (discarded)
3033 	FLUID_LOG(FLUID_WARN,
3034 	  _("Instrument \"%s\": Some invalid generators were discarded"),
3035 	  ((SFInst *) (p->data))->name);
3036       p = fluid_list_next (p);
3037     }
3038 
3039   /* for those non-terminal record cases, grr! */
3040   if (size == 0)
3041     return (OK);
3042 
3043   size -= SFGENSIZE;
3044   if (size != 0)
3045     return (gerr (ErrCorr, _("IGEN chunk size mismatch")));
3046   FSKIP (SFGENSIZE, fd);	/* terminal gen */
3047 
3048   return (OK);
3049 }
3050 
3051 /* sample header loader */
3052 static int
load_shdr(unsigned int size,SFData * sf,FILE * fd)3053 load_shdr (unsigned int size, SFData * sf, FILE * fd)
3054 {
3055   unsigned int i;
3056   SFSample *p;
3057 
3058   if (size % SFSHDRSIZE || size == 0)	/* size is multiple of SHDR size? */
3059     return (gerr (ErrCorr, _("Sample header has invalid size")));
3060 
3061   size = size / SFSHDRSIZE - 1;
3062   if (size == 0)
3063     {				/* at least one sample + term record? */
3064       FLUID_LOG (FLUID_WARN, _("File contains no samples"));
3065       FSKIP (SFSHDRSIZE, fd);
3066       return (OK);
3067     }
3068 
3069   /* load all sample headers */
3070   for (i = 0; i < size; i++)
3071     {
3072       p = FLUID_NEW (SFSample);
3073       sf->sample = fluid_list_append (sf->sample, p);
3074       READSTR (&p->name, fd);
3075       READD (p->start, fd);
3076       READD (p->end, fd);	/* - end, loopstart and loopend */
3077       READD (p->loopstart, fd);	/* - will be checked and turned into */
3078       READD (p->loopend, fd);	/* - offsets in fixup_sample() */
3079       READD (p->samplerate, fd);
3080       READB (p->origpitch, fd);
3081       READB (p->pitchadj, fd);
3082       FSKIPW (fd);		/* skip sample link */
3083       READW (p->sampletype, fd);
3084       p->samfile = 0;
3085     }
3086 
3087   FSKIP (SFSHDRSIZE, fd);	/* skip terminal shdr */
3088 
3089   return (OK);
3090 }
3091 
3092 /* "fixup" (inst # -> inst ptr) instrument references in preset list */
3093 static int
fixup_pgen(SFData * sf)3094 fixup_pgen (SFData * sf)
3095 {
3096   fluid_list_t *p, *p2, *p3;
3097   SFZone *z;
3098   int i;
3099 
3100   p = sf->preset;
3101   while (p)
3102     {
3103       p2 = ((SFPreset *) (p->data))->zone;
3104       while (p2)
3105 	{			/* traverse this preset's zones */
3106 	  z = (SFZone *) (p2->data);
3107 	  if ((i = GPOINTER_TO_INT (z->instsamp)))
3108 	    {			/* load instrument # */
3109 	      p3 = fluid_list_nth (sf->inst, i - 1);
3110 	      if (!p3)
3111 		return (gerr (ErrCorr,
3112 		    _("Preset %03d %03d: Invalid instrument reference"),
3113 		    ((SFPreset *) (p->data))->bank,
3114 		    ((SFPreset *) (p->data))->prenum));
3115 	      z->instsamp = p3;
3116 	    }
3117 	  else
3118 	    z->instsamp = NULL;
3119 	  p2 = fluid_list_next (p2);
3120 	}
3121       p = fluid_list_next (p);
3122     }
3123 
3124   return (OK);
3125 }
3126 
3127 /* "fixup" (sample # -> sample ptr) sample references in instrument list */
3128 static int
fixup_igen(SFData * sf)3129 fixup_igen (SFData * sf)
3130 {
3131   fluid_list_t *p, *p2, *p3;
3132   SFZone *z;
3133   int i;
3134 
3135   p = sf->inst;
3136   while (p)
3137     {
3138       p2 = ((SFInst *) (p->data))->zone;
3139       while (p2)
3140 	{			/* traverse instrument's zones */
3141 	  z = (SFZone *) (p2->data);
3142 	  if ((i = GPOINTER_TO_INT (z->instsamp)))
3143 	    {			/* load sample # */
3144 	      p3 = fluid_list_nth (sf->sample, i - 1);
3145 	      if (!p3)
3146 		return (gerr (ErrCorr,
3147 		    _("Instrument \"%s\": Invalid sample reference"),
3148 		    ((SFInst *) (p->data))->name));
3149 	      z->instsamp = p3;
3150 	    }
3151 	  p2 = fluid_list_next (p2);
3152 	}
3153       p = fluid_list_next (p);
3154     }
3155 
3156   return (OK);
3157 }
3158 
3159 /* convert sample end, loopstart and loopend to offsets and check if valid */
3160 static int
fixup_sample(SFData * sf)3161 fixup_sample (SFData * sf)
3162 {
3163   fluid_list_t *p;
3164   SFSample *sam;
3165 
3166   p = sf->sample;
3167   while (p)
3168     {
3169       sam = (SFSample *) (p->data);
3170 
3171       /* if sample is not a ROM sample and end is over the sample data chunk
3172          or sam start is greater than 4 less than the end (at least 4 samples) */
3173       if ((!(sam->sampletype & FLUID_SAMPLETYPE_ROM)
3174 	  && sam->end > sdtachunk_size) || sam->start > (sam->end - 4))
3175 	{
3176 	  FLUID_LOG (FLUID_WARN, _("Sample '%s' start/end file positions are invalid,"
3177 	      " disabling and will not be saved"), sam->name);
3178 
3179 	  /* disable sample by setting all sample markers to 0 */
3180 	  sam->start = sam->end = sam->loopstart = sam->loopend = 0;
3181 
3182 	  return (OK);
3183 	}
3184       else if (sam->loopend > sam->end || sam->loopstart >= sam->loopend
3185 	|| sam->loopstart <= sam->start)
3186 	{			/* loop is fowled?? (cluck cluck :) */
3187 	  /* can pad loop by 8 samples and ensure at least 4 for loop (2*8+4) */
3188 	  if ((sam->end - sam->start) >= 20)
3189 	    {
3190 	      sam->loopstart = sam->start + 8;
3191 	      sam->loopend = sam->end - 8;
3192 	    }
3193 	  else
3194 	    {			/* loop is fowled, sample is tiny (can't pad 8 samples) */
3195 	      sam->loopstart = sam->start + 1;
3196 	      sam->loopend = sam->end - 1;
3197 	    }
3198 	}
3199 
3200       /* convert sample end, loopstart, loopend to offsets from sam->start */
3201       sam->end -= sam->start + 1;	/* marks last sample, contrary to SF spec. */
3202       sam->loopstart -= sam->start;
3203       sam->loopend -= sam->start;
3204 
3205       p = fluid_list_next (p);
3206     }
3207 
3208   return (OK);
3209 }
3210 
3211 /*=================================sfont.c========================
3212   Smurf SoundFont Editor
3213   ================================================================*/
3214 
3215 
3216 /* optimum chunk area sizes (could be more optimum) */
3217 #define PRESET_CHUNK_OPTIMUM_AREA	256
3218 #define INST_CHUNK_OPTIMUM_AREA		256
3219 #define SAMPLE_CHUNK_OPTIMUM_AREA	256
3220 #define ZONE_CHUNK_OPTIMUM_AREA		256
3221 #define MOD_CHUNK_OPTIMUM_AREA		256
3222 #define GEN_CHUNK_OPTIMUM_AREA		256
3223 
3224 unsigned short badgen[] = { Gen_Unused1, Gen_Unused2, Gen_Unused3, Gen_Unused4,
3225   Gen_Reserved1, Gen_Reserved2, Gen_Reserved3, 0
3226 };
3227 
3228 unsigned short badpgen[] = { Gen_StartAddrOfs, Gen_EndAddrOfs, Gen_StartLoopAddrOfs,
3229   Gen_EndLoopAddrOfs, Gen_StartAddrCoarseOfs, Gen_EndAddrCoarseOfs,
3230   Gen_StartLoopAddrCoarseOfs, Gen_Keynum, Gen_Velocity,
3231   Gen_EndLoopAddrCoarseOfs, Gen_SampleModes, Gen_ExclusiveClass,
3232   Gen_OverrideRootKey, 0
3233 };
3234 
3235 /* close SoundFont file and delete a SoundFont structure */
3236 void
sfont_close(SFData * sf)3237 sfont_close (SFData * sf)
3238 {
3239   fluid_list_t *p, *p2;
3240 
3241   if (sf->sffd)
3242     fclose (sf->sffd);
3243 
3244   if (sf->fname)
3245     free (sf->fname);
3246 
3247   p = sf->info;
3248   while (p)
3249     {
3250       free (p->data);
3251       p = fluid_list_next (p);
3252     }
3253   delete_fluid_list(sf->info);
3254   sf->info = NULL;
3255 
3256   p = sf->preset;
3257   while (p)
3258     {				/* loop over presets */
3259       p2 = ((SFPreset *) (p->data))->zone;
3260       while (p2)
3261 	{			/* loop over preset's zones */
3262 	  sfont_free_zone (p2->data);
3263 	  p2 = fluid_list_next (p2);
3264 	}			/* free preset's zone list */
3265       delete_fluid_list (((SFPreset *) (p->data))->zone);
3266       FLUID_FREE (p->data);	/* free preset chunk */
3267       p = fluid_list_next (p);
3268     }
3269   delete_fluid_list (sf->preset);
3270   sf->preset = NULL;
3271 
3272   p = sf->inst;
3273   while (p)
3274     {				/* loop over instruments */
3275       p2 = ((SFInst *) (p->data))->zone;
3276       while (p2)
3277 	{			/* loop over inst's zones */
3278 	  sfont_free_zone (p2->data);
3279 	  p2 = fluid_list_next (p2);
3280 	}			/* free inst's zone list */
3281       delete_fluid_list (((SFInst *) (p->data))->zone);
3282       FLUID_FREE (p->data);
3283       p = fluid_list_next (p);
3284     }
3285   delete_fluid_list (sf->inst);
3286   sf->inst = NULL;
3287 
3288   p = sf->sample;
3289   while (p)
3290     {
3291       FLUID_FREE (p->data);
3292       p = fluid_list_next (p);
3293     }
3294   delete_fluid_list (sf->sample);
3295   sf->sample = NULL;
3296 
3297   FLUID_FREE (sf);
3298 }
3299 
3300 /* free all elements of a zone (Preset or Instrument) */
3301 void
sfont_free_zone(SFZone * zone)3302 sfont_free_zone (SFZone * zone)
3303 {
3304   fluid_list_t *p;
3305 
3306   if (!zone)
3307     return;
3308 
3309   p = zone->gen;
3310   while (p)
3311     {				/* Free gen chunks for this zone */
3312       if (p->data)
3313 	FLUID_FREE (p->data);
3314       p = fluid_list_next (p);
3315     }
3316   delete_fluid_list (zone->gen);	/* free genlist */
3317 
3318   p = zone->mod;
3319   while (p)
3320     {				/* Free mod chunks for this zone */
3321       if (p->data)
3322 	FLUID_FREE (p->data);
3323       p = fluid_list_next (p);
3324     }
3325   delete_fluid_list (zone->mod);	/* free modlist */
3326 
3327   FLUID_FREE (zone);	/* free zone chunk */
3328 }
3329 
3330 /* preset sort function, first by bank, then by preset # */
3331 int
sfont_preset_compare_func(void * a,void * b)3332 sfont_preset_compare_func (void* a, void* b)
3333 {
3334   int aval, bval;
3335 
3336   aval = (int) (((SFPreset *) a)->bank) << 16 | ((SFPreset *) a)->prenum;
3337   bval = (int) (((SFPreset *) b)->bank) << 16 | ((SFPreset *) b)->prenum;
3338 
3339   return (aval - bval);
3340 }
3341 
3342 /* delete zone from zone list */
3343 void
sfont_zone_delete(SFData * sf,fluid_list_t ** zlist,SFZone * zone)3344 sfont_zone_delete (SFData * sf, fluid_list_t ** zlist, SFZone * zone)
3345 {
3346   *zlist = fluid_list_remove (*zlist, (void*) zone);
3347   sfont_free_zone (zone);
3348 }
3349 
3350 /* Find generator in gen list */
3351 fluid_list_t *
gen_inlist(int gen,fluid_list_t * genlist)3352 gen_inlist (int gen, fluid_list_t * genlist)
3353 {				/* is generator in gen list? */
3354   fluid_list_t *p;
3355 
3356   p = genlist;
3357   while (p)
3358     {
3359       if (p->data == NULL)
3360 	return (NULL);
3361       if (gen == ((SFGen *) p->data)->id)
3362 	break;
3363       p = fluid_list_next (p);
3364     }
3365   return (p);
3366 }
3367 
3368 /* check validity of instrument generator */
3369 int
gen_valid(int gen)3370 gen_valid (int gen)
3371 {				/* is generator id valid? */
3372   int i = 0;
3373 
3374   if (gen > Gen_MaxValid)
3375     return (FALSE);
3376   while (badgen[i] && badgen[i] != gen)
3377     i++;
3378   return (badgen[i] == 0);
3379 }
3380 
3381 /* check validity of preset generator */
3382 int
gen_validp(int gen)3383 gen_validp (int gen)
3384 {				/* is preset generator valid? */
3385   int i = 0;
3386 
3387   if (!gen_valid (gen))
3388     return (FALSE);
3389   while (badpgen[i] && badpgen[i] != (unsigned short) gen)
3390     i++;
3391   return (badpgen[i] == 0);
3392 }
3393 
3394 /*================================util.c===========================*/
3395 
3396 /* Logging function, returns FAIL to use as a return value in calling funcs */
3397 int
gerr(int ev,char * fmt,...)3398 gerr (int ev, char * fmt, ...)
3399 {
3400   va_list args;
3401 
3402   va_start (args, fmt);
3403   vprintf(fmt, args);
3404   va_end (args);
3405 
3406   printf("\n");
3407 
3408   return (FAIL);
3409 }
3410 
3411 int
safe_fread(void * buf,int count,FILE * fd)3412 safe_fread (void *buf, int count, FILE * fd)
3413 {
3414   if (fread (buf, count, 1, fd) != 1)
3415     {				/* size_t = count, nmemb = 1 */
3416       if (feof (fd))
3417 	gerr (ErrEof, _("EOF while attemping to read %d bytes"), count);
3418       else
3419 	FLUID_LOG (FLUID_ERR, _("File read failed"));
3420       return (FAIL);
3421     }
3422   return (OK);
3423 }
3424 
3425 int
safe_fseek(FILE * fd,long ofs,int whence)3426 safe_fseek (FILE * fd, long ofs, int whence)
3427 {
3428   if (fseek (fd, ofs, whence) == -1) {
3429     FLUID_LOG (FLUID_ERR, _("File seek failed with offset = %ld and whence = %d"), ofs, whence);
3430     return (FAIL);
3431   }
3432   return (OK);
3433 }
3434