mirror of
https://github.com/ZDoom/fluidsynth.git
synced 2024-11-10 06:51:54 +00:00
add seek to player
This commit is contained in:
parent
ad9c185dca
commit
6c8a72fa0a
3 changed files with 85 additions and 1 deletions
|
@ -138,7 +138,8 @@ FLUIDSYNTH_API int fluid_player_get_current_tick(fluid_player_t * player);
|
|||
FLUIDSYNTH_API int fluid_player_get_total_ticks(fluid_player_t * player);
|
||||
FLUIDSYNTH_API int fluid_player_get_bpm(fluid_player_t * player);
|
||||
FLUIDSYNTH_API int fluid_player_get_midi_tempo(fluid_player_t * player);
|
||||
|
||||
FLUIDSYNTH_API int fluid_player_seek(fluid_player_t *player, int ticks);
|
||||
|
||||
///
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -1276,6 +1276,7 @@ new_fluid_player(fluid_synth_t *synth)
|
|||
player->deltatime = 4.0;
|
||||
player->cur_msec = 0;
|
||||
player->cur_ticks = 0;
|
||||
player->seek_ticks = -1;
|
||||
fluid_player_set_playback_callback(player, fluid_synth_handle_midi_event, synth);
|
||||
|
||||
player->use_system_timer = fluid_settings_str_equal(synth->settings,
|
||||
|
@ -1596,6 +1597,66 @@ fluid_player_playlist_load(fluid_player_t *player, unsigned int msec)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Seek to position player->seek_ticks in midi ticks. Should be called from fluid_player_callback.
|
||||
*/
|
||||
void
|
||||
fluid_player_seek_local(fluid_player_t *player, unsigned int msec) {
|
||||
int i, tempo;
|
||||
unsigned int mticks, tempo_ticks, earliest, t;
|
||||
fluid_track_t *track, *active_track;
|
||||
fluid_midi_event_t *event;
|
||||
|
||||
/* the target seek position in midi-ticks */
|
||||
mticks = player->seek_ticks;
|
||||
|
||||
for (i = 0; i < player->ntracks; i++) { /* only reset tracks if seeking backwards */
|
||||
track = player->track[i];
|
||||
if (track != NULL && track->ticks > mticks) fluid_track_reset (track);
|
||||
}
|
||||
tempo = -1; /* if positive, value of the last tempo change before target time */
|
||||
tempo_ticks = 0; /* corresponding time of this tempo change */
|
||||
earliest = 0; /* time value (midi ticks) where the next (earliest) event occurs */
|
||||
while (1) {
|
||||
active_track = NULL; /* find track with the next event in overall time order (ealiest) */
|
||||
for (i = 0; i < player->ntracks; i++) {
|
||||
track = player->track[i];
|
||||
if (track == NULL) continue;
|
||||
event = track->cur;
|
||||
if (event == NULL) continue;
|
||||
t = track->ticks;
|
||||
if (active_track != NULL && t >= earliest) continue; /* event occurs later than (or at same time as) the earliest one */
|
||||
active_track = track; /* remember track where earliest event occurs */
|
||||
earliest = t; /* current earliest time */
|
||||
}
|
||||
if (active_track == NULL) break; /* no more events available */
|
||||
track = active_track;
|
||||
event = track->cur; /* this is the next event in overall time order */
|
||||
if (track->ticks >= mticks) break; /* we are at the right position */
|
||||
|
||||
if (event->type == MIDI_SET_TEMPO && track->ticks >= tempo_ticks) {
|
||||
tempo = event->param1; /* the very last tempo change */
|
||||
tempo_ticks = track->ticks;
|
||||
} else if (event->type == NOTE_ON || event->type == NOTE_OFF) {
|
||||
/* skip on/off messages */
|
||||
} else { /* but process all other events */
|
||||
if (player->playback_callback) /* == fluid_synth_handle_midi_event */
|
||||
player->playback_callback (player->playback_userdata, event); /* playback_userdata == synth instance */
|
||||
}
|
||||
track->ticks += event->dtime; /* move time to the next event in this track */
|
||||
fluid_track_next_event (track); /* move track->cur to point to the next event */
|
||||
}
|
||||
|
||||
if (tempo > 0) {
|
||||
fluid_player_set_midi_tempo (player, tempo);
|
||||
}
|
||||
player->start_ticks = mticks; /* tick position of last tempo value (which is now) */
|
||||
player->cur_ticks = mticks; /* current playback position */
|
||||
player->begin_msec = msec; /* only used to calculate the duration of playing */
|
||||
player->start_msec = msec; /* should be the (synth)-time of the last tempo change */
|
||||
/* player->cur_msec is set after return in fluid_player_callback */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* fluid_player_callback
|
||||
|
@ -1621,6 +1682,11 @@ fluid_player_callback(void *data, unsigned int msec)
|
|||
}
|
||||
}
|
||||
|
||||
if (player->seek_ticks >= 0) { /* seek until player->seek_ticks */
|
||||
fluid_player_seek_local (player, msec);
|
||||
player->seek_ticks = -1;
|
||||
}
|
||||
|
||||
player->cur_msec = msec;
|
||||
player->cur_ticks = (player->start_ticks
|
||||
+ (int) ((double) (player->cur_msec - player->start_msec)
|
||||
|
@ -1715,6 +1781,22 @@ fluid_player_get_status(fluid_player_t *player)
|
|||
return player->status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Seek to position in midi ticks.
|
||||
* @param player MIDI player instance
|
||||
* @param mticks
|
||||
* @return the current position
|
||||
* @since 1.1.8
|
||||
*
|
||||
* The actual seek is performed during the player_callback.
|
||||
*/
|
||||
int fluid_player_seek(fluid_player_t *player, int ticks)
|
||||
{
|
||||
player->seek_ticks = ticks;
|
||||
return player->cur_ticks;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Enable looping of a MIDI player
|
||||
* @param player MIDI player instance
|
||||
|
|
|
@ -296,6 +296,7 @@ struct _fluid_player_t {
|
|||
char send_program_change; /* should we ignore the program changes? */
|
||||
char use_system_timer; /* if zero, use sample timers, otherwise use system clock timer */
|
||||
char reset_synth_between_songs; /* 1 if system reset should be sent to the synth between songs. */
|
||||
int seek_ticks; /* new position in tempo ticks (midi ticks) for seeking */
|
||||
int start_ticks; /* the number of tempo ticks passed at the last tempo change */
|
||||
int cur_ticks; /* the number of tempo ticks passed */
|
||||
int begin_msec; /* the time (msec) of the beginning of the file */
|
||||
|
|
Loading…
Reference in a new issue