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;
       }