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