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