fluid_seqbind.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. /*
  21.  2002 : API design by Peter Hanappe and Antoine Schmitt
  22.  August 2002 : Implementation by Antoine Schmitt as@gratin.org
  23.                as part of the infiniteCD author project
  24.                http://www.infiniteCD.org/
  25. */
  26. #include "fluidsynth_priv.h"
  27. #include "fluid_synth.h"
  28. #include "fluid_midi.h"
  29. #include "fluid_event_priv.h"
  30.  /***************************************************************
  31.  *
  32.  *                           SEQUENCER BINDING
  33.  */
  34. struct _fluid_seqbind_t {
  35. fluid_synth_t* synth;
  36. fluid_sequencer_t* seq;
  37. fluid_sample_timer_t* sample_timer;
  38. short client_id;
  39. };
  40. typedef struct _fluid_seqbind_t fluid_seqbind_t;
  41. int fluid_seqbind_timer_callback(void* data, unsigned int msec);
  42. void fluid_seq_fluidsynth_callback(unsigned int time, fluid_event_t* event, fluid_sequencer_t* seq, void* data);
  43. /* Proper cleanup of the seqbind struct. */
  44. void 
  45. delete_fluid_seqbind(fluid_seqbind_t* seqbind) 
  46. {
  47. if (seqbind == NULL) {
  48. return;
  49. }
  50. if ((seqbind->client_id != -1) && (seqbind->seq != NULL)) {
  51. fluid_sequencer_unregister_client(seqbind->seq, seqbind->client_id);
  52. seqbind->client_id = -1;
  53. }
  54. if ((seqbind->sample_timer != NULL) && (seqbind->synth != NULL)) {
  55. delete_fluid_sample_timer(seqbind->synth, seqbind->sample_timer);
  56. seqbind->sample_timer = NULL;
  57. }
  58. FLUID_FREE(seqbind);
  59. }
  60. /** 
  61.  * Registers a synthesizer as a destination client of the given sequencer.
  62.  * The a synth is registered with the name "fluidsynth".
  63.  * @param seq Sequencer instance
  64.  * @param synth Synthesizer instance
  65.  * @returns Sequencer client ID, or #FLUID_FAILED on error.
  66.  */
  67. short 
  68. fluid_sequencer_register_fluidsynth (fluid_sequencer_t* seq, fluid_synth_t* synth)
  69. {
  70. fluid_seqbind_t* seqbind;
  71. seqbind = FLUID_NEW(fluid_seqbind_t);
  72. if (seqbind == NULL) {
  73. fluid_log(FLUID_PANIC, "sequencer: Out of memoryn");
  74. return FLUID_FAILED;
  75. }
  76. seqbind->synth = synth;
  77. seqbind->seq = seq;
  78. seqbind->sample_timer = NULL;
  79. seqbind->client_id = -1;
  80. /* set up the sample timer */
  81. if (!fluid_sequencer_get_use_system_timer(seq)) {
  82. seqbind->sample_timer = 
  83. new_fluid_sample_timer(synth, fluid_seqbind_timer_callback, (void *) seqbind);
  84. if (seqbind->sample_timer == NULL) {
  85. fluid_log(FLUID_PANIC, "sequencer: Out of memoryn");
  86. delete_fluid_seqbind(seqbind);
  87. return FLUID_FAILED;
  88. }
  89. }
  90. /* register fluidsynth itself */
  91. seqbind->client_id = 
  92. fluid_sequencer_register_client(seq, "fluidsynth", fluid_seq_fluidsynth_callback, (void *)seqbind);
  93. if (seqbind->client_id == -1) {
  94. delete_fluid_seqbind(seqbind);
  95. return FLUID_FAILED;
  96. }
  97. return seqbind->client_id;
  98. }
  99. /* Callback for sample timer */
  100. int
  101. fluid_seqbind_timer_callback(void* data, unsigned int msec)
  102. {
  103. fluid_seqbind_t* seqbind = (fluid_seqbind_t *) data;
  104. fluid_sequencer_process(seqbind->seq, msec);
  105. return 1;
  106. }
  107. /* Callback for midi events */
  108. void 
  109. fluid_seq_fluidsynth_callback(unsigned int time, fluid_event_t* evt, fluid_sequencer_t* seq, void* data)
  110. {
  111. fluid_synth_t* synth;
  112. fluid_seqbind_t* seqbind = (fluid_seqbind_t *) data;
  113. synth = seqbind->synth;
  114.   switch (fluid_event_get_type(evt)) {
  115.   case FLUID_SEQ_NOTEON:
  116.    fluid_synth_noteon(synth, fluid_event_get_channel(evt), fluid_event_get_key(evt), fluid_event_get_velocity(evt));
  117.    break;
  118.   case FLUID_SEQ_NOTEOFF:
  119.    fluid_synth_noteoff(synth, fluid_event_get_channel(evt), fluid_event_get_key(evt));
  120.    break;
  121.   case FLUID_SEQ_NOTE:
  122.   {
  123.    unsigned int dur;
  124.    fluid_synth_noteon(synth, fluid_event_get_channel(evt), fluid_event_get_key(evt), fluid_event_get_velocity(evt));
  125.    dur = fluid_event_get_duration(evt);
  126.    fluid_event_noteoff(evt, fluid_event_get_channel(evt), fluid_event_get_key(evt));
  127.    fluid_sequencer_send_at(seq, evt, dur, 0);
  128.   }
  129.    break;
  130. case FLUID_SEQ_ALLSOUNDSOFF:
  131. /* NYI */
  132.    break;
  133.   case FLUID_SEQ_ALLNOTESOFF:
  134.    fluid_synth_cc(synth, fluid_event_get_channel(evt), 0x7B, 0);
  135.    break;
  136.   case FLUID_SEQ_BANKSELECT:
  137.    fluid_synth_bank_select(synth, fluid_event_get_channel(evt), fluid_event_get_bank(evt));
  138.    break;
  139.   case FLUID_SEQ_PROGRAMCHANGE:
  140.    fluid_synth_program_change(synth, fluid_event_get_channel(evt), fluid_event_get_program(evt));
  141.    break;
  142.   case FLUID_SEQ_PROGRAMSELECT:
  143.    fluid_synth_program_select(synth, fluid_event_get_channel(evt), fluid_event_get_sfont_id(evt),
  144. fluid_event_get_bank(evt), fluid_event_get_program(evt));
  145.    break;
  146.   case FLUID_SEQ_ANYCONTROLCHANGE:
  147.    /* nothing = only used by remove_events */
  148.    break;
  149.   case FLUID_SEQ_PITCHBEND:
  150.    fluid_synth_pitch_bend(synth, fluid_event_get_channel(evt), fluid_event_get_pitch(evt));
  151.    break;
  152.   case FLUID_SEQ_PITCHWHHELSENS:
  153.    fluid_synth_pitch_wheel_sens(synth, fluid_event_get_channel(evt), fluid_event_get_value(evt));
  154.    break;
  155.   case FLUID_SEQ_CONTROLCHANGE:
  156.  fluid_synth_cc(synth, fluid_event_get_channel(evt), fluid_event_get_control(evt), fluid_event_get_value(evt));
  157.    break;
  158.   case FLUID_SEQ_MODULATION:
  159.   {
  160.    short ctrl = 0x01; // MODULATION_MSB
  161.    fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt));
  162.   }
  163.    break;
  164.   case FLUID_SEQ_SUSTAIN:
  165.   {
  166.    short ctrl = 0x40; // SUSTAIN_SWITCH
  167.    fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt));
  168.   }
  169.    break;
  170.   case FLUID_SEQ_PAN:
  171.   {
  172.    short ctrl = 0x0A; // PAN_MSB
  173.    fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt));
  174.   }
  175.    break;
  176.   case FLUID_SEQ_VOLUME:
  177.   {
  178.    short ctrl = 0x07; // VOLUME_MSB
  179.    fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt));
  180.   }
  181.    break;
  182.   case FLUID_SEQ_REVERBSEND:
  183.   {
  184.    short ctrl = 0x5B; // EFFECTS_DEPTH1
  185.    fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt));
  186.   }
  187.    break;
  188.   case FLUID_SEQ_CHORUSSEND:
  189.   {
  190.    short ctrl = 0x5D; // EFFECTS_DEPTH3
  191.    fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt));
  192.   }
  193.    break;
  194.   case FLUID_SEQ_CHANNELPRESSURE: 
  195.   {
  196. fluid_synth_channel_pressure(synth, fluid_event_get_channel(evt), fluid_event_get_value(evt));
  197.   }
  198. break;
  199.   case FLUID_SEQ_SYSTEMRESET: 
  200.   {
  201. fluid_synth_system_reset(synth);
  202.   }
  203. break;
  204.   case FLUID_SEQ_UNREGISTERING: /* free ourselves */
  205.   {
  206. seqbind->client_id = -1; /* avoid recursive call to fluid_sequencer_unregister_client */
  207.         delete_fluid_seqbind(seqbind);
  208.   }
  209. break;
  210.   case FLUID_SEQ_TIMER:
  211.   /* nothing in fluidsynth */
  212.    break;
  213. default:
  214.    break;
  215. }
  216. }
  217. static int get_fluidsynth_dest(fluid_sequencer_t* seq) 
  218. {
  219. int i, id;
  220. char* name;
  221. int j = fluid_sequencer_count_clients(seq);
  222. for (i = 0; i < j; i++) {
  223. id = fluid_sequencer_get_client_id(seq, i);
  224. name = fluid_sequencer_get_client_name(seq, id);
  225. if (strcmp(name, "fluidsynth") == 0) {
  226. return id;
  227. }
  228. }
  229. return -1;
  230. }
  231. /**
  232.  * Transforms an incoming midi event (from a midi driver or midi router) to a 
  233.  * sequencer event and adds it to the sequencer queue for sending as soon as possible.
  234.  * @param data The sequencer, must be a valid #fluid_sequencer_t
  235.  * @param event MIDI event
  236.  * @return #FLUID_OK or #FLUID_FAILED
  237.  * @since 1.1.0
  238.  */
  239. int
  240. fluid_sequencer_add_midi_event_to_buffer(void* data, fluid_midi_event_t* event)
  241. {
  242. fluid_event_t evt;
  243. fluid_sequencer_t* seq = (fluid_sequencer_t*) data;
  244. int chan = fluid_midi_event_get_channel(event);
  245. fluid_event_clear(&evt);
  246. fluid_event_set_time(&evt, fluid_sequencer_get_tick(seq));
  247. fluid_event_set_dest(&evt, get_fluidsynth_dest(seq));
  248. switch (fluid_midi_event_get_type(event)) {
  249. case NOTE_OFF:
  250. fluid_event_noteoff(&evt, chan, fluid_midi_event_get_key(event));
  251. break;  
  252. case NOTE_ON:
  253. fluid_event_noteon(&evt, fluid_midi_event_get_channel(event),
  254.                    fluid_midi_event_get_key(event), fluid_midi_event_get_velocity(event));
  255. break;  
  256. case CONTROL_CHANGE:
  257. fluid_event_control_change(&evt, chan, fluid_midi_event_get_control(event),
  258.                            fluid_midi_event_get_value(event));
  259. break;
  260. case PROGRAM_CHANGE:
  261. fluid_event_program_change(&evt, chan, fluid_midi_event_get_program(event));
  262. break;
  263. case PITCH_BEND:
  264. fluid_event_pitch_bend(&evt, chan, fluid_midi_event_get_pitch(event));
  265. break;
  266. case CHANNEL_PRESSURE:
  267. fluid_event_channel_pressure(&evt, chan, fluid_midi_event_get_program(event));
  268. break;
  269. case MIDI_SYSTEM_RESET:
  270. fluid_event_system_reset(&evt);
  271. break;
  272. default:  /* Not yet implemented */
  273. return FLUID_FAILED; 
  274. }
  275. /* Schedule for sending at next call to fluid_sequencer_process */
  276. return fluid_sequencer_send_at(seq, &evt, 0, 0);
  277. }