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

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_chan.h"
  21. #include "fluid_mod.h"
  22. #include "fluid_synth.h"
  23. #include "fluid_sfont.h"
  24. /* Field shift amounts for sfont_bank_prog bit field integer */
  25. #define PROG_SHIFTVAL   0
  26. #define BANK_SHIFTVAL   8
  27. #define SFONT_SHIFTVAL  22
  28. /* Field mask values for sfont_bank_prog bit field integer */
  29. #define PROG_MASKVAL    0x000000FF      /* Bit 7 is used to indicate unset state */
  30. #define BANK_MASKVAL    0x003FFF00
  31. #define BANKLSB_MASKVAL 0x00007F00
  32. #define BANKMSB_MASKVAL 0x003F8000
  33. #define SFONT_MASKVAL   0xFFC00000
  34. static void fluid_channel_init(fluid_channel_t* chan);
  35. fluid_channel_t*
  36. new_fluid_channel(fluid_synth_t* synth, int num)
  37. {
  38.   fluid_channel_t* chan;
  39.   chan = FLUID_NEW(fluid_channel_t);
  40.   if (chan == NULL) {
  41.     FLUID_LOG(FLUID_ERR, "Out of memory");
  42.     return NULL;
  43.   }
  44.   chan->synth = synth;
  45.   chan->channum = num;
  46.   chan->preset = NULL;
  47.   chan->shadow_preset = NULL;
  48.   chan->tuning = NULL;
  49.   fluid_channel_init(chan);
  50.   fluid_channel_init_ctrl(chan, 0);
  51.   return chan;
  52. }
  53. static void
  54. fluid_channel_init(fluid_channel_t* chan)
  55. {
  56.   fluid_event_queue_elem_t *event;
  57.   fluid_preset_t *newpreset;
  58.   int prognum, banknum;
  59.   prognum = 0;
  60.   banknum = (chan->channum == 9)? 128 : 0; /* ?? */
  61.   chan->sfont_bank_prog = 0 << SFONT_SHIFTVAL | banknum << BANK_SHIFTVAL
  62.     | prognum << PROG_SHIFTVAL;
  63.   /* FIXME - fluid_synth_find_preset not real-time safe */
  64.   newpreset = fluid_synth_find_preset(chan->synth, banknum, prognum);
  65.   fluid_channel_set_preset(chan, newpreset);
  66.   chan->interp_method = FLUID_INTERP_DEFAULT;
  67.   chan->tuning_bank = 0;
  68.   chan->tuning_prog = 0;
  69.   chan->nrpn_select = 0;
  70.   chan->nrpn_active = 0;
  71.   if (chan->tuning)
  72.   {
  73.     event = fluid_event_queue_get_inptr (chan->synth->return_queue);
  74.     if (event)
  75.     {
  76.       event->type = FLUID_EVENT_QUEUE_ELEM_UNREF_TUNING;
  77.       event->unref_tuning.tuning = chan->tuning;
  78.       event->unref_tuning.count = 1;
  79.       fluid_event_queue_next_inptr (chan->synth->return_queue);
  80.     }
  81.     else
  82.     { /* Just unref it in synthesis thread if queue is full */
  83.       fluid_tuning_unref (chan->tuning, 1);
  84.       FLUID_LOG (FLUID_ERR, "Synth return event queue full");
  85.     }
  86.     chan->tuning = NULL;
  87.   }
  88. }
  89. /*
  90.   @param is_all_ctrl_off if nonzero, only resets some controllers, according to 
  91.   http://www.midi.org/techspecs/rp15.php 
  92. */
  93. void
  94. fluid_channel_init_ctrl(fluid_channel_t* chan, int is_all_ctrl_off)
  95. {
  96.   int i;
  97.   chan->key_pressure = 0;
  98.   chan->channel_pressure = 0;
  99.   chan->pitch_bend = 0x2000; /* Range is 0x4000, pitch bend wheel starts in centered position */
  100.   for (i = 0; i < GEN_LAST; i++) {
  101.     chan->gen[i] = 0.0f;
  102.     chan->gen_abs[i] = 0;
  103.   }
  104.   if (is_all_ctrl_off) {
  105.     for (i = 0; i < ALL_SOUND_OFF; i++) {
  106.       if (i >= EFFECTS_DEPTH1 && i <= EFFECTS_DEPTH5) {
  107.         continue;
  108.       }
  109.       if (i >= SOUND_CTRL1 && i <= SOUND_CTRL10) {
  110.         continue;
  111.       }
  112.       if (i == BANK_SELECT_MSB || i == BANK_SELECT_LSB || i == VOLUME_MSB || 
  113.           i == VOLUME_LSB || i == PAN_MSB || i == PAN_LSB) {
  114.         continue;
  115.       }
  116.       fluid_channel_set_cc (chan, i, 0);
  117.     }
  118.   }
  119.   else {
  120.     for (i = 0; i < 128; i++) {
  121.       fluid_channel_set_cc (chan, i, 0);
  122.     }
  123.   }
  124.   /* Set RPN controllers to NULL state */
  125.   fluid_channel_set_cc (chan, RPN_LSB, 127);
  126.   fluid_channel_set_cc (chan, RPN_MSB, 127);
  127.   /* Set NRPN controllers to NULL state */
  128.   fluid_channel_set_cc (chan, NRPN_LSB, 127);
  129.   fluid_channel_set_cc (chan, NRPN_MSB, 127);
  130.   /* Expression (MSB & LSB) */
  131.   fluid_channel_set_cc (chan, EXPRESSION_MSB, 127);
  132.   fluid_channel_set_cc (chan, EXPRESSION_LSB, 127);
  133.   if (!is_all_ctrl_off) {
  134.     chan->pitch_wheel_sensitivity = 2; /* two semi-tones */
  135.     /* Just like panning, a value of 64 indicates no change for sound ctrls */
  136.     for (i = SOUND_CTRL1; i <= SOUND_CTRL10; i++) {
  137.       fluid_channel_set_cc (chan, i, 64);
  138.     }
  139.     /* Volume / initial attenuation (MSB & LSB) */
  140.     fluid_channel_set_cc (chan, VOLUME_MSB, 100);
  141.     fluid_channel_set_cc (chan, VOLUME_LSB, 0);
  142.     /* Pan (MSB & LSB) */
  143.     fluid_channel_set_cc (chan, PAN_MSB, 64);
  144.     fluid_channel_set_cc (chan, PAN_LSB, 0);
  145.     /* Reverb */
  146.     /* fluid_channel_set_cc (chan, EFFECTS_DEPTH1, 40); */
  147.     /* Note: although XG standard specifies the default amount of reverb to 
  148.        be 40, most people preferred having it at zero.
  149.        See http://lists.gnu.org/archive/html/fluid-dev/2009-07/msg00016.html */
  150.   }
  151. }
  152. /* Only called by delete_fluid_synth(), so no need to queue a preset free event */
  153. int
  154. delete_fluid_channel(fluid_channel_t* chan)
  155. {
  156.   if (chan->preset) delete_fluid_preset (chan->preset);
  157.   FLUID_FREE(chan);
  158.   return FLUID_OK;
  159. }
  160. /* FIXME - Calls fluid_channel_init() potentially in synthesis context */
  161. void
  162. fluid_channel_reset(fluid_channel_t* chan)
  163. {
  164.   fluid_channel_init(chan);
  165.   fluid_channel_init_ctrl(chan, 0);
  166. }
  167. /* Should only be called from synthesis context */
  168. int
  169. fluid_channel_set_preset(fluid_channel_t* chan, fluid_preset_t* preset)
  170. {
  171.   fluid_event_queue_elem_t *event;
  172.   fluid_preset_notify (chan->preset, FLUID_PRESET_UNSELECTED, chan->channum);
  173.   /* Set shadow preset again, so it contains the actual latest assigned value */
  174.   fluid_atomic_pointer_set (&chan->shadow_preset, preset);
  175.   if (chan->preset)     /* Queue preset free (shouldn't free() in synth context) */
  176.   {
  177.     event = fluid_event_queue_get_inptr (chan->synth->return_queue);
  178.     if (!event)
  179.     {
  180.       FLUID_LOG (FLUID_ERR, "Synth return event queue full");
  181.       return FLUID_FAILED;
  182.     }
  183.     event->type = FLUID_EVENT_QUEUE_ELEM_FREE_PRESET;
  184.     event->pval = chan->preset;
  185.     fluid_event_queue_next_inptr (chan->synth->return_queue);
  186.   }
  187.   chan->preset = preset;
  188.   fluid_preset_notify (preset, FLUID_PRESET_SELECTED, chan->channum);
  189.   return FLUID_OK;
  190. }
  191. /* Set SoundFont ID, MIDI bank and/or program.  Use -1 to use current value. */
  192. void
  193. fluid_channel_set_sfont_bank_prog(fluid_channel_t* chan, int sfontnum,
  194.                                   int banknum, int prognum)
  195. {
  196.   int oldval, newval, oldmask;
  197.   newval = ((sfontnum != -1) ? sfontnum << SFONT_SHIFTVAL : 0)
  198.     | ((banknum != -1) ? banknum << BANK_SHIFTVAL : 0)
  199.     | ((prognum != -1) ? prognum << PROG_SHIFTVAL : 0);
  200.   oldmask = ((sfontnum != -1) ? 0 : SFONT_MASKVAL)
  201.     | ((banknum != -1) ? 0 : BANK_MASKVAL)
  202.     | ((prognum != -1) ? 0 : PROG_MASKVAL);
  203.   /* Loop until SoundFont, bank and program integer is atomically assigned */
  204.   do
  205.   {
  206.     oldval = fluid_atomic_int_get (&chan->sfont_bank_prog);
  207.     newval = (newval & ~oldmask) | (oldval & oldmask);
  208.   }
  209.   while (newval != oldval
  210.          && !fluid_atomic_int_compare_and_exchange (&chan->sfont_bank_prog,
  211.                                                     oldval, newval));
  212. }
  213. /* Set bank LSB 7 bits */
  214. void
  215. fluid_channel_set_bank_lsb(fluid_channel_t* chan, int banklsb)
  216. {
  217.   int oldval, newval;
  218.   /* Loop until bank LSB is atomically assigned */
  219.   do
  220.   {
  221.     oldval = fluid_atomic_int_get (&chan->sfont_bank_prog);
  222.     newval = (oldval & ~BANKLSB_MASKVAL) | (banklsb << BANK_SHIFTVAL);
  223.   }
  224.   while (newval != oldval
  225.          && !fluid_atomic_int_compare_and_exchange (&chan->sfont_bank_prog,
  226.                                                     oldval, newval));
  227. }
  228. /* Set bank MSB 7 bits */
  229. void
  230. fluid_channel_set_bank_msb(fluid_channel_t* chan, int bankmsb)
  231. {
  232.   int oldval, newval;
  233.   /* Loop until bank MSB is atomically assigned */
  234.   do
  235.   {
  236.     oldval = fluid_atomic_int_get (&chan->sfont_bank_prog);
  237.     newval = (oldval & ~BANKMSB_MASKVAL) | (bankmsb << (BANK_SHIFTVAL + 7));
  238.   }
  239.   while (newval != oldval
  240.          && !fluid_atomic_int_compare_and_exchange (&chan->sfont_bank_prog,
  241.                                                     oldval, newval));
  242. }
  243. /* Get SoundFont ID, MIDI bank and/or program.  Use NULL to ignore a value. */
  244. void
  245. fluid_channel_get_sfont_bank_prog(fluid_channel_t* chan, int *sfont,
  246.                                   int *bank, int *prog)
  247. {
  248.   int sfont_bank_prog;
  249.   sfont_bank_prog = fluid_atomic_int_get (&chan->sfont_bank_prog);
  250.   if (sfont) *sfont = (sfont_bank_prog & SFONT_MASKVAL) >> SFONT_SHIFTVAL;
  251.   if (bank) *bank = (sfont_bank_prog & BANK_MASKVAL) >> BANK_SHIFTVAL;
  252.   if (prog) *prog = (sfont_bank_prog & PROG_MASKVAL) >> PROG_SHIFTVAL;
  253. }