Skip to content

Commit

Permalink
Add support for player.extend-playback to avoid truncating end of audio
Browse files Browse the repository at this point in the history
  • Loading branch information
Topaz committed Sep 20, 2022
1 parent 405a7b4 commit 24a467b
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 8 deletions.
9 changes: 9 additions & 0 deletions doc/fluidsettings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -808,6 +808,15 @@ Developers:
</midi>

<player label="MIDI player settings">
<setting>
<name>extend-playback</name>
<type>int</type>
<def>0</def>
<min>0</min>
<max>2147483647</max>
<realtime/>
<desc>The number of milliseconds by which playback should be extended (to allow for audio to finish instead of abruptly ending after the last MIDI event).</desc>
</setting>
<setting>
<name>reset-synth</name>
<type>bool</type>
Expand Down
12 changes: 11 additions & 1 deletion src/fluidsynth.c
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,7 @@ int main(int argc, char **argv)
int audio_channels = 0;
int dump = 0;
int fast_render = 0;
static const char optchars[] = "a:C:c:dE:f:F:G:g:hijK:L:lm:nO:o:p:QqR:r:sT:Vvz:";
static const char optchars[] = "a:C:c:dE:f:F:G:g:hijK:L:lm:nO:o:p:QqR:r:sT:Vvx:z:";
#ifdef HAVE_LASH
int connect_lash = 1;
int enabled_lash = 0; /* set to TRUE if lash gets enabled */
Expand Down Expand Up @@ -446,6 +446,7 @@ int main(int argc, char **argv)
{"connect-jack-outputs", 0, 0, 'j'},
{"disable-lash", 0, 0, 'l'},
{"dump", 0, 0, 'd'},
{"extend-playback", 1, 0, 'x'},
{"fast-render", 1, 0, 'F'},
{"gain", 1, 0, 'g'},
{"help", 0, 0, 'h'},
Expand Down Expand Up @@ -806,6 +807,13 @@ int main(int argc, char **argv)
fluid_set_log_function(FLUID_DBG, fluid_default_log_function, NULL);
break;

case 'x':
if(fluid_settings_setint(settings, "player.extend-playback", atoi(optarg)) != FLUID_OK)
{
goto cleanup;
}
break;

case 'z':
if(fluid_settings_setint(settings, "audio.period-size", atoi(optarg)) != FLUID_OK)
{
Expand Down Expand Up @@ -1323,6 +1331,8 @@ print_help(fluid_settings_t *settings)
" Print out verbose messages about midi events (synth.verbose=1) as well as other debug messages\n");
printf(" -V, --version\n"
" Show version of program\n");
printf(" -x, --extend-playback=[milliseconds]\n"
" Amount of extra time to wait after last midi event beforep playback ends.\n");
printf(" -z, --audio-bufsize=[size]\n"
" Size of each audio buffer\n");

