[xiph-cvs] cvs commit: vorbis/lib scales.h vorbisfile.c
Monty
xiphmont at xiph.org
Wed Mar 6 19:41:04 PST 2002
xiphmont 02/03/06 19:41:04
Modified: examples chaining_example.c
include/vorbis vorbisfile.h
lib scales.h vorbisfile.c
Log:
Numerous vorbisfile fixes:
Fixed a seek bug that didn't cause any wrong answers but did have a
minor negative impact on seeking performance
Corrected ov_read_float() prototype ot more closely match how
ov_read() is used.
Rendered all of vorbisfile 64 bit clean for >2GB files. This required
changing ov_seek_raw(OggVorbis_File *vf,long position) to
ov_seek_raw(OggVorbis_File *vf,ogg_int64_t position). This breaks lib
compatability for those using this function, please increment the
version number.
Fixed vorbisfile handling of logical streams that begin at a non-zero
PCM offset. captured live streams, and cut streams, for example, now
behave.
Revision Changes Path
1.16 +2 -1 vorbis/examples/chaining_example.c
Index: chaining_example.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis/examples/chaining_example.c,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -r1.15 -r1.16
--- chaining_example.c 2001/12/20 01:00:24 1.15
+++ chaining_example.c 2002/03/07 03:41:02 1.16
@@ -11,10 +11,11 @@
********************************************************************
function: illustrate simple use of chained bitstream and vorbisfile.a
- last mod: $Id: chaining_example.c,v 1.15 2001/12/20 01:00:24 segher Exp $
+ last mod: $Id: chaining_example.c,v 1.16 2002/03/07 03:41:02 xiphmont Exp $
********************************************************************/
+#include <stdlib.h>
#include <vorbis/codec.h>
#include <vorbis/vorbisfile.h>
<p><p>1.17 +6 -4 vorbis/include/vorbis/vorbisfile.h
Index: vorbisfile.h
===================================================================
RCS file: /usr/local/cvsroot/vorbis/include/vorbis/vorbisfile.h,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -r1.16 -r1.17
--- vorbisfile.h 2001/12/20 01:00:25 1.16
+++ vorbisfile.h 2002/03/07 03:41:03 1.17
@@ -11,7 +11,7 @@
********************************************************************
function: stdio-based convenience library for opening/seeking/decoding
- last mod: $Id: vorbisfile.h,v 1.16 2001/12/20 01:00:25 segher Exp $
+ last mod: $Id: vorbisfile.h,v 1.17 2002/03/07 03:41:03 xiphmont Exp $
********************************************************************/
@@ -62,7 +62,9 @@
ogg_int64_t *offsets;
ogg_int64_t *dataoffsets;
long *serialnos;
- ogg_int64_t *pcmlengths;
+ ogg_int64_t *pcmlengths; /* overloaded to maintain binary
+ compatability; x2 size, stores both
+ beginning and end values */
vorbis_info *vi;
vorbis_comment *vc;
@@ -104,7 +106,7 @@
extern ogg_int64_t ov_pcm_total(OggVorbis_File *vf,int i);
extern double ov_time_total(OggVorbis_File *vf,int i);
-extern int ov_raw_seek(OggVorbis_File *vf,long pos);
+extern int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos);
extern int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos);
extern int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos);
extern int ov_time_seek(OggVorbis_File *vf,double pos);
@@ -117,7 +119,7 @@
extern vorbis_info *ov_info(OggVorbis_File *vf,int link);
extern vorbis_comment *ov_comment(OggVorbis_File *vf,int link);
-extern long ov_read_float(OggVorbis_File *vf,float ***pcm_channels,
+extern long ov_read_float(OggVorbis_File *vf,float ***pcm_channels,int samples,
int *bitstream);
extern long ov_read(OggVorbis_File *vf,char *buffer,int length,
int bigendianp,int word,int sgned,int *bitstream);
<p><p>1.20 +11 -0 vorbis/lib/scales.h
Index: scales.h
===================================================================
RCS file: /usr/local/cvsroot/vorbis/lib/scales.h,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -r1.19 -r1.20
--- scales.h 2002/03/06 04:07:58 1.19
+++ scales.h 2002/03/07 03:41:03 1.20
@@ -11,7 +11,7 @@
********************************************************************
function: linear scale -> dB, Bark and Mel scales
- last mod: $Id: scales.h,v 1.19 2002/03/06 04:07:58 xiphmont Exp $
+ last mod: $Id: scales.h,v 1.20 2002/03/07 03:41:03 xiphmont Exp $
********************************************************************/
@@ -23,6 +23,12 @@
/* 20log10(x) */
#ifdef VORBIS_IEEE_FLOAT32
+static float unitnorm(float x){
+ ogg_uint32_t *ix=(ogg_uint32_t *)&x;
+ *ix=(*ix&0x80000000UL)|(0x3f800000UL);
+ return(x);
+}
+
static float todB_LOOKUP[256]={
-140.277330f, -139.633636f, -139.034372f, -138.473797f,
-137.450747f, -136.535597f, -135.707743f, -134.951972f,
@@ -100,6 +106,11 @@
#define todB_nn(x) todB(x)
#else
+
+static float unitnorm(float x){
+ if(x<0)return(-1.f);
+ return(1.f);
+}
#define todB(x) (*(x)==0?-400.f:log(*(x)**(x))*4.34294480f)
#define todB_nn(x) (*(x)==0.f?-400.f:log(*(x))*8.6858896f)
<p><p>1.59 +190 -121 vorbis/lib/vorbisfile.c
Index: vorbisfile.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis/lib/vorbisfile.c,v
retrieving revision 1.58
retrieving revision 1.59
diff -u -r1.58 -r1.59
--- vorbisfile.c 2002/03/04 01:02:04 1.58
+++ vorbisfile.c 2002/03/07 03:41:03 1.59
@@ -11,7 +11,7 @@
********************************************************************
function: stdio-based convenience library for opening/seeking/decoding
- last mod: $Id: vorbisfile.c,v 1.58 2002/03/04 01:02:04 xiphmont Exp $
+ last mod: $Id: vorbisfile.c,v 1.59 2002/03/07 03:41:03 xiphmont Exp $
********************************************************************/
@@ -73,7 +73,7 @@
}
/* save a tiny smidge of verbosity to make the code more readable */
-static void _seek_helper(OggVorbis_File *vf,long offset){
+static void _seek_helper(OggVorbis_File *vf,ogg_int64_t offset){
if(vf->datasource){
(vf->callbacks.seek_func)(vf->datasource, offset, SEEK_SET);
vf->offset=offset;
@@ -97,7 +97,8 @@
return: <0) did not find a page (OV_FALSE, OV_EOF, OV_EREAD)
n) found a page at absolute offset n */
-static long _get_next_page(OggVorbis_File *vf,ogg_page *og,int boundary){
+static ogg_int64_t _get_next_page(OggVorbis_File *vf,ogg_page *og,
+ ogg_int64_t boundary){
if(boundary>0)boundary+=vf->offset;
while(1){
long more;
@@ -120,7 +121,7 @@
}else{
/* got a page. Return the offset at the page beginning,
advance the internal offset past the page end */
- long ret=vf->offset;
+ ogg_int64_t ret=vf->offset;
vf->offset+=more;
return(ret);
@@ -134,11 +135,11 @@
backward search linkage. no 'readp' as it will certainly have to
read. */
/* returns offset or OV_EREAD, OV_FAULT */
-static long _get_prev_page(OggVorbis_File *vf,ogg_page *og){
- long begin=vf->offset;
- long end=begin;
- long ret;
- int offset=-1;
+static ogg_int64_t _get_prev_page(OggVorbis_File *vf,ogg_page *og){
+ ogg_int64_t begin=vf->offset;
+ ogg_int64_t end=begin;
+ ogg_int64_t ret;
+ ogg_int64_t offset=-1;
while(offset==-1){
begin-=CHUNKSIZE;
@@ -171,20 +172,20 @@
Recurses for each link so it can alloc the link storage after
finding them all, then unroll and fill the cache at the same time */
static int _bisect_forward_serialno(OggVorbis_File *vf,
- long begin,
- long searched,
- long end,
+ ogg_int64_t begin,
+ ogg_int64_t searched,
+ ogg_int64_t end,
long currentno,
long m){
- long endsearched=end;
- long next=end;
+ ogg_int64_t endsearched=end;
+ ogg_int64_t next=end;
ogg_page og;
- long ret;
+ ogg_int64_t ret;
/* the below guards against garbage seperating the last and
first pages of two links. */
while(searched<endsearched){
- long bisect;
+ ogg_int64_t bisect;
if(endsearched-searched<CHUNKSIZE){
bisect=searched;
@@ -209,7 +210,8 @@
if(searched>=end || ret<0){
vf->links=m+1;
- vf->offsets=_ogg_malloc((m+2)*sizeof(*vf->offsets));
+ vf->offsets=_ogg_malloc((vf->links+1)*sizeof(*vf->offsets));
+ vf->serialnos=_ogg_malloc(vf->links*sizeof(*vf->serialnos));
vf->offsets[m+1]=searched;
}else{
ret=_bisect_forward_serialno(vf,next,vf->offset,
@@ -218,6 +220,7 @@
}
vf->offsets[m]=begin;
+ vf->serialnos[m]=currentno;
return(0);
}
@@ -227,17 +230,17 @@
long *serialno,ogg_page *og_ptr){
ogg_page og;
ogg_packet op;
- int i,ret=0;
+ int i,ret;
if(!og_ptr){
- ret=_get_next_page(vf,&og,CHUNKSIZE);
- if(ret==OV_EREAD)return(OV_EREAD);
- if(ret<0)return OV_ENOTVORBIS;
+ ogg_int64_t llret=_get_next_page(vf,&og,CHUNKSIZE);
+ if(llret==OV_EREAD)return(OV_EREAD);
+ if(llret<0)return OV_ENOTVORBIS;
og_ptr=&og;
}
- if(serialno)*serialno=ogg_page_serialno(og_ptr);
- ogg_stream_init(&vf->os,ogg_page_serialno(og_ptr));
+ ogg_stream_reset_serialno(&vf->os,ogg_page_serialno(og_ptr));
+ if(serialno)*serialno=vf->os.serialno;
vf->ready_state=STREAMSET;
/* extract the initial header from the first page and verify that the
@@ -272,7 +275,6 @@
bail_header:
vorbis_info_clear(vi);
vorbis_comment_clear(vc);
- ogg_stream_clear(&vf->os);
vf->ready_state=OPENED;
return ret;
@@ -287,20 +289,22 @@
able to open and use damaged bitstreams as well as we can. Just
watch out for missing information for links in the OggVorbis_File
struct */
-static void _prefetch_all_headers(OggVorbis_File *vf, long dataoffset){
+static void _prefetch_all_headers(OggVorbis_File *vf, ogg_int64_t dataoffset){
ogg_page og;
- int i,ret;
+ int i;
+ ogg_int64_t ret;
vf->vi=_ogg_realloc(vf->vi,vf->links*sizeof(*vf->vi));
vf->vc=_ogg_realloc(vf->vc,vf->links*sizeof(*vf->vc));
vf->dataoffsets=_ogg_malloc(vf->links*sizeof(*vf->dataoffsets));
- vf->pcmlengths=_ogg_malloc(vf->links*sizeof(*vf->pcmlengths));
- vf->serialnos=_ogg_malloc(vf->links*sizeof(*vf->serialnos));
+ vf->pcmlengths=_ogg_malloc(vf->links*2*sizeof(*vf->pcmlengths));
for(i=0;i<vf->links;i++){
if(i==0){
/* we already grabbed the initial header earlier. Just set the offset */
vf->dataoffsets[i]=dataoffset;
+ _seek_helper(vf,dataoffset);
+
}else{
/* seek to the location of the initial header */
@@ -310,14 +314,59 @@
vf->dataoffsets[i]=-1;
}else{
vf->dataoffsets[i]=vf->offset;
- ogg_stream_clear(&vf->os);
}
}
+
+ /* fetch beginning PCM offset */
+
+ if(vf->dataoffsets[i]!=-1){
+ ogg_int64_t accumulated=0;
+ long lastblock=-1;
+ int result;
+
+ ogg_stream_reset_serialno(&vf->os,vf->serialnos[i]);
+
+ while(1){
+ ogg_packet op;
+
+ ret=_get_next_page(vf,&og,-1);
+ if(ret<0)
+ /* this should not be possible unless the file is
+ truncated/mangled */
+ break;
+
+ if(ogg_page_serialno(&og)!=vf->serialnos[i])
+ break;
+
+ /* count blocksizes of all frames in the page */
+ ogg_stream_pagein(&vf->os,&og);
+ while((result=ogg_stream_packetout(&vf->os,&op))){
+ if(result>0){ /* ignore holes */
+ long thisblock=vorbis_packet_blocksize(vf->vi+i,&op);
+ if(lastblock!=-1)
+ accumulated+=(lastblock+thisblock)>>2;
+ lastblock=thisblock;
+ }
+ }
+
+ if(ogg_page_granulepos(&og)!=-1){
+ /* pcm offset of last packet on the first audio page */
+ accumulated= ogg_page_granulepos(&og)-accumulated;
+ break;
+ }
+ }
+
+ /* less than zero? This is a stream with samples trimmed off
+ the beginning, a normal occurrence; set the offset to zero */
+ if(accumulated<0)accumulated=0;
+
+ vf->pcmlengths[i*2]=accumulated;
+ }
- /* get the serial number and PCM length of this link. To do this,
+ /* get the PCM length of this link. To do this,
get the last page of the stream */
{
- long end=vf->offsets[i+1];
+ ogg_int64_t end=vf->offsets[i+1];
_seek_helper(vf,end);
while(1){
@@ -329,8 +378,7 @@
break;
}
if(ogg_page_granulepos(&og)!=-1){
- vf->serialnos[i]=ogg_page_serialno(&og);
- vf->pcmlengths[i]=ogg_page_granulepos(&og);
+ vf->pcmlengths[i*2+1]=ogg_page_granulepos(&og)-vf->pcmlengths[i*2];
break;
}
vf->offset=ret;
@@ -353,7 +401,7 @@
static int _open_seekable2(OggVorbis_File *vf){
long serialno=vf->current_serialno,end;
- long dataoffset=vf->offset;
+ ogg_int64_t dataoffset=vf->offset;
ogg_page og;
/* we're partially open and have a first link header state in
@@ -388,7 +436,6 @@
/* clear out the current logical bitstream decoder */
static void _decode_clear(OggVorbis_File *vf){
- ogg_stream_clear(&vf->os);
vorbis_dsp_clear(&vf->vd);
vorbis_block_clear(&vf->vb);
vf->ready_state=OPENED;
@@ -468,12 +515,18 @@
So, we need a previous granulepos from an in-sequence page
to have a reference point. Thus the !op_ptr->e_o_s clause
above */
-
+
+ granulepos-=vf->pcmlengths[link*2];
+ if(granulepos<0)granulepos=0; /* actually, this
+ shouldn't be possible
+ here unless the stream
+ is very broken */
+
samples=vorbis_synthesis_pcmout(&vf->vd,NULL);
granulepos-=samples;
for(i=0;i<link;i++)
- granulepos+=vf->pcmlengths[i];
+ granulepos+=vf->pcmlengths[i*2+1];
vf->pcm_offset=granulepos;
}
return(1);
@@ -536,8 +589,7 @@
vf->current_link=link;
- ogg_stream_init(&vf->os,vf->current_serialno);
- ogg_stream_reset(&vf->os);
+ ogg_stream_reset_serialno(&vf->os,vf->current_serialno);
vf->ready_state=STREAMSET;
}else{
@@ -557,14 +609,16 @@
}
}
+/* if, eg, 64 bit stdio is configured by default, this will build with
+ fseek64 */
static int _fseek64_wrap(FILE *f,ogg_int64_t off,int whence){
if(f==NULL)return(-1);
- return fseek(f,(int)off,whence);
+ return fseek(f,off,whence);
}
static int _ov_open1(void *f,OggVorbis_File *vf,char *initial,
long ibytes, ov_callbacks callbacks){
- long offset=(f?callbacks.seek_func(f,0,SEEK_CUR):-1);
+ int offsettest=(f?callbacks.seek_func(f,0,SEEK_CUR):-1);
int ret;
memset(vf,0,sizeof(*vf));
@@ -585,14 +639,15 @@
}
/* can we seek? Stevens suggests the seek test was portable */
- if(offset!=-1)vf->seekable=1;
+ if(offsettest!=-1)vf->seekable=1;
/* No seeking yet; Set up a 'single' (current) logical bitstream
entry for partial open */
vf->links=1;
vf->vi=_ogg_calloc(vf->links,sizeof(*vf->vi));
vf->vc=_ogg_calloc(vf->links,sizeof(*vf->vc));
-
+ ogg_stream_init(&vf->os,-1); /* fill in the serialno later */
+
/* Try to fetch the headers, maintaining all the storage */
if((ret=_fetch_headers(vf,vf->vi,vf->vc,&vf->current_serialno,NULL))<0){
vf->datasource=NULL;
@@ -786,7 +841,7 @@
if(vf->ready_state<OPENED)return(OV_EINVAL);
if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
if(i<0){
- long acc=0;
+ ogg_int64_t acc=0;
int i;
for(i=0;i<vf->links;i++)
acc+=ov_raw_total(vf,i);
@@ -811,7 +866,7 @@
acc+=ov_pcm_total(vf,i);
return(acc);
}else{
- return(vf->pcmlengths[i]);
+ return(vf->pcmlengths[i*2+1]);
}
}
@@ -830,7 +885,7 @@
acc+=ov_time_total(vf,i);
return(acc);
}else{
- return((float)(vf->pcmlengths[i])/vf->vi[i].rate);
+ return((double)(vf->pcmlengths[i*2+1])/vf->vi[i].rate);
}
}
@@ -841,14 +896,14 @@
returns zero on success, nonzero on failure */
-int ov_raw_seek(OggVorbis_File *vf,long pos){
+int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){
ogg_stream_state work_os;
if(vf->ready_state<OPENED)return(OV_EINVAL);
if(!vf->seekable)
return(OV_ENOSEEK); /* don't dump machine if we can't seek */
- if(pos<0 || pos>vf->offsets[vf->links])return(OV_EINVAL);
+ if(pos<0 || pos>vf->end)return(OV_EINVAL);
/* clear out decoding machine state */
vf->pcm_offset=-1;
@@ -879,9 +934,7 @@
int thisblock;
int eosflag;
- memset(&work_os,0,sizeof(work_os));/* so that it's safe to clear
- it later even if we don't
- init it */
+ ogg_stream_init(&work_os,-1); /* get the memory ready */
while(1){
if(vf->ready_state==STREAMSET){
@@ -899,10 +952,11 @@
if(op.granulepos!=-1){
int i,link=vf->current_link;
- ogg_int64_t granulepos=op.granulepos;
+ ogg_int64_t granulepos=op.granulepos-vf->pcmlengths[link*2];
+ if(granulepos<0)granulepos=0;
for(i=0;i<link;i++)
- granulepos+=vf->pcmlengths[i];
+ granulepos+=vf->pcmlengths[i*2+1];
vf->pcm_offset=granulepos-accblock;
break;
}
@@ -940,10 +994,8 @@
machine uninitialized */
vf->current_link=link;
- ogg_stream_init(&vf->os,vf->current_serialno);
- ogg_stream_reset(&vf->os);
- ogg_stream_init(&work_os,vf->current_serialno);
- ogg_stream_reset(&work_os);
+ ogg_stream_reset_serialno(&vf->os,vf->current_serialno);
+ ogg_stream_reset_serialno(&work_os,vf->current_serialno);
vf->ready_state=STREAMSET;
}
@@ -972,17 +1024,18 @@
location, such that decoding past the returned point will quickly
arrive at the requested position. */
int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
- int link=-1;
- long ret;
+ int link=-1,ret=0;
+ ogg_int64_t result;
ogg_int64_t total=ov_pcm_total(vf,-1);
if(vf->ready_state<OPENED)return(OV_EINVAL);
if(!vf->seekable)return(OV_ENOSEEK);
+
if(pos<0 || pos>total)return(OV_EINVAL);
/* which bitstream section does this pcm offset occur in? */
for(link=vf->links-1;link>=0;link--){
- total-=vf->pcmlengths[link];
+ total-=vf->pcmlengths[link*2+1];
if(pos>=total)break;
}
@@ -994,16 +1047,16 @@
/* new search algorithm by HB (Nicholas Vinen) */
{
- ogg_int64_t target=pos-total;
- long end=vf->offsets[link+1];
- long begin=vf->offsets[link];
- ogg_int64_t endtime = vf->pcmlengths[link];
- ogg_int64_t begintime = 0;
- long best=begin;
+ ogg_int64_t end=vf->offsets[link+1];
+ ogg_int64_t begin=vf->offsets[link];
+ ogg_int64_t begintime = vf->pcmlengths[link*2];
+ ogg_int64_t endtime = vf->pcmlengths[link*2+1]+begintime;
+ ogg_int64_t target=pos-total+begintime;
+ ogg_int64_t best=begin;
ogg_page og;
while(begin<end){
- long bisect;
+ ogg_int64_t bisect;
if(end-begin<CHUNKSIZE){
bisect=begin;
@@ -1014,12 +1067,13 @@
if(bisect<=begin)
bisect=begin+1;
}
+
_seek_helper(vf,bisect);
while(begin<end){
- ret=_get_next_page(vf,&og,end-bisect);
- if(ret==OV_EREAD) goto seek_error;
- if(ret<0){
+ result=_get_next_page(vf,&og,end-vf->offset);
+ if(result==OV_EREAD) goto seek_error;
+ if(result<0){
if(bisect<=begin+1)
end=begin; /* found it */
else{
@@ -1030,24 +1084,25 @@
}
}else{
ogg_int64_t granulepos=ogg_page_granulepos(&og);
+ if(granulepos==-1)continue;
if(granulepos<target){
- best=ret; /* raw offset of packet with granulepos */
+ best=result; /* raw offset of packet with granulepos */
begin=vf->offset; /* raw offset of next page */
begintime=granulepos;
- if(target-begin>44100)break;
+ if(target-begintime>44100)break;
bisect=begin; /* *not* begin + 1 */
}else{
if(bisect<=begin+1)
end=begin; /* found it */
else{
if(end==vf->offset){ /* we're pretty close - we'd be stuck in */
- end=ret;
+ end=result;
bisect-=CHUNKSIZE; /* an endless loop otherwise. */
if(bisect<=begin)bisect=begin+1;
_seek_helper(vf,bisect);
}else{
- end=ret;
+ end=result;
endtime=granulepos;
break;
}
@@ -1071,15 +1126,14 @@
vf->current_serialno=ogg_page_serialno(&og);
vf->current_link=link;
- ogg_stream_init(&vf->os,vf->current_serialno);
- ogg_stream_reset(&vf->os);
+ 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 */
while(1){
- ret=ogg_stream_packetpeek(&vf->os,&op);
- if(ret==0){
+ result=ogg_stream_packetpeek(&vf->os,&op);
+ if(result==0){
/* !!! the packet finishing this page originated on a
preceeding page. Keep fetching previous pages until we
get one with a granulepos or without the 'continued' flag
@@ -1089,21 +1143,23 @@
_seek_helper(vf,best);
while(1){
- ret=_get_prev_page(vf,&og);
- if(ret<0)goto seek_error;
+ result=_get_prev_page(vf,&og);
+ if(result<0)goto seek_error;
if(ogg_page_granulepos(&og)>-1 ||
!ogg_page_continued(&og)){
- return ov_raw_seek(vf,ret);
+ return ov_raw_seek(vf,result);
}
- vf->offset=ret;
+ vf->offset=result;
}
}
- if(ret<0)goto seek_error;
+ if(result<0)goto seek_error;
if(op.granulepos!=-1){
- vf->pcm_offset=op.granulepos+total;
+ vf->pcm_offset=op.granulepos-vf->pcmlengths[vf->current_link*2];
+ if(vf->pcm_offset<0)vf->pcm_offset=0;
+ vf->pcm_offset+=total;
break;
}else
- ret=ogg_stream_packetout(&vf->os,NULL);
+ result=ogg_stream_packetout(&vf->os,NULL);
}
}
}
@@ -1160,9 +1216,10 @@
if(op.granulepos>-1){
int i;
/* always believe the stream markers */
- vf->pcm_offset=op.granulepos;
+ vf->pcm_offset=op.granulepos-vf->pcmlengths[vf->current_link*2];
+ if(vf->pcm_offset<0)vf->pcm_offset=0;
for(i=0;i<vf->current_link;i++)
- vf->pcm_offset+=vf->pcmlengths[i];
+ vf->pcm_offset+=vf->pcmlengths[i*2+1];
}
lastblock=thisblock;
@@ -1183,8 +1240,7 @@
if(link==vf->links)return(OV_EBADLINK);
vf->current_link=link;
- ogg_stream_init(&vf->os,vf->current_serialno);
- ogg_stream_reset(&vf->os);
+ ogg_stream_reset_serialno(&vf->os,vf->current_serialno);
vf->ready_state=STREAMSET;
_make_decode_ready(vf);
lastblock=0;
@@ -1198,7 +1254,7 @@
logical bitstream boundary with abandon is OK. */
while(vf->pcm_offset<pos){
float **pcm;
- long target=pos-vf->pcm_offset;
+ ogg_int64_t target=pos-vf->pcm_offset;
long samples=vorbis_synthesis_pcmout(&vf->vd,&pcm);
if(samples>target)samples=target;
@@ -1227,7 +1283,7 @@
/* which bitstream section does this time offset occur in? */
for(link=vf->links-1;link>=0;link--){
- pcm_total-=vf->pcmlengths[link];
+ pcm_total-=vf->pcmlengths[link*2+1];
time_total-=ov_time_total(vf,link);
if(seconds>=time_total)break;
}
@@ -1254,7 +1310,7 @@
/* which bitstream section does this time offset occur in? */
for(link=vf->links-1;link>=0;link--){
- pcm_total-=vf->pcmlengths[link];
+ pcm_total-=vf->pcmlengths[link*2+1];
time_total-=ov_time_total(vf,link);
if(seconds>=time_total)break;
}
@@ -1294,7 +1350,7 @@
/* which bitstream section does this time offset occur in? */
for(link=vf->links-1;link>=0;link--){
- pcm_total-=vf->pcmlengths[link];
+ pcm_total-=vf->pcmlengths[link*2+1];
time_total-=ov_time_total(vf,link);
if(vf->pcm_offset>=pcm_total)break;
}
@@ -1384,34 +1440,6 @@
*section) set to the logical bitstream number */
-long ov_read_float(OggVorbis_File *vf,float ***pcm_channels,int *bitstream){
-
- if(vf->ready_state<OPENED)return(OV_EINVAL);
-
- while(1){
- if(vf->ready_state>=STREAMSET){
- float **pcm;
- long samples=vorbis_synthesis_pcmout(&vf->vd,&pcm);
- if(samples){
- if(pcm_channels)*pcm_channels=pcm;
- vorbis_synthesis_read(&vf->vd,samples);
- vf->pcm_offset+=samples;
- if(bitstream)*bitstream=vf->current_link;
- return samples;
-
- }
- }
-
- /* suck in another packet */
- {
- int ret=_fetch_and_process_packet(vf,NULL,1);
- if(ret==OV_EOF)return(0);
- if(ret<=0)return(ret);
- }
-
- }
-}
-
long ov_read(OggVorbis_File *vf,char *buffer,int length,
int bigendianp,int word,int sgned,int *bitstream){
int i,j;
@@ -1538,6 +1566,47 @@
}
}
+/* input values: pcm_channels) a float vector per channel of output
+ length) the sample length being read by the app
+
+ return values: <0) error/hole in data (OV_HOLE), partial open (OV_EINVAL)
+ 0) EOF
+ n) number of samples of PCM actually returned. The
+ below works on a packet-by-packet basis, so the
+ return length is not related to the 'length' passed
+ in, just guaranteed to fit.
+
+ *section) set to the logical bitstream number */
+
+
+long ov_read_float(OggVorbis_File *vf,float ***pcm_channels,int length,
+ int *bitstream){
+ if(vf->ready_state<OPENED)return(OV_EINVAL);
+
+ while(1){
+ if(vf->ready_state>=STREAMSET){
+ float **pcm;
+ long samples=vorbis_synthesis_pcmout(&vf->vd,&pcm);
+ if(samples){
+ if(pcm_channels)*pcm_channels=pcm;
+ if(samples>length)samples=length;
+ vorbis_synthesis_read(&vf->vd,samples);
+ vf->pcm_offset+=samples;
+ if(bitstream)*bitstream=vf->current_link;
+ return samples;
+
+ }
+ }
+
+ /* suck in another packet */
+ {
+ int ret=_fetch_and_process_packet(vf,NULL,1);
+ if(ret==OV_EOF)return(0);
+ if(ret<=0)return(ret);
+ }
+
+ }
+}
<p><p><p>--- >8 ----
List archives: http://www.xiph.org/archives/
Ogg project homepage: http://www.xiph.org/ogg/
To unsubscribe from this list, send a message to 'cvs-request at xiph.org'
containing only the word 'unsubscribe' in the body. No subject is needed.
Unsubscribe messages sent to the list will be ignored/filtered.
More information about the commits
mailing list