fluid_ramsfont.c
上传用户:tjmskj2
上传日期:2020-08-17
资源大小:577k
文件大小:35k
源码类别:

midi

开发平台:

C/C++

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