********************************************************************
function: stdio-based convenience library for opening/seeking/decoding
- last mod: $Id: vorbisfile.h,v 1.5 2000/06/14 10:13:35 xiphmont Exp $
+ last mod: $Id: vorbisfile.h,v 1.6 2000/06/15 12:17:03 xiphmont Exp $
********************************************************************/
long current_serialno;
int current_link;
+ double bittrack;
+ double samptrack;
+
ogg_stream_state os; /* take physical pages, weld into a logical
stream of packets */
vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */
char *initial, long ibytes, ov_callbacks callbacks);
extern long ov_bitrate(OggVorbis_File *vf,int i);
+extern long ov_bitrate_instant(OggVorbis_File *vf);
extern long ov_streams(OggVorbis_File *vf);
extern long ov_seekable(OggVorbis_File *vf);
extern long ov_serialnumber(OggVorbis_File *vf,int i);
********************************************************************
function: PCM data vector blocking, windowing and dis/reassembly
- last mod: $Id: block.c,v 1.31 2000/06/14 10:13:35 xiphmont Exp $
+ last mod: $Id: block.c,v 1.32 2000/06/15 12:17:03 xiphmont Exp $
Handle windowing, overlap-add, etc of the PCM vectors. This is made
more amusing by Vorbis' current two allowed block sizes.
return(0);
}
+/* pcm==NULL indicates we just want the pending samples, no more */
int vorbis_synthesis_pcmout(vorbis_dsp_state *v,double ***pcm){
vorbis_info *vi=v->vi;
if(v->pcm_returned<v->centerW){
- int i;
- for(i=0;i<vi->channels;i++)
- v->pcmret[i]=v->pcm[i]+v->pcm_returned;
- *pcm=v->pcmret;
+ if(pcm){
+ int i;
+ for(i=0;i<vi->channels;i++)
+ v->pcmret[i]=v->pcm[i]+v->pcm_returned;
+ *pcm=v->pcmret;
+ }
return(v->centerW-v->pcm_returned);
}
return(0);
********************************************************************
function: stdio-based convenience library for opening/seeking/decoding
- last mod: $Id: vorbisfile.c,v 1.24 2000/06/14 10:13:35 xiphmont Exp $
+ last mod: $Id: vorbisfile.c,v 1.25 2000/06/15 12:17:03 xiphmont Exp $
********************************************************************/
ogg_stream_clear(&vf->os);
vorbis_dsp_clear(&vf->vd);
vorbis_block_clear(&vf->vb);
- vf->pcm_offset=-1;
vf->decode_ready=0;
+
+ vf->bittrack=0.;
+ vf->samptrack=0.;
}
/* fetch and process a packet. Handles the case where we're at a
submit them,
vorbis_synthesis will
reject them */
- vorbis_synthesis_blockin(&vf->vd,&vf->vb);
+
+ /* suck in the synthesis data and track bitrate */
+ {
+ int oldsamples=vorbis_synthesis_pcmout(&vf->vd,NULL);
+ vorbis_synthesis_blockin(&vf->vd,&vf->vb);
+ vf->samptrack+=vorbis_synthesis_pcmout(&vf->vd,NULL)-oldsamples;
+ vf->bittrack+=op.bytes*8;
+ }
/* update the pcm offset. */
if(frameno!=-1 && !op.e_o_s){
int link=(vf->seekable?vf->current_link:0);
- double **dummy;
int i,samples;
/* this packet has a pcm_offset on it (the last packet
to have a reference point. Thus the !op.e_o_s clause
above */
- samples=vorbis_synthesis_pcmout(&vf->vd,&dummy);
+ samples=vorbis_synthesis_pcmout(&vf->vd,NULL);
frameno-=samples;
for(i=0;i<link;i++)
if(!readp)return(0);
if(_get_next_page(vf,&og,-1)<0)return(0); /* 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->decode_ready){
if(vf->current_serialno!=ogg_page_serialno(&og)){
}
}
+/* returns the actual bitrate since last call. returns -1 if no
+ additional data to offer since last call (or at beginning of stream) */
+long ov_bitrate_instant(OggVorbis_File *vf){
+ int link=(vf->seekable?vf->current_link:0);
+ long ret;
+ if(vf->samptrack==0)return(-1);
+ ret=vf->bittrack/vf->samptrack*vf->vi[link].rate+.5;
+ vf->bittrack=0.;
+ vf->samptrack=0.;
+ return(ret);
+}
+
/* Guess */
long ov_serialnumber(OggVorbis_File *vf,int i){
if(i>=vf->links)return(-1);
if(pos<0 || pos>vf->offsets[vf->links])goto seek_error;
/* clear out decoding machine state */
+ vf->pcm_offset=-1;
_decode_clear(vf);
/* seek */
seek_error:
/* dump the machine so we're in a known state */
+ vf->pcm_offset=-1;
_decode_clear(vf);
return -1;
}
seek_error:
/* dump machine so we're in a known state */
+ vf->pcm_offset=-1;
_decode_clear(vf);
return -1;
}
seek_error:
/* dump machine so we're in a known state */
+ vf->pcm_offset=-1;
_decode_clear(vf);
return -1;
}
for(link=vf->links-1;link>=0;link--){
pcm_total-=vf->pcmlengths[link];
time_total-=ov_time_total(vf,link);
- if(vf->pcm_offset>pcm_total)break;
+ if(vf->pcm_offset>=pcm_total)break;
}
}