Skip to content

Commit

Permalink
Per-channel ALL_SOUND_OFF when seeking/stopping player (#980)
Browse files Browse the repository at this point in the history
- Only send all sound off on channels which had notes playing
- Send it as ALL_SOUND_OFF CC to a MIDI router to route it to a different synth channel afterwards
  • Loading branch information
albedozero authored Sep 28, 2021
1 parent 9265818 commit 6c59318
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 2 deletions.
32 changes: 30 additions & 2 deletions src/midi/fluid_midi.c
Original file line number Diff line number Diff line change
Expand Up @@ -1604,6 +1604,10 @@ fluid_track_send_events(fluid_track_t *track,
if(player->playback_callback)
{
player->playback_callback(player->playback_userdata, event);
if(event->type == NOTE_ON && event->param2 != 0 && !player->channel_isplaying[event->channel])
{
player->channel_isplaying[event->channel] = TRUE;
}
}
}

Expand Down Expand Up @@ -1787,6 +1791,11 @@ fluid_player_reset(fluid_player_t *player)
}
}

for(i = 0; i < MAX_NUMBER_OF_CHANNELS; i++)
{
player->channel_isplaying[i] = FALSE;
}

/* player->current_file = NULL; */
/* player->status = FLUID_PLAYER_READY; */
/* player->loop = 1; */
Expand Down Expand Up @@ -2080,18 +2089,30 @@ fluid_player_callback(void *data, unsigned int msec)
int i;
int loadnextfile;
int status = FLUID_PLAYER_DONE;
fluid_midi_event_t mute_event;
fluid_player_t *player;
fluid_synth_t *synth;
player = (fluid_player_t *) data;
synth = player->synth;

loadnextfile = player->currentfile == NULL ? 1 : 0;

fluid_midi_event_set_type(&mute_event, CONTROL_CHANGE);
mute_event.param1 = ALL_SOUND_OFF;
mute_event.param2 = 1;

if(fluid_player_get_status(player) != FLUID_PLAYER_PLAYING)
{
if(fluid_atomic_int_get(&player->stopping))
{
fluid_synth_all_notes_off(synth, -1);
for(i = 0; i < synth->midi_channels; i++)
{
if(player->channel_isplaying[i])
{
fluid_midi_event_set_channel(&mute_event, i);
player->playback_callback(player->playback_userdata, &mute_event);
}
}
fluid_atomic_int_set(&player->stopping, 0);
}
return 1;
Expand Down Expand Up @@ -2121,7 +2142,14 @@ fluid_player_callback(void *data, unsigned int msec)
seek_ticks = fluid_atomic_int_get(&player->seek_ticks);
if(seek_ticks >= 0)
{
fluid_synth_all_sounds_off(synth, -1); /* avoid hanging notes */
for(i = 0; i < synth->midi_channels; i++)
{
if(player->channel_isplaying[i])
{
fluid_midi_event_set_channel(&mute_event, i);
player->playback_callback(player->playback_userdata, &mute_event);
}
}
}

for(i = 0; i < player->ntracks; i++)
Expand Down
3 changes: 3 additions & 0 deletions src/midi/fluid_midi.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ fluid_midi_event_t *fluid_midi_parser_parse(fluid_midi_parser_t *parser, unsigne


#define MAX_NUMBER_OF_TRACKS 128
#define MAX_NUMBER_OF_CHANNELS 16

enum fluid_midi_event_type
{
Expand Down Expand Up @@ -325,6 +326,8 @@ struct _fluid_player_t
void *playback_userdata; /* pointer to user-defined data passed to playback_callback function */
handle_midi_tick_func_t tick_callback; /* function fired on each tick change */
void *tick_userdata; /* pointer to user-defined data passed to tick_callback function */

int channel_isplaying[MAX_NUMBER_OF_CHANNELS]; /* flags indicating channels on which notes have played */
};

void fluid_player_settings(fluid_settings_t *settings);
Expand Down

0 comments on commit 6c59318

Please sign in to comment.