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 */ 29int fluid_rampreset_add_sample(fluid_rampreset_t* preset, fluid_sample_t* sample, int lokey, int hikey); 30int fluid_rampreset_izone_set_gen(fluid_rampreset_t* preset, fluid_sample_t* sample, int gen_type, float value); 31int fluid_rampreset_izone_set_loop(fluid_rampreset_t* preset, fluid_sample_t* sample, int on, float loopstart, float loopend); 32int fluid_rampreset_remove_izone(fluid_rampreset_t* preset, fluid_sample_t* sample); 33void fluid_rampreset_updatevoices(fluid_rampreset_t* preset, int gen_type, float val); 34 35/* 36 * fluid_ramsfont_create_sfont 37 */ 38fluid_sfont_t* 39fluid_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 71int 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 79char* fluid_ramsfont_sfont_get_name(fluid_sfont_t* sfont) 80{ 81 return fluid_ramsfont_get_name((fluid_ramsfont_t*) sfont->data); 82} 83 84fluid_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 113void fluid_ramsfont_sfont_iteration_start(fluid_sfont_t* sfont) 114{ 115 fluid_ramsfont_iteration_start((fluid_ramsfont_t*) sfont->data); 116} 117 118int 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 130int fluid_rampreset_preset_delete(fluid_preset_t* preset) 131{ 132 FLUID_FREE(preset); 133 134/* TODO: free modulators */ 135 136 return 0; 137} 138 139char* fluid_rampreset_preset_get_name(fluid_preset_t* preset) 140{ 141 return fluid_rampreset_get_name((fluid_rampreset_t*) preset->data); 142} 143 144int fluid_rampreset_preset_get_banknum(fluid_preset_t* preset) 145{ 146 return fluid_rampreset_get_banknum((fluid_rampreset_t*) preset->data); 147} 148 149int fluid_rampreset_preset_get_num(fluid_preset_t* preset) 150{ 151 return fluid_rampreset_get_num((fluid_rampreset_t*) preset->data); 152} 153 154int 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 */ 170fluid_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 */ 190int 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 */ 227char* fluid_ramsfont_get_name(fluid_ramsfont_t* sfont) 228{ 229 return sfont->name; 230} 231 232/* 233 * fluid_ramsfont_set_name 234 */ 235int 236fluid_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 */ 247int 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 */ 281int 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 323int 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 */ 345int 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 */ 358int 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 */ 372fluid_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 */ 387void fluid_ramsfont_iteration_start(fluid_ramsfont_t* sfont) 388{ 389 sfont->iter_cur = sfont->preset; 390} 391 392/* 393 * fluid_ramsfont_iteration_next 394 */ 395int 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 411typedef struct _fluid_rampreset_voice_t fluid_rampreset_voice_t; 412struct _fluid_rampreset_voice_t { 413 fluid_voice_t *voice; 414 unsigned int voiceID; 415}; 416 417/* 418 * new_fluid_rampreset 419 */ 420fluid_rampreset_t* 421new_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 */ 442int 443delete_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 481int 482fluid_rampreset_get_banknum(fluid_rampreset_t* preset) 483{ 484 return preset->bank; 485} 486 487int 488fluid_rampreset_get_num(fluid_rampreset_t* preset) 489{ 490 return preset->num; 491} 492 493char* 494fluid_rampreset_get_name(fluid_rampreset_t* preset) 495{ 496 return preset->name; 497} 498 499/* 500 * fluid_rampreset_next 501 */ 502fluid_rampreset_t* 503fluid_rampreset_next(fluid_rampreset_t* preset) 504{ 505 return preset->next; 506} 507 508 509/* 510 * fluid_rampreset_add_zone 511 */ 512int 513fluid_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 */ 529int 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 575fluid_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 592int 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 659int 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 673int 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 */ 724int 725fluid_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 */ 748void 749fluid_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 */ 789int 790fluid_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 */ 1018int 1019fluid_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 */ 1028int 1029fluid_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 */ 1087fluid_sample_t* 1088new_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 */ 1107int 1108delete_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