1 /* FluidSynth - A Software Synthesizer
2 *
3 * Copyright (C) 2003 Peter Hanappe and others.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public License
7 * as published by the Free Software Foundation; either version 2 of
8 * the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the Free
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 * 02111-1307, USA
19 */
20
21 #include "fluid_ramsfont.h"
22 #include "fluid_sys.h"
23 #include "fluid_synth.h"
24
25 /* thenumber of samples before the start and after the end */
26 #define SAMPLE_LOOP_MARGIN 8
27
28 /* Prototypes */
29 int fluid_rampreset_add_sample(fluid_rampreset_t* preset, fluid_sample_t* sample, int lokey, int hikey);
30 int fluid_rampreset_izone_set_gen(fluid_rampreset_t* preset, fluid_sample_t* sample, int gen_type, float value);
31 int fluid_rampreset_izone_set_loop(fluid_rampreset_t* preset, fluid_sample_t* sample, int on, float loopstart, float loopend);
32 int fluid_rampreset_remove_izone(fluid_rampreset_t* preset, fluid_sample_t* sample);
33 void fluid_rampreset_updatevoices(fluid_rampreset_t* preset, int gen_type, float val);
34
35 /*
36 * fluid_ramsfont_create_sfont
37 */
38 fluid_sfont_t*
fluid_ramsfont_create_sfont()39 fluid_ramsfont_create_sfont()
40 {
41 fluid_sfont_t* sfont;
42 fluid_ramsfont_t* ramsfont;
43
44 ramsfont = new_fluid_ramsfont();
45 if (ramsfont == NULL) {
46 return NULL;
47 }
48
49 sfont = FLUID_NEW(fluid_sfont_t);
50 if (sfont == NULL) {
51 FLUID_LOG(FLUID_ERR, "Out of memory");
52 return NULL;
53 }
54
55 sfont->data = ramsfont;
56 sfont->free = fluid_ramsfont_sfont_delete;
57 sfont->get_name = fluid_ramsfont_sfont_get_name;
58 sfont->get_preset = fluid_ramsfont_sfont_get_preset;
59 sfont->iteration_start = fluid_ramsfont_sfont_iteration_start;
60 sfont->iteration_next = fluid_ramsfont_sfont_iteration_next;
61
62 return sfont;
63
64 }
65
66 /***************************************************************
67 *
68 * PUBLIC INTERFACE
69 */
70
fluid_ramsfont_sfont_delete(fluid_sfont_t * sfont)71 int fluid_ramsfont_sfont_delete(fluid_sfont_t* sfont)
72 {
73 if (delete_fluid_ramsfont(sfont->data) != 0)
74 return -1;
75 FLUID_FREE(sfont);
76 return 0;
77 }
78
fluid_ramsfont_sfont_get_name(fluid_sfont_t * sfont)79 char* fluid_ramsfont_sfont_get_name(fluid_sfont_t* sfont)
80 {
81 return fluid_ramsfont_get_name((fluid_ramsfont_t*) sfont->data);
82 }
83
fluid_ramsfont_sfont_get_preset(fluid_sfont_t * sfont,unsigned int bank,unsigned int prenum)84 fluid_preset_t* fluid_ramsfont_sfont_get_preset(fluid_sfont_t* sfont, unsigned int bank, unsigned int prenum)
85 {
86 fluid_preset_t* preset;
87 fluid_rampreset_t* rampreset;
88
89 rampreset = fluid_ramsfont_get_preset((fluid_ramsfont_t*) sfont->data, bank, prenum);
90
91 if (rampreset == NULL) {
92 return NULL;
93 }
94
95 preset = FLUID_NEW(fluid_preset_t);
96 if (preset == NULL) {
97 FLUID_LOG(FLUID_ERR, "Out of memory");
98 return NULL;
99 }
100
101 preset->sfont = sfont;
102 preset->data = rampreset;
103 preset->free = fluid_rampreset_preset_delete;
104 preset->get_name = fluid_rampreset_preset_get_name;
105 preset->get_banknum = fluid_rampreset_preset_get_banknum;
106 preset->get_num = fluid_rampreset_preset_get_num;
107 preset->noteon = fluid_rampreset_preset_noteon;
108 preset->notify = NULL;
109
110 return preset;
111 }
112
fluid_ramsfont_sfont_iteration_start(fluid_sfont_t * sfont)113 void fluid_ramsfont_sfont_iteration_start(fluid_sfont_t* sfont)
114 {
115 fluid_ramsfont_iteration_start((fluid_ramsfont_t*) sfont->data);
116 }
117
fluid_ramsfont_sfont_iteration_next(fluid_sfont_t * sfont,fluid_preset_t * preset)118 int fluid_ramsfont_sfont_iteration_next(fluid_sfont_t* sfont, fluid_preset_t* preset)
119 {
120 preset->free = fluid_rampreset_preset_delete;
121 preset->get_name = fluid_rampreset_preset_get_name;
122 preset->get_banknum = fluid_rampreset_preset_get_banknum;
123 preset->get_num = fluid_rampreset_preset_get_num;
124 preset->noteon = fluid_rampreset_preset_noteon;
125 preset->notify = NULL;
126
127 return fluid_ramsfont_iteration_next((fluid_ramsfont_t*) sfont->data, preset);
128 }
129
fluid_rampreset_preset_delete(fluid_preset_t * preset)130 int fluid_rampreset_preset_delete(fluid_preset_t* preset)
131 {
132 FLUID_FREE(preset);
133
134 /* TODO: free modulators */
135
136 return 0;
137 }
138
fluid_rampreset_preset_get_name(fluid_preset_t * preset)139 char* fluid_rampreset_preset_get_name(fluid_preset_t* preset)
140 {
141 return fluid_rampreset_get_name((fluid_rampreset_t*) preset->data);
142 }
143
fluid_rampreset_preset_get_banknum(fluid_preset_t * preset)144 int fluid_rampreset_preset_get_banknum(fluid_preset_t* preset)
145 {
146 return fluid_rampreset_get_banknum((fluid_rampreset_t*) preset->data);
147 }
148
fluid_rampreset_preset_get_num(fluid_preset_t * preset)149 int fluid_rampreset_preset_get_num(fluid_preset_t* preset)
150 {
151 return fluid_rampreset_get_num((fluid_rampreset_t*) preset->data);
152 }
153
fluid_rampreset_preset_noteon(fluid_preset_t * preset,fluid_synth_t * synth,int chan,int key,int vel)154 int fluid_rampreset_preset_noteon(fluid_preset_t* preset, fluid_synth_t* synth, int chan, int key, int vel)
155 {
156 return fluid_rampreset_noteon((fluid_rampreset_t*) preset->data, synth, chan, key, vel);
157 }
158
159
160
161
162 /***************************************************************
163 *
164 * SFONT
165 */
166
167 /*
168 * new_fluid_ramsfont
169 */
new_fluid_ramsfont()170 fluid_ramsfont_t* new_fluid_ramsfont()
171 {
172 fluid_ramsfont_t* sfont;
173
174 sfont = FLUID_NEW(fluid_ramsfont_t);
175 if (sfont == NULL) {
176 FLUID_LOG(FLUID_ERR, "Out of memory");
177 return NULL;
178 }
179
180 sfont->name[0] = 0;
181 sfont->sample = NULL;
182 sfont->preset = NULL;
183
184 return sfont;
185 }
186
187 /*
188 * delete_fluid_ramsfont
189 */
delete_fluid_ramsfont(fluid_ramsfont_t * sfont)190 int delete_fluid_ramsfont(fluid_ramsfont_t* sfont)
191 {
192 fluid_list_t *list;
193 fluid_rampreset_t* preset;
194
195 /* Check that no samples are currently used */
196 for (list = sfont->sample; list; list = fluid_list_next(list)) {
197 fluid_sample_t* sam = (fluid_sample_t*) fluid_list_get(list);
198 if (fluid_sample_refcount(sam) != 0) {
199 return -1;
200 }
201 }
202
203 for (list = sfont->sample; list; list = fluid_list_next(list)) {
204 /* in ram soundfonts, the samples hold their data : so we should free it ourselves */
205 fluid_sample_t* sam = (fluid_sample_t*)fluid_list_get(list);
206 delete_fluid_ramsample(sam);
207 }
208
209 if (sfont->sample) {
210 delete_fluid_list(sfont->sample);
211 }
212
213 preset = sfont->preset;
214 while (preset != NULL) {
215 sfont->preset = preset->next;
216 delete_fluid_rampreset(preset);
217 preset = sfont->preset;
218 }
219
220 FLUID_FREE(sfont);
221 return FLUID_OK;
222 }
223
224 /*
225 * fluid_ramsfont_get_name
226 */
fluid_ramsfont_get_name(fluid_ramsfont_t * sfont)227 char* fluid_ramsfont_get_name(fluid_ramsfont_t* sfont)
228 {
229 return sfont->name;
230 }
231
232 /*
233 * fluid_ramsfont_set_name
234 */
235 int
fluid_ramsfont_set_name(fluid_ramsfont_t * sfont,char * name)236 fluid_ramsfont_set_name(fluid_ramsfont_t* sfont, char * name)
237 {
238 FLUID_MEMCPY(sfont->name, name, 20);
239 return FLUID_OK;
240 }
241
242
243 /* fluid_ramsfont_add_preset
244 *
245 * Add a preset to the SoundFont
246 */
fluid_ramsfont_add_preset(fluid_ramsfont_t * sfont,fluid_rampreset_t * preset)247 int fluid_ramsfont_add_preset(fluid_ramsfont_t* sfont, fluid_rampreset_t* preset)
248 {
249 fluid_rampreset_t *cur, *prev;
250 if (sfont->preset == NULL) {
251 preset->next = NULL;
252 sfont->preset = preset;
253 } else {
254 /* sort them as we go along. very basic sorting trick. */
255 cur = sfont->preset;
256 prev = NULL;
257 while (cur != NULL) {
258 if ((preset->bank < cur->bank)
259 || ((preset->bank == cur->bank) && (preset->num < cur->num))) {
260 if (prev == NULL) {
261 preset->next = cur;
262 sfont->preset = preset;
263 } else {
264 preset->next = cur;
265 prev->next = preset;
266 }
267 return FLUID_OK;
268 }
269 prev = cur;
270 cur = cur->next;
271 }
272 preset->next = NULL;
273 prev->next = preset;
274 }
275 return FLUID_OK;
276 }
277
278 /*
279 * fluid_ramsfont_add_ramsample
280 */
fluid_ramsfont_add_izone(fluid_ramsfont_t * sfont,unsigned int bank,unsigned int num,fluid_sample_t * sample,int lokey,int hikey)281 int fluid_ramsfont_add_izone(fluid_ramsfont_t* sfont,
282 unsigned int bank, unsigned int num, fluid_sample_t* sample,
283 int lokey, int hikey)
284 {
285 /*- find or create a preset
286 - add it the sample using the fluid_rampreset_add_sample fucntion
287 - add the sample to the list of samples
288 */
289 int err;
290
291 fluid_rampreset_t* preset = fluid_ramsfont_get_preset(sfont, bank, num);
292 if (preset == NULL) {
293 // Create it
294 preset = new_fluid_rampreset(sfont);
295 if (preset == NULL) {
296 return FLUID_FAILED;
297 }
298
299 preset->bank = bank;
300 preset->num = num;
301
302 err = fluid_rampreset_add_sample(preset, sample, lokey, hikey);
303 if (err != FLUID_OK) {
304 return FLUID_FAILED;
305 }
306
307 // sort the preset
308 fluid_ramsfont_add_preset(sfont, preset);
309
310 } else {
311
312 // just add it
313 err = fluid_rampreset_add_sample(preset, sample, lokey, hikey);
314 if (err != FLUID_OK) {
315 return FLUID_FAILED;
316 }
317 }
318
319 sfont->sample = fluid_list_append(sfont->sample, sample);
320 return FLUID_OK;
321 }
322
fluid_ramsfont_remove_izone(fluid_ramsfont_t * sfont,unsigned int bank,unsigned int num,fluid_sample_t * sample)323 int fluid_ramsfont_remove_izone(fluid_ramsfont_t* sfont,
324 unsigned int bank, unsigned int num, fluid_sample_t* sample) {
325 int err;
326 fluid_rampreset_t* preset = fluid_ramsfont_get_preset(sfont, bank, num);
327 if (preset == NULL) {
328 return FLUID_FAILED;
329 }
330
331 // Fixed a crash bug : remove the sample from the sfont list after
332 // removing the izone (aschmitt august 2005)
333 err = fluid_rampreset_remove_izone(preset, sample);
334 if (err != FLUID_OK)
335 return err;
336
337 // now we must remove the sample from sfont->sample
338 sfont->sample = fluid_list_remove(sfont->sample, sample);
339
340 return FLUID_OK;
341 }
342
343
344 /* Note for version 2.0 : missing API fluid_ramsfont_izone_get_gen - Antoine Schmitt May 2003 */
fluid_ramsfont_izone_set_gen(fluid_ramsfont_t * sfont,unsigned int bank,unsigned int num,fluid_sample_t * sample,int gen_type,float value)345 int fluid_ramsfont_izone_set_gen(fluid_ramsfont_t* sfont,
346 unsigned int bank, unsigned int num, fluid_sample_t* sample,
347 int gen_type, float value) {
348
349 fluid_rampreset_t* preset = fluid_ramsfont_get_preset(sfont, bank, num);
350 if (preset == NULL) {
351 return FLUID_FAILED;
352 }
353
354 return fluid_rampreset_izone_set_gen(preset, sample, gen_type, value);
355 }
356
357 /* Note for version 2.0 : missing API fluid_ramsfont_izone_get_loop - Antoine Schmitt May 2003 */
fluid_ramsfont_izone_set_loop(fluid_ramsfont_t * sfont,unsigned int bank,unsigned int num,fluid_sample_t * sample,int on,float loopstart,float loopend)358 int fluid_ramsfont_izone_set_loop(fluid_ramsfont_t* sfont,
359 unsigned int bank, unsigned int num, fluid_sample_t* sample,
360 int on, float loopstart, float loopend) {
361 fluid_rampreset_t* preset = fluid_ramsfont_get_preset(sfont, bank, num);
362 if (preset == NULL) {
363 return FLUID_FAILED;
364 }
365
366 return fluid_rampreset_izone_set_loop(preset, sample, on, loopstart, loopend);
367 }
368
369 /*
370 * fluid_ramsfont_get_preset
371 */
fluid_ramsfont_get_preset(fluid_ramsfont_t * sfont,unsigned int bank,unsigned int num)372 fluid_rampreset_t* fluid_ramsfont_get_preset(fluid_ramsfont_t* sfont, unsigned int bank, unsigned int num)
373 {
374 fluid_rampreset_t* preset = sfont->preset;
375 while (preset != NULL) {
376 if ((preset->bank == bank) && ((preset->num == num))) {
377 return preset;
378 }
379 preset = preset->next;
380 }
381 return NULL;
382 }
383
384 /*
385 * fluid_ramsfont_iteration_start
386 */
fluid_ramsfont_iteration_start(fluid_ramsfont_t * sfont)387 void fluid_ramsfont_iteration_start(fluid_ramsfont_t* sfont)
388 {
389 sfont->iter_cur = sfont->preset;
390 }
391
392 /*
393 * fluid_ramsfont_iteration_next
394 */
fluid_ramsfont_iteration_next(fluid_ramsfont_t * sfont,fluid_preset_t * preset)395 int fluid_ramsfont_iteration_next(fluid_ramsfont_t* sfont, fluid_preset_t* preset)
396 {
397 if (sfont->iter_cur == NULL) {
398 return 0;
399 }
400
401 preset->data = (void*) sfont->iter_cur;
402 sfont->iter_cur = fluid_rampreset_next(sfont->iter_cur);
403 return 1;
404 }
405
406 /***************************************************************
407 *
408 * PRESET
409 */
410
411 typedef struct _fluid_rampreset_voice_t fluid_rampreset_voice_t;
412 struct _fluid_rampreset_voice_t {
413 fluid_voice_t *voice;
414 unsigned int voiceID;
415 };
416
417 /*
418 * new_fluid_rampreset
419 */
420 fluid_rampreset_t*
new_fluid_rampreset(fluid_ramsfont_t * sfont)421 new_fluid_rampreset(fluid_ramsfont_t* sfont)
422 {
423 fluid_rampreset_t* preset = FLUID_NEW(fluid_rampreset_t);
424 if (preset == NULL) {
425 FLUID_LOG(FLUID_ERR, "Out of memory");
426 return NULL;
427 }
428 preset->next = NULL;
429 preset->sfont = sfont;
430 preset->name[0] = 0;
431 preset->bank = 0;
432 preset->num = 0;
433 preset->global_zone = NULL;
434 preset->zone = NULL;
435 preset->presetvoices = NULL;
436 return preset;
437 }
438
439 /*
440 * delete_fluid_rampreset
441 */
442 int
delete_fluid_rampreset(fluid_rampreset_t * preset)443 delete_fluid_rampreset(fluid_rampreset_t* preset)
444 {
445 int err = FLUID_OK;
446 fluid_preset_zone_t* zone;
447 fluid_rampreset_voice_t *data;
448
449 if (preset->global_zone != NULL) {
450 if (delete_fluid_preset_zone(preset->global_zone) != FLUID_OK) {
451 err = FLUID_FAILED;
452 }
453 preset->global_zone = NULL;
454 }
455 zone = preset->zone;
456 while (zone != NULL) {
457 preset->zone = zone->next;
458 if (delete_fluid_preset_zone(zone) != FLUID_OK) {
459 err = FLUID_FAILED;
460 }
461 zone = preset->zone;
462 }
463
464 if (preset->presetvoices != NULL) {
465 fluid_list_t *tmp = preset->presetvoices, *next;
466 while (tmp) {
467 data = (fluid_rampreset_voice_t *)(tmp->data);
468 FLUID_FREE(data);
469
470 next = tmp->next;
471 FLUID_FREE(tmp);
472 tmp = next;
473 }
474 }
475 preset->presetvoices = NULL;
476
477 FLUID_FREE(preset);
478 return err;
479 }
480
481 int
fluid_rampreset_get_banknum(fluid_rampreset_t * preset)482 fluid_rampreset_get_banknum(fluid_rampreset_t* preset)
483 {
484 return preset->bank;
485 }
486
487 int
fluid_rampreset_get_num(fluid_rampreset_t * preset)488 fluid_rampreset_get_num(fluid_rampreset_t* preset)
489 {
490 return preset->num;
491 }
492
493 char*
fluid_rampreset_get_name(fluid_rampreset_t * preset)494 fluid_rampreset_get_name(fluid_rampreset_t* preset)
495 {
496 return preset->name;
497 }
498
499 /*
500 * fluid_rampreset_next
501 */
502 fluid_rampreset_t*
fluid_rampreset_next(fluid_rampreset_t * preset)503 fluid_rampreset_next(fluid_rampreset_t* preset)
504 {
505 return preset->next;
506 }
507
508
509 /*
510 * fluid_rampreset_add_zone
511 */
512 int
fluid_rampreset_add_zone(fluid_rampreset_t * preset,fluid_preset_zone_t * zone)513 fluid_rampreset_add_zone(fluid_rampreset_t* preset, fluid_preset_zone_t* zone)
514 {
515 if (preset->zone == NULL) {
516 zone->next = NULL;
517 preset->zone = zone;
518 } else {
519 zone->next = preset->zone;
520 preset->zone = zone;
521 }
522 return FLUID_OK;
523 }
524
525
526 /*
527 * fluid_rampreset_add_sample
528 */
fluid_rampreset_add_sample(fluid_rampreset_t * preset,fluid_sample_t * sample,int lokey,int hikey)529 int fluid_rampreset_add_sample(fluid_rampreset_t* preset, fluid_sample_t* sample, int lokey, int hikey)
530 {
531 /* create a new instrument zone, with the given sample */
532
533 /* one preset zone */
534 if (preset->zone == NULL) {
535 fluid_preset_zone_t* zone;
536 zone = new_fluid_preset_zone("");
537 if (zone == NULL) {
538 return FLUID_FAILED;
539 }
540
541 /* its instrument */
542 zone->inst = (fluid_inst_t*) new_fluid_inst();
543 if (zone->inst == NULL) {
544 delete_fluid_preset_zone(zone);
545 return FLUID_FAILED;
546 }
547
548 fluid_rampreset_add_zone(preset, zone);
549 }
550
551 /* add an instrument zone for each sample */
552 {
553 fluid_inst_t* inst = fluid_preset_zone_get_inst(preset->zone);
554 fluid_inst_zone_t* izone = new_fluid_inst_zone("");
555 if (izone == NULL) {
556 return FLUID_FAILED;
557 }
558
559 if (fluid_inst_add_zone(inst, izone) != FLUID_OK) {
560 delete_fluid_inst_zone(izone);
561 return FLUID_FAILED;
562 }
563
564 izone->sample = sample;
565 izone->keylo = lokey;
566 izone->keyhi = hikey;
567
568 // give the preset the name of the sample
569 FLUID_MEMCPY(preset->name, sample->name, 20);
570 }
571
572 return FLUID_OK;
573 }
574
fluid_rampreset_izoneforsample(fluid_rampreset_t * preset,fluid_sample_t * sample)575 fluid_inst_zone_t* fluid_rampreset_izoneforsample(fluid_rampreset_t* preset, fluid_sample_t* sample)
576 {
577 fluid_inst_t* inst;
578 fluid_inst_zone_t* izone;
579
580 if (preset->zone == NULL) return NULL;
581
582 inst = fluid_preset_zone_get_inst(preset->zone);
583 izone = inst->zone;
584 while (izone) {
585 if (izone->sample == sample)
586 return izone;
587 izone = izone->next;
588 }
589 return NULL;
590 }
591
fluid_rampreset_izone_set_loop(fluid_rampreset_t * preset,fluid_sample_t * sample,int on,float loopstart,float loopend)592 int fluid_rampreset_izone_set_loop(fluid_rampreset_t* preset, fluid_sample_t* sample,
593 int on, float loopstart, float loopend) {
594 fluid_inst_zone_t* izone = fluid_rampreset_izoneforsample(preset, sample);
595 short coarse, fine;
596
597 if (izone == NULL)
598 return FLUID_FAILED;
599
600 if (!on) {
601 izone->gen[GEN_SAMPLEMODE].flags = GEN_SET;
602 izone->gen[GEN_SAMPLEMODE].val = FLUID_UNLOOPED;
603 fluid_rampreset_updatevoices(preset, GEN_SAMPLEMODE, FLUID_UNLOOPED);
604 return FLUID_OK;
605 }
606
607 /* NOTE : We should check that (sample->startloop + loopStart <= sample->endloop - loopend - 32) */
608
609 /* loopstart */
610 if (loopstart > 32767. || loopstart < -32767.) {
611 coarse = (short)(loopstart/32768.);
612 fine = (short)(loopstart - (float)(coarse)*32768.);
613 } else {
614 coarse = 0;
615 fine = (short)loopstart;
616 }
617 izone->gen[GEN_STARTLOOPADDROFS].flags = GEN_SET;
618 izone->gen[GEN_STARTLOOPADDROFS].val = fine;
619 fluid_rampreset_updatevoices(preset, GEN_STARTLOOPADDROFS, fine);
620 if (coarse) {
621 izone->gen[GEN_STARTLOOPADDRCOARSEOFS].flags = GEN_SET;
622 izone->gen[GEN_STARTLOOPADDRCOARSEOFS].val = coarse;
623 } else {
624 izone->gen[GEN_STARTLOOPADDRCOARSEOFS].flags = GEN_UNUSED;
625 }
626 fluid_rampreset_updatevoices(preset, GEN_STARTLOOPADDRCOARSEOFS, coarse);
627
628 /* loopend */
629 if (loopend > 32767. || loopend < -32767.) {
630 coarse = (short)(loopend/32768.);
631 fine = (short)(loopend - (float)(coarse)*32768.);
632 } else {
633 coarse = 0;
634 fine = (short)loopend;
635 }
636 izone->gen[GEN_ENDLOOPADDROFS].flags = GEN_SET;
637 izone->gen[GEN_ENDLOOPADDROFS].val = fine;
638 fluid_rampreset_updatevoices(preset, GEN_ENDLOOPADDROFS, fine);
639 if (coarse) {
640 izone->gen[GEN_ENDLOOPADDRCOARSEOFS].flags = GEN_SET;
641 izone->gen[GEN_ENDLOOPADDRCOARSEOFS].val = coarse;
642 } else {
643 izone->gen[GEN_ENDLOOPADDRCOARSEOFS].flags = GEN_UNUSED;
644 }
645 fluid_rampreset_updatevoices(preset, GEN_ENDLOOPADDRCOARSEOFS, coarse);
646
647 izone->gen[GEN_SAMPLEMODE].flags = GEN_SET;
648 izone->gen[GEN_SAMPLEMODE].val = FLUID_LOOP_DURING_RELEASE;
649 fluid_rampreset_updatevoices(preset, GEN_SAMPLEMODE, FLUID_LOOP_DURING_RELEASE);
650
651 /* If the loop points are the whole samples, we are supposed to
652 copy the frames around in the margins (the start to the end margin and
653 the end to the start margin), but it works fine without this. Maybe some time
654 it will be needed (see SAMPLE_LOOP_MARGIN) -- Antoie Schmitt May 2003 */
655
656 return FLUID_OK;
657 }
658
fluid_rampreset_izone_set_gen(fluid_rampreset_t * preset,fluid_sample_t * sample,int gen_type,float value)659 int fluid_rampreset_izone_set_gen(fluid_rampreset_t* preset, fluid_sample_t* sample,
660 int gen_type, float value) {
661 fluid_inst_zone_t* izone = fluid_rampreset_izoneforsample(preset, sample);
662 if (izone == NULL)
663 return FLUID_FAILED;
664
665 izone->gen[gen_type].flags = GEN_SET;
666 izone->gen[gen_type].val = value;
667
668 fluid_rampreset_updatevoices(preset, gen_type, value);
669
670 return FLUID_OK;
671 }
672
fluid_rampreset_remove_izone(fluid_rampreset_t * preset,fluid_sample_t * sample)673 int fluid_rampreset_remove_izone(fluid_rampreset_t* preset, fluid_sample_t* sample) {
674 fluid_inst_t* inst;
675 fluid_inst_zone_t* izone, * prev;
676 int found = 0;
677
678 if (preset->zone == NULL) return FLUID_FAILED;
679 inst = fluid_preset_zone_get_inst(preset->zone);
680 izone = inst->zone;
681 prev = NULL;
682 while (izone && !found) {
683 if (izone->sample == sample) {
684 if (prev == NULL) {
685 inst->zone = izone->next;
686 } else {
687 prev->next = izone->next;
688 }
689 izone->next = NULL;
690 delete_fluid_inst_zone(izone);
691 found = 1;
692 } else {
693 prev = izone;
694 izone = izone->next;
695 }
696 }
697 if (!found)
698 return FLUID_FAILED;
699
700 // stop all the voices that use this sample, so that
701 // the sample can be cleared up
702 {
703 fluid_list_t *tmp = preset->presetvoices;
704 while (tmp) {
705 fluid_rampreset_voice_t *presetvoice = (fluid_rampreset_voice_t *)(tmp->data);
706 fluid_voice_t *voice = presetvoice->voice;
707 if (fluid_voice_is_playing(voice) && (fluid_voice_get_id(voice) == presetvoice->voiceID)) {
708 // still belongs to the preset
709 if (voice->sample == sample) {
710 // uses this sample : turn it off.
711 // our presetvoices struct will be cleaneup at the next update
712 fluid_voice_off(voice);
713 }
714 }
715 tmp = tmp->next;
716 }
717 }
718 return FLUID_OK;
719 }
720
721 /*
722 * fluid_rampreset_remembervoice
723 */
724 int
fluid_rampreset_remembervoice(fluid_rampreset_t * preset,fluid_voice_t * voice)725 fluid_rampreset_remembervoice(fluid_rampreset_t* preset, fluid_voice_t* voice) {
726 /* stores the voice and the its ID in the preset for later update on gen_set */
727 fluid_rampreset_voice_t *presetvoice = FLUID_NEW(fluid_rampreset_voice_t);
728 if (presetvoice == NULL) {
729 FLUID_LOG(FLUID_ERR, "Out of memory");
730 return FLUID_FAILED;
731 }
732
733 presetvoice->voice = voice;
734 presetvoice->voiceID = fluid_voice_get_id(voice);
735
736 preset->presetvoices = fluid_list_append(preset->presetvoices, (void *)presetvoice);
737 if (preset->presetvoices == NULL) {
738 FLUID_FREE(presetvoice);
739 FLUID_LOG(FLUID_ERR, "Out of memory");
740 return FLUID_FAILED;
741 }
742 return FLUID_OK;
743 }
744
745 /*
746 * fluid_rampreset_updatevoice
747 */
748 void
fluid_rampreset_updatevoices(fluid_rampreset_t * preset,int gen_type,float val)749 fluid_rampreset_updatevoices(fluid_rampreset_t* preset, int gen_type, float val) {
750 fluid_list_t *tmp = preset->presetvoices, *prev = NULL, *next;
751
752 /* walk the presetvoice to update them if they are still active and ours.
753 If their ID has changed or their state is not playing, they are not ours, so we forget them
754 */
755 while (tmp) {
756 fluid_rampreset_voice_t *presetvoice = (fluid_rampreset_voice_t *)(tmp->data);
757 fluid_voice_t *voice = presetvoice->voice;
758 if (!fluid_voice_is_playing(voice) || (fluid_voice_get_id(voice) != presetvoice->voiceID)) {
759 /* forget it */
760 FLUID_FREE(presetvoice);
761
762 /* unlink it */
763 next = tmp->next;
764 FLUID_FREE(tmp);
765 if (prev) {
766 prev->next = next;
767 } else {
768 preset->presetvoices = next;
769 }
770 tmp = next;
771
772 } else {
773
774 /* update */
775 fluid_voice_gen_set(voice, gen_type, val);
776 fluid_voice_update_param(voice, gen_type);
777
778 /* next */
779 prev = tmp;
780 tmp = tmp->next;
781 }
782 }
783 }
784
785
786 /*
787 * fluid_rampreset_noteon
788 */
789 int
fluid_rampreset_noteon(fluid_rampreset_t * preset,fluid_synth_t * synth,int chan,int key,int vel)790 fluid_rampreset_noteon(fluid_rampreset_t* preset, fluid_synth_t* synth, int chan, int key, int vel)
791 {
792 fluid_preset_zone_t *preset_zone;
793 fluid_inst_t* inst;
794 fluid_inst_zone_t *inst_zone, *global_inst_zone, *z;
795 fluid_sample_t* sample;
796 fluid_voice_t* voice;
797 fluid_mod_t * mod;
798 fluid_mod_t * mod_list[FLUID_NUM_MOD]; /* list for 'sorting' preset modulators */
799 int mod_list_count;
800 int i;
801
802 /* run thru all the zones of this preset */
803 preset_zone = preset->zone;
804 while (preset_zone != NULL) {
805
806 /* check if the note falls into the key and velocity range of this
807 preset */
808 if (fluid_preset_zone_inside_range(preset_zone, key, vel)) {
809
810 inst = fluid_preset_zone_get_inst(preset_zone);
811 global_inst_zone = fluid_inst_get_global_zone(inst);
812
813 /* run thru all the zones of this instrument */
814 inst_zone = fluid_inst_get_zone(inst);
815 while (inst_zone != NULL) {
816
817 /* make sure this instrument zone has a valid sample */
818 sample = fluid_inst_zone_get_sample(inst_zone);
819 if (fluid_sample_in_rom(sample) || (sample == NULL)) {
820 inst_zone = fluid_inst_zone_next(inst_zone);
821 continue;
822 }
823
824 /* check if the note falls into the key and velocity range of this
825 instrument */
826
827 if (fluid_inst_zone_inside_range(inst_zone, key, vel) && (sample != NULL)) {
828
829 /* this is a good zone. allocate a new synthesis process and
830 initialize it */
831
832 voice = fluid_synth_alloc_voice(synth, sample, chan, key, vel);
833 if (voice == NULL) {
834 return FLUID_FAILED;
835 }
836
837 if (fluid_rampreset_remembervoice(preset, voice) != FLUID_OK) {
838 return FLUID_FAILED;
839 }
840
841 z = inst_zone;
842
843 /* Instrument level, generators */
844
845 for (i = 0; i < GEN_LAST; i++) {
846
847 /* SF 2.01 section 9.4 'bullet' 4:
848 *
849 * A generator in a local instrument zone supersedes a
850 * global instrument zone generator. Both cases supersede
851 * the default generator -> voice_gen_set */
852
853 if (inst_zone->gen[i].flags){
854 fluid_voice_gen_set(voice, i, inst_zone->gen[i].val);
855
856 } else if (global_inst_zone != NULL && global_inst_zone->gen[i].flags){
857 fluid_voice_gen_set(voice, i, global_inst_zone->gen[i].val);
858
859 } else {
860 /* The generator has not been defined in this instrument.
861 * Do nothing, leave it at the default.
862 */
863 };
864
865 }; /* for all generators */
866
867 /* global instrument zone, modulators: Put them all into a
868 * list. */
869
870 mod_list_count = 0;
871
872 if (global_inst_zone){
873 mod = global_inst_zone->mod;
874 while (mod){
875 mod_list[mod_list_count++] = mod;
876 mod = mod->next;
877 };
878 };
879
880 /* local instrument zone, modulators.
881 * Replace modulators with the same definition in the list:
882 * SF 2.01 page 69, 'bullet' 8
883 */
884 mod = inst_zone->mod;
885
886 while (mod){
887
888 /* 'Identical' modulators will be deleted by setting their
889 * list entry to NULL. The list length is known, NULL
890 * entries will be ignored later. SF2.01 section 9.5.1
891 * page 69, 'bullet' 3 defines 'identical'. */
892
893 for (i = 0; i < mod_list_count; i++){
894 if (fluid_mod_test_identity(mod,mod_list[i])){
895 mod_list[i] = NULL;
896 };
897 };
898
899 /* Finally add the new modulator to to the list. */
900 mod_list[mod_list_count++] = mod;
901 mod = mod->next;
902 };
903
904 /* Add instrument modulators (global / local) to the voice. */
905 for (i = 0; i < mod_list_count; i++){
906
907 mod = mod_list[i];
908
909 if (mod != NULL){ /* disabled modulators CANNOT be skipped. */
910
911 /* Instrument modulators -supersede- existing (default)
912 * modulators. SF 2.01 page 69, 'bullet' 6 */
913 fluid_voice_add_mod(voice, mod, FLUID_VOICE_OVERWRITE);
914 };
915 };
916
917 /* Preset level, generators */
918
919 for (i = 0; i < GEN_LAST; i++) {
920
921 /* SF 2.01 section 8.5 page 58: If some generators are
922 * encountered at preset level, they should be ignored */
923 if ((i != GEN_STARTADDROFS)
924 && (i != GEN_ENDADDROFS)
925 && (i != GEN_STARTLOOPADDROFS)
926 && (i != GEN_ENDLOOPADDROFS)
927 && (i != GEN_STARTADDRCOARSEOFS)
928 && (i != GEN_ENDADDRCOARSEOFS)
929 && (i != GEN_STARTLOOPADDRCOARSEOFS)
930 && (i != GEN_KEYNUM)
931 && (i != GEN_VELOCITY)
932 && (i != GEN_ENDLOOPADDRCOARSEOFS)
933 && (i != GEN_SAMPLEMODE)
934 && (i != GEN_EXCLUSIVECLASS)
935 && (i != GEN_OVERRIDEROOTKEY)) {
936
937 /* SF 2.01 section 9.4 'bullet' 9: A generator in a
938 * local preset zone supersedes a global preset zone
939 * generator. The effect is -added- to the destination
940 * summing node -> voice_gen_incr */
941
942 if (preset_zone->gen[i].flags){
943 fluid_voice_gen_incr(voice, i, preset_zone->gen[i].val);
944 } else {
945 /* The generator has not been defined in this preset
946 * Do nothing, leave it unchanged.
947 */
948 };
949 }; /* if available at preset level */
950 }; /* for all generators */
951
952
953 /* Global preset zone, modulators: put them all into a
954 * list. */
955 mod_list_count = 0;
956
957 /* Process the modulators of the local preset zone. Kick
958 * out all identical modulators from the global preset zone
959 * (SF 2.01 page 69, second-last bullet) */
960
961 mod = preset_zone->mod;
962 while (mod){
963 for (i = 0; i < mod_list_count; i++){
964 if (fluid_mod_test_identity(mod,mod_list[i])){
965 mod_list[i] = NULL;
966 };
967 };
968
969 /* Finally add the new modulator to the list. */
970 mod_list[mod_list_count++] = mod;
971 mod = mod->next;
972 };
973
974 /* Add preset modulators (global / local) to the voice. */
975 for (i = 0; i < mod_list_count; i++){
976 mod = mod_list[i];
977 if ((mod != NULL) && (mod->amount != 0)) { /* disabled modulators can be skipped. */
978
979 /* Preset modulators -add- to existing instrument /
980 * default modulators. SF2.01 page 70 first bullet on
981 * page */
982 fluid_voice_add_mod(voice, mod, FLUID_VOICE_ADD);
983 };
984 };
985
986 /* add the synthesis process to the synthesis loop. */
987 fluid_synth_start_voice(synth, voice);
988
989 /* Store the ID of the first voice that was created by this noteon event.
990 * Exclusive class may only terminate older voices.
991 * That avoids killing voices, which have just been created.
992 * (a noteon event can create several voice processes with the same exclusive
993 * class - for example when using stereo samples)
994 */
995 }
996
997 inst_zone = fluid_inst_zone_next(inst_zone);
998 }
999 }
1000 preset_zone = fluid_preset_zone_next(preset_zone);
1001 }
1002
1003 return FLUID_OK;
1004 }
1005
1006
1007
1008 /***************************************************************
1009 *
1010 * SAMPLE
1011 */
1012
1013
1014
1015 /*
1016 * fluid_sample_set_name
1017 */
1018 int
fluid_sample_set_name(fluid_sample_t * sample,char * name)1019 fluid_sample_set_name(fluid_sample_t* sample, char * name)
1020 {
1021 FLUID_MEMCPY(sample->name, name, 20);
1022 return FLUID_OK;
1023 }
1024
1025 /*
1026 * fluid_sample_set_sound_data
1027 */
1028 int
fluid_sample_set_sound_data(fluid_sample_t * sample,short * data,unsigned int nbframes,short copy_data,int rootkey)1029 fluid_sample_set_sound_data(fluid_sample_t* sample, short *data, unsigned int nbframes, short copy_data, int rootkey)
1030 {
1031 /* 16 bit mono 44.1KHz data in */
1032 /* in all cases, the sample has ownership of the data : it will release it in the end */
1033 unsigned int storedNbFrames;
1034
1035 /* in case we already have some data */
1036 if (sample->data != NULL) {
1037 FLUID_FREE(sample->data);
1038 }
1039
1040 if (copy_data) {
1041
1042 /* nbframes should be >= 48 (SoundFont specs) */
1043 storedNbFrames = nbframes;
1044 if (storedNbFrames < 48) storedNbFrames = 48;
1045
1046 sample->data = FLUID_MALLOC(storedNbFrames*2 + 4*SAMPLE_LOOP_MARGIN);
1047 if (sample->data == NULL) {
1048 FLUID_LOG(FLUID_ERR, "Out of memory");
1049 return FLUID_FAILED;
1050 }
1051 FLUID_MEMSET(sample->data, 0, storedNbFrames*2 + 4*SAMPLE_LOOP_MARGIN);
1052 FLUID_MEMCPY((char*)(sample->data) + 2*SAMPLE_LOOP_MARGIN, data, nbframes*2);
1053
1054 #if 0
1055 /* this would do the fill of the margins */
1056 FLUID_MEMCPY((char*)(sample->data) + 2*SAMPLE_LOOP_MARGIN + storedNbFrames*2, (char*)data, 2*SAMPLE_LOOP_MARGIN);
1057 FLUID_MEMCPY((char*)(sample->data), (char*)data + nbframes*2 - 2*SAMPLE_LOOP_MARGIN, 2*SAMPLE_LOOP_MARGIN);
1058 #endif
1059
1060 /* pointers */
1061 /* all from the start of data */
1062 sample->start = SAMPLE_LOOP_MARGIN;
1063 sample->end = SAMPLE_LOOP_MARGIN + storedNbFrames;
1064 } else {
1065 /* we cannot assure the SAMPLE_LOOP_MARGIN */
1066 sample->data = data;
1067 sample->start = 0;
1068 sample->end = nbframes;
1069 }
1070
1071 /* only used as markers for the LOOP generators : set them on the first real frame */
1072 sample->loopstart = sample->start;
1073 sample->loopend = sample->end;
1074
1075 sample->samplerate = 44100;
1076 sample->origpitch = rootkey;
1077 sample->pitchadj = 0;
1078 sample->sampletype = FLUID_SAMPLETYPE_MONO;
1079 sample->valid = 1;
1080
1081 return FLUID_OK;
1082 }
1083
1084 /*
1085 * new_fluid_ramsample
1086 */
1087 fluid_sample_t*
new_fluid_ramsample()1088 new_fluid_ramsample()
1089 {
1090 /* same as new_fluid_sample. Only here so that it is exported */
1091 fluid_sample_t* sample = NULL;
1092
1093 sample = FLUID_NEW(fluid_sample_t);
1094 if (sample == NULL) {
1095 FLUID_LOG(FLUID_ERR, "Out of memory");
1096 return NULL;
1097 }
1098
1099 memset(sample, 0, sizeof(fluid_sample_t));
1100
1101 return sample;
1102 }
1103
1104 /*
1105 * delete_fluid_ramsample
1106 */
1107 int
delete_fluid_ramsample(fluid_sample_t * sample)1108 delete_fluid_ramsample(fluid_sample_t* sample)
1109 {
1110 /* same as delete_fluid_sample, plus frees the data */
1111 if (sample->data != NULL) {
1112 FLUID_FREE(sample->data);
1113 }
1114 sample->data = NULL;
1115 FLUID_FREE(sample);
1116 return FLUID_OK;
1117 }
1118