summaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
authorGravatar Alexey Yakovenko <wakeroid@gmail.com>2009-09-21 21:50:19 +0200
committerGravatar Alexey Yakovenko <wakeroid@gmail.com>2009-09-21 21:50:19 +0200
commit3b873783f1fd9df75154863770d5bb33a573062a (patch)
tree9468355d2338a24f36fa61ab45ae5160bb39d774 /plugins
parent9eb4ecb9651b07cec55d38fa5c45020fa2985187 (diff)
more precise vorbis seeking
Diffstat (limited to 'plugins')
-rw-r--r--plugins/vorbis/vorbis.c52
1 files changed, 30 insertions, 22 deletions
diff --git a/plugins/vorbis/vorbis.c b/plugins/vorbis/vorbis.c
index cb271e69..5a03209a 100644
--- a/plugins/vorbis/vorbis.c
+++ b/plugins/vorbis/vorbis.c
@@ -25,6 +25,12 @@
#endif
#include "../../deadbeef.h"
+#define min(x,y) ((x)<(y)?(x):(y))
+#define max(x,y) ((x)>(y)?(x):(y))
+
+//#define trace(...) { fprintf(stderr, __VA_ARGS__); }
+#define trace(fmt,...)
+
static DB_decoder_t plugin;
static DB_functions_t *deadbeef;
@@ -36,6 +42,7 @@ static float timestart;
static float timeend;
static int startsample;
static int endsample;
+static int currentsample;
static void
cvorbis_free (void);
@@ -63,6 +70,7 @@ cvorbis_init (DB_playItem_t *it) {
plugin.info.channels = vi->channels;
plugin.info.samplerate = vi->rate;
plugin.info.readpos = 0;
+ currentsample = 0;
if (it->timeend > 0) {
timestart = it->timestart;
timeend = it->timeend;
@@ -91,9 +99,13 @@ cvorbis_free (void) {
static int
cvorbis_read (char *bytes, int size) {
- if (plugin.info.readpos >= (timeend - timestart)) {
+ if (currentsample > endsample) {
+ trace ("[1] ogg finished at sample %d (%d)\n", currentsample, ov_pcm_total (&vorbis_file, -1));
return 0;
}
+// if (plugin.info.readpos >= (timeend - timestart)) {
+// return 0;
+// }
int initsize = size;
for (;;)
{
@@ -102,46 +114,36 @@ cvorbis_read (char *bytes, int size) {
#if WORDS_BIGENDIAN
endianess = 1;
#endif
- long ret=ov_read (&vorbis_file, bytes, size, endianess, 2, 1, &cur_bit_stream);
- if (ret < 0)
- {
+ int nmax = endsample - currentsample + 1;
+ nmax *= vi->channels * 2;
+ int sz = min (size, nmax);
+ if (sz == 0) {
+ trace ("[2] ogg finished at sample %d (%d)\n", currentsample, ov_pcm_total (&vorbis_file, -1));
break;
}
- else if (ret == 0) {
+ long ret=ov_read (&vorbis_file, bytes, sz, endianess, 2, 1, &cur_bit_stream);
+ if (ret <= 0)
+ {
+ // error or eof
break;
}
else if (ret < size)
{
+ currentsample += ret / (vi->channels * 2);
size -= ret;
bytes += ret;
}
else {
+ currentsample += ret / (vi->channels * 2);
size = 0;
break;
}
}
plugin.info.readpos = ov_time_tell(&vorbis_file) - timestart;
- if (plugin.info.readpos >= (timeend - timestart)) {
- return 0;
- }
-
return initsize - size;
}
static int
-cvorbis_seek (float time) {
- time += timestart;
- if (!file) {
- return -1;
- }
- int res = ov_time_seek (&vorbis_file, time);
- if (res != 0 && res != OV_ENOSEEK)
- return -1;
- plugin.info.readpos = ov_time_tell(&vorbis_file) - timestart;
- return 0;
-}
-
-static int
cvorbis_seek_sample (int sample) {
if (!file) {
return -1;
@@ -154,10 +156,16 @@ cvorbis_seek_sample (int sample) {
if (tell != sample) {
fprintf (stderr, "oggvorbis: failed to do sample-accurate seek (%d->%d)\n", sample, tell);
}
+ currentsample = sample;
plugin.info.readpos = ov_time_tell(&vorbis_file) - timestart;
return 0;
}
+static int
+cvorbis_seek (float time) {
+ return cvorbis_seek_sample (time * vi->rate);
+}
+
static DB_playItem_t *
cvorbis_insert (DB_playItem_t *after, const char *fname) {
// check for validity