summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--vorbisfile.c35
1 files changed, 33 insertions, 2 deletions
diff --git a/vorbisfile.c b/vorbisfile.c
index 7594c85..bc4b153 100644
--- a/vorbisfile.c
+++ b/vorbisfile.c
@@ -1352,6 +1352,36 @@ int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){
return OV_EBADLINK;
}
+/* rescales the number x from the range of [0,from] to [0,to]
+ x is in the range [0,from]
+ from, to are in the range [1, 1<<62-1] */
+ogg_int64_t rescale64(ogg_int64_t x, ogg_int64_t from, ogg_int64_t to){
+ ogg_int64_t frac=0;
+ ogg_int64_t ret=0;
+ int i;
+ if(x >= from) return to;
+ if(x <= 0) return 0;
+
+ for(i=0;i<64;i++){
+ if(x>=from){
+ frac|=1;
+ x-=from;
+ }
+ x<<=1;
+ frac<<=1;
+ }
+
+ for(i=0;i<64;i++){
+ if(frac & 1){
+ ret+=to;
+ }
+ frac>>=1;
+ ret>>=1;
+ }
+
+ return ret;
+}
+
/* Page granularity seek (faster than sample granularity because we
don't do the last bit of decode to find a specific sample).
@@ -1397,8 +1427,9 @@ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
bisect=begin;
}else{
/* take a (pretty decent) guess. */
- bisect=begin +
- (target-begintime)*(end-begin)/(endtime-begintime) - CHUNKSIZE;
+ bisect=begin + rescale64(target-begintime,
+ endtime-begintime,
+ end-begin) - CHUNKSIZE;
if(bisect<begin+CHUNKSIZE)
bisect=begin;
}