Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/fluidsynth/src/sfloader/fluid_defsfont.c
4396 views
1
/* FluidSynth - A Software Synthesizer
2
*
3
* Copyright (C) 2003 Peter Hanappe and others.
4
*
5
* SoundFont file loading code borrowed from Smurf SoundFont Editor
6
* Copyright (C) 1999-2001 Josh Green
7
*
8
* This library is free software; you can redistribute it and/or
9
* modify it under the terms of the GNU Lesser General Public License
10
* as published by the Free Software Foundation; either version 2.1 of
11
* the License, or (at your option) any later version.
12
*
13
* This library is distributed in the hope that it will be useful, but
14
* WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
* Lesser General Public License for more details.
17
*
18
* You should have received a copy of the GNU Lesser General Public
19
* License along with this library; if not, write to the Free
20
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21
* 02110-1301, USA
22
*/
23
24
25
#include "fluid_defsfont.h"
26
#include "fluid_sfont.h"
27
#include "fluid_sys.h"
28
#include "fluid_synth.h"
29
#include "fluid_samplecache.h"
30
#include "fluid_chan.h"
31
32
/* EMU8k/10k hardware applies this factor to initial attenuation generator values set at preset and
33
* instrument level in a soundfont. We apply this factor when loading the generator values to stay
34
* compatible as most existing soundfonts expect exactly this (strange, non-standard) behaviour. */
35
#define EMU_ATTENUATION_FACTOR (0.4f)
36
37
/* Dynamic sample loading functions */
38
static int pin_preset_samples(fluid_defsfont_t *defsfont, fluid_preset_t *preset);
39
static int unpin_preset_samples(fluid_defsfont_t *defsfont, fluid_preset_t *preset);
40
static int load_preset_samples(fluid_defsfont_t *defsfont, fluid_preset_t *preset);
41
static int unload_preset_samples(fluid_defsfont_t *defsfont, fluid_preset_t *preset);
42
static void unload_sample(fluid_sample_t *sample);
43
static int dynamic_samples_preset_notify(fluid_preset_t *preset, int reason, int chan);
44
static int dynamic_samples_sample_notify(fluid_sample_t *sample, int reason);
45
static int fluid_preset_zone_create_voice_zones(fluid_preset_zone_t *preset_zone);
46
static fluid_inst_t *find_inst_by_idx(fluid_defsfont_t *defsfont, int idx);
47
48
49
/***************************************************************
50
*
51
* SFONT LOADER
52
*/
53
54
/**
55
* Creates a default soundfont2 loader that can be used with fluid_synth_add_sfloader().
56
* By default every synth instance has an initial default soundfont loader instance.
57
* Calling this function is usually only necessary to load a soundfont from memory, by providing custom callback functions via fluid_sfloader_set_callbacks().
58
*
59
* @param settings A settings instance obtained by new_fluid_settings()
60
* @return A default soundfont2 loader struct
61
*/
62
fluid_sfloader_t *new_fluid_defsfloader(fluid_settings_t *settings)
63
{
64
fluid_sfloader_t *loader;
65
fluid_return_val_if_fail(settings != NULL, NULL);
66
67
loader = new_fluid_sfloader(fluid_defsfloader_load, delete_fluid_sfloader);
68
69
if(loader == NULL)
70
{
71
FLUID_LOG(FLUID_ERR, "Out of memory");
72
return NULL;
73
}
74
75
fluid_sfloader_set_data(loader, settings);
76
77
return loader;
78
}
79
80
fluid_sfont_t *fluid_defsfloader_load(fluid_sfloader_t *loader, const char *filename)
81
{
82
fluid_defsfont_t *defsfont;
83
fluid_sfont_t *sfont;
84
85
defsfont = new_fluid_defsfont(fluid_sfloader_get_data(loader));
86
87
if(defsfont == NULL)
88
{
89
return NULL;
90
}
91
92
sfont = new_fluid_sfont(fluid_defsfont_sfont_get_name,
93
fluid_defsfont_sfont_get_preset,
94
fluid_defsfont_sfont_iteration_start,
95
fluid_defsfont_sfont_iteration_next,
96
fluid_defsfont_sfont_delete);
97
98
if(sfont == NULL)
99
{
100
delete_fluid_defsfont(defsfont);
101
return NULL;
102
}
103
104
fluid_sfont_set_data(sfont, defsfont);
105
106
defsfont->sfont = sfont;
107
108
if(fluid_defsfont_load(defsfont, &loader->file_callbacks, filename) == FLUID_FAILED)
109
{
110
fluid_defsfont_sfont_delete(sfont);
111
return NULL;
112
}
113
114
return sfont;
115
}
116
117
118
119
/***************************************************************
120
*
121
* PUBLIC INTERFACE
122
*/
123
124
int fluid_defsfont_sfont_delete(fluid_sfont_t *sfont)
125
{
126
if(delete_fluid_defsfont(fluid_sfont_get_data(sfont)) != FLUID_OK)
127
{
128
return -1;
129
}
130
131
delete_fluid_sfont(sfont);
132
return 0;
133
}
134
135
const char *fluid_defsfont_sfont_get_name(fluid_sfont_t *sfont)
136
{
137
return fluid_defsfont_get_name(fluid_sfont_get_data(sfont));
138
}
139
140
fluid_preset_t *
141
fluid_defsfont_sfont_get_preset(fluid_sfont_t *sfont, int bank, int prenum)
142
{
143
return fluid_defsfont_get_preset(fluid_sfont_get_data(sfont), bank, prenum);
144
}
145
146
void fluid_defsfont_sfont_iteration_start(fluid_sfont_t *sfont)
147
{
148
fluid_defsfont_iteration_start(fluid_sfont_get_data(sfont));
149
}
150
151
fluid_preset_t *fluid_defsfont_sfont_iteration_next(fluid_sfont_t *sfont)
152
{
153
return fluid_defsfont_iteration_next(fluid_sfont_get_data(sfont));
154
}
155
156
void fluid_defpreset_preset_delete(fluid_preset_t *preset)
157
{
158
fluid_defsfont_t *defsfont;
159
fluid_defpreset_t *defpreset;
160
161
defsfont = fluid_sfont_get_data(preset->sfont);
162
defpreset = fluid_preset_get_data(preset);
163
164
if(defsfont)
165
{
166
defsfont->preset = fluid_list_remove(defsfont->preset, defpreset);
167
}
168
169
delete_fluid_defpreset(defpreset);
170
delete_fluid_preset(preset);
171
}
172
173
const char *fluid_defpreset_preset_get_name(fluid_preset_t *preset)
174
{
175
return fluid_defpreset_get_name(fluid_preset_get_data(preset));
176
}
177
178
int fluid_defpreset_preset_get_banknum(fluid_preset_t *preset)
179
{
180
return fluid_defpreset_get_banknum(fluid_preset_get_data(preset));
181
}
182
183
int fluid_defpreset_preset_get_num(fluid_preset_t *preset)
184
{
185
return fluid_defpreset_get_num(fluid_preset_get_data(preset));
186
}
187
188
int fluid_defpreset_preset_noteon(fluid_preset_t *preset, fluid_synth_t *synth,
189
int chan, int key, int vel)
190
{
191
return fluid_defpreset_noteon(fluid_preset_get_data(preset), synth, chan, key, vel);
192
}
193
194
195
/***************************************************************
196
*
197
* SFONT
198
*/
199
200
/*
201
* new_fluid_defsfont
202
*/
203
fluid_defsfont_t *new_fluid_defsfont(fluid_settings_t *settings)
204
{
205
fluid_defsfont_t *defsfont;
206
207
defsfont = FLUID_NEW(fluid_defsfont_t);
208
209
if(defsfont == NULL)
210
{
211
FLUID_LOG(FLUID_ERR, "Out of memory");
212
return NULL;
213
}
214
215
FLUID_MEMSET(defsfont, 0, sizeof(*defsfont));
216
217
fluid_settings_getint(settings, "synth.lock-memory", &defsfont->mlock);
218
fluid_settings_getint(settings, "synth.dynamic-sample-loading", &defsfont->dynamic_samples);
219
220
return defsfont;
221
}
222
223
/*
224
* delete_fluid_defsfont
225
*/
226
int delete_fluid_defsfont(fluid_defsfont_t *defsfont)
227
{
228
fluid_list_t *list;
229
fluid_preset_t *preset;
230
fluid_sample_t *sample;
231
232
fluid_return_val_if_fail(defsfont != NULL, FLUID_OK);
233
234
/* If we use dynamic sample loading, make sure we unpin any
235
* pinned presets before removing this soundfont */
236
if(defsfont->dynamic_samples)
237
{
238
for(list = defsfont->preset; list; list = fluid_list_next(list))
239
{
240
preset = (fluid_preset_t *)fluid_list_get(list);
241
unpin_preset_samples(defsfont, preset);
242
}
243
}
244
245
/* Check that no samples are currently used */
246
for(list = defsfont->sample; list; list = fluid_list_next(list))
247
{
248
sample = (fluid_sample_t *) fluid_list_get(list);
249
250
if(sample->refcount != 0)
251
{
252
return FLUID_FAILED;
253
}
254
}
255
256
if(defsfont->filename != NULL)
257
{
258
FLUID_FREE(defsfont->filename);
259
}
260
261
for(list = defsfont->sample; list; list = fluid_list_next(list))
262
{
263
sample = (fluid_sample_t *) fluid_list_get(list);
264
265
/* If the sample data pointer is different to the sampledata chunk of
266
* the soundfont, then the sample has been loaded individually (SF3)
267
* and needs to be unloaded explicitly. This is safe even if using
268
* dynamic sample loading, as the sample_unload mechanism sets
269
* sample->data to NULL after unload. */
270
if ((sample->data != NULL) && (sample->data != defsfont->sampledata))
271
{
272
fluid_samplecache_unload(sample->data);
273
}
274
delete_fluid_sample(sample);
275
}
276
277
if(defsfont->sample)
278
{
279
delete_fluid_list(defsfont->sample);
280
}
281
282
if(defsfont->sampledata != NULL)
283
{
284
fluid_samplecache_unload(defsfont->sampledata);
285
}
286
287
for(list = defsfont->preset; list; list = fluid_list_next(list))
288
{
289
preset = (fluid_preset_t *)fluid_list_get(list);
290
fluid_defpreset_preset_delete(preset);
291
}
292
293
delete_fluid_list(defsfont->preset);
294
295
for(list = defsfont->inst; list; list = fluid_list_next(list))
296
{
297
delete_fluid_inst(fluid_list_get(list));
298
}
299
300
delete_fluid_list(defsfont->inst);
301
302
FLUID_FREE(defsfont);
303
return FLUID_OK;
304
}
305
306
/*
307
* fluid_defsfont_get_name
308
*/
309
const char *fluid_defsfont_get_name(fluid_defsfont_t *defsfont)
310
{
311
return defsfont->filename;
312
}
313
314
/* Load sample data for a single sample from the Soundfont file.
315
* Returns FLUID_OK on error, otherwise FLUID_FAILED
316
*/
317
int fluid_defsfont_load_sampledata(fluid_defsfont_t *defsfont, SFData *sfdata, fluid_sample_t *sample)
318
{
319
int num_samples;
320
unsigned int source_end = sample->source_end;
321
322
/* For uncompressed samples we want to include the 46 zero sample word area following each sample
323
* in the Soundfont. Otherwise samples with loopend > end, which we have decided not to correct, would
324
* be corrected after all in fluid_sample_sanitize_loop */
325
if(!(sample->sampletype & FLUID_SAMPLETYPE_OGG_VORBIS))
326
{
327
source_end += 46; /* Length of zero sample word after each sample, according to SF specs */
328
329
/* Safeguard against Soundfonts that are not quite valid and don't include 46 sample words after the
330
* last sample */
331
if(source_end >= (defsfont->samplesize / sizeof(short)))
332
{
333
source_end = defsfont->samplesize / sizeof(short);
334
}
335
}
336
337
num_samples = fluid_samplecache_load(
338
sfdata, sample->source_start, source_end, sample->sampletype,
339
defsfont->mlock, &sample->data, &sample->data24);
340
341
if(num_samples < 0)
342
{
343
return FLUID_FAILED;
344
}
345
346
if(num_samples == 0)
347
{
348
sample->start = sample->end = 0;
349
sample->loopstart = sample->loopend = 0;
350
return FLUID_OK;
351
}
352
353
/* Ogg Vorbis samples already have loop pointers relative to the individual decompressed sample,
354
* but SF2 samples are relative to sample chunk start, so they need to be adjusted */
355
if(!(sample->sampletype & FLUID_SAMPLETYPE_OGG_VORBIS))
356
{
357
sample->loopstart = sample->source_loopstart - sample->source_start;
358
sample->loopend = sample->source_loopend - sample->source_start;
359
}
360
361
/* As we've just loaded an individual sample into it's own buffer, we need to adjust the start
362
* and end pointers */
363
sample->start = 0;
364
sample->end = num_samples - 1;
365
366
return FLUID_OK;
367
}
368
369
/* Loads the sample data for all samples from the Soundfont file. For SF2 files, it loads the data in
370
* one large block. For SF3 files, each compressed sample gets loaded individually.
371
* Returns FLUID_OK on success, otherwise FLUID_FAILED
372
*/
373
int fluid_defsfont_load_all_sampledata(fluid_defsfont_t *defsfont, SFData *sfdata)
374
{
375
fluid_list_t *list;
376
fluid_sample_t *sample;
377
int sf3_file = (sfdata->version.major == 3);
378
int sample_parsing_result = FLUID_OK;
379
int invalid_loops_were_sanitized = FALSE;
380
381
/* For SF2 files, we load the sample data in one large block */
382
if(!sf3_file)
383
{
384
int read_samples;
385
int num_samples = sfdata->samplesize / sizeof(short);
386
387
read_samples = fluid_samplecache_load(sfdata, 0, num_samples - 1, 0, defsfont->mlock,
388
&defsfont->sampledata, &defsfont->sample24data);
389
390
if(read_samples != num_samples)
391
{
392
FLUID_LOG(FLUID_ERR, "Attempted to read %d words of sample data, but got %d instead",
393
num_samples, read_samples);
394
return FLUID_FAILED;
395
}
396
}
397
398
#pragma omp parallel
399
#pragma omp single
400
for(list = defsfont->sample; list; list = fluid_list_next(list))
401
{
402
sample = fluid_list_get(list);
403
404
if(sf3_file)
405
{
406
/* SF3 samples get loaded individually, as most (or all) of them are in Ogg Vorbis format
407
* anyway */
408
#pragma omp task firstprivate(sample,sfdata,defsfont) shared(sample_parsing_result, invalid_loops_were_sanitized) default(none)
409
{
410
if(fluid_defsfont_load_sampledata(defsfont, sfdata, sample) == FLUID_FAILED)
411
{
412
#pragma omp critical
413
{
414
FLUID_LOG(FLUID_ERR, "Failed to load sample '%s'", sample->name);
415
sample_parsing_result = FLUID_FAILED;
416
}
417
}
418
else
419
{
420
int modified = fluid_sample_sanitize_loop(sample, (sample->end + 1) * sizeof(short));
421
if(modified)
422
{
423
#pragma omp critical
424
{
425
invalid_loops_were_sanitized = TRUE;
426
}
427
}
428
fluid_voice_optimize_sample(sample);
429
}
430
}
431
}
432
else
433
{
434
#pragma omp task firstprivate(sample, defsfont) shared(invalid_loops_were_sanitized) default(none)
435
{
436
int modified;
437
/* Data pointers of SF2 samples point to large sample data block loaded above */
438
sample->data = defsfont->sampledata;
439
sample->data24 = defsfont->sample24data;
440
modified = fluid_sample_sanitize_loop(sample, defsfont->samplesize);
441
if(modified)
442
{
443
#pragma omp critical
444
{
445
invalid_loops_were_sanitized = TRUE;
446
}
447
}
448
fluid_voice_optimize_sample(sample);
449
}
450
}
451
}
452
453
if(invalid_loops_were_sanitized)
454
{
455
FLUID_LOG(FLUID_WARN,
456
"Some invalid sample loops were sanitized! If you experience audible glitches, "
457
"start fluidsynth in verbose mode for detailed information.");
458
}
459
460
return sample_parsing_result;
461
}
462
463
/*
464
* fluid_defsfont_load
465
*/
466
int fluid_defsfont_load(fluid_defsfont_t *defsfont, const fluid_file_callbacks_t *fcbs, const char *file)
467
{
468
SFData *sfdata;
469
fluid_list_t *p;
470
SFPreset *sfpreset;
471
SFSample *sfsample;
472
fluid_sample_t *sample;
473
fluid_defpreset_t *defpreset = NULL;
474
475
defsfont->filename = FLUID_STRDUP(file);
476
477
if(defsfont->filename == NULL)
478
{
479
FLUID_LOG(FLUID_ERR, "Out of memory");
480
return FLUID_FAILED;
481
}
482
483
defsfont->fcbs = fcbs;
484
485
/* The actual loading is done in the sfont and sffile files */
486
sfdata = fluid_sffile_open(file, fcbs);
487
488
if(sfdata == NULL)
489
{
490
/* error message already printed */
491
return FLUID_FAILED;
492
}
493
494
if(fluid_sffile_parse_presets(sfdata) == FLUID_FAILED)
495
{
496
FLUID_LOG(FLUID_ERR, "Couldn't parse presets from soundfont file");
497
goto err_exit;
498
}
499
500
/* Keep track of the position and size of the sample data because
501
it's loaded separately (and might be unoaded/reloaded in future) */
502
defsfont->samplepos = sfdata->samplepos;
503
defsfont->samplesize = sfdata->samplesize;
504
defsfont->sample24pos = sfdata->sample24pos;
505
defsfont->sample24size = sfdata->sample24size;
506
507
/* Create all samples from sample headers */
508
p = sfdata->sample;
509
510
while(p != NULL)
511
{
512
sfsample = (SFSample *)fluid_list_get(p);
513
514
sample = new_fluid_sample();
515
516
if(sample == NULL)
517
{
518
goto err_exit;
519
}
520
521
if(fluid_sample_import_sfont(sample, sfsample, defsfont) == FLUID_OK)
522
{
523
fluid_defsfont_add_sample(defsfont, sample);
524
}
525
else
526
{
527
delete_fluid_sample(sample);
528
sample = NULL;
529
}
530
531
/* Store reference to FluidSynth sample in SFSample for later IZone fixups */
532
sfsample->fluid_sample = sample;
533
534
p = fluid_list_next(p);
535
}
536
537
/* If dynamic sample loading is disabled, load all samples in the Soundfont */
538
if(!defsfont->dynamic_samples)
539
{
540
if(fluid_defsfont_load_all_sampledata(defsfont, sfdata) == FLUID_FAILED)
541
{
542
FLUID_LOG(FLUID_ERR, "Unable to load all sample data");
543
goto err_exit;
544
}
545
}
546
547
/* Load all the presets */
548
p = sfdata->preset;
549
550
while(p != NULL)
551
{
552
sfpreset = (SFPreset *)fluid_list_get(p);
553
defpreset = new_fluid_defpreset();
554
555
if(defpreset == NULL)
556
{
557
goto err_exit;
558
}
559
560
if(fluid_defpreset_import_sfont(defpreset, sfpreset, defsfont, sfdata) != FLUID_OK)
561
{
562
goto err_exit;
563
}
564
565
if(fluid_defsfont_add_preset(defsfont, defpreset) == FLUID_FAILED)
566
{
567
goto err_exit;
568
}
569
570
p = fluid_list_next(p);
571
}
572
573
fluid_sffile_close(sfdata);
574
575
return FLUID_OK;
576
577
err_exit:
578
fluid_sffile_close(sfdata);
579
delete_fluid_defpreset(defpreset);
580
return FLUID_FAILED;
581
}
582
583
/* fluid_defsfont_add_sample
584
*
585
* Add a sample to the SoundFont
586
*/
587
int fluid_defsfont_add_sample(fluid_defsfont_t *defsfont, fluid_sample_t *sample)
588
{
589
defsfont->sample = fluid_list_prepend(defsfont->sample, sample);
590
return FLUID_OK;
591
}
592
593
/* fluid_defsfont_add_preset
594
*
595
* Add a preset to the SoundFont
596
*/
597
int fluid_defsfont_add_preset(fluid_defsfont_t *defsfont, fluid_defpreset_t *defpreset)
598
{
599
fluid_preset_t *preset;
600
601
preset = new_fluid_preset(defsfont->sfont,
602
fluid_defpreset_preset_get_name,
603
fluid_defpreset_preset_get_banknum,
604
fluid_defpreset_preset_get_num,
605
fluid_defpreset_preset_noteon,
606
fluid_defpreset_preset_delete);
607
608
if(preset == NULL)
609
{
610
return FLUID_FAILED;
611
}
612
613
if(defsfont->dynamic_samples)
614
{
615
preset->notify = dynamic_samples_preset_notify;
616
}
617
618
fluid_preset_set_data(preset, defpreset);
619
620
defsfont->preset = fluid_list_append(defsfont->preset, preset);
621
622
return FLUID_OK;
623
}
624
625
/*
626
* fluid_defsfont_get_preset
627
*/
628
fluid_preset_t *fluid_defsfont_get_preset(fluid_defsfont_t *defsfont, int bank, int num)
629
{
630
fluid_preset_t *preset;
631
fluid_list_t *list;
632
633
for(list = defsfont->preset; list != NULL; list = fluid_list_next(list))
634
{
635
preset = (fluid_preset_t *)fluid_list_get(list);
636
637
if((fluid_preset_get_banknum(preset) == bank) && (fluid_preset_get_num(preset) == num))
638
{
639
return preset;
640
}
641
}
642
643
return NULL;
644
}
645
646
/*
647
* fluid_defsfont_iteration_start
648
*/
649
void fluid_defsfont_iteration_start(fluid_defsfont_t *defsfont)
650
{
651
defsfont->preset_iter_cur = defsfont->preset;
652
}
653
654
/*
655
* fluid_defsfont_iteration_next
656
*/
657
fluid_preset_t *fluid_defsfont_iteration_next(fluid_defsfont_t *defsfont)
658
{
659
fluid_preset_t *preset = (fluid_preset_t *)fluid_list_get(defsfont->preset_iter_cur);
660
661
defsfont->preset_iter_cur = fluid_list_next(defsfont->preset_iter_cur);
662
663
return preset;
664
}
665
666
/***************************************************************
667
*
668
* PRESET
669
*/
670
671
/*
672
* new_fluid_defpreset
673
*/
674
fluid_defpreset_t *
675
new_fluid_defpreset(void)
676
{
677
fluid_defpreset_t *defpreset = FLUID_NEW(fluid_defpreset_t);
678
679
if(defpreset == NULL)
680
{
681
FLUID_LOG(FLUID_ERR, "Out of memory");
682
return NULL;
683
}
684
685
defpreset->next = NULL;
686
defpreset->name[0] = 0;
687
defpreset->bank = 0;
688
defpreset->num = 0;
689
defpreset->global_zone = NULL;
690
defpreset->zone = NULL;
691
defpreset->pinned = FALSE;
692
return defpreset;
693
}
694
695
/*
696
* delete_fluid_defpreset
697
*/
698
void
699
delete_fluid_defpreset(fluid_defpreset_t *defpreset)
700
{
701
fluid_preset_zone_t *zone;
702
703
fluid_return_if_fail(defpreset != NULL);
704
705
delete_fluid_preset_zone(defpreset->global_zone);
706
defpreset->global_zone = NULL;
707
708
zone = defpreset->zone;
709
710
while(zone != NULL)
711
{
712
defpreset->zone = zone->next;
713
delete_fluid_preset_zone(zone);
714
zone = defpreset->zone;
715
}
716
717
FLUID_FREE(defpreset);
718
}
719
720
int
721
fluid_defpreset_get_banknum(fluid_defpreset_t *defpreset)
722
{
723
return defpreset->bank;
724
}
725
726
int
727
fluid_defpreset_get_num(fluid_defpreset_t *defpreset)
728
{
729
return defpreset->num;
730
}
731
732
const char *
733
fluid_defpreset_get_name(fluid_defpreset_t *defpreset)
734
{
735
return defpreset->name;
736
}
737
738
/*
739
* fluid_defpreset_next
740
*/
741
fluid_defpreset_t *
742
fluid_defpreset_next(fluid_defpreset_t *defpreset)
743
{
744
return defpreset->next;
745
}
746
747
/*
748
* Adds global and local modulators list to the voice. This is done in 2 steps:
749
* - Step 1: Local modulators replace identical global modulators.
750
* - Step 2: global + local modulators are added to the voice using mode.
751
*
752
* Instrument zone list (local/global) must be added using FLUID_VOICE_OVERWRITE.
753
* Preset zone list (local/global) must be added using FLUID_VOICE_ADD.
754
*
755
* @param voice voice instance.
756
* @param global_mod global list of modulators.
757
* @param local_mod local list of modulators.
758
* @param mode Determines how to handle an existing identical modulator.
759
* #FLUID_VOICE_ADD to add (offset) the modulator amounts,
760
* #FLUID_VOICE_OVERWRITE to replace the modulator,
761
*/
762
static void
763
fluid_defpreset_noteon_add_mod_to_voice(fluid_voice_t *voice,
764
fluid_mod_t *global_mod, fluid_mod_t *local_mod,
765
int mode)
766
{
767
fluid_mod_t *mod;
768
/* list for 'sorting' global/local modulators */
769
fluid_mod_t *mod_list[FLUID_NUM_MOD];
770
int mod_list_count, i;
771
772
/* identity_limit_count is the modulator upper limit number to handle with
773
* existing identical modulators.
774
* When identity_limit_count is below the actual number of modulators, this
775
* will restrict identity check to this upper limit,
776
* This is useful when we know by advance that there is no duplicate with
777
* modulators at index above this limit. This avoid wasting cpu cycles at
778
* noteon.
779
*/
780
int identity_limit_count;
781
782
/* Step 1: Local modulators replace identical global modulators. */
783
784
/* local (instrument zone/preset zone), modulators: Put them all into a list. */
785
mod_list_count = 0;
786
787
while(local_mod)
788
{
789
/* As modulators number in local_mod list was limited to FLUID_NUM_MOD at
790
soundfont loading time (fluid_limit_mod_list()), here we don't need
791
to check if mod_list is full.
792
*/
793
mod_list[mod_list_count++] = local_mod;
794
local_mod = local_mod->next;
795
}
796
797
/* global (instrument zone/preset zone), modulators.
798
* Replace modulators with the same definition in the global list:
799
* (Instrument zone: SF 2.01 page 69, 'bullet' 8)
800
* (Preset zone: SF 2.01 page 69, second-last bullet).
801
*
802
* mod_list contains local modulators. Now we know that there
803
* is no global modulator identical to another global modulator (this has
804
* been checked at soundfont loading time). So global modulators
805
* are only checked against local modulators number.
806
*/
807
808
/* Restrict identity check to the number of local modulators */
809
identity_limit_count = mod_list_count;
810
811
while(global_mod)
812
{
813
/* 'Identical' global modulators are ignored.
814
* SF2.01 section 9.5.1
815
* page 69, 'bullet' 3 defines 'identical'. */
816
817
for(i = 0; i < identity_limit_count; i++)
818
{
819
if(fluid_mod_test_identity(global_mod, mod_list[i]))
820
{
821
break;
822
}
823
}
824
825
/* Finally add the new modulator to the list. */
826
if(i >= identity_limit_count)
827
{
828
/* Although local_mod and global_mod lists was limited to
829
FLUID_NUM_MOD at soundfont loading time, it is possible that
830
local + global modulators exceeds FLUID_NUM_MOD.
831
So, checks if mod_list_count reaches the limit.
832
*/
833
if(mod_list_count >= FLUID_NUM_MOD)
834
{
835
/* mod_list is full, we silently forget this modulator and
836
next global modulators. When mod_list will be added to the
837
voice, a warning will be displayed if the voice list is full.
838
(see fluid_voice_add_mod_local()).
839
*/
840
break;
841
}
842
843
mod_list[mod_list_count++] = global_mod;
844
}
845
846
global_mod = global_mod->next;
847
}
848
849
/* Step 2: global + local modulators are added to the voice using mode. */
850
851
/*
852
* mod_list contains local and global modulators, we know that:
853
* - there is no global modulator identical to another global modulator,
854
* - there is no local modulator identical to another local modulator,
855
* So these local/global modulators are only checked against
856
* actual number of voice modulators.
857
*/
858
859
/* Restrict identity check to the actual number of voice modulators */
860
/* Actual number of voice modulators : defaults + [instruments] */
861
identity_limit_count = voice->mod_count;
862
863
for(i = 0; i < mod_list_count; i++)
864
{
865
866
mod = mod_list[i];
867
/* in mode FLUID_VOICE_OVERWRITE disabled instruments modulators CANNOT be skipped. */
868
/* in mode FLUID_VOICE_ADD disabled preset modulators can be skipped. */
869
870
if((mode == FLUID_VOICE_OVERWRITE) || (mod->amount != 0))
871
{
872
/* Instrument modulators -supersede- existing (default) modulators.
873
SF 2.01 page 69, 'bullet' 6 */
874
875
/* Preset modulators -add- to existing instrument modulators.
876
SF2.01 page 70 first bullet on page */
877
fluid_voice_add_mod_local(voice, mod, mode, identity_limit_count);
878
}
879
}
880
}
881
882
/*
883
* fluid_defpreset_noteon
884
*/
885
int
886
fluid_defpreset_noteon(fluid_defpreset_t *defpreset, fluid_synth_t *synth, int chan, int key, int vel)
887
{
888
fluid_preset_zone_t *preset_zone, *global_preset_zone;
889
fluid_inst_t *inst;
890
fluid_inst_zone_t *inst_zone, *global_inst_zone;
891
fluid_voice_zone_t *voice_zone;
892
fluid_list_t *list;
893
fluid_voice_t *voice;
894
int tuned_key;
895
int i;
896
897
/* For detuned channels it might be better to use another key for Soundfont sample selection
898
* giving better approximations for the pitch than the original key.
899
* Example: play key 60 on 6370 Hz => use tuned key 64 for sample selection
900
*
901
* This feature is only enabled for melodic channels.
902
* For drum channels we always select Soundfont samples by key numbers.
903
*/
904
905
if(synth->channel[chan]->channel_type == CHANNEL_TYPE_MELODIC)
906
{
907
tuned_key = (int)(fluid_channel_get_key_pitch(synth->channel[chan], key) / 100.0f + 0.5f);
908
}
909
else
910
{
911
tuned_key = key;
912
}
913
914
global_preset_zone = fluid_defpreset_get_global_zone(defpreset);
915
916
/* run thru all the zones of this preset */
917
preset_zone = fluid_defpreset_get_zone(defpreset);
918
919
while(preset_zone != NULL)
920
{
921
922
/* check if the note falls into the key and velocity range of this
923
preset */
924
if(fluid_zone_inside_range(&preset_zone->range, tuned_key, vel))
925
{
926
927
inst = fluid_preset_zone_get_inst(preset_zone);
928
global_inst_zone = fluid_inst_get_global_zone(inst);
929
930
/* run thru all the zones of this instrument that could start a voice */
931
for(list = preset_zone->voice_zone; list != NULL; list = fluid_list_next(list))
932
{
933
voice_zone = fluid_list_get(list);
934
935
/* check if the instrument zone is ignored and the note falls into
936
the key and velocity range of this instrument zone.
937
An instrument zone must be ignored when its voice is already running
938
played by a legato passage (see fluid_synth_noteon_monopoly_legato()) */
939
if(fluid_zone_inside_range(&voice_zone->range, tuned_key, vel))
940
{
941
942
inst_zone = voice_zone->inst_zone;
943
944
/* this is a good zone. allocate a new synthesis process and initialize it */
945
voice = fluid_synth_alloc_voice_LOCAL(synth, inst_zone->sample, chan, key, vel, &voice_zone->range);
946
947
if(voice == NULL)
948
{
949
return FLUID_FAILED;
950
}
951
952
953
/* Instrument level, generators */
954
955
for(i = 0; i < GEN_LAST; i++)
956
{
957
/* SF 2.01 section 9.4 'bullet' 4:
958
*
959
* A generator in a local instrument zone supersedes a
960
* global instrument zone generator. Both cases supersede
961
* the default generator -> voice_gen_set */
962
963
if(inst_zone->gen[i].flags)
964
{
965
fluid_voice_gen_set(voice, i, inst_zone->gen[i].val);
966
967
}
968
else if((global_inst_zone != NULL) && (global_inst_zone->gen[i].flags))
969
{
970
fluid_voice_gen_set(voice, i, global_inst_zone->gen[i].val);
971
972
}
973
else
974
{
975
/* The generator has not been defined in this instrument.
976
* Do nothing, leave it at the default.
977
*/
978
}
979
} /* for all generators */
980
981
/* Adds instrument zone modulators (global and local) to the voice.*/
982
fluid_defpreset_noteon_add_mod_to_voice(voice,
983
/* global instrument modulators */
984
global_inst_zone ? global_inst_zone->mod : NULL,
985
inst_zone->mod, /* local instrument modulators */
986
FLUID_VOICE_OVERWRITE); /* mode */
987
988
/* Preset level, generators */
989
990
for(i = 0; i < GEN_LAST; i++)
991
{
992
fluid_real_t awe_val;
993
/* SF 2.01 section 8.5 page 58: If some generators are
994
encountered at preset level, they should be ignored.
995
However this check is not necessary when the soundfont
996
loader has ignored invalid preset generators.
997
Actually load_pgen()has ignored these invalid preset
998
generators:
999
GEN_STARTADDROFS, GEN_ENDADDROFS,
1000
GEN_STARTLOOPADDROFS, GEN_ENDLOOPADDROFS,
1001
GEN_STARTADDRCOARSEOFS,GEN_ENDADDRCOARSEOFS,
1002
GEN_STARTLOOPADDRCOARSEOFS,
1003
GEN_KEYNUM, GEN_VELOCITY,
1004
GEN_ENDLOOPADDRCOARSEOFS,
1005
GEN_SAMPLEMODE, GEN_EXCLUSIVECLASS,GEN_OVERRIDEROOTKEY
1006
*/
1007
1008
/* SF 2.01 section 9.4 'bullet' 9: A generator in a
1009
* local preset zone supersedes a global preset zone
1010
* generator. The effect is -added- to the destination
1011
* summing node -> voice_gen_incr */
1012
1013
if(preset_zone->gen[i].flags)
1014
{
1015
fluid_voice_gen_incr(voice, i, preset_zone->gen[i].val);
1016
}
1017
else if((global_preset_zone != NULL) && global_preset_zone->gen[i].flags)
1018
{
1019
fluid_voice_gen_incr(voice, i, global_preset_zone->gen[i].val);
1020
}
1021
else
1022
{
1023
/* The generator has not been defined in this preset
1024
* Do nothing, leave it unchanged.
1025
*/
1026
}
1027
1028
/* ...unless the default value has been overridden by an AWE32 NRPN */
1029
if (fluid_channel_get_override_gen_default(synth->channel[chan], i, &awe_val))
1030
{
1031
fluid_voice_gen_set(voice, i, awe_val);
1032
}
1033
} /* for all generators */
1034
1035
/* Adds preset zone modulators (global and local) to the voice.*/
1036
fluid_defpreset_noteon_add_mod_to_voice(voice,
1037
/* global preset modulators */
1038
global_preset_zone ? global_preset_zone->mod : NULL,
1039
preset_zone->mod, /* local preset modulators */
1040
FLUID_VOICE_ADD); /* mode */
1041
1042
/* add the synthesis process to the synthesis loop. */
1043
fluid_synth_start_voice(synth, voice);
1044
1045
/* Store the ID of the first voice that was created by this noteon event.
1046
* Exclusive class may only terminate older voices.
1047
* That avoids killing voices, which have just been created.
1048
* (a noteon event can create several voice processes with the same exclusive
1049
* class - for example when using stereo samples)
1050
*/
1051
}
1052
}
1053
}
1054
1055
preset_zone = fluid_preset_zone_next(preset_zone);
1056
}
1057
1058
return FLUID_OK;
1059
}
1060
1061
/*
1062
* fluid_defpreset_set_global_zone
1063
*/
1064
int
1065
fluid_defpreset_set_global_zone(fluid_defpreset_t *defpreset, fluid_preset_zone_t *zone)
1066
{
1067
defpreset->global_zone = zone;
1068
return FLUID_OK;
1069
}
1070
1071
/*
1072
* fluid_defpreset_import_sfont
1073
*/
1074
int
1075
fluid_defpreset_import_sfont(fluid_defpreset_t *defpreset,
1076
SFPreset *sfpreset,
1077
fluid_defsfont_t *defsfont,
1078
SFData *sfdata)
1079
{
1080
fluid_list_t *p;
1081
SFZone *sfzone;
1082
fluid_preset_zone_t *zone;
1083
int count;
1084
char zone_name[256];
1085
1086
if(FLUID_STRLEN(sfpreset->name) > 0)
1087
{
1088
FLUID_STRCPY(defpreset->name, sfpreset->name);
1089
}
1090
else
1091
{
1092
FLUID_SNPRINTF(defpreset->name, sizeof(defpreset->name), "Bank%d,Pre%d", sfpreset->bank, sfpreset->prenum);
1093
}
1094
1095
defpreset->bank = sfpreset->bank;
1096
defpreset->num = sfpreset->prenum;
1097
p = sfpreset->zone;
1098
count = 0;
1099
1100
while(p != NULL)
1101
{
1102
sfzone = (SFZone *)fluid_list_get(p);
1103
FLUID_SNPRINTF(zone_name, sizeof(zone_name), "pz:%s/%d", defpreset->name, count);
1104
zone = new_fluid_preset_zone(zone_name);
1105
1106
if(zone == NULL)
1107
{
1108
return FLUID_FAILED;
1109
}
1110
1111
if(fluid_preset_zone_import_sfont(zone, defpreset->global_zone, sfzone, defsfont, sfdata) != FLUID_OK)
1112
{
1113
delete_fluid_preset_zone(zone);
1114
return FLUID_FAILED;
1115
}
1116
1117
if((count == 0) && (fluid_preset_zone_get_inst(zone) == NULL))
1118
{
1119
fluid_defpreset_set_global_zone(defpreset, zone);
1120
}
1121
else if(fluid_defpreset_add_zone(defpreset, zone) != FLUID_OK)
1122
{
1123
delete_fluid_preset_zone(zone);
1124
return FLUID_FAILED;
1125
}
1126
1127
p = fluid_list_next(p);
1128
count++;
1129
}
1130
1131
return FLUID_OK;
1132
}
1133
1134
/*
1135
* fluid_defpreset_add_zone
1136
*/
1137
int
1138
fluid_defpreset_add_zone(fluid_defpreset_t *defpreset, fluid_preset_zone_t *zone)
1139
{
1140
if(defpreset->zone == NULL)
1141
{
1142
zone->next = NULL;
1143
defpreset->zone = zone;
1144
}
1145
else
1146
{
1147
zone->next = defpreset->zone;
1148
defpreset->zone = zone;
1149
}
1150
1151
return FLUID_OK;
1152
}
1153
1154
/*
1155
* fluid_defpreset_get_zone
1156
*/
1157
fluid_preset_zone_t *
1158
fluid_defpreset_get_zone(fluid_defpreset_t *defpreset)
1159
{
1160
return defpreset->zone;
1161
}
1162
1163
/*
1164
* fluid_defpreset_get_global_zone
1165
*/
1166
fluid_preset_zone_t *
1167
fluid_defpreset_get_global_zone(fluid_defpreset_t *defpreset)
1168
{
1169
return defpreset->global_zone;
1170
}
1171
1172
/***************************************************************
1173
*
1174
* PRESET_ZONE
1175
*/
1176
1177
/*
1178
* fluid_preset_zone_next
1179
*/
1180
fluid_preset_zone_t *
1181
fluid_preset_zone_next(fluid_preset_zone_t *zone)
1182
{
1183
return zone->next;
1184
}
1185
1186
/*
1187
* new_fluid_preset_zone
1188
*/
1189
fluid_preset_zone_t *
1190
new_fluid_preset_zone(char *name)
1191
{
1192
fluid_preset_zone_t *zone = NULL;
1193
zone = FLUID_NEW(fluid_preset_zone_t);
1194
1195
if(zone == NULL)
1196
{
1197
FLUID_LOG(FLUID_ERR, "Out of memory");
1198
return NULL;
1199
}
1200
1201
zone->next = NULL;
1202
zone->voice_zone = NULL;
1203
zone->name = FLUID_STRDUP(name);
1204
1205
if(zone->name == NULL)
1206
{
1207
FLUID_LOG(FLUID_ERR, "Out of memory");
1208
FLUID_FREE(zone);
1209
return NULL;
1210
}
1211
1212
zone->inst = NULL;
1213
zone->range.keylo = 0;
1214
zone->range.keyhi = 128;
1215
zone->range.vello = 0;
1216
zone->range.velhi = 128;
1217
zone->range.ignore = FALSE;
1218
1219
/* Flag all generators as unused (default, they will be set when they are found
1220
* in the sound font).
1221
* This also sets the generator values to default, but that is of no concern here.*/
1222
fluid_gen_init(&zone->gen[0], NULL);
1223
zone->mod = NULL; /* list of modulators */
1224
return zone;
1225
}
1226
1227
/*
1228
* delete list of modulators.
1229
*/
1230
void delete_fluid_list_mod(fluid_mod_t *mod)
1231
{
1232
fluid_mod_t *tmp;
1233
1234
while(mod) /* delete the modulators */
1235
{
1236
tmp = mod;
1237
mod = mod->next;
1238
delete_fluid_mod(tmp);
1239
}
1240
}
1241
1242
/*
1243
* delete_fluid_preset_zone
1244
*/
1245
void
1246
delete_fluid_preset_zone(fluid_preset_zone_t *zone)
1247
{
1248
fluid_list_t *list;
1249
1250
fluid_return_if_fail(zone != NULL);
1251
1252
delete_fluid_list_mod(zone->mod);
1253
1254
for(list = zone->voice_zone; list != NULL; list = fluid_list_next(list))
1255
{
1256
FLUID_FREE(fluid_list_get(list));
1257
}
1258
1259
delete_fluid_list(zone->voice_zone);
1260
1261
FLUID_FREE(zone->name);
1262
FLUID_FREE(zone);
1263
}
1264
1265
static int fluid_preset_zone_create_voice_zones(fluid_preset_zone_t *preset_zone)
1266
{
1267
fluid_inst_zone_t *inst_zone;
1268
fluid_sample_t *sample;
1269
fluid_voice_zone_t *voice_zone;
1270
fluid_zone_range_t *irange;
1271
fluid_zone_range_t *prange = &preset_zone->range;
1272
1273
fluid_return_val_if_fail(preset_zone->inst != NULL, FLUID_FAILED);
1274
1275
inst_zone = fluid_inst_get_zone(preset_zone->inst);
1276
1277
while(inst_zone != NULL)
1278
{
1279
1280
/* We only create voice ranges for zones that could actually start a voice,
1281
* i.e. that have a sample and don't point to ROM */
1282
sample = fluid_inst_zone_get_sample(inst_zone);
1283
1284
if((sample == NULL) || fluid_sample_in_rom(sample))
1285
{
1286
inst_zone = fluid_inst_zone_next(inst_zone);
1287
continue;
1288
}
1289
1290
voice_zone = FLUID_NEW(fluid_voice_zone_t);
1291
1292
if(voice_zone == NULL)
1293
{
1294
FLUID_LOG(FLUID_ERR, "Out of memory");
1295
return FLUID_FAILED;
1296
}
1297
1298
voice_zone->inst_zone = inst_zone;
1299
1300
irange = &inst_zone->range;
1301
1302
voice_zone->range.keylo = (prange->keylo > irange->keylo) ? prange->keylo : irange->keylo;
1303
voice_zone->range.keyhi = (prange->keyhi < irange->keyhi) ? prange->keyhi : irange->keyhi;
1304
voice_zone->range.vello = (prange->vello > irange->vello) ? prange->vello : irange->vello;
1305
voice_zone->range.velhi = (prange->velhi < irange->velhi) ? prange->velhi : irange->velhi;
1306
voice_zone->range.ignore = FALSE;
1307
1308
preset_zone->voice_zone = fluid_list_append(preset_zone->voice_zone, voice_zone);
1309
1310
inst_zone = fluid_inst_zone_next(inst_zone);
1311
}
1312
1313
return FLUID_OK;
1314
}
1315
1316
/**
1317
* Checks if modulator mod is identical to another modulator in the list
1318
* (specs SF 2.0X 7.4, 7.8).
1319
* @param mod, modulator list.
1320
* @param name, if not NULL, pointer on a string displayed as warning.
1321
* @return TRUE if mod is identical to another modulator, FALSE otherwise.
1322
*/
1323
static int
1324
fluid_zone_is_mod_identical(fluid_mod_t *mod, char *name)
1325
{
1326
fluid_mod_t *next = mod->next;
1327
1328
while(next)
1329
{
1330
/* is mod identical to next ? */
1331
if(fluid_mod_test_identity(mod, next))
1332
{
1333
if(name)
1334
{
1335
FLUID_LOG(FLUID_WARN, "Ignoring identical modulator %s", name);
1336
}
1337
1338
return TRUE;
1339
}
1340
1341
next = next->next;
1342
}
1343
1344
return FALSE;
1345
}
1346
1347
/**
1348
* Limits the number of modulators in a modulator list.
1349
* This is appropriate to internal synthesizer modulators tables
1350
* which have a fixed size (FLUID_NUM_MOD).
1351
*
1352
* @param zone_name, zone name
1353
* @param list_mod, address of pointer on modulator list.
1354
*/
1355
static void fluid_limit_mod_list(char *zone_name, fluid_mod_t **list_mod)
1356
{
1357
int mod_idx = 0; /* modulator index */
1358
fluid_mod_t *prev_mod = NULL; /* previous modulator in list_mod */
1359
fluid_mod_t *mod = *list_mod; /* first modulator in list_mod */
1360
1361
while(mod)
1362
{
1363
if((mod_idx + 1) > FLUID_NUM_MOD)
1364
{
1365
/* truncation of list_mod */
1366
if(mod_idx)
1367
{
1368
prev_mod->next = NULL;
1369
}
1370
else
1371
{
1372
*list_mod = NULL;
1373
}
1374
1375
delete_fluid_list_mod(mod);
1376
FLUID_LOG(FLUID_WARN, "%s, modulators count limited to %d", zone_name,
1377
FLUID_NUM_MOD);
1378
break;
1379
}
1380
1381
mod_idx++;
1382
prev_mod = mod;
1383
mod = mod->next;
1384
}
1385
}
1386
1387
/**
1388
* Checks and remove invalid modulators from a zone modulators list.
1389
* - checks valid modulator sources (specs SF 2.01 7.4, 7.8, 8.2.1).
1390
* - checks identical modulators in the list (specs SF 2.01 7.4, 7.8).
1391
* @param zone_name, zone name.
1392
* @param list_mod, address of pointer on modulators list.
1393
*/
1394
static void
1395
fluid_zone_check_mod(char *zone_name, fluid_mod_t **list_mod)
1396
{
1397
fluid_mod_t *prev_mod = NULL; /* previous modulator in list_mod */
1398
fluid_mod_t *mod = *list_mod; /* first modulator in list_mod */
1399
int mod_idx = 0; /* modulator index */
1400
1401
while(mod)
1402
{
1403
char zone_mod_name[256];
1404
fluid_mod_t *next = mod->next;
1405
1406
/* prepare modulator name: zonename/#modulator */
1407
FLUID_SNPRINTF(zone_mod_name, sizeof(zone_mod_name), "%s/mod%d", zone_name, mod_idx);
1408
1409
/* has mod invalid sources ? */
1410
if(!fluid_mod_check_sources(mod, zone_mod_name)
1411
/* or is mod identical to any following modulator ? */
1412
|| fluid_zone_is_mod_identical(mod, zone_mod_name))
1413
{
1414
/* the modulator is useless so we remove it */
1415
if(prev_mod)
1416
{
1417
prev_mod->next = next;
1418
}
1419
else
1420
{
1421
*list_mod = next;
1422
}
1423
1424
delete_fluid_mod(mod); /* freeing */
1425
}
1426
else
1427
{
1428
prev_mod = mod;
1429
}
1430
1431
mod = next;
1432
mod_idx++;
1433
}
1434
1435
/* limits the size of modulators list */
1436
fluid_limit_mod_list(zone_name, list_mod);
1437
}
1438
1439
/*
1440
* fluid_zone_gen_import_sfont
1441
* Imports generators from sfzone to gen and range.
1442
* @param gen, pointer on destination generators table.
1443
* @param range, pointer on destination range generators.
1444
* @param sfzone, pointer on soundfont zone generators.
1445
*/
1446
static void
1447
fluid_zone_gen_import_sfont(fluid_gen_t *gen, fluid_zone_range_t *range, fluid_zone_range_t *global_range, SFZone *sfzone)
1448
{
1449
fluid_list_t *r;
1450
SFGen *sfgen;
1451
1452
if(global_range != NULL)
1453
{
1454
// All zones are initialized with the default range of 0-127. However, local zones should be superseded by
1455
// the range of their global zone in case that local zone lacks a GEN_KEYRANGE or GEN_VELRANGE
1456
// (see issue #1250).
1457
range->keylo = global_range->keylo;
1458
range->keyhi = global_range->keyhi;
1459
range->vello = global_range->vello;
1460
range->velhi = global_range->velhi;
1461
}
1462
1463
for(r = sfzone->gen; r != NULL;)
1464
{
1465
sfgen = (SFGen *)fluid_list_get(r);
1466
1467
switch(sfgen->id)
1468
{
1469
case GEN_KEYRANGE:
1470
range->keylo = sfgen->amount.range.lo;
1471
range->keyhi = sfgen->amount.range.hi;
1472
break;
1473
1474
case GEN_VELRANGE:
1475
range->vello = sfgen->amount.range.lo;
1476
range->velhi = sfgen->amount.range.hi;
1477
break;
1478
1479
case GEN_ATTENUATION:
1480
/* EMU8k/10k hardware applies a scale factor to initial attenuation generator values set at
1481
* preset and instrument level */
1482
gen[sfgen->id].val = (fluid_real_t) sfgen->amount.sword * EMU_ATTENUATION_FACTOR;
1483
gen[sfgen->id].flags = GEN_SET;
1484
break;
1485
1486
case GEN_INSTRUMENT:
1487
case GEN_SAMPLEID:
1488
gen[sfgen->id].val = (fluid_real_t) sfgen->amount.uword;
1489
gen[sfgen->id].flags = GEN_SET;
1490
break;
1491
1492
default:
1493
gen[sfgen->id].val = (fluid_real_t) sfgen->amount.sword;
1494
gen[sfgen->id].flags = GEN_SET;
1495
break;
1496
}
1497
1498
r = fluid_list_next(r);
1499
}
1500
}
1501
1502
/*
1503
* fluid_zone_mod_source_import_sfont
1504
* Imports source information from sf_source to src and flags.
1505
* @param src, pointer on destination modulator source.
1506
* @param flags, pointer on destination modulator flags.
1507
* @param sf_source, soundfont modulator source.
1508
* @return return TRUE if success, FALSE if source type is unknown.
1509
*/
1510
static int
1511
fluid_zone_mod_source_import_sfont(unsigned char *src, unsigned char *flags, unsigned short sf_source)
1512
{
1513
int type;
1514
unsigned char flags_dest; /* destination flags */
1515
1516
/* sources */
1517
*src = sf_source & 127; /* index of source, seven-bit value, SF2.01 section 8.2, page 50 */
1518
1519
/* Bit 7: CC flag SF 2.01 section 8.2.1 page 50*/
1520
flags_dest = 0;
1521
1522
if(sf_source & (1 << 7))
1523
{
1524
flags_dest |= FLUID_MOD_CC;
1525
}
1526
else
1527
{
1528
flags_dest |= FLUID_MOD_GC;
1529
}
1530
1531
/* Bit 8: D flag SF 2.01 section 8.2.2 page 51*/
1532
if(sf_source & (1 << 8))
1533
{
1534
flags_dest |= FLUID_MOD_NEGATIVE;
1535
}
1536
else
1537
{
1538
flags_dest |= FLUID_MOD_POSITIVE;
1539
}
1540
1541
/* Bit 9: P flag SF 2.01 section 8.2.3 page 51*/
1542
if(sf_source & (1 << 9))
1543
{
1544
flags_dest |= FLUID_MOD_BIPOLAR;
1545
}
1546
else
1547
{
1548
flags_dest |= FLUID_MOD_UNIPOLAR;
1549
}
1550
1551
/* modulator source types: SF2.01 section 8.2.1 page 52 */
1552
type = sf_source >> 10;
1553
type &= 63; /* type is a 6-bit value */
1554
1555
if(type == 0)
1556
{
1557
flags_dest |= FLUID_MOD_LINEAR;
1558
}
1559
else if(type == 1)
1560
{
1561
flags_dest |= FLUID_MOD_CONCAVE;
1562
}
1563
else if(type == 2)
1564
{
1565
flags_dest |= FLUID_MOD_CONVEX;
1566
}
1567
else if(type == 3)
1568
{
1569
flags_dest |= FLUID_MOD_SWITCH;
1570
}
1571
else
1572
{
1573
*flags = flags_dest;
1574
/* This shouldn't happen - unknown type! */
1575
return FALSE;
1576
}
1577
1578
*flags = flags_dest;
1579
return TRUE;
1580
}
1581
1582
/*
1583
* fluid_zone_mod_import_sfont
1584
* Imports modulators from sfzone to modulators list mod.
1585
* @param zone_name, zone name.
1586
* @param mod, address of pointer on modulators list to return.
1587
* @param sfzone, pointer on soundfont zone.
1588
* @return FLUID_OK if success, FLUID_FAILED otherwise.
1589
*/
1590
static int
1591
fluid_zone_mod_import_sfont(char *zone_name, fluid_mod_t **mod, SFZone *sfzone)
1592
{
1593
fluid_list_t *r;
1594
int count;
1595
1596
/* Import the modulators (only SF2.1 and higher) */
1597
for(count = 0, r = sfzone->mod; r != NULL; count++)
1598
{
1599
1600
SFMod *mod_src = (SFMod *)fluid_list_get(r);
1601
fluid_mod_t *mod_dest = new_fluid_mod();
1602
1603
if(mod_dest == NULL)
1604
{
1605
return FLUID_FAILED;
1606
}
1607
1608
mod_dest->next = NULL; /* pointer to next modulator, this is the end of the list now.*/
1609
1610
/* *** Amount *** */
1611
mod_dest->amount = mod_src->amount;
1612
1613
/* *** Source *** */
1614
if(!fluid_zone_mod_source_import_sfont(&mod_dest->src1, &mod_dest->flags1, mod_src->src))
1615
{
1616
/* This shouldn't happen - unknown type!
1617
* Deactivate the modulator by setting the amount to 0. */
1618
mod_dest->amount = 0;
1619
}
1620
1621
/* *** Dest *** */
1622
mod_dest->dest = mod_src->dest; /* index of controlled generator */
1623
1624
/* *** Amount source *** */
1625
if(!fluid_zone_mod_source_import_sfont(&mod_dest->src2, &mod_dest->flags2, mod_src->amtsrc))
1626
{
1627
/* This shouldn't happen - unknown type!
1628
* Deactivate the modulator by setting the amount to 0. */
1629
mod_dest->amount = 0;
1630
}
1631
1632
/**
1633
* *** Transform Type ***
1634
* Only 2 types of transform are defined in the sf2 specification.
1635
*/
1636
if(mod_src->trans != FLUID_MOD_TRANSFORM_LINEAR && mod_src->trans != FLUID_MOD_TRANSFORM_ABS)
1637
{
1638
/* disable the modulator as the transform is invalid */
1639
mod_dest->amount = 0;
1640
mod_dest->trans = FLUID_MOD_TRANSFORM_LINEAR;
1641
}
1642
else
1643
{
1644
mod_dest->trans = mod_src->trans;
1645
}
1646
1647
/* Store the new modulator in the zone The order of modulators
1648
* will make a difference, at least in an instrument context: The
1649
* second modulator overwrites the first one, if they only differ
1650
* in amount. */
1651
if(count == 0)
1652
{
1653
*mod = mod_dest;
1654
}
1655
else
1656
{
1657
fluid_mod_t *last_mod = *mod;
1658
1659
/* Find the end of the list */
1660
while(last_mod->next != NULL)
1661
{
1662
last_mod = last_mod->next;
1663
}
1664
1665
last_mod->next = mod_dest;
1666
}
1667
1668
r = fluid_list_next(r);
1669
} /* foreach modulator */
1670
1671
/* checks and removes invalid modulators in modulators list*/
1672
fluid_zone_check_mod(zone_name, mod);
1673
return FLUID_OK;
1674
}
1675
1676
/*
1677
* fluid_preset_zone_import_sfont
1678
*/
1679
int
1680
fluid_preset_zone_import_sfont(fluid_preset_zone_t *zone, fluid_preset_zone_t *global_zone, SFZone *sfzone, fluid_defsfont_t *defsfont, SFData *sfdata)
1681
{
1682
/* import the generators */
1683
fluid_zone_gen_import_sfont(zone->gen, &zone->range, global_zone ? &global_zone->range : NULL, sfzone);
1684
1685
if(zone->gen[GEN_INSTRUMENT].flags == GEN_SET)
1686
{
1687
int inst_idx = (int) zone->gen[GEN_INSTRUMENT].val;
1688
1689
zone->inst = find_inst_by_idx(defsfont, inst_idx);
1690
1691
if(zone->inst == NULL)
1692
{
1693
zone->inst = fluid_inst_import_sfont(inst_idx, defsfont, sfdata);
1694
}
1695
1696
if(zone->inst == NULL)
1697
{
1698
1699
FLUID_LOG(FLUID_ERR, "Preset zone %s: Invalid instrument reference",
1700
zone->name);
1701
return FLUID_FAILED;
1702
}
1703
1704
if(fluid_preset_zone_create_voice_zones(zone) == FLUID_FAILED)
1705
{
1706
return FLUID_FAILED;
1707
}
1708
1709
/* We don't need this generator anymore */
1710
zone->gen[GEN_INSTRUMENT].flags = GEN_UNUSED;
1711
}
1712
1713
/* Import the modulators (only SF2.1 and higher) */
1714
return fluid_zone_mod_import_sfont(zone->name, &zone->mod, sfzone);
1715
}
1716
1717
/*
1718
* fluid_preset_zone_get_inst
1719
*/
1720
fluid_inst_t *
1721
fluid_preset_zone_get_inst(fluid_preset_zone_t *zone)
1722
{
1723
return zone->inst;
1724
}
1725
1726
1727
/***************************************************************
1728
*
1729
* INST
1730
*/
1731
1732
/*
1733
* new_fluid_inst
1734
*/
1735
fluid_inst_t *
1736
new_fluid_inst(void)
1737
{
1738
fluid_inst_t *inst = FLUID_NEW(fluid_inst_t);
1739
1740
if(inst == NULL)
1741
{
1742
FLUID_LOG(FLUID_ERR, "Out of memory");
1743
return NULL;
1744
}
1745
1746
inst->name[0] = 0;
1747
inst->global_zone = NULL;
1748
inst->zone = NULL;
1749
return inst;
1750
}
1751
1752
/*
1753
* delete_fluid_inst
1754
*/
1755
void
1756
delete_fluid_inst(fluid_inst_t *inst)
1757
{
1758
fluid_inst_zone_t *zone;
1759
1760
fluid_return_if_fail(inst != NULL);
1761
1762
delete_fluid_inst_zone(inst->global_zone);
1763
inst->global_zone = NULL;
1764
1765
zone = inst->zone;
1766
1767
while(zone != NULL)
1768
{
1769
inst->zone = zone->next;
1770
delete_fluid_inst_zone(zone);
1771
zone = inst->zone;
1772
}
1773
1774
FLUID_FREE(inst);
1775
}
1776
1777
/*
1778
* fluid_inst_set_global_zone
1779
*/
1780
int
1781
fluid_inst_set_global_zone(fluid_inst_t *inst, fluid_inst_zone_t *zone)
1782
{
1783
inst->global_zone = zone;
1784
return FLUID_OK;
1785
}
1786
1787
/*
1788
* fluid_inst_import_sfont
1789
*/
1790
fluid_inst_t *
1791
fluid_inst_import_sfont(int inst_idx, fluid_defsfont_t *defsfont, SFData *sfdata)
1792
{
1793
fluid_list_t *p;
1794
fluid_list_t *inst_list;
1795
fluid_inst_t *inst;
1796
SFZone *sfzone;
1797
SFInst *sfinst;
1798
fluid_inst_zone_t *inst_zone;
1799
char zone_name[256];
1800
int count;
1801
1802
for (inst_list = sfdata->inst; inst_list; inst_list = fluid_list_next(inst_list))
1803
{
1804
sfinst = fluid_list_get(inst_list);
1805
if (sfinst->idx == inst_idx)
1806
{
1807
break;
1808
}
1809
}
1810
if (inst_list == NULL)
1811
{
1812
return NULL;
1813
}
1814
1815
inst = (fluid_inst_t *) new_fluid_inst();
1816
1817
if(inst == NULL)
1818
{
1819
FLUID_LOG(FLUID_ERR, "Out of memory");
1820
return NULL;
1821
}
1822
1823
inst->source_idx = sfinst->idx;
1824
1825
p = sfinst->zone;
1826
1827
if(FLUID_STRLEN(sfinst->name) > 0)
1828
{
1829
FLUID_STRCPY(inst->name, sfinst->name);
1830
}
1831
else
1832
{
1833
FLUID_STRCPY(inst->name, "<untitled>");
1834
}
1835
1836
count = 0;
1837
1838
while(p != NULL)
1839
{
1840
1841
sfzone = (SFZone *)fluid_list_get(p);
1842
/* instrument zone name */
1843
FLUID_SNPRINTF(zone_name, sizeof(zone_name), "iz:%s/%d", inst->name, count);
1844
1845
inst_zone = new_fluid_inst_zone(zone_name);
1846
if(inst_zone == NULL)
1847
{
1848
FLUID_LOG(FLUID_ERR, "Out of memory");
1849
goto error;
1850
}
1851
1852
if(fluid_inst_zone_import_sfont(inst_zone, inst->global_zone, sfzone, defsfont, sfdata) != FLUID_OK)
1853
{
1854
FLUID_LOG(FLUID_ERR, "fluid_inst_zone_import_sfont() failed for instrument %s", inst->name);
1855
delete_fluid_inst_zone(inst_zone);
1856
goto error;
1857
}
1858
1859
if((count == 0) && (fluid_inst_zone_get_sample(inst_zone) == NULL))
1860
{
1861
fluid_inst_set_global_zone(inst, inst_zone);
1862
1863
}
1864
else if(fluid_inst_add_zone(inst, inst_zone) != FLUID_OK)
1865
{
1866
FLUID_LOG(FLUID_ERR, "fluid_inst_add_zone() failed for instrument %s", inst->name);
1867
delete_fluid_inst_zone(inst_zone);
1868
goto error;
1869
}
1870
1871
p = fluid_list_next(p);
1872
count++;
1873
}
1874
1875
defsfont->inst = fluid_list_append(defsfont->inst, inst);
1876
return inst;
1877
1878
error:
1879
delete_fluid_inst(inst);
1880
return NULL;
1881
}
1882
1883
/*
1884
* fluid_inst_add_zone
1885
*/
1886
int
1887
fluid_inst_add_zone(fluid_inst_t *inst, fluid_inst_zone_t *zone)
1888
{
1889
if(inst->zone == NULL)
1890
{
1891
zone->next = NULL;
1892
inst->zone = zone;
1893
}
1894
else
1895
{
1896
zone->next = inst->zone;
1897
inst->zone = zone;
1898
}
1899
1900
return FLUID_OK;
1901
}
1902
1903
/*
1904
* fluid_inst_get_zone
1905
*/
1906
fluid_inst_zone_t *
1907
fluid_inst_get_zone(fluid_inst_t *inst)
1908
{
1909
return inst->zone;
1910
}
1911
1912
/*
1913
* fluid_inst_get_global_zone
1914
*/
1915
fluid_inst_zone_t *
1916
fluid_inst_get_global_zone(fluid_inst_t *inst)
1917
{
1918
return inst->global_zone;
1919
}
1920
1921
/***************************************************************
1922
*
1923
* INST_ZONE
1924
*/
1925
1926
/*
1927
* new_fluid_inst_zone
1928
*/
1929
fluid_inst_zone_t *
1930
new_fluid_inst_zone(char *name)
1931
{
1932
fluid_inst_zone_t *zone = NULL;
1933
zone = FLUID_NEW(fluid_inst_zone_t);
1934
1935
if(zone == NULL)
1936
{
1937
FLUID_LOG(FLUID_ERR, "Out of memory");
1938
return NULL;
1939
}
1940
1941
zone->next = NULL;
1942
zone->name = FLUID_STRDUP(name);
1943
1944
if(zone->name == NULL)
1945
{
1946
FLUID_LOG(FLUID_ERR, "Out of memory");
1947
FLUID_FREE(zone);
1948
return NULL;
1949
}
1950
1951
zone->sample = NULL;
1952
zone->range.keylo = 0;
1953
zone->range.keyhi = 128;
1954
zone->range.vello = 0;
1955
zone->range.velhi = 128;
1956
zone->range.ignore = FALSE;
1957
/* Flag the generators as unused.
1958
* This also sets the generator values to default, but they will be overwritten anyway, if used.*/
1959
fluid_gen_init(&zone->gen[0], NULL);
1960
zone->mod = NULL; /* list of modulators */
1961
return zone;
1962
}
1963
1964
/*
1965
* delete_fluid_inst_zone
1966
*/
1967
void
1968
delete_fluid_inst_zone(fluid_inst_zone_t *zone)
1969
{
1970
fluid_return_if_fail(zone != NULL);
1971
1972
delete_fluid_list_mod(zone->mod);
1973
1974
FLUID_FREE(zone->name);
1975
FLUID_FREE(zone);
1976
}
1977
1978
/*
1979
* fluid_inst_zone_next
1980
*/
1981
fluid_inst_zone_t *
1982
fluid_inst_zone_next(fluid_inst_zone_t *zone)
1983
{
1984
return zone->next;
1985
}
1986
1987
/*
1988
* fluid_inst_zone_import_sfont
1989
*/
1990
int
1991
fluid_inst_zone_import_sfont(fluid_inst_zone_t *inst_zone, fluid_inst_zone_t *global_inst_zone, SFZone *sfzone, fluid_defsfont_t *defsfont, SFData *sfdata)
1992
{
1993
/* import the generators */
1994
fluid_zone_gen_import_sfont(inst_zone->gen, &inst_zone->range, global_inst_zone ? &global_inst_zone->range : NULL, sfzone);
1995
1996
/* FIXME */
1997
/* if (zone->gen[GEN_EXCLUSIVECLASS].flags == GEN_SET) { */
1998
/* FLUID_LOG(FLUID_DBG, "ExclusiveClass=%d\n", (int) zone->gen[GEN_EXCLUSIVECLASS].val); */
1999
/* } */
2000
2001
if (inst_zone->gen[GEN_SAMPLEID].flags == GEN_SET)
2002
{
2003
fluid_list_t *list;
2004
SFSample *sfsample;
2005
int sample_idx = (int) inst_zone->gen[GEN_SAMPLEID].val;
2006
2007
/* find the SFSample by index */
2008
for(list = sfdata->sample; list; list = fluid_list_next(list))
2009
{
2010
sfsample = fluid_list_get(list);
2011
if (sfsample->idx == sample_idx)
2012
{
2013
break;
2014
}
2015
}
2016
if (list == NULL)
2017
{
2018
FLUID_LOG(FLUID_ERR, "Instrument zone '%s': Invalid sample reference",
2019
inst_zone->name);
2020
return FLUID_FAILED;
2021
}
2022
2023
inst_zone->sample = sfsample->fluid_sample;
2024
2025
/* we don't need this generator anymore, mark it as unused */
2026
inst_zone->gen[GEN_SAMPLEID].flags = GEN_UNUSED;
2027
}
2028
2029
/* Import the modulators (only SF2.1 and higher) */
2030
return fluid_zone_mod_import_sfont(inst_zone->name, &inst_zone->mod, sfzone);
2031
}
2032
2033
/*
2034
* fluid_inst_zone_get_sample
2035
*/
2036
fluid_sample_t *
2037
fluid_inst_zone_get_sample(fluid_inst_zone_t *zone)
2038
{
2039
return zone->sample;
2040
}
2041
2042
2043
int
2044
fluid_zone_inside_range(fluid_zone_range_t *range, int key, int vel)
2045
{
2046
/* ignoreInstrumentZone is set in mono legato playing */
2047
int ignore_zone = range->ignore;
2048
2049
/* Reset the 'ignore' request */
2050
range->ignore = FALSE;
2051
2052
return !ignore_zone && ((range->keylo <= key) &&
2053
(range->keyhi >= key) &&
2054
(range->vello <= vel) &&
2055
(range->velhi >= vel));
2056
}
2057
2058
/***************************************************************
2059
*
2060
* SAMPLE
2061
*/
2062
2063
/*
2064
* fluid_sample_in_rom
2065
*/
2066
int
2067
fluid_sample_in_rom(fluid_sample_t *sample)
2068
{
2069
return (sample->sampletype & FLUID_SAMPLETYPE_ROM);
2070
}
2071
2072
2073
/*
2074
* fluid_sample_import_sfont
2075
*/
2076
int
2077
fluid_sample_import_sfont(fluid_sample_t *sample, SFSample *sfsample, fluid_defsfont_t *defsfont)
2078
{
2079
FLUID_STRCPY(sample->name, sfsample->name);
2080
2081
sample->source_start = sfsample->start;
2082
sample->source_end = (sfsample->end > 0) ? sfsample->end - 1 : 0; /* marks last sample, contrary to SF spec. */
2083
sample->source_loopstart = sfsample->loopstart;
2084
sample->source_loopend = sfsample->loopend;
2085
2086
sample->start = sample->source_start;
2087
sample->end = sample->source_end;
2088
sample->loopstart = sample->source_loopstart;
2089
sample->loopend = sample->source_loopend;
2090
sample->samplerate = sfsample->samplerate;
2091
sample->origpitch = sfsample->origpitch;
2092
sample->pitchadj = sfsample->pitchadj;
2093
sample->sampletype = sfsample->sampletype;
2094
2095
if(defsfont->dynamic_samples)
2096
{
2097
sample->notify = dynamic_samples_sample_notify;
2098
}
2099
2100
if(fluid_sample_validate(sample, defsfont->samplesize) == FLUID_FAILED)
2101
{
2102
return FLUID_FAILED;
2103
}
2104
2105
return FLUID_OK;
2106
}
2107
2108
/* Called if a sample is no longer used by a voice. Used by dynamic sample loading
2109
* to unload a sample that is not used by any loaded presets anymore but couldn't
2110
* be unloaded straight away because it was still in use by a voice. */
2111
static int dynamic_samples_sample_notify(fluid_sample_t *sample, int reason)
2112
{
2113
if(reason == FLUID_SAMPLE_DONE && sample->preset_count == 0)
2114
{
2115
unload_sample(sample);
2116
}
2117
2118
return FLUID_OK;
2119
}
2120
2121
/* Called if a preset has been selected for or unselected from a channel. Used by
2122
* dynamic sample loading to load and unload samples on demand. */
2123
static int dynamic_samples_preset_notify(fluid_preset_t *preset, int reason, int chan)
2124
{
2125
fluid_defsfont_t *defsfont;
2126
2127
if(reason == FLUID_PRESET_SELECTED)
2128
{
2129
FLUID_LOG(FLUID_DBG, "Selected preset '%s' on channel %d", fluid_preset_get_name(preset), chan);
2130
defsfont = fluid_sfont_get_data(preset->sfont);
2131
return load_preset_samples(defsfont, preset);
2132
}
2133
2134
if(reason == FLUID_PRESET_UNSELECTED)
2135
{
2136
FLUID_LOG(FLUID_DBG, "Deselected preset '%s' from channel %d", fluid_preset_get_name(preset), chan);
2137
defsfont = fluid_sfont_get_data(preset->sfont);
2138
return unload_preset_samples(defsfont, preset);
2139
}
2140
2141
if(reason == FLUID_PRESET_PIN)
2142
{
2143
defsfont = fluid_sfont_get_data(preset->sfont);
2144
return pin_preset_samples(defsfont, preset);
2145
}
2146
2147
if(reason == FLUID_PRESET_UNPIN)
2148
{
2149
defsfont = fluid_sfont_get_data(preset->sfont);
2150
return unpin_preset_samples(defsfont, preset);
2151
}
2152
2153
return FLUID_OK;
2154
}
2155
2156
2157
static int pin_preset_samples(fluid_defsfont_t *defsfont, fluid_preset_t *preset)
2158
{
2159
fluid_defpreset_t *defpreset;
2160
2161
defpreset = fluid_preset_get_data(preset);
2162
if (defpreset->pinned)
2163
{
2164
return FLUID_OK;
2165
}
2166
2167
FLUID_LOG(FLUID_DBG, "Pinning preset '%s'", fluid_preset_get_name(preset));
2168
2169
if(load_preset_samples(defsfont, preset) == FLUID_FAILED)
2170
{
2171
return FLUID_FAILED;
2172
}
2173
2174
defpreset->pinned = TRUE;
2175
2176
return FLUID_OK;
2177
}
2178
2179
2180
static int unpin_preset_samples(fluid_defsfont_t *defsfont, fluid_preset_t *preset)
2181
{
2182
fluid_defpreset_t *defpreset;
2183
2184
defpreset = fluid_preset_get_data(preset);
2185
if (!defpreset->pinned)
2186
{
2187
return FLUID_OK;
2188
}
2189
2190
FLUID_LOG(FLUID_DBG, "Unpinning preset '%s'", fluid_preset_get_name(preset));
2191
2192
if(unload_preset_samples(defsfont, preset) == FLUID_FAILED)
2193
{
2194
return FLUID_FAILED;
2195
}
2196
2197
defpreset->pinned = FALSE;
2198
2199
return FLUID_OK;
2200
}
2201
2202
2203
/* Walk through all samples used by the passed in preset and make sure that the
2204
* sample data is loaded for each sample. Used by dynamic sample loading. */
2205
static int load_preset_samples(fluid_defsfont_t *defsfont, fluid_preset_t *preset)
2206
{
2207
fluid_defpreset_t *defpreset;
2208
fluid_preset_zone_t *preset_zone;
2209
fluid_inst_t *inst;
2210
fluid_inst_zone_t *inst_zone;
2211
fluid_sample_t *sample;
2212
SFData *sffile = NULL;
2213
2214
defpreset = fluid_preset_get_data(preset);
2215
preset_zone = fluid_defpreset_get_zone(defpreset);
2216
2217
while(preset_zone != NULL)
2218
{
2219
inst = fluid_preset_zone_get_inst(preset_zone);
2220
inst_zone = fluid_inst_get_zone(inst);
2221
2222
while(inst_zone != NULL)
2223
{
2224
sample = fluid_inst_zone_get_sample(inst_zone);
2225
2226
if((sample != NULL) && (sample->start != sample->end))
2227
{
2228
sample->preset_count++;
2229
2230
/* If this is the first time this sample has been selected,
2231
* load the sampledata */
2232
if(sample->preset_count == 1)
2233
{
2234
/* Make sure we have an open Soundfont file. Do this here
2235
* to avoid having to open the file if no loading is necessary
2236
* for a preset */
2237
if(sffile == NULL)
2238
{
2239
sffile = fluid_sffile_open(defsfont->filename, defsfont->fcbs);
2240
2241
if(sffile == NULL)
2242
{
2243
FLUID_LOG(FLUID_ERR, "Unable to open Soundfont file");
2244
return FLUID_FAILED;
2245
}
2246
}
2247
2248
if(fluid_defsfont_load_sampledata(defsfont, sffile, sample) == FLUID_OK)
2249
{
2250
fluid_sample_sanitize_loop(sample, (sample->end + 1) * sizeof(short));
2251
fluid_voice_optimize_sample(sample);
2252
}
2253
else
2254
{
2255
FLUID_LOG(FLUID_ERR, "Unable to load sample '%s', disabling", sample->name);
2256
sample->start = sample->end = 0;
2257
}
2258
}
2259
}
2260
2261
inst_zone = fluid_inst_zone_next(inst_zone);
2262
}
2263
2264
preset_zone = fluid_preset_zone_next(preset_zone);
2265
}
2266
2267
if(sffile != NULL)
2268
{
2269
fluid_sffile_close(sffile);
2270
}
2271
2272
return FLUID_OK;
2273
}
2274
2275
/* Walk through all samples used by the passed in preset and unload the sample data
2276
* of each sample that is not used by any selected preset anymore. Used by dynamic
2277
* sample loading. */
2278
static int unload_preset_samples(fluid_defsfont_t *defsfont, fluid_preset_t *preset)
2279
{
2280
fluid_defpreset_t *defpreset;
2281
fluid_preset_zone_t *preset_zone;
2282
fluid_inst_t *inst;
2283
fluid_inst_zone_t *inst_zone;
2284
fluid_sample_t *sample;
2285
2286
defpreset = fluid_preset_get_data(preset);
2287
preset_zone = fluid_defpreset_get_zone(defpreset);
2288
2289
while(preset_zone != NULL)
2290
{
2291
inst = fluid_preset_zone_get_inst(preset_zone);
2292
inst_zone = fluid_inst_get_zone(inst);
2293
2294
while(inst_zone != NULL)
2295
{
2296
sample = fluid_inst_zone_get_sample(inst_zone);
2297
2298
if((sample != NULL) && (sample->preset_count > 0))
2299
{
2300
sample->preset_count--;
2301
2302
/* If the sample is not used by any preset or used by a
2303
* sounding voice, unload it from the sample cache. If it's
2304
* still in use by a voice, dynamic_samples_sample_notify will
2305
* take care of unloading the sample as soon as the voice is
2306
* finished with it (but only on the next API call). */
2307
if(sample->preset_count == 0 && sample->refcount == 0)
2308
{
2309
unload_sample(sample);
2310
}
2311
}
2312
2313
inst_zone = fluid_inst_zone_next(inst_zone);
2314
}
2315
2316
preset_zone = fluid_preset_zone_next(preset_zone);
2317
}
2318
2319
return FLUID_OK;
2320
}
2321
2322
/* Unload an unused sample from the samplecache */
2323
static void unload_sample(fluid_sample_t *sample)
2324
{
2325
fluid_return_if_fail(sample != NULL);
2326
fluid_return_if_fail(sample->data != NULL);
2327
fluid_return_if_fail(sample->preset_count == 0);
2328
fluid_return_if_fail(sample->refcount == 0);
2329
2330
FLUID_LOG(FLUID_DBG, "Unloading sample '%s'", sample->name);
2331
2332
if(fluid_samplecache_unload(sample->data) == FLUID_FAILED)
2333
{
2334
FLUID_LOG(FLUID_ERR, "Unable to unload sample '%s'", sample->name);
2335
}
2336
else
2337
{
2338
sample->data = NULL;
2339
sample->data24 = NULL;
2340
}
2341
}
2342
2343
static fluid_inst_t *find_inst_by_idx(fluid_defsfont_t *defsfont, int idx)
2344
{
2345
fluid_list_t *list;
2346
fluid_inst_t *inst;
2347
2348
for(list = defsfont->inst; list != NULL; list = fluid_list_next(list))
2349
{
2350
inst = fluid_list_get(list);
2351
2352
if(inst->source_idx == idx)
2353
{
2354
return inst;
2355
}
2356
}
2357
2358
return NULL;
2359
}
2360
2361