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