diff --git a/include/fluidsynth/seq.h b/include/fluidsynth/seq.h index 35c46eed..2e079754 100644 --- a/include/fluidsynth/seq.h +++ b/include/fluidsynth/seq.h @@ -47,7 +47,7 @@ extern "C" { * @param data User defined data registered with the client * * @note @p time may not be of the same tick value as the scheduled event! In fact, depending on - * the sequencer's scale and the synth's sample-rate, @p time may a few ticks too late. Although this + * the sequencer's scale and the synth's sample-rate, @p time may be a few ticks too late. Although this * itself is inaudible, it is important to consider, * when you use this callback for enqueuing additional events over and over again with * fluid_sequencer_send_at(): If you enqueue new events with a relative tick value you might introduce diff --git a/src/synth/fluid_event.c b/src/synth/fluid_event.c index 3741c65c..ddc6aa8b 100644 --- a/src/synth/fluid_event.c +++ b/src/synth/fluid_event.c @@ -142,10 +142,18 @@ fluid_event_timer(fluid_event_t *evt, void *data) * @param channel MIDI channel number * @param key MIDI note number (0-127) * @param vel MIDI velocity value (0-127) + * @note Since fluidsynth 2.2.2, this function will give you a #FLUID_SEQ_NOTEOFF when + * called with @p vel being zero. */ void fluid_event_noteon(fluid_event_t *evt, int channel, short key, short vel) { + if(vel == 0) + { + fluid_event_noteoff(evt, channel, key); + return; + } + evt->type = FLUID_SEQ_NOTEON; evt->channel = channel; evt->key = key; @@ -176,10 +184,11 @@ fluid_event_noteoff(fluid_event_t *evt, int channel, short key) * @param evt Sequencer event structure * @param channel MIDI channel number * @param key MIDI note number (0-127) - * @param vel MIDI velocity value (0-127) - * @param duration Duration of note in the time scale used by the sequencer (by default milliseconds) + * @param vel MIDI velocity value (1-127) + * @param duration Duration of note in the time scale used by the sequencer * * @note The application should decide whether to use only Notes with duration, or separate NoteOn and NoteOff events. + * @warning Calling this function with @p vel or @p duration being zero results in undefined behavior! */ void fluid_event_note(fluid_event_t *evt, int channel, short key, short vel, unsigned int duration) diff --git a/test/test_seq_evt_order.c b/test/test_seq_evt_order.c index 78150cd5..9bb6c34b 100644 --- a/test/test_seq_evt_order.c +++ b/test/test_seq_evt_order.c @@ -12,7 +12,7 @@ int main(void) fluid_event_set_time(evt1, 1); fluid_event_set_time(evt2, 1); - // double negation below, because we want to check for leftIsBeforeRight, however, event_compare() returns !leftIsBeforeRight + // Note that event_compare() returns !leftIsBeforeRight TEST_ASSERT( !event_compare_for_test(evt1, evt1)); TEST_ASSERT( !event_compare_for_test(evt2, evt2)); @@ -28,12 +28,26 @@ int main(void) TEST_ASSERT(!!event_compare_for_test(evt1, evt2)); TEST_ASSERT( !event_compare_for_test(evt2, evt1)); - fluid_event_noteon(evt1, 0, 0, 0); + fluid_event_noteon(evt1, 0, 0, 60); fluid_event_noteoff(evt2, 0, 0); TEST_ASSERT(!!event_compare_for_test(evt1, evt2)); TEST_ASSERT( !event_compare_for_test(evt2, evt1)); + // make sure noteons with vel=0 are handled like noteoffs + fluid_event_noteon(evt1, 0, 0, 60); + fluid_event_noteon(evt2, 0, 0, 0); + + TEST_ASSERT(!!event_compare_for_test(evt1, evt2)); + TEST_ASSERT( !event_compare_for_test(evt2, evt1)); + + // two noteoffs + fluid_event_noteon(evt1, 0, 0, 0); + fluid_event_noteoff(evt2, 0, 0); + + TEST_ASSERT( !event_compare_for_test(evt1, evt2)); + TEST_ASSERT( !event_compare_for_test(evt2, evt1)); + fluid_event_unregistering(evt1); fluid_event_system_reset(evt2);