Expand Down
54 changes: 47 additions & 7 deletions src/midi/fluid_midi.c
Original file line number Diff line number Diff line change
Expand Up @@ -1632,6 +1632,10 @@ fluid_track_send_events(fluid_track_t *track,
*
* fluid_player
*/

/**
* fluid_player_handle_reset_synth
*/
static void
fluid_player_handle_reset_synth(void *data, const char *name, int value)
{
Expand All @@ -1641,6 +1645,18 @@ fluid_player_handle_reset_synth(void *data, const char *name, int value)
player->reset_synth_between_songs = value;
}

/**
* fluid_player_handle_extend_playback
*/
static void
fluid_player_handle_extend_playback(void *data, const char *name, int value)
{
fluid_player_t *player = data;
fluid_return_if_fail(player != NULL);

player->extend_playback = value;
}

/**
* Create a new MIDI player.
* @param synth Fluid synthesizer instance to create player for
Expand Down Expand Up @@ -1687,6 +1703,7 @@ new_fluid_player(fluid_synth_t *synth)
player->deltatime = 4.0;
player->cur_msec = 0;
player->cur_ticks = 0;
player->end_msec = -1;
player->last_callback_ticks = -1;
fluid_atomic_int_set(&player->seek_ticks, -1);
fluid_player_set_playback_callback(player, fluid_synth_handle_midi_event, synth);
Expand Down Expand Up @@ -1716,10 +1733,14 @@ new_fluid_player(fluid_synth_t *synth)

fluid_settings_getint(synth->settings, "player.reset-synth", &i);
fluid_player_handle_reset_synth(player, NULL, i);

fluid_settings_callback_int(synth->settings, "player.reset-synth",
fluid_player_handle_reset_synth, player);

fluid_settings_getint(synth->settings, "player.extend-playback", &i);
fluid_player_handle_extend_playback(player, NULL, i);
fluid_settings_callback_int(synth->settings, "player.extend-playback",
fluid_player_handle_extend_playback, player);

return player;

err:
Expand All @@ -1744,6 +1765,8 @@ delete_fluid_player(fluid_player_t *player)

fluid_settings_callback_int(player->synth->settings, "player.reset-synth",
NULL, NULL);
fluid_settings_callback_int(player->synth->settings, "player.extend-playback",
NULL, NULL);

fluid_player_stop(player);
fluid_player_reset(player);
Expand Down Expand Up @@ -1779,6 +1802,10 @@ fluid_player_settings(fluid_settings_t *settings)

/* Selects whether the player should reset the synth between songs, or not. */
fluid_settings_register_int(settings, "player.reset-synth", 1, 0, 1, FLUID_HINT_TOGGLED);

/* Number of milliseconds by which playback should be extended (to allow
for audio to finish instead of abruptly ending after the last event) */
fluid_settings_register_int(settings, "player.extend-playback", 0, 0, 2147483647, 0);
}


Expand Down Expand Up @@ -2177,6 +2204,17 @@ fluid_player_callback(void *data, unsigned int msec)
fluid_atomic_int_set(&player->seek_ticks, -1); /* clear seek_ticks */
}

/* If playback would end but extend_playback was specified and hasn't already been applied */
if(status == FLUID_PLAYER_DONE && player->extend_playback && player->end_msec < 0)
{
player->end_msec = msec + player->extend_playback;
}
/* If playback is currently extended */
if (player->end_msec >= 0 && msec < (unsigned int) player->end_msec)
{
status = FLUID_PLAYER_PLAYING;
}

if(status == FLUID_PLAYER_DONE)
{
FLUID_LOG(FLUID_DBG, "%s: %d: Duration=%.3f sec", __FILE__,
Expand Down Expand Up @@ -2225,12 +2263,14 @@ fluid_player_play(fluid_player_t *player)
fluid_sample_timer_reset(player->synth, player->sample_timer);
}

/* If we're at the end of the playlist and there are no loops left, loop once */
if(player->currentfile == NULL && player->loop == 0)
{
player->loop = 1;
}

/* If we're at the end of the playlist and there are no loops left, loop once */
if(player->currentfile == NULL && player->loop == 0)
{
player->loop = 1;
}

player->end_msec = -1;

fluid_atomic_int_set(&player->status, FLUID_PLAYER_PLAYING);

return FLUID_OK;
Expand Down
2 changes: 2 additions & 0 deletions src/midi/fluid_midi.h
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,8 @@ struct _fluid_player_t
int begin_msec; /* the time (msec) of the beginning of the file */
int start_msec; /* the start time of the last tempo change */
int cur_msec; /* the current time */
int extend_playback; /* the milliseconds by which to extend playback */
int end_msec; /* when >=0, playback is extended until this time */
/* sync mode: indicates the tempo mode the player is driven by (see fluid_player_set_tempo()):
1, the player is driven by internal tempo (miditempo). This is the default.
0, the player is driven by external tempo (exttempo)
Expand Down

0 comments on commit 24a467b

Please sign in to comment.