fluid_seqbind.c
上传用户:tjmskj2
上传日期:2020-08-17
资源大小:577k
文件大小:9k
- /* FluidSynth - A Software Synthesizer
- *
- * Copyright (C) 2003 Peter Hanappe and others.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public License
- * as published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- * 02111-1307, USA
- */
- /*
- 2002 : API design by Peter Hanappe and Antoine Schmitt
- August 2002 : Implementation by Antoine Schmitt as@gratin.org
- as part of the infiniteCD author project
- http://www.infiniteCD.org/
- */
- #include "fluidsynth_priv.h"
- #include "fluid_synth.h"
- #include "fluid_midi.h"
- #include "fluid_event_priv.h"
- /***************************************************************
- *
- * SEQUENCER BINDING
- */
- struct _fluid_seqbind_t {
- fluid_synth_t* synth;
- fluid_sequencer_t* seq;
- fluid_sample_timer_t* sample_timer;
- short client_id;
- };
- typedef struct _fluid_seqbind_t fluid_seqbind_t;
- int fluid_seqbind_timer_callback(void* data, unsigned int msec);
- void fluid_seq_fluidsynth_callback(unsigned int time, fluid_event_t* event, fluid_sequencer_t* seq, void* data);
- /* Proper cleanup of the seqbind struct. */
- void
- delete_fluid_seqbind(fluid_seqbind_t* seqbind)
- {
- if (seqbind == NULL) {
- return;
- }
- if ((seqbind->client_id != -1) && (seqbind->seq != NULL)) {
- fluid_sequencer_unregister_client(seqbind->seq, seqbind->client_id);
- seqbind->client_id = -1;
- }
- if ((seqbind->sample_timer != NULL) && (seqbind->synth != NULL)) {
- delete_fluid_sample_timer(seqbind->synth, seqbind->sample_timer);
- seqbind->sample_timer = NULL;
- }
- FLUID_FREE(seqbind);
- }
- /**
- * Registers a synthesizer as a destination client of the given sequencer.
- * The a synth is registered with the name "fluidsynth".
- * @param seq Sequencer instance
- * @param synth Synthesizer instance
- * @returns Sequencer client ID, or #FLUID_FAILED on error.
- */
- short
- fluid_sequencer_register_fluidsynth (fluid_sequencer_t* seq, fluid_synth_t* synth)
- {
- fluid_seqbind_t* seqbind;
-
- seqbind = FLUID_NEW(fluid_seqbind_t);
- if (seqbind == NULL) {
- fluid_log(FLUID_PANIC, "sequencer: Out of memoryn");
- return FLUID_FAILED;
- }
- seqbind->synth = synth;
- seqbind->seq = seq;
- seqbind->sample_timer = NULL;
- seqbind->client_id = -1;
- /* set up the sample timer */
- if (!fluid_sequencer_get_use_system_timer(seq)) {
- seqbind->sample_timer =
- new_fluid_sample_timer(synth, fluid_seqbind_timer_callback, (void *) seqbind);
- if (seqbind->sample_timer == NULL) {
- fluid_log(FLUID_PANIC, "sequencer: Out of memoryn");
- delete_fluid_seqbind(seqbind);
- return FLUID_FAILED;
- }
- }
- /* register fluidsynth itself */
- seqbind->client_id =
- fluid_sequencer_register_client(seq, "fluidsynth", fluid_seq_fluidsynth_callback, (void *)seqbind);
- if (seqbind->client_id == -1) {
- delete_fluid_seqbind(seqbind);
- return FLUID_FAILED;
- }
- return seqbind->client_id;
- }
- /* Callback for sample timer */
- int
- fluid_seqbind_timer_callback(void* data, unsigned int msec)
- {
- fluid_seqbind_t* seqbind = (fluid_seqbind_t *) data;
- fluid_sequencer_process(seqbind->seq, msec);
- return 1;
- }
- /* Callback for midi events */
- void
- fluid_seq_fluidsynth_callback(unsigned int time, fluid_event_t* evt, fluid_sequencer_t* seq, void* data)
- {
- fluid_synth_t* synth;
- fluid_seqbind_t* seqbind = (fluid_seqbind_t *) data;
- synth = seqbind->synth;
- switch (fluid_event_get_type(evt)) {
- case FLUID_SEQ_NOTEON:
- fluid_synth_noteon(synth, fluid_event_get_channel(evt), fluid_event_get_key(evt), fluid_event_get_velocity(evt));
- break;
- case FLUID_SEQ_NOTEOFF:
- fluid_synth_noteoff(synth, fluid_event_get_channel(evt), fluid_event_get_key(evt));
- break;
- case FLUID_SEQ_NOTE:
- {
- unsigned int dur;
- fluid_synth_noteon(synth, fluid_event_get_channel(evt), fluid_event_get_key(evt), fluid_event_get_velocity(evt));
- dur = fluid_event_get_duration(evt);
- fluid_event_noteoff(evt, fluid_event_get_channel(evt), fluid_event_get_key(evt));
- fluid_sequencer_send_at(seq, evt, dur, 0);
- }
- break;
- case FLUID_SEQ_ALLSOUNDSOFF:
- /* NYI */
- break;
- case FLUID_SEQ_ALLNOTESOFF:
- fluid_synth_cc(synth, fluid_event_get_channel(evt), 0x7B, 0);
- break;
- case FLUID_SEQ_BANKSELECT:
- fluid_synth_bank_select(synth, fluid_event_get_channel(evt), fluid_event_get_bank(evt));
- break;
- case FLUID_SEQ_PROGRAMCHANGE:
- fluid_synth_program_change(synth, fluid_event_get_channel(evt), fluid_event_get_program(evt));
- break;
- case FLUID_SEQ_PROGRAMSELECT:
- fluid_synth_program_select(synth, fluid_event_get_channel(evt), fluid_event_get_sfont_id(evt),
- fluid_event_get_bank(evt), fluid_event_get_program(evt));
- break;
- case FLUID_SEQ_ANYCONTROLCHANGE:
- /* nothing = only used by remove_events */
- break;
- case FLUID_SEQ_PITCHBEND:
- fluid_synth_pitch_bend(synth, fluid_event_get_channel(evt), fluid_event_get_pitch(evt));
- break;
- case FLUID_SEQ_PITCHWHHELSENS:
- fluid_synth_pitch_wheel_sens(synth, fluid_event_get_channel(evt), fluid_event_get_value(evt));
- break;
- case FLUID_SEQ_CONTROLCHANGE:
- fluid_synth_cc(synth, fluid_event_get_channel(evt), fluid_event_get_control(evt), fluid_event_get_value(evt));
- break;
- case FLUID_SEQ_MODULATION:
- {
- short ctrl = 0x01; // MODULATION_MSB
- fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt));
- }
- break;
- case FLUID_SEQ_SUSTAIN:
- {
- short ctrl = 0x40; // SUSTAIN_SWITCH
- fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt));
- }
- break;
- case FLUID_SEQ_PAN:
- {
- short ctrl = 0x0A; // PAN_MSB
- fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt));
- }
- break;
- case FLUID_SEQ_VOLUME:
- {
- short ctrl = 0x07; // VOLUME_MSB
- fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt));
- }
- break;
- case FLUID_SEQ_REVERBSEND:
- {
- short ctrl = 0x5B; // EFFECTS_DEPTH1
- fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt));
- }
- break;
- case FLUID_SEQ_CHORUSSEND:
- {
- short ctrl = 0x5D; // EFFECTS_DEPTH3
- fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt));
- }
- break;
- case FLUID_SEQ_CHANNELPRESSURE:
- {
- fluid_synth_channel_pressure(synth, fluid_event_get_channel(evt), fluid_event_get_value(evt));
- }
- break;
- case FLUID_SEQ_SYSTEMRESET:
- {
- fluid_synth_system_reset(synth);
- }
- break;
- case FLUID_SEQ_UNREGISTERING: /* free ourselves */
- {
- seqbind->client_id = -1; /* avoid recursive call to fluid_sequencer_unregister_client */
- delete_fluid_seqbind(seqbind);
- }
- break;
- case FLUID_SEQ_TIMER:
- /* nothing in fluidsynth */
- break;
- default:
- break;
- }
- }
- static int get_fluidsynth_dest(fluid_sequencer_t* seq)
- {
- int i, id;
- char* name;
- int j = fluid_sequencer_count_clients(seq);
- for (i = 0; i < j; i++) {
- id = fluid_sequencer_get_client_id(seq, i);
- name = fluid_sequencer_get_client_name(seq, id);
- if (strcmp(name, "fluidsynth") == 0) {
- return id;
- }
- }
- return -1;
- }
- /**
- * Transforms an incoming midi event (from a midi driver or midi router) to a
- * sequencer event and adds it to the sequencer queue for sending as soon as possible.
- * @param data The sequencer, must be a valid #fluid_sequencer_t
- * @param event MIDI event
- * @return #FLUID_OK or #FLUID_FAILED
- * @since 1.1.0
- */
- int
- fluid_sequencer_add_midi_event_to_buffer(void* data, fluid_midi_event_t* event)
- {
- fluid_event_t evt;
- fluid_sequencer_t* seq = (fluid_sequencer_t*) data;
- int chan = fluid_midi_event_get_channel(event);
- fluid_event_clear(&evt);
- fluid_event_set_time(&evt, fluid_sequencer_get_tick(seq));
- fluid_event_set_dest(&evt, get_fluidsynth_dest(seq));
- switch (fluid_midi_event_get_type(event)) {
- case NOTE_OFF:
- fluid_event_noteoff(&evt, chan, fluid_midi_event_get_key(event));
- break;
- case NOTE_ON:
- fluid_event_noteon(&evt, fluid_midi_event_get_channel(event),
- fluid_midi_event_get_key(event), fluid_midi_event_get_velocity(event));
- break;
- case CONTROL_CHANGE:
- fluid_event_control_change(&evt, chan, fluid_midi_event_get_control(event),
- fluid_midi_event_get_value(event));
- break;
- case PROGRAM_CHANGE:
- fluid_event_program_change(&evt, chan, fluid_midi_event_get_program(event));
- break;
- case PITCH_BEND:
- fluid_event_pitch_bend(&evt, chan, fluid_midi_event_get_pitch(event));
- break;
- case CHANNEL_PRESSURE:
- fluid_event_channel_pressure(&evt, chan, fluid_midi_event_get_program(event));
- break;
- case MIDI_SYSTEM_RESET:
- fluid_event_system_reset(&evt);
- break;
- default: /* Not yet implemented */
- return FLUID_FAILED;
- }
- /* Schedule for sending at next call to fluid_sequencer_process */
- return fluid_sequencer_send_at(seq, &evt, 0, 0);
- }