static void sendnoteoff(Data *data, int chan, short key, int velocity, unsigned int time) { int fluid_res; if(velocity>127) // not supported by fluidsynth velocity=127; fluid_event_clear(data->event); fluid_event_set_source(data->event, -1); fluid_event_set_dest(data->event, data->synth_seq_ID); fluid_event_noteoff(data->event, chan, key); fluid_res = fluid_sequencer_send_at(data->sequencer, data->event, get_fluidsynth_time(data,time), 1); if(fluid_res==FLUID_FAILED) printf("Unable to send noteOFF %d (vel: %d) at time %d. Time now: %d\n",key,velocity,time,(int)data->time); }
/** * 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); }
/* 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; } }