diff --git a/vorbisfile.c b/vorbisfile.c index 7594c856d9e0fde31a20178d8bf4c3699adffe4d..bc4b153ea247e5097b0a1dc10125c5b465b6d36d 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; }