********************************************************************
function: illustrate simple use of chained bitstream and vorbisfile.a
- last mod: $Id: chaining_example.c,v 1.4 2000/03/10 13:21:18 xiphmont Exp $
+ last mod: $Id: chaining_example.c,v 1.5 2000/06/14 10:13:35 xiphmont Exp $
********************************************************************/
printf("\t\t%ldHz %d channels bitrate %ldkbps serial number=%ld\n",
vi->rate,vi->channels,ov_bitrate(&ov,i)/1000,
ov_serialnumber(&ov,i));
- printf("\t\tcompressed length: %ld bytes ",ov_raw_total(&ov,i));
+ printf("\t\tcompressed length: %ld bytes ",(long)(ov_raw_total(&ov,i)));
printf(" play time: %lds\n",(long)ov_time_total(&ov,i));
}
********************************************************************
function: simple example decoder
- last mod: $Id: decoder_example.c,v 1.7 2000/05/12 08:38:20 msmith Exp $
+ last mod: $Id: decoder_example.c,v 1.8 2000/06/14 10:13:35 xiphmont Exp $
********************************************************************/
this point */
while(1){
result=ogg_stream_packetout(&os,&op);
+
if(result==0)break; /* need more data */
if(result==-1){ /* missing or corrupt data at this page position */
/* no reason to complain; already complained above */
}
if(clipflag)
- fprintf(stderr,"Clipping in frame %ld\n",vd.sequence);
+ fprintf(stderr,"Clipping in frame %ld\n",(long)(vd.sequence));
fwrite(convbuffer,2*vi.channels,bout,stdout);
********************************************************************
function: libvorbis codec headers
- last mod: $Id: codec.h,v 1.16 2000/06/14 01:38:27 xiphmont Exp $
+ last mod: $Id: codec.h,v 1.17 2000/06/14 10:13:35 xiphmont Exp $
********************************************************************/
int b_o_s; /* set after we've written the initial page
of a logical bitstream */
long serialno;
- long pageno;
- long packetno; /* sequence number for decode; the framing
+ int pageno;
+ int64_t packetno; /* sequence number for decode; the framing
knows where there's a hole in the data,
but we need coupling so that the codec
(which is in a seperate abstraction
long e_o_s;
int64_t frameno;
- long packetno; /* sequence number for decode; the framing
+ int64_t packetno; /* sequence number for decode; the framing
knows where there's a hole in the data,
but we need coupling so that the codec
(which is in a seperate abstraction
long nW;
long centerW;
- long frameno;
- long sequence;
+ int64_t frameno;
+ int64_t sequence;
int64_t glue_bits;
int64_t time_bits;
int mode;
int eofflag;
- int frameno;
- int sequence;
+ int64_t frameno;
+ int64_t sequence;
vorbis_dsp_state *vd; /* For read-only access of configuration */
/* local storage to avoid remallocing; it's up to the mapping to
********************************************************************
function: stdio-based convenience library for opening/seeking/decoding
- last mod: $Id: vorbisfile.h,v 1.4 2000/04/23 15:34:12 msmith Exp $
+ last mod: $Id: vorbisfile.h,v 1.5 2000/06/14 10:13:35 xiphmont Exp $
********************************************************************/
*/
typedef struct {
size_t (*read_func) (void *ptr, size_t size, size_t nmemb, void *datasource);
- int (*seek_func) (void *datasource, long offset, int whence);
+ int (*seek_func) (void *datasource, int64_t offset, int whence);
int (*close_func) (void *datasource);
long (*tell_func) (void *datasource);
} ov_callbacks;
typedef struct {
void *datasource; /* Pointer to a FILE *, etc. */
int seekable;
- long offset;
- long end;
+ int64_t offset;
+ int64_t end;
ogg_sync_state oy;
/* If the FILE handle isn't seekable (eg, a pipe), only the current
stream appears */
int links;
- long *offsets;
- long *dataoffsets;
+ int64_t *offsets;
+ int64_t *dataoffsets;
long *serialnos;
int64_t *pcmlengths;
vorbis_info *vi;
extern long ov_seekable(OggVorbis_File *vf);
extern long ov_serialnumber(OggVorbis_File *vf,int i);
-extern long ov_raw_total(OggVorbis_File *vf,int i);
+extern int64_t ov_raw_total(OggVorbis_File *vf,int i);
extern int64_t ov_pcm_total(OggVorbis_File *vf,int i);
extern double ov_time_total(OggVorbis_File *vf,int i);
extern int ov_pcm_seek(OggVorbis_File *vf,int64_t pos);
extern int ov_time_seek(OggVorbis_File *vf,double pos);
-extern long ov_raw_tell(OggVorbis_File *vf);
+extern int64_t ov_raw_tell(OggVorbis_File *vf);
extern int64_t ov_pcm_tell(OggVorbis_File *vf);
extern double ov_time_tell(OggVorbis_File *vf);
********************************************************************
function: PCM data vector blocking, windowing and dis/reassembly
- last mod: $Id: block.c,v 1.30 2000/05/08 20:49:48 xiphmont Exp $
+ last mod: $Id: block.c,v 1.31 2000/06/14 10:13:35 xiphmont Exp $
Handle windowing, overlap-add, etc of the PCM vectors. This is made
more amusing by Vorbis' current two allowed block sizes.
if(v->centerW>=v->eofflag){
v->eofflag=-1;
vb->eofflag=1;
+ return(1);
}
}
int movementW=centerNext-new_centerNext;
int movementM=movementW/vi->envelopesa;
+
+
/* the multipliers and pcm stay synced up because the blocksize
must be multiples of samples_per_envelope_step (minimum
multiple is 2) */
v->centerW=new_centerNext;
v->sequence++;
- v->frameno+=movementW;
- if(v->eofflag)
+ if(v->eofflag){
v->eofflag-=movementW;
+ /* do not add padding to end of stream! */
+ if(v->centerW>=v->eofflag){
+ v->frameno+=v->eofflag;
+ }else{
+ v->frameno+=movementW;
+ }
+ }else
+ v->frameno+=movementW;
}
/* done */
/* Adjust centerW to allow an easier mechanism for determining output */
v->pcm_returned=v->centerW;
v->centerW-= vi->blocksizes[v->W]/4+vi->blocksizes[v->lW]/4;
+ v->frameno=-1;
+ v->sequence=-1;
+
return(0);
}
v->time_bits+=vb->time_bits;
v->floor_bits+=vb->floor_bits;
v->res_bits+=vb->res_bits;
+
+ if(v->sequence+1 != vb->sequence)v->frameno=-1; /* out of sequence;
+ lose count */
+
v->sequence=vb->sequence;
{
pcm[i]=vb->pcm[j][i];
}
+ /* track the frame number... This is for convenience, but also
+ making sure our last packet doesn't end with added padding. If
+ the last packet is partial, the number of samples we'll have to
+ return will be past the vb->frameno.
+
+ This is not foolproof! It will be confused if we begin
+ decoding at the last page after a seek or hole. In that case,
+ we don't have a starting point to judge where the last frame
+ is. For this reason, vorbisfile will always try to make sure
+ it reads the last two marked pages in proper sequence */
+
+ if(v->frameno==-1)
+ v->frameno=vb->frameno;
+ else{
+ v->frameno+=(centerW-v->centerW);
+ if(vb->frameno!=-1 && v->frameno!=vb->frameno){
+ if(v->frameno>vb->frameno && vb->eofflag){
+ /* partial last frame. Strip the padding off */
+ centerW-=(v->frameno-vb->frameno);
+ }/* else{ Shouldn't happen *unless* the bitstream is out of
+ spec. Either way, believe the bitstream } */
+ v->frameno=vb->frameno;
+ }
+ }
+
/* Update, cleanup */
v->centerW=centerW;
if(vb->eofflag)v->eofflag=1;
}
+
return(0);
}
********************************************************************
function: stdio-based convenience library for opening/seeking/decoding
- last mod: $Id: vorbisfile.c,v 1.23 2000/05/16 11:38:36 msmith Exp $
+ last mod: $Id: vorbisfile.c,v 1.24 2000/06/14 10:13:35 xiphmont Exp $
********************************************************************/
if(searched>=end || ret==-1){
vf->links=m+1;
- vf->offsets=malloc((m+2)*sizeof(long));
+ vf->offsets=malloc((m+2)*sizeof(int64_t));
vf->offsets[m+1]=searched;
}else{
_bisect_forward_serialno(vf,next,vf->offset,
vf->vi=calloc(vf->links,sizeof(vorbis_info));
vf->vc=calloc(vf->links,sizeof(vorbis_info));
- vf->dataoffsets=malloc(vf->links*sizeof(long));
+ vf->dataoffsets=malloc(vf->links*sizeof(int64_t));
vf->pcmlengths=malloc(vf->links*sizeof(int64_t));
vf->serialnos=malloc(vf->links*sizeof(long));
vorbis_synthesis_blockin(&vf->vd,&vf->vb);
/* update the pcm offset. */
- if(frameno!=-1){
+ 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
completed on a page carries the offset) After processing
(above), we know the pcm position of the *last* sample
- ready to be returned. Find the offset of the *first* */
+ ready to be returned. Find the offset of the *first*
+
+ As an aside, this trick is inaccurate if we begin
+ reading anew right at the last page; the end-of-stream
+ frameno declares the last frame in the stream, and the
+ last packet of the last page may be a partial frame.
+ So, we need a previous frameno from an in-sequence page
+ to have a reference point. Thus the !op.e_o_s clause
+ above */
samples=vorbis_synthesis_pcmout(&vf->vd,&dummy);
return(0);
}
+static int _fseek64_wrap(FILE *f,int64_t off,int whence){
+ return fseek(f,(int)off,whence);
+}
+
/* inspects the OggVorbis file and finds/documents all the logical
bitstreams contained in it. Tries to be tolerant of logical
bitstream sections that are truncated/woogie.
int ov_open(FILE *f,OggVorbis_File *vf,char *initial,long ibytes){
ov_callbacks callbacks = {
(size_t (*)(void *, size_t, size_t, void *)) fread,
- (int (*)(void *, long, int)) fseek,
+ (int (*)(void *, int64_t, int)) _fseek64_wrap,
(int (*)(void *)) fclose,
(long (*)(void *)) ftell
};
raw (compressed) length of that logical bitstream for i==0 to n
-1 if the stream is not seekable (we can't know the length)
*/
-long ov_raw_total(OggVorbis_File *vf,int i){
+int64_t ov_raw_total(OggVorbis_File *vf,int i){
if(!vf->seekable || i>=vf->links)return(-1);
if(i<0){
long acc=0;
/* tell the current stream offset cursor. Note that seek followed by
tell will likely not give the set offset due to caching */
-long ov_raw_tell(OggVorbis_File *vf){
+int64_t ov_raw_tell(OggVorbis_File *vf){
return(vf->offset);
}