diff options
author | Alexey Yakovenko <wakeroid@gmail.com> | 2009-09-16 21:27:08 +0200 |
---|---|---|
committer | Alexey Yakovenko <wakeroid@gmail.com> | 2009-09-16 21:27:08 +0200 |
commit | 6d505b25848c8db7363e54a6902aebc859f53bc7 (patch) | |
tree | ea8bd4b5d748f61c838214de550997d734c95aec /plugins/ffap | |
parent | 743cf8e3a236a18080de2fb9467185d54e60afe4 (diff) |
gapless playback 2nd iteration - sample-accurate seeking on flac and ape
Diffstat (limited to 'plugins/ffap')
-rw-r--r-- | plugins/ffap/ffap.c | 46 |
1 files changed, 41 insertions, 5 deletions
diff --git a/plugins/ffap/ffap.c b/plugins/ffap/ffap.c index 8e7d0748..f995f9b2 100644 --- a/plugins/ffap/ffap.c +++ b/plugins/ffap/ffap.c @@ -38,11 +38,16 @@ #define ENABLE_DEBUG 0 +#define trace(...) { fprintf(stderr, __VA_ARGS__); } +//#define trace(fmt,...) + static DB_decoder_t plugin; static DB_functions_t *deadbeef; -float timestart; -float timeend; +static float timestart; +static float timeend; +static int startsample; +static int endsample; #define PACKET_BUFFER_SIZE 100000 @@ -695,13 +700,18 @@ ffap_init(DB_playItem_t *it) plugin.info.channels = ape_ctx.channels; plugin.info.readpos = 0; if (it->timeend > 0) { + startsample = it->startsample; + endsample = it->endsample; timestart = it->timestart; timeend = it->timeend; - plugin.seek (0); + plugin.seek_sample (0); + trace ("start: %d/%f, end: %d/%f\n", startsample, timestart, endsample, timeend); } else { timestart = 0; timeend = it->duration; + startsample = 0; + endsample = ape_ctx.totalsamples-1; } return 0; } @@ -1632,7 +1642,7 @@ ffap_insert (DB_playItem_t *after, const char *fname) { float duration = ape_ctx.totalsamples / (float)ape_ctx.samplerate; DB_playItem_t *it; - it = deadbeef->pl_insert_cue (after, fname, &plugin, "APE", duration); + it = deadbeef->pl_insert_cue (after, fname, &plugin, "APE", ape_ctx.totalsamples, ape_ctx.samplerate); if (it) { fclose (fp); ape_free_ctx (&ape_ctx); @@ -1707,6 +1717,31 @@ ffap_read_int16 (char *buffer, int size) { } static int +ffap_seek_sample (int sample) { + sample += startsample; + trace ("seeking to %d/%d\n", sample, ape_ctx.totalsamples); + uint32_t newsample = sample; + if (newsample > ape_ctx.totalsamples) { + trace ("eof\n"); + return -1; + } + int nframe = newsample / ape_ctx.blocksperframe; + if (nframe >= ape_ctx.totalframes) { + trace ("eof2\n"); + return -1; + } + ape_ctx.currentframe = nframe; + ape_ctx.samplestoskip = newsample - nframe * ape_ctx.blocksperframe; + + // reset decoder + ape_ctx.packet_remaining = 0; + ape_ctx.samples = 0; + ape_ctx.currentsample = newsample; + plugin.info.readpos = (float)newsample/ape_ctx.samplerate-timestart; + return 0; +} + +static int ffap_seek (float seconds) { seconds += timestart; uint32_t newsample = seconds * plugin.info.samplerate; @@ -1724,7 +1759,7 @@ ffap_seek (float seconds) { ape_ctx.packet_remaining = 0; ape_ctx.samples = 0; ape_ctx.currentsample = newsample; - plugin.info.readpos = seconds - timestart; + plugin.info.readpos = (float)newsample / ape_ctx.samplerate - timestart; return 0; } @@ -1745,6 +1780,7 @@ static DB_decoder_t plugin = { .free = ffap_free, .read_int16 = ffap_read_int16, .seek = ffap_seek, + .seek_sample = ffap_seek_sample, .insert = ffap_insert, .exts = exts, .id = "ffap", |