vorbisfile has a flaw where a bad link is not initialized [proper
[platform/upstream/libvorbis.git] / lib / vorbisfile.c
index 983e80c..24011d7 100644 (file)
@@ -11,7 +11,7 @@
  ********************************************************************
 
  function: stdio-based convenience library for opening/seeking/decoding
- last mod: $Id: vorbisfile.c,v 1.69 2003/03/11 23:52:02 xiphmont Exp $
+ last mod: $Id: vorbisfile.c,v 1.73 2003/09/02 04:39:26 xiphmont Exp $
 
  ********************************************************************/
 
@@ -387,18 +387,20 @@ static void _prefetch_all_headers(OggVorbis_File *vf, ogg_int64_t dataoffset){
   }
 }
 
-static void _make_decode_ready(OggVorbis_File *vf){
-  if(vf->ready_state!=STREAMSET)return;
+static int _make_decode_ready(OggVorbis_File *vf){
+  if(vf->ready_state!=STREAMSET)return OV_EFAULT;
   if(vf->seekable){
-    vorbis_synthesis_init(&vf->vd,vf->vi+vf->current_link);
+    if(vorbis_synthesis_init(&vf->vd,vf->vi+vf->current_link))
+      return OV_EBADLINK;
   }else{
-    vorbis_synthesis_init(&vf->vd,vf->vi);
+    if(vorbis_synthesis_init(&vf->vd,vf->vi))
+      return OV_EBADLINK;
   }    
   vorbis_block_init(&vf->vd,&vf->vb);
   vf->ready_state=INITSET;
   vf->bittrack=0.f;
   vf->samptrack=0.f;
-  return;
+  return 0;
 }
 
 static int _open_seekable2(OggVorbis_File *vf){
@@ -611,7 +613,10 @@ static int _fetch_and_process_packet(OggVorbis_File *vf,
        }
       }
       
-      _make_decode_ready(vf);
+      {
+       int ret=_make_decode_ready(vf);
+       if(ret<0)return ret;
+      }
     }
     ogg_stream_pagein(&vf->os,&og);
   }
@@ -660,7 +665,7 @@ static int _ov_open1(void *f,OggVorbis_File *vf,char *initial,
   if((ret=_fetch_headers(vf,vf->vi,vf->vc,&vf->current_serialno,NULL))<0){
     vf->datasource=NULL;
     ov_clear(vf);
-  }else if(vf->ready_state < PARTOPEN)
+  }else 
     vf->ready_state=PARTOPEN;
   return(ret);
 }
@@ -735,7 +740,35 @@ int ov_open(FILE *f,OggVorbis_File *vf,char *initial,long ibytes){
 
   return ov_open_callbacks((void *)f, vf, initial, ibytes, callbacks);
 }
+/* cheap hack for game usage where downsampling is desirable; there's
+   no need for SRC as we can just do it cheaply in libvorbis. */
+int ov_halfrate(OggVorbis_File *vf,int flag){
+  int i;
+  if(vf->vi==NULL)return OV_EINVAL;
+  if(!vf->seekable)return OV_EINVAL;
+  if(vf->ready_state>=STREAMSET)
+    _decode_clear(vf); /* clear out stream state; later on libvorbis
+                          will be able to swap this on the fly, but
+                          for now dumping the decode machine is needed
+                          to reinit the MDCT lookups.  1.1 libvorbis
+                          is planned to be able to switch on the fly */
   
+  for(i=0;i<vf->links;i++){
+    if(vorbis_synthesis_halfrate(vf->vi+i,flag)){
+      ov_halfrate(vf,0);
+      return OV_EINVAL;
+    }
+  }
+  return 0;
+}
+
+int ov_halfrate_p(OggVorbis_File *vf){
+  if(vf->vi==NULL)return OV_EINVAL;
+  return vorbis_synthesis_halfrate_p(vf->vi);
+}
+
 /* Only partially open the vorbis file; test for Vorbisness, and load
    the headers for the first chain.  Do not seek (although test for
    seekability).  Use ov_test_open to finish opening the file, else
@@ -1230,7 +1263,7 @@ int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos){
   int thisblock,lastblock=0;
   int ret=ov_pcm_seek_page(vf,pos);
   if(ret<0)return(ret);
-  _make_decode_ready(vf);
+  if((ret=_make_decode_ready(vf)))return ret;
 
   /* discard leading packets we don't need for the lapping of the
      position we want; don't decode them */
@@ -1290,7 +1323,8 @@ int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos){
        
        ogg_stream_reset_serialno(&vf->os,vf->current_serialno); 
        vf->ready_state=STREAMSET;      
-       _make_decode_ready(vf);
+       ret=_make_decode_ready(vf);
+       if(ret)return ret;
        lastblock=0;
       }
 
@@ -1663,6 +1697,8 @@ long ov_read_float(OggVorbis_File *vf,float ***pcm_channels,int length,
 }
 
 extern float *vorbis_window(vorbis_dsp_state *v,int W);
+extern void _analysis_output_always(char *base,int i,float *v,int n,int bark,int dB,
+                            ogg_int64_t off);
 
 static void _ov_splice(float **pcm,float **lappcm,
                       int n1, int n2,
@@ -1681,6 +1717,7 @@ static void _ov_splice(float **pcm,float **lappcm,
   for(j=0;j<ch1 && j<ch2;j++){
     float *s=lappcm[j];
     float *d=pcm[j];
+
     for(i=0;i<n;i++){
       float wd=w[i]*w[i];
       float ws=1.-wd;
@@ -1695,6 +1732,7 @@ static void _ov_splice(float **pcm,float **lappcm,
       d[i]=d[i]*wd;
     }
   }
+
 }
                
 /* make sure vf is INITSET */
@@ -1756,11 +1794,16 @@ static void _ov_getlap(OggVorbis_File *vf,vorbis_info *vi,vorbis_dsp_state *vd,
        postextrapolation buffering, or the second half of the MDCT
        from the last packet */
     int samples=vorbis_synthesis_lapout(&vf->vd,&pcm);
-    if(samples>lapsize-lapcount)samples=lapsize-lapcount;
-    for(i=0;i<vi->channels;i++)
-      memcpy(lappcm[i]+lapcount,pcm[i],sizeof(**pcm)*samples);
-    lapcount+=samples;
-
+    if(samples==0){
+      for(i=0;i<vi->channels;i++)
+       memset(lappcm[i]+lapcount,0,sizeof(**pcm)*lapsize-lapcount);
+      lapcount=lapsize;
+    }else{
+      if(samples>lapsize-lapcount)samples=lapsize-lapcount;
+      for(i=0;i<vi->channels;i++)
+       memcpy(lappcm[i]+lapcount,pcm[i],sizeof(**pcm)*samples);
+      lapcount+=samples;
+    }
   }
 }
 
@@ -1771,7 +1814,7 @@ int ov_crosslap(OggVorbis_File *vf1, OggVorbis_File *vf2){
   float **lappcm;
   float **pcm;
   float *w1,*w2;
-  int n1,n2,i,ret;
+  int n1,n2,i,ret,hs1,hs2;
 
   if(vf1==vf2)return(0); /* degenerate case */
   if(vf1->ready_state<OPENED)return(OV_EINVAL);
@@ -1788,10 +1831,12 @@ int ov_crosslap(OggVorbis_File *vf1, OggVorbis_File *vf2){
 
   vi1=ov_info(vf1,-1);
   vi2=ov_info(vf2,-1);
-  
+  hs1=ov_halfrate_p(vf1);
+  hs2=ov_halfrate_p(vf2);
+
   lappcm=alloca(sizeof(*lappcm)*vi1->channels);
-  n1=vorbis_info_blocksize(vi1,0)/2;
-  n2=vorbis_info_blocksize(vi2,0)/2;
+  n1=vorbis_info_blocksize(vi1,0)>>(1+hs1);
+  n2=vorbis_info_blocksize(vi2,0)>>(1+hs2);
   w1=vorbis_window(&vf1->vd,0);
   w2=vorbis_window(&vf2->vd,0);
 
@@ -1804,6 +1849,8 @@ int ov_crosslap(OggVorbis_File *vf1, OggVorbis_File *vf2){
      buffer of vf2 */
   /* consolidate and expose the buffer. */
   vorbis_synthesis_lapout(&vf2->vd,&pcm);
+  _analysis_output_always("pcmL",0,pcm[0],n1*2,0,0,0);
+  _analysis_output_always("pcmR",0,pcm[1],n1*2,0,0,0);
 
   /* splice */
   _ov_splice(pcm,lappcm,n1,n2,vi1->channels,vi2->channels,w1,w2);
@@ -1818,16 +1865,17 @@ static int _ov_64_seek_lap(OggVorbis_File *vf,ogg_int64_t pos,
   float **lappcm;
   float **pcm;
   float *w1,*w2;
-  int n1,n2,ch1,ch2;
+  int n1,n2,ch1,ch2,hs;
   int i,ret;
 
   if(vf->ready_state<OPENED)return(OV_EINVAL);
   ret=_ov_initset(vf);
   if(ret)return(ret);
   vi=ov_info(vf,-1);
+  hs=ov_halfrate_p(vf);
   
   ch1=vi->channels;
-  n1=vorbis_info_blocksize(vi,0)/2;
+  n1=vorbis_info_blocksize(vi,0)>>(1+hs);
   w1=vorbis_window(&vf->vd,0);  /* window arrays from libvorbis are
                                   persistent; even if the decode state
                                   from this link gets dumped, this
@@ -1847,7 +1895,7 @@ static int _ov_64_seek_lap(OggVorbis_File *vf,ogg_int64_t pos,
  /* Guard against cross-link changes; they're perfectly legal */
   vi=ov_info(vf,-1);
   ch2=vi->channels;
-  n2=vorbis_info_blocksize(vi,0)/2;
+  n2=vorbis_info_blocksize(vi,0)>>(1+hs);
   w2=vorbis_window(&vf->vd,0);
 
   /* consolidate and expose the buffer. */
@@ -1878,16 +1926,17 @@ static int _ov_d_seek_lap(OggVorbis_File *vf,double pos,
   float **lappcm;
   float **pcm;
   float *w1,*w2;
-  int n1,n2,ch1,ch2;
+  int n1,n2,ch1,ch2,hs;
   int i,ret;
 
   if(vf->ready_state<OPENED)return(OV_EINVAL);
   ret=_ov_initset(vf);
   if(ret)return(ret);
   vi=ov_info(vf,-1);
-  
+  hs=ov_halfrate_p(vf);
+
   ch1=vi->channels;
-  n1=vorbis_info_blocksize(vi,0)/2;
+  n1=vorbis_info_blocksize(vi,0)>>(1+hs);
   w1=vorbis_window(&vf->vd,0);  /* window arrays from libvorbis are
                                   persistent; even if the decode state
                                   from this link gets dumped, this
@@ -1907,7 +1956,7 @@ static int _ov_d_seek_lap(OggVorbis_File *vf,double pos,
  /* Guard against cross-link changes; they're perfectly legal */
   vi=ov_info(vf,-1);
   ch2=vi->channels;
-  n2=vorbis_info_blocksize(vi,0)/2;
+  n2=vorbis_info_blocksize(vi,0)>>(1+hs);
   w2=vorbis_window(&vf->vd,0);
 
   /* consolidate and expose the buffer. */