handle seeking in fluid_track_send_events

This commit is contained in:
loki666 2017-11-02 10:15:53 +01:00
parent 3f1a05cf38
commit 64eda30cf4

View file

@ -1202,6 +1202,13 @@ fluid_track_send_events(fluid_track_t *track,
{
int status = FLUID_OK;
fluid_midi_event_t *event;
int seeking = player->seek_ticks >= 0;
if (seeking) {
ticks = player->seek_ticks; /* update target ticks */
if (track->ticks > ticks)
fluid_track_reset (track); /* reset track if seeking backwards */
}
while (1) {
@ -1228,6 +1235,9 @@ fluid_track_send_events(fluid_track_t *track,
else if (event->type == MIDI_SET_TEMPO) {
fluid_player_set_midi_tempo(player, event->param1);
}
else if (seeking && (event->type == NOTE_ON || event->type == NOTE_OFF)) {
/* skip on/off messages */
}
else {
if (player->playback_callback)
player->playback_callback(player->playback_userdata, event);
@ -1597,67 +1607,6 @@ 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
*/
@ -1682,11 +1631,6 @@ 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)
@ -1702,6 +1646,14 @@ fluid_player_callback(void *data, unsigned int msec)
}
}
if (player->seek_ticks >= 0) {
player->start_ticks = player->seek_ticks; /* tick position of last tempo value (which is now) */
player->cur_ticks = player->seek_ticks;
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->seek_ticks = -1; /* clear seek_ticks */
}
if (status == FLUID_PLAYER_DONE) {
FLUID_LOG(FLUID_DBG, "%s: %d: Duration=%.3f sec", __FILE__,
__LINE__, (msec - player->begin_msec) / 1000.0);