********************************************************************
function: PCM data vector blocking, windowing and dis/reassembly
- last mod: $Id: block.c,v 1.70 2003/03/02 21:32:00 xiphmont Exp $
+ last mod: $Id: block.c,v 1.71 2003/03/04 21:22:11 xiphmont Exp $
Handle windowing, overlap-add, etc of the PCM vectors. This is made
more amusing by Vorbis' current two allowed block sizes.
mdct_init(b->transform[1][0],ci->blocksizes[1]);
/* Vorbis I uses only window type 0 */
- b->window[0]=_vorbis_window(0,ci->blocksizes[0]/2);
- b->window[1]=_vorbis_window(0,ci->blocksizes[1]/2);
+ b->window[0]=_vorbis_window_create(0,ci->blocksizes[0]/2);
+ b->window[1]=_vorbis_window_create(0,ci->blocksizes[1]/2);
if(encp){ /* encode/decode differ here */
return(1);
}
-int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi){
- _vds_shared_init(v,vi,0);
+int vorbis_synthesis_restart(vorbis_dsp_state *v){
+ vorbis_info *vi=v->vi;
+ codec_setup_info *ci;
+
+ if(!v->backend_state)return -1;
+ if(!vi)return -1;
+ ci=vi->codec_setup;
+ if(!ci)return -1;
+ v->centerW=ci->blocksizes[1]/2;
+ v->pcm_current=v->centerW;
+
v->pcm_returned=-1;
v->granulepos=-1;
v->sequence=-1;
+ v->eofflag=0;
((private_state *)(v->backend_state))->sample_count=-1;
return(0);
}
+int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi){
+ _vds_shared_init(v,vi,0);
+ vorbis_synthesis_restart(v);
+
+ return(0);
+}
+
/* Unlike in analysis, the window is only partially applied for each
block. The time domain envelope is not yet handled at the point of
calling (as it relies on the previous block). */
********************************************************************
function: stdio-based convenience library for opening/seeking/decoding
- last mod: $Id: vorbisfile.c,v 1.66 2003/03/02 21:32:00 xiphmont Exp $
+ last mod: $Id: vorbisfile.c,v 1.67 2003/03/04 21:22:11 xiphmont Exp $
********************************************************************/
vf->samptrack=0.f;
}
+/* restart the decoder, but don't clear out machine init */
+static void _decode_restart(OggVorbis_File *vf){
+ vorbis_synthesis_restart(&vf->vd);
+ vf->bittrack=0.f;
+ vf->samptrack=0.f;
+}
+
+
/* fetch and process a packet. Handles the case where we're at a
bitstream boundary and dumps the decoding machine. If the decoding
machine is unloaded, it loads it. It also keeps pcm_offset up to
}
if(vf->ready_state>=OPENED){
+ int ret;
if(!readp)return(0);
- if(_get_next_page(vf,&og,-1)<0)return(OV_EOF); /* eof.
- leave unitialized */
- /* bitrate tracking; add the header's bytes here, the body bytes
- are done by packet above */
+ if((ret=_get_next_page(vf,&og,-1))<0){
+ return(OV_EOF); /* eof.
+ leave unitialized */
+ }
+
+ /* bitrate tracking; add the header's bytes here, the body bytes
+ are done by packet above */
vf->bittrack+=og.header_len*8;
/* has our decoding just traversed a bitstream boundary? */
if(vf->ready_state==INITSET){
if(vf->current_serialno!=ogg_page_serialno(&og)){
- if(!spanp)return(OV_EOF);
+ if(!spanp)
+ return(OV_EOF);
_decode_clear(vf);
int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){
ogg_stream_state work_os;
+ int i;
+ ogg_int64_t count=0;
if(vf->ready_state<OPENED)return(OV_EINVAL);
if(!vf->seekable)
if(pos<0 || pos>vf->end)return(OV_EINVAL);
- /* clear out decoding machine state */
+ /* don't yet clear out decoding machine (if it's initialized), in
+ the case we're in the same link. Restart the decode lapping, and
+ let _fetch_and_process_packet deal with a potential bitstream
+ boundary */
vf->pcm_offset=-1;
- _decode_clear(vf);
+ ogg_stream_reset_serialno(&vf->os,
+ vf->current_serialno); /* must set serialno */
+ _decode_restart(vf);
+ //_decode_clear(vf);
_seek_helper(vf,pos);
int thisblock;
int eosflag;
- ogg_stream_init(&work_os,-1); /* get the memory ready */
+ ogg_stream_init(&work_os,vf->current_serialno); /* get the memory ready */
+ ogg_stream_reset(&work_os); /* eliminate the spurious OV_HOLE
+ return from not necessarily
+ starting from the beginning */
while(1){
- if(vf->ready_state==STREAMSET){
+ if(vf->ready_state>=STREAMSET){
/* snarf/scan a packet if we can */
int result=ogg_stream_packetout(&work_os,&op);
if(result>0){
- if(vf->vi[vf->current_link].codec_setup)
+ if(vf->vi[vf->current_link].codec_setup){
thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op);
+ if(thisblock<0){
+ ogg_stream_packetout(&vf->os,NULL);
+ continue;
+ }
+ }
if(eosflag)
ogg_stream_packetout(&vf->os,NULL);
else
}
/* has our decoding just traversed a bitstream boundary? */
- if(vf->ready_state==STREAMSET)
+ if(vf->ready_state>=STREAMSET)
if(vf->current_serialno!=ogg_page_serialno(&og)){
- _decode_clear(vf); /* clear out stream state */
- ogg_stream_clear(&work_os);
- }
+ _decode_clear(vf); /* clear out stream state */
+ ogg_stream_clear(&work_os);
+ }
if(vf->ready_state<STREAMSET){
int link;
{
ogg_page og;
ogg_packet op;
- /* clear out decoding machine state */
- _decode_clear(vf);
+
/* seek */
_seek_helper(vf,best);
+ vf->pcm_offset=-1;
if(_get_next_page(vf,&og,-1)<0)return(OV_EOF); /* shouldn't happen */
- vf->current_serialno=ogg_page_serialno(&og);
- vf->current_link=link;
+ if(link!=vf->current_link){
+ /* Different link; dump entire decode machine */
+ _decode_clear(vf);
+
+ vf->current_link=link;
+ vf->current_serialno=ogg_page_serialno(&og);
+ vf->ready_state=STREAMSET;
+
+ }else{
+ _decode_restart(vf);
+ }
+
ogg_stream_reset_serialno(&vf->os,vf->current_serialno);
- vf->ready_state=STREAMSET;
ogg_stream_pagein(&vf->os,&og);
/* pull out all but last packet; the one with granulepos */
preceeding page. Keep fetching previous pages until we
get one with a granulepos or without the 'continued' flag
set. Then just use raw_seek for simplicity. */
-
- _decode_clear(vf);
+
+ //_decode_restart(vf);
_seek_helper(vf,best);
-
+
while(1){
result=_get_prev_page(vf,&og);
if(result<0) goto seek_error;
}
}
if(result<0){
- result = OV_EBADPACKET;
- goto seek_error;
- }
+ result = OV_EBADPACKET;
+ goto seek_error;
+ }
if(op.granulepos!=-1){
vf->pcm_offset=op.granulepos-vf->pcmlengths[vf->current_link*2];
if(vf->pcm_offset<0)vf->pcm_offset=0;
int ret=ogg_stream_packetpeek(&vf->os,&op);
if(ret>0){
thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op);
- if(thisblock<0)thisblock=0; /* non audio packet */
+ if(thisblock<0){
+ ogg_stream_packetout(&vf->os,NULL);
+ continue; /* non audio packet */
+ }
if(lastblock)vf->pcm_offset+=(lastblock+thisblock)>>2;
if(vf->pcm_offset+((thisblock+
/* suck in another packet */
{
int ret=_fetch_and_process_packet(vf,NULL,1,1);
- if(ret==OV_EOF)return(0);
- if(ret<=0)return(ret);
+ if(ret==OV_EOF)
+ return(0);
+ if(ret<=0)
+ return(ret);
}
}