********************************************************************
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 $
********************************************************************/
}
}
-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){
}
}
- _make_decode_ready(vf);
+ {
+ int ret=_make_decode_ready(vf);
+ if(ret<0)return ret;
+ }
}
ogg_stream_pagein(&vf->os,&og);
}
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);
}
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
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 */
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;
}
}
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,
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;
d[i]=d[i]*wd;
}
}
+
}
/* make sure vf is INITSET */
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;
+ }
}
}
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);
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);
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);
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
/* 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. */
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
/* 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. */