diff options
| author | Monty <xiphmont@xiph.org> | 2000-01-28 09:05:21 +0000 |
|---|---|---|
| committer | Monty <xiphmont@xiph.org> | 2000-01-28 09:05:21 +0000 |
| commit | 5365ea64b6b252a9902a5f9d4b141ad14884510a (patch) | |
| tree | aee16d5733620eb3221820714f0ef5a89a9f5af8 /lib | |
| parent | cab466d0585827812b4e562eb41a752dd56f1e53 (diff) | |
| download | libvorbis-git-5365ea64b6b252a9902a5f9d4b141ad14884510a.tar.gz | |
The lib and vq, at least, build again. Tackling the examples and xmms
now. There are still unfinished portions of the lib rearranging
(notably, floor0.c and res0.c)
Monty
svn path=/trunk/vorbis/; revision=244
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/Makefile.in | 6 | ||||
| -rw-r--r-- | lib/block.c | 20 | ||||
| -rw-r--r-- | lib/bookinternal.h | 11 | ||||
| -rw-r--r-- | lib/codebook.c | 204 | ||||
| -rw-r--r-- | lib/floor0.c | 27 | ||||
| -rw-r--r-- | lib/info.c | 353 | ||||
| -rw-r--r-- | lib/lpc.c | 19 | ||||
| -rw-r--r-- | lib/lpc.h | 4 | ||||
| -rw-r--r-- | lib/mapping0.c | 345 | ||||
| -rw-r--r-- | lib/psy.c | 31 | ||||
| -rw-r--r-- | lib/psy.h | 13 | ||||
| -rw-r--r-- | lib/res0.c | 48 | ||||
| -rw-r--r-- | lib/spectrum.c | 181 | ||||
| -rw-r--r-- | lib/vorbisfile.c | 62 |
14 files changed, 603 insertions, 721 deletions
diff --git a/lib/Makefile.in b/lib/Makefile.in index eac125dc..af28f6aa 100644 --- a/lib/Makefile.in +++ b/lib/Makefile.in @@ -1,6 +1,6 @@ # vorbis makefile configured for use with gcc on any platform -# $Id: Makefile.in,v 1.23 2000/01/22 13:28:13 xiphmont Exp $ +# $Id: Makefile.in,v 1.24 2000/01/28 09:05:05 xiphmont Exp $ ############################################################################### # # @@ -28,14 +28,14 @@ RANLIB=@RANLIB@ LIBS=@LIBS@ -lm HFILES = ../include/vorbis/codec.h ../include/vorbis/vorbisfile.h \ - ../include/vorbis/internal.h ../include/vorbis/backend.h \ + ../include/vorbis/internal.h ../include/vorbis/backends.h \ ../include/vorbis/codebook.h \ bitwise.h envelope.h lpc.h lsp.h bookinternal.h misc.h\ psy.h smallft.h window.h scales.h os.h mdct.h registry.h LFILES = framing.o mdct.o smallft.o block.o envelope.o window.o\ lsp.o lpc.o analysis.o synthesis.o psy.o info.o bitwise.o\ time0.o floor0.o res0.o mapping0.o registry.o\ - spectrum.o codebook.o vorbisfile.o + codebook.o vorbisfile.o all: $(MAKE) target CFLAGS="$(OPT)" diff --git a/lib/block.c b/lib/block.c index 74a75cf1..c6173723 100644 --- a/lib/block.c +++ b/lib/block.c @@ -12,7 +12,7 @@ ******************************************************************** function: PCM data vector blocking, windowing and dis/reassembly - last mod: $Id: block.c,v 1.23 2000/01/22 13:28:15 xiphmont Exp $ + last mod: $Id: block.c,v 1.24 2000/01/28 09:05:06 xiphmont Exp $ Handle windowing, overlap-add, etc of the PCM vectors. This is made more amusing by Vorbis' current two allowed block sizes. @@ -204,11 +204,6 @@ static int _vds_shared_init(vorbis_dsp_state *v,vorbis_info *vi){ vi->map_param[maptype]); } - /* finish the codebooks */ - v->fullbooks=calloc(vi->books,sizeof(codebook)); - for(i=0;i<vi->books;i++) - vorbis_book_finish(v->fullbooks+i,vi->book_param[i]); - /* initialize the storage vectors to a decent size greater than the minimum */ @@ -237,9 +232,14 @@ static int _vds_shared_init(vorbis_dsp_state *v,vorbis_info *vi){ /* arbitrary settings and spec-mandated numbers get filled in here */ int vorbis_analysis_init(vorbis_dsp_state *v,vorbis_info *vi){ - + int i; _vds_shared_init(v,vi); + /* finish the codebooks */ + v->fullbooks=calloc(vi->books,sizeof(codebook)); + for(i=0;i<vi->books;i++) + vorbis_book_init_encode(v->fullbooks+i,vi->book_param[i]); + /* Initialize the envelope multiplier storage */ v->envelope_storage=v->pcm_storage/vi->envelopesa; @@ -522,8 +522,14 @@ int vorbis_analysis_blockout(vorbis_dsp_state *v,vorbis_block *vb){ } int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi){ + int i; _vds_shared_init(v,vi); + /* finish the codebooks */ + v->fullbooks=calloc(vi->books,sizeof(codebook)); + for(i=0;i<vi->books;i++) + vorbis_book_init_decode(v->fullbooks+i,vi->book_param[i]); + /* 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; diff --git a/lib/bookinternal.h b/lib/bookinternal.h index 0d74deb2..e5e7b7ab 100644 --- a/lib/bookinternal.h +++ b/lib/bookinternal.h @@ -12,7 +12,7 @@ ******************************************************************** function: basic codebook pack/unpack/code/decode operations - last mod: $Id: bookinternal.h,v 1.4 2000/01/22 13:28:16 xiphmont Exp $ + last mod: $Id: bookinternal.h,v 1.5 2000/01/28 09:05:07 xiphmont Exp $ ********************************************************************/ @@ -22,10 +22,13 @@ #include "vorbis/codebook.h" #include "bitwise.h" -extern void vorbis_book_finish(codebook *dest,const static_codebook *source); +extern int vorbis_staticbook_pack(const static_codebook *c,oggpack_buffer *b); +extern int vorbis_staticbook_unpack(oggpack_buffer *b,static_codebook *c); +extern void vorbis_staticbook_clear(static_codebook *b); + +extern int vorbis_book_init_encode(codebook *dest,const static_codebook *source); +extern int vorbis_book_init_decode(codebook *dest,const static_codebook *source); extern void vorbis_book_clear(codebook *b); -extern int vorbis_book_pack(codebook *c,oggpack_buffer *b); -extern int vorbis_book_unpack(oggpack_buffer *b,codebook *c); extern int vorbis_book_encode(codebook *book, int a, oggpack_buffer *b); extern int vorbis_book_encodev(codebook *book, double *a, oggpack_buffer *b); diff --git a/lib/codebook.c b/lib/codebook.c index 0990591f..a51cf4fe 100644 --- a/lib/codebook.c +++ b/lib/codebook.c @@ -12,7 +12,7 @@ ******************************************************************** function: basic codebook pack/unpack/code/decode operations - last mod: $Id: codebook.c,v 1.3 2000/01/22 13:28:17 xiphmont Exp $ + last mod: $Id: codebook.c,v 1.4 2000/01/28 09:05:08 xiphmont Exp $ ********************************************************************/ @@ -33,20 +33,7 @@ static int ilog(unsigned int v){ return(ret); } -static long _float24_pack(double val){ - int sign=0; - long exp; - long mant; - if(val<0){ - sign=0x800000; - val= -val; - } - exp= floor(log(val)/log(2)); - mant=rint(ldexp(val,17-exp)); - exp=(exp+VQ_FEXP_BIAS)<<18; - - return(sign|exp|mant); -} +/* code that packs the 24 bit float can be found in vq/bookutil.c */ static double _float24_unpack(long val){ double mant=val&0x3ffff; @@ -121,8 +108,43 @@ long *_make_words(long *l,long n){ return(r); } +/* build the decode helper tree from the codewords */ +decode_aux *_make_decode_tree(codebook *c){ + const static_codebook *s=c->c; + long top=0,i,j; + decode_aux *t=malloc(sizeof(decode_aux)); + long *ptr0=t->ptr0=calloc(c->entries*2,sizeof(long)); + long *ptr1=t->ptr1=calloc(c->entries*2,sizeof(long)); + long *codelist=_make_words(s->lengthlist,s->entries); + + if(codelist==NULL)return(NULL); + t->aux=c->entries*2; + + for(i=0;i<c->entries;i++){ + long ptr=0; + for(j=0;j<s->lengthlist[i]-1;j++){ + int bit=(codelist[i]>>j)&1; + if(!bit){ + if(!ptr0[ptr]) + ptr0[ptr]= ++top; + ptr=ptr0[ptr]; + }else{ + if(!ptr1[ptr]) + ptr1[ptr]= ++top; + ptr=ptr1[ptr]; + } + } + if(!((codelist[i]>>j)&1)) + ptr0[ptr]=-i; + else + ptr1[ptr]=-i; + } + free(codelist); + return(t); +} + /* unpack the quantized list of values for encode/decode ***********/ -static double *_book_unquantize(static_codebook *b){ +static double *_book_unquantize(const static_codebook *b){ long j,k; double mindel=_float24_unpack(b->q_min); double delta=_float24_unpack(b->q_delta); @@ -139,8 +161,23 @@ static double *_book_unquantize(static_codebook *b){ return(r); } +void vorbis_staticbook_clear(static_codebook *b){ + if(b->quantlist)free(b->quantlist); + if(b->lengthlist)free(b->lengthlist); + if(b->encode_tree){ + free(b->encode_tree->ptr0); + free(b->encode_tree->ptr1); + free(b->encode_tree->p); + free(b->encode_tree->q); + memset(b->encode_tree,0,sizeof(encode_aux)); + free(b->encode_tree); + } + memset(b,0,sizeof(static_codebook)); +} + void vorbis_book_clear(codebook *b){ - /* static book is not cleared. It exists only in encode */ + /* static book is not cleared; we're likely called on the lookup and + the static codebook belongs to the info struct */ if(b->decode_tree){ free(b->decode_tree->ptr0); free(b->decode_tree->ptr1); @@ -152,19 +189,33 @@ void vorbis_book_clear(codebook *b){ memset(b,0,sizeof(codebook)); } -int vorbis_book_finish(codebook *c, static_codebook *s){ +int vorbis_book_init_encode(codebook *c,const static_codebook *s){ + memset(c,0,sizeof(codebook)); + c->c=s; + c->entries=s->entries; + c->dim=s->dim; + c->codelist=_make_words(s->lengthlist,s->entries); + c->valuelist=_book_unquantize(s); + return(0); +} + +int vorbis_book_init_decode(codebook *c,const static_codebook *s){ memset(c,0,sizeof(codebook)); c->c=s; - c->elements=s->elements; + c->entries=s->entries; c->dim=s->dim; - c->codelist=_make_words(c->lengthlist,c->entries); - c->valuelist=_book_unquantize(c); + c->valuelist=_book_unquantize(s); + c->decode_tree=_make_decode_tree(c); + if(c->decode_tree==NULL)goto err_out; return(0); + err_out: + vorbis_book_clear(c); + return(-1); } /* packs the given codebook into the bitstream **************************/ -int vorbis_book_pack(static_codebook *c,oggpack_buffer *opb){ +int vorbis_staticbook_pack(const static_codebook *c,oggpack_buffer *opb){ long i,j; int ordered=0; @@ -235,45 +286,41 @@ int vorbis_book_pack(static_codebook *c,oggpack_buffer *opb){ /* unpacks a codebook from the packet buffer into the codebook struct, readies the codebook auxiliary structures for decode *************/ -int vorbis_book_unpack(oggpack_buffer *opb,codebook *c){ +int vorbis_staticbook_unpack(oggpack_buffer *opb,static_codebook *s){ long i,j; - long *lengthlist=NULL; - long *codelist=NULL; - static codebook s; - memset(c,0,sizeof(codebook)); - memset(&s,0,sizeof(s)); + memset(s,0,sizeof(static_codebook)); /* make sure alignment is correct */ if(_oggpack_read(opb,24)!=0x564342)goto _eofout; /* first the basic parameters */ - c->dim=_oggpack_read(opb,16); - c->entries=_oggpack_read(opb,24); - if(c->entries==-1)goto _eofout; + s->dim=_oggpack_read(opb,16); + s->entries=_oggpack_read(opb,24); + if(s->entries==-1)goto _eofout; /* codeword ordering.... length ordered or unordered? */ switch(_oggpack_read(opb,1)){ case 0: /* unordered */ - lengthlist=malloc(sizeof(long)*c->entries); - for(i=0;i<c->entries;i++){ + s->lengthlist=malloc(sizeof(long)*s->entries); + for(i=0;i<s->entries;i++){ long num=_oggpack_read(opb,5); if(num==-1)goto _eofout; - lengthlist[i]=num+1; + s->lengthlist[i]=num+1; } - + break; case 1: /* ordered */ { long length=_oggpack_read(opb,5)+1; - lengthlist=malloc(sizeof(long)*c->entries); - - for(i=0;i<c->entries;){ - long num=_oggpack_read(opb,ilog(c->entries-i)); + s->lengthlist=malloc(sizeof(long)*s->entries); + + for(i=0;i<s->entries;){ + long num=_oggpack_read(opb,ilog(s->entries-i)); if(num==-1)goto _eofout; for(j=0;j<num;j++,i++) - lengthlist[i]=length; + s->lengthlist[i]=length; length++; } } @@ -283,60 +330,20 @@ int vorbis_book_unpack(oggpack_buffer *opb,codebook *c){ return(-1); } - /* now we generate the codewords for the given lengths */ - codelist=_make_words(c->lengthlist,c->entries); - if(codelist==NULL)goto _errout; - - /* ...and the decode helper tree from the codewords */ - { - long top=0; - decode_aux *t=c->decode_tree=malloc(sizeof(decode_aux)); - long *ptr0=t->ptr0=calloc(c->entries*2,sizeof(long)); - long *ptr1=t->ptr1=calloc(c->entries*2,sizeof(long)); - t->aux=c->entries*2; - - for(i=0;i<c->entries;i++){ - long ptr=0; - for(j=0;j<lengthlist[i]-1;j++){ - int bit=(codelist[i]>>j)&1; - if(!bit){ - if(!ptr0[ptr]) - ptr0[ptr]= ++top; - ptr=ptr0[ptr]; - }else{ - if(!ptr1[ptr]) - ptr1[ptr]= ++top; - ptr=ptr1[ptr]; - } - } - if(!((codelist[i]>>j)&1)) - ptr0[ptr]=-i; - else - ptr1[ptr]=-i; - } - } - /* no longer needed */ - free(lengthlist); - free(codelist); - /* Do we have a mapping to unpack? */ if(_oggpack_read(opb,1)){ /* values that define the dequantization */ - s.q_min=_oggpack_read(opb,24); - s.q_delta=_oggpack_read(opb,24); - s.q_quant=_oggpack_read(opb,4)+1; - s.q_sequencep=_oggpack_read(opb,1); - s.dim=c->dim; - s.entries=c->entries; + s->q_min=_oggpack_read(opb,24); + s->q_delta=_oggpack_read(opb,24); + s->q_quant=_oggpack_read(opb,4)+1; + s->q_sequencep=_oggpack_read(opb,1); /* quantized values */ - s.quantlist=malloc(sizeof(double)*c->entries*c->dim); - for(i=0;i<c->entries*c->dim;i++) - s.quantlist[i]=_oggpack_read(opb,s.q_quant); - if(s.quantlist[i-1]==-1)goto _eofout; - c->valuelist=_book_unquantize(&s); - free(s.quantlist);memset(&s,0,sizeof(s)); + s->quantlist=malloc(sizeof(double)*s->entries*s->dim); + for(i=0;i<s->entries*s->dim;i++) + s->quantlist[i]=_oggpack_read(opb,s->q_quant); + if(s->quantlist[i-1]==-1)goto _eofout; } /* all set */ @@ -344,12 +351,8 @@ int vorbis_book_unpack(oggpack_buffer *opb,codebook *c){ _errout: _eofout: - if(lengthlist)free(lengthlist); - if(s.quantlist)free(s.quantlist); - if(codelist)free(codelist); - vorbis_book_clear(c); - return(-1); - + vorbis_staticbook_clear(s); + return(-1); } /* returns the number of bits ***************************************/ @@ -539,6 +542,7 @@ int main(){ while(testlist[ptr]){ codebook c; + static_codebook s; double *qv=alloca(sizeof(double)*TESTSIZE); double *iv=alloca(sizeof(double)*TESTSIZE); memcpy(qv,testvec[ptr],sizeof(double)*TESTSIZE); @@ -547,8 +551,9 @@ int main(){ /* pack the codebook, write the testvector */ _oggpack_reset(&write); - vorbis_book_finish(&c,testlist[ptr]); /* get it into memory we can write */ - vorbis_book_pack(&c,&write); + vorbis_book_init_encode(&c,testlist[ptr]); /* get it into memory + we can write */ + vorbis_book_pack(testlist[ptr],&write); fprintf(stderr,"Codebook size %ld bytes... ",_oggpack_bytes(&write)); for(i=0;i<TESTSIZE;i+=TESTDIM) vorbis_book_encodev(&c,qv+i,&write); @@ -559,10 +564,15 @@ int main(){ /* transfer the write data to a read buffer and unpack/read */ _oggpack_readinit(&read,_oggpack_buffer(&write),_oggpack_bytes(&write)); - if(vorbis_book_unpack(&read,&c)){ + if(vorbis_book_unpack(&read,&s)){ fprintf(stderr,"Error unpacking codebook.\n"); exit(1); } + if(vorbis_book_init_decode(&c,&s)){ + fprintf(stderr,"Error initializing codebook.\n"); + exit(1); + } + for(i=0;i<TESTSIZE;i+=TESTDIM) if(vorbis_book_decodev(&c,iv+i,&read)){ fprintf(stderr,"Error reading codebook test data (EOP).\n"); diff --git a/lib/floor0.c b/lib/floor0.c index ee5b0f13..ef36f4a3 100644 --- a/lib/floor0.c +++ b/lib/floor0.c @@ -12,7 +12,7 @@ ******************************************************************** function: floor backend 0 implementation - last mod: $Id: floor0.c,v 1.2 2000/01/22 13:28:19 xiphmont Exp $ + last mod: $Id: floor0.c,v 1.3 2000/01/28 09:05:09 xiphmont Exp $ ********************************************************************/ @@ -22,6 +22,16 @@ #include "bitwise.h" #include "registry.h" +static void free_info(vorbis_info_floor *i){ + vorbis_info_floor0 *d=(vorbis_info_floor0 *)i; + if(d){ + if(d->books)free(d->books); + memset(i,0,sizeof(vorbis_info_floor0)); + } +} +static void free_look(vorbis_look_floor *i){ +} + static void pack (vorbis_info_floor *i,oggpack_buffer *opb){ vorbis_info_floor0 *d=(vorbis_info_floor0 *)i; int j; @@ -61,17 +71,8 @@ static vorbis_look_floor *look (vorbis_info *vi,vorbis_info_mode *mi, vorbis_info_floor *i){ } -static void free_info(vorbis_info_floor *i){ - vorbis_info_floor0 *d=(vorbis_info_floor0 *)i; - if(d){ - if(d->books)free(d->books); - memset(i,0,sizeof(vorbis_info_floor0)); - } -} -static void free_look(vorbis_look_floor *i){ -} -static void forward(vorbis_block *vb,vorbis_look_floor *i, +static int forward(vorbis_block *vb,vorbis_look_floor *i, double *in,double *out){ @@ -93,8 +94,8 @@ static void forward(vorbis_block *vb,vorbis_look_floor *i, vorbis_lpc_to_curve(curve,lpc,vb->amp[i],vl);*/ return(0); } -static void inverse(vorbis_block *vb,vorbis_look_floor *i, - double *in,double *out){ +static int inverse(vorbis_block *vb,vorbis_look_floor *i, + double *buf){ return(0); } @@ -12,7 +12,7 @@ ******************************************************************** function: maintain the info structure, info <-> header packets - last mod: $Id: info.c,v 1.17 2000/01/22 13:28:21 xiphmont Exp $ + last mod: $Id: info.c,v 1.18 2000/01/28 09:05:10 xiphmont Exp $ ********************************************************************/ @@ -22,6 +22,7 @@ #include <stdlib.h> #include <string.h> #include "vorbis/codec.h" +#include "vorbis/backends.h" #include "bitwise.h" #include "bookinternal.h" #include "registry.h" @@ -29,7 +30,6 @@ #include "psy.h" /* helpers */ - static int ilog2(unsigned int v){ int ret=0; while(v>1){ @@ -51,71 +51,29 @@ static void _v_readstring(oggpack_buffer *o,char *buf,int bytes){ } } -/* convenience functions for the interface */ -int vorbis_dsp_addcomment(vorbis_dsp_state *v,char *comment){ - vorbis_info *vi=v->vi; - vi->user_comments=realloc(vi->user_comments, - (vi->comments+2)*sizeof(char *)); - vi->user_comments[vi->comments]=strdup(comment); - vi->comments++; - vi->user_comments[vi->comments]=NULL; - return(0); +void vorbis_comment_init(vorbis_comment *vc){ + memset(vc,0,sizeof(vorbis_comment)); } -/* used by analysis, which has a minimally replicated vi */ -void _vorbis_info_anrep(vorbis_info *dest, vorbis_info *source){ - -/* libVorbis expects modes to be submitted in an already valid - vorbis_info structure, but also expects some of the elements to be - allocated storage. To make this easier, the Vorbis distribution - includes a number of modes in static storage as headers. To - allocate a copy, run it through vorbis_info_dup */ - -/* note that due to codebook size, codebooks are not fully duplicated. - The info structure (aside from the embedded codebook elements) will - be fully dupped */ - -int vorbis_info_dup(vorbis_info *dest,vorbis_info *source){ - int i; - memcpy(dest,source,sizeof(vorbis_info)); - - /* also dup individual pieces that need to be allocated */ - /* dup user comments (unlikely to have any, but for completeness */ - if(source->comments>0){ - dest->user_comments=calloc(source->comments+1,sizeof(char *)); - for(i=0;i<source->comments;i++) - dest->user_comments[i]=strdup(source->user_comments[i]); - } - dest->vendor=NULL; - - /* modes, maps, times, floors, residues, psychoacoustics are not - dupped; the pointer is just replicated by the above copy */ - - /* dup (partially) books */ - if(source->books){ - dest->booklist=malloc(source->books*sizeof(codebook *)); - for(i=0;i<source->books;i++){ - dest->booklist[i]=calloc(1,sizeof(codebook)); - vorbis_book_dup(dest->booklist[i],source->booklist[i]); - } - } - - return(0); -err_out: - vorbis_info_clear(dest); - return(-1); +void vorbis_comment_add(vorbis_comment *vc,char *comment){ + vc->user_comments=realloc(vc->user_comments, + (vc->comments+2)*sizeof(char *)); + vc->user_comments[vc->comments]=strdup(comment); + vc->comments++; + vc->user_comments[vc->comments]=NULL; } - - memset(vi,0,sizeof(vorbis_info)); -} - -void vorbis_info_anclear(vorbis_info *vi){ - memset(vi,0,sizeof(vorbis_info)); +void vorbis_comment_clear(vorbis_comment *vc){ + if(vc){ + long i; + for(i=0;i<vc->comments;i++) + if(vc->user_comments[i])free(vc->user_comments[i]); + if(vc->user_comments)free(vc->user_comments); + if(vc->vendor)free(vc->vendor); + } + memset(vc,0,sizeof(vorbis_comment)); } - - /* used by synthesis, which has a full, alloced vi */ void vorbis_info_init(vorbis_info *vi){ memset(vi,0,sizeof(vorbis_info)); @@ -123,62 +81,44 @@ void vorbis_info_init(vorbis_info *vi){ void vorbis_info_clear(vorbis_info *vi){ int i; - if(vi->comments){ - for(i=0;i<vi->comments;i++) - if(vi->user_comments[i])free(vi->user_comments[i]); - free(vi->user_comments); - } - if(vi->vendor)free(vi->vendor); - if(vi->windowtypes)free(vi->windowtypes); - if(vi->transformtypes)free(vi->transformtypes); - if(vi->modes){ - for(i=0;i<vi->modes;i++) - if(vi->mappingtypes[i]>=0 && vi->mappingtypes[i]<VI_MAPB) - vorbis_map_free_P[vi->mappingtypes[i]](vi->modelist[i]); - free(vi->modelist); - free(vi->mappingtypes); - free(vi->blockflags); - } - if(vi->times){ - for(i=0;i<vi->times;i++) - if(vi->timetypes[i]>=0 && vi->timetypes[i]<VI_TIMEB) - vorbis_time_free_P[vi->timetypes[i]](vi->timelist[i]); - free(vi->timelist); - free(vi->timetypes); - } - if(vi->floors){ - for(i=0;i<vi->floors;i++) - if(vi->floortypes[i]>=0 && vi->floortypes[i]<VI_FLOORB) - vorbis_floor_free_P[vi->floortypes[i]](vi->floorlist[i]); - free(vi->floorlist); - free(vi->floortypes); - } - if(vi->residues){ - for(i=0;i<vi->residues;i++) - if(vi->residuetypes[i]>=0 && vi->residuetypes[i]<VI_RESB) - vorbis_res_free_P[vi->residuetypes[i]](vi->residuelist[i]); - free(vi->residuelist); - free(vi->residuetypes); - } - if(vi->books){ - for(i=0;i<vi->books;i++){ - if(vi->booklist[i]){ - vorbis_book_clear(vi->booklist[i]); - free(vi->booklist[i]); - } + + for(i=0;i<vi->modes;i++) + if(vi->mode_param[i])free(vi->mode_param[i]); + if(vi->mode_param)free(vi->mode_param); + + for(i=0;i<vi->maps;i++) /* unpack does the range checking */ + _mapping_P[i]->free_info(vi->map_param[i]); + if(vi->map_param)free(vi->map_param); + + for(i=0;i<vi->times;i++) /* unpack does the range checking */ + _time_P[i]->free_info(vi->time_param[i]); + if(vi->time_param)free(vi->time_param); + + for(i=0;i<vi->floors;i++) /* unpack does the range checking */ + _floor_P[i]->free_info(vi->floor_param[i]); + if(vi->floor_param)free(vi->floor_param); + + for(i=0;i<vi->residues;i++) /* unpack does the range checking */ + _residue_P[i]->free_info(vi->residue_param[i]); + if(vi->residue_param)free(vi->residue_param); + + /* the static codebooks *are* freed if you call info_clear, because + decode side does alloc a 'static' codebook. Calling clear on the + full codebook does not clear the static codebook (that's our + responsibility) */ + for(i=0;i<vi->books;i++){ + /* just in case the decoder pre-cleared to save space */ + if(vi->book_param[i]){ + vorbis_staticbook_clear(vi->book_param[i]); + free(vi->book_param[i]); } - free(vi->booklist); } - if(vi->psys){ - for(i=0;i<vi->psys;i++) - _vi_psy_free(vi->psylist[i]); - free(vi->psylist); - } - - if(vi->header)free(vi->header); - if(vi->header1)free(vi->header1); - if(vi->header2)free(vi->header2); + if(vi->book_param)free(vi->book_param); + for(i=0;i<vi->psys;i++) + _vi_psy_free(vi->psy_param[i]); + if(vi->psy_param)free(vi->psy_param); + memset(vi,0,sizeof(vorbis_info)); } @@ -211,27 +151,27 @@ static int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb){ return(-1); } -static int _vorbis_unpack_comments(vorbis_info *vi,oggpack_buffer *opb){ +static int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb){ int i; int vendorlen=_oggpack_read(opb,32); if(vendorlen<0)goto err_out; - vi->vendor=calloc(vendorlen+1,1); - _v_readstring(opb,vi->vendor,vendorlen); - vi->comments=_oggpack_read(opb,32); - if(vi->comments<0)goto err_out; - vi->user_comments=calloc(vi->comments+1,sizeof(char **)); + vc->vendor=calloc(vendorlen+1,1); + _v_readstring(opb,vc->vendor,vendorlen); + vc->comments=_oggpack_read(opb,32); + if(vc->comments<0)goto err_out; + vc->user_comments=calloc(vc->comments+1,sizeof(char **)); - for(i=0;i<vi->comments;i++){ + for(i=0;i<vc->comments;i++){ int len=_oggpack_read(opb,32); if(len<0)goto err_out; - vi->user_comments[i]=calloc(len+1,1); - _v_readstring(opb,vi->user_comments[i],len); + vc->user_comments[i]=calloc(len+1,1); + _v_readstring(opb,vc->user_comments[i],len); } if(_oggpack_read(opb,1)!=1)goto err_out; /* EOP check */ return(0); err_out: - vorbis_info_clear(vi); + vorbis_comment_clear(vc); return(-1); } @@ -240,71 +180,77 @@ static int _vorbis_unpack_comments(vorbis_info *vi,oggpack_buffer *opb){ static int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb){ int i; + /* codebooks */ + vi->books=_oggpack_read(opb,16); + vi->book_param=calloc(vi->books,sizeof(static_codebook *)); + for(i=0;i<vi->books;i++){ + vi->book_param[i]=calloc(1,sizeof(static_codebook)); + if(vorbis_staticbook_unpack(opb,vi->book_param[i]))goto err_out; + } + /* time backend settings */ vi->times=_oggpack_read(opb,8); - vi->timetypes=malloc(vi->times*sizeof(int)); - vi->timelist=calloc(vi->times,sizeof(void *)); + vi->time_type=malloc(vi->times*sizeof(int)); + vi->time_param=calloc(vi->times,sizeof(void *)); for(i=0;i<vi->times;i++){ - vi->timetypes[i]=_oggpack_read(opb,16); - if(vi->timetypes[i]<0 || vi->timetypes[i]>VI_TIMEB)goto err_out; - vi->timelist[i]=vorbis_time_unpack_P[vi->timetypes[i]](vi,opb); - if(!vi->timelist[i])goto err_out; + vi->time_type[i]=_oggpack_read(opb,16); + if(vi->time_type[i]<0 || vi->time_type[i]>=VI_TIMEB)goto err_out; + vi->time_param[i]=_time_P[vi->time_type[i]]->unpack(vi,opb); + if(!vi->time_param[i])goto err_out; } /* floor backend settings */ vi->floors=_oggpack_read(opb,8); - vi->floortypes=malloc(vi->floors*sizeof(int)); - vi->floorlist=calloc(vi->floors,sizeof(void *)); + vi->floor_type=malloc(vi->floors*sizeof(int)); + vi->floor_param=calloc(vi->floors,sizeof(void *)); for(i=0;i<vi->floors;i++){ - vi->floortypes[i]=_oggpack_read(opb,16); - if(vi->floortypes[i]<0 || vi->floortypes[i]>VI_FLOORB)goto err_out; - vi->floorlist[i]=vorbis_floor_unpack_P[vi->floortypes[i]](vi,opb); - if(!vi->floorlist[i])goto err_out; + vi->floor_type[i]=_oggpack_read(opb,16); + if(vi->floor_type[i]<0 || vi->floor_type[i]>=VI_FLOORB)goto err_out; + vi->floor_param[i]=_floor_P[vi->floor_type[i]]->unpack(vi,opb); + if(!vi->floor_param[i])goto err_out; } /* residue backend settings */ vi->residues=_oggpack_read(opb,8); - vi->residuetypes=malloc(vi->residues*sizeof(int)); - vi->residuelist=calloc(vi->residues,sizeof(void *)); + vi->residue_type=malloc(vi->residues*sizeof(int)); + vi->residue_param=calloc(vi->residues,sizeof(void *)); for(i=0;i<vi->residues;i++){ - vi->residuetypes[i]=_oggpack_read(opb,16); - if(vi->residuetypes[i]<0 || vi->residuetypes[i]>VI_RESB)goto err_out; - vi->residuelist[i]=vorbis_res_unpack_P[vi->residuetypes[i]](vi,opb); - if(!vi->residuelist[i])goto err_out; + vi->residue_type[i]=_oggpack_read(opb,16); + if(vi->residue_type[i]<0 || vi->residue_type[i]>=VI_RESB)goto err_out; + vi->residue_param[i]=_residue_P[vi->residue_type[i]]->unpack(vi,opb); + if(!vi->residue_param[i])goto err_out; } - /* codebooks */ - vi->books=_oggpack_read(opb,16); - vi->booklist=calloc(vi->books,sizeof(codebook *)); - for(i=0;i<vi->books;i++){ - vi->booklist[i]=calloc(1,sizeof(codebook)); - if(vorbis_book_unpack(opb,vi->booklist[i]))goto err_out; + /* map backend settings */ + vi->maps=_oggpack_read(opb,8); + vi->map_type=malloc(vi->maps*sizeof(int)); + vi->map_param=calloc(vi->maps,sizeof(void *)); + for(i=0;i<vi->maps;i++){ + vi->map_type[i]=_oggpack_read(opb,16); + if(vi->map_type[i]<0 || vi->map_type[i]>=VI_MAPB)goto err_out; + vi->map_param[i]=_mapping_P[vi->map_type[i]]->unpack(vi,opb); + if(!vi->map_param[i])goto err_out; } - - /* modes/mappings; these are loaded last in order that the mappings - can range-check their time/floor/res/book settings */ + + /* mode settings */ vi->modes=_oggpack_read(opb,8); - vi->blockflags=malloc(vi->modes*sizeof(int)); - vi->windowtypes=malloc(vi->modes*sizeof(int)); - vi->transformtypes=malloc(vi->modes*sizeof(int)); - vi->mappingtypes=malloc(vi->modes*sizeof(int)); - vi->modelist=calloc(vi->modes,sizeof(void *)); + vi->mode_param=calloc(vi->modes,sizeof(void *)); for(i=0;i<vi->modes;i++){ - vi->blockflags[i]=_oggpack_read(opb,1); - vi->windowtypes[i]=_oggpack_read(opb,16); - vi->transformtypes[i]=_oggpack_read(opb,16); - vi->mappingtypes[i]=_oggpack_read(opb,16); - if(vi->windowtypes[i]<0 || vi->windowtypes[i]>VI_WINDOWB)goto err_out; - if(vi->transformtypes[i]<0 || vi->transformtypes[i]>VI_TRANSFORMB)goto err_out; - if(vi->mappingtypes[i]<0 || vi->mappingtypes[i]>VI_MAPB)goto err_out; - vi->modelist[i]=vorbis_map_unpack_P[vi->mappingtypes[i]](vi,opb); - if(!vi->modelist[i])goto err_out; + vi->mode_param[i]=calloc(1,sizeof(vorbis_info_mode)); + vi->mode_param[i]->blockflag=_oggpack_read(opb,1); + vi->mode_param[i]->windowtype=_oggpack_read(opb,16); + vi->mode_param[i]->transformtype=_oggpack_read(opb,16); + vi->mode_param[i]->mapping=_oggpack_read(opb,8); + + if(vi->mode_param[i]->windowtype>=VI_WINDOWB)goto err_out; + if(vi->mode_param[i]->transformtype>=VI_WINDOWB)goto err_out; + if(vi->mode_param[i]->mapping>=vi->maps)goto err_out; } - + if(_oggpack_read(opb,1)!=1)goto err_out; /* top level EOP check */ return(0); -err_out: + err_out: vorbis_info_clear(vi); return(-1); } @@ -314,8 +260,7 @@ err_out: with bitstream comments and a third packet that holds the codebook. */ -int vorbis_info_headerin(vorbis_info *vi,ogg_packet *op){ - +int vorbis_synthesis_headerin(vorbis_info *vi,vorbis_comment *vc,ogg_packet *op){ oggpack_buffer opb; if(op){ @@ -350,10 +295,10 @@ int vorbis_info_headerin(vorbis_info *vi,ogg_packet *op){ return(-1); } - return(_vorbis_unpack_comments(vi,&opb)); + return(_vorbis_unpack_comment(vc,&opb)); case 0x82: - if(vi->rate==0 || vi->vendor==NULL){ + if(vi->rate==0 || vc->vendor==NULL){ /* um... we didn;t get the initial header or comments yet */ return(-1); } @@ -393,8 +338,8 @@ static int _vorbis_pack_info(oggpack_buffer *opb,vorbis_info *vi){ return(0); } -static int _vorbis_pack_comments(oggpack_buffer *opb,vorbis_info *vi){ - char temp[]="Xiphophorus libVorbis I 20000114"; +static int _vorbis_pack_comment(oggpack_buffer *opb,vorbis_comment *vc){ + char temp[]="Xiphophorus libVorbis I 20000121"; /* preamble */ _v_writestring(opb,"vorbis"); @@ -406,13 +351,13 @@ static int _vorbis_pack_comments(oggpack_buffer *opb,vorbis_info *vi){ /* comments */ - _oggpack_write(opb,vi->comments,32); - if(vi->comments){ + _oggpack_write(opb,vc->comments,32); + if(vc->comments){ int i; - for(i=0;i<vi->comments;i++){ - if(vi->user_comments[i]){ - _oggpack_write(opb,strlen(vi->user_comments[i]),32); - _v_writestring(opb,vi->user_comments[i]); + for(i=0;i<vc->comments;i++){ + if(vc->user_comments[i]){ + _oggpack_write(opb,strlen(vc->user_comments[i]),32); + _v_writestring(opb,vc->user_comments[i]); }else{ _oggpack_write(opb,0,32); } @@ -428,43 +373,47 @@ static int _vorbis_pack_books(oggpack_buffer *opb,vorbis_info *vi){ _v_writestring(opb,"vorbis"); _oggpack_write(opb,0x82,8); + /* books */ + _oggpack_write(opb,vi->books,16); + for(i=0;i<vi->books;i++) + if(vorbis_staticbook_pack(vi->book_param[i],opb))goto err_out; + /* times */ _oggpack_write(opb,vi->times,8); for(i=0;i<vi->times;i++){ - _oggpack_write(opb,vi->timetypes[i],16); - vorbis_time_pack_P[vi->timetypes[i]](opb,vi->timelist[i]); + _oggpack_write(opb,vi->time_type[i],16); + _time_P[vi->time_type[i]]->pack(vi->time_param[i],opb); } /* floors */ _oggpack_write(opb,vi->floors,8); for(i=0;i<vi->floors;i++){ - _oggpack_write(opb,vi->floortypes[i],16); - vorbis_floor_pack_P[vi->floortypes[i]](opb,vi->floorlist[i]); + _oggpack_write(opb,vi->floor_type[i],16); + _floor_P[vi->floor_type[i]]->pack(vi->floor_param[i],opb); } /* residues */ _oggpack_write(opb,vi->residues,8); for(i=0;i<vi->residues;i++){ - _oggpack_write(opb,vi->residuetypes[i],16); - vorbis_res_pack_P[vi->residuetypes[i]](opb,vi->residuelist[i]); + _oggpack_write(opb,vi->residue_type[i],16); + _residue_P[vi->residue_type[i]]->pack(vi->residue_param[i],opb); } - /* books */ - _oggpack_write(opb,vi->books,16); - for(i=0;i<vi->books;i++) - if(vorbis_book_pack(vi->booklist[i],opb))goto err_out; - - /* mode mappings */ + /* maps */ + _oggpack_write(opb,vi->maps,8); + for(i=0;i<vi->maps;i++){ + _oggpack_write(opb,vi->map_type[i],16); + _mapping_P[vi->map_type[i]]->pack(vi,vi->map_param[i],opb); + } + /* modes */ _oggpack_write(opb,vi->modes,8); for(i=0;i<vi->modes;i++){ - _oggpack_write(opb,vi->blockflags[i],1); - _oggpack_write(opb,vi->windowtypes[i],16); - _oggpack_write(opb,vi->transformtypes[i],16); - _oggpack_write(opb,vi->mappingtypes[i],16); - vorbis_map_pack_P[vi->mappingtypes[i]](vi,opb,vi->modelist[i]); + _oggpack_write(opb,vi->mode_param[i]->blockflag,1); + _oggpack_write(opb,vi->mode_param[i]->windowtype,16); + _oggpack_write(opb,vi->mode_param[i]->transformtype,16); + _oggpack_write(opb,vi->mode_param[i]->mapping,8); } - _oggpack_write(opb,1,1); return(0); @@ -473,6 +422,7 @@ err_out: } int vorbis_analysis_headerout(vorbis_dsp_state *v, + vorbis_comment *vc, ogg_packet *op, ogg_packet *op_comm, ogg_packet *op_code){ @@ -499,7 +449,7 @@ int vorbis_analysis_headerout(vorbis_dsp_state *v, _oggpack_reset(&opb); _v_writestring(&opb,"vorbis"); _oggpack_write(&opb,0x81,8); - if(_vorbis_pack_comments(&opb,vi))goto err_out; + if(_vorbis_pack_comment(&opb,vc))goto err_out; if(v->header1)free(v->header1); v->header1=malloc(_oggpack_bytes(&opb)); @@ -533,6 +483,13 @@ int vorbis_analysis_headerout(vorbis_dsp_state *v, memset(op,0,sizeof(ogg_packet)); memset(op_comm,0,sizeof(ogg_packet)); memset(op_code,0,sizeof(ogg_packet)); + + if(v->header)free(v->header); + if(v->header1)free(v->header1); + if(v->header2)free(v->header2); + v->header=NULL; + v->header1=NULL; + v->header2=NULL; return(-1); } @@ -12,7 +12,7 @@ ******************************************************************** function: LPC low level routines - last mod: $Id: lpc.c,v 1.14 2000/01/20 04:43:01 xiphmont Exp $ + last mod: $Id: lpc.c,v 1.15 2000/01/28 09:05:11 xiphmont Exp $ ********************************************************************/ @@ -352,23 +352,6 @@ void vorbis_lpc_to_curve(double *curve,double *lpc,double amp,lpc_lookup *l){ #endif } -void vorbis_lpc_apply(double *residue,double *lpc,double amp,lpc_lookup *l){ - double *lcurve=alloca(sizeof(double)*((l->ln+l->n)*2)); - int i; - - if(amp==0){ - memset(residue,0,l->n*sizeof(double)); - }else{ - - _vlpc_de_helper(lcurve,lpc,amp,l); - - for(i=0;i<l->ln;i++)lcurve[i]/=l->barknorm[i]; - for(i=0;i<l->n;i++) - if(residue[i]!=0) - residue[i]*=lcurve[l->linearmap[i]]; - } -} - /* subtract or add an lpc filter to data. Vorbis doesn't actually use this. */ void vorbis_lpc_residue(double *coeff,double *prime,int m, @@ -12,7 +12,7 @@ ******************************************************************** function: LPC low level routines - last mod: $Id: lpc.h,v 1.8 2000/01/22 13:28:22 xiphmont Exp $ + last mod: $Id: lpc.h,v 1.9 2000/01/28 09:05:12 xiphmont Exp $ ********************************************************************/ @@ -45,8 +45,6 @@ extern double vorbis_lpc_from_spectrum(double *curve,double *lpc,lpc_lookup *l); extern double vorbis_curve_to_lpc(double *curve,double *lpc,lpc_lookup *l); extern void vorbis_lpc_to_curve(double *curve,double *lpc, double amp, lpc_lookup *l); -extern void vorbis_lpc_apply(double *residue,double *lpc, double amp, - lpc_lookup *l); /* standard lpc stuff */ extern void vorbis_lpc_residue(double *coeff,double *prime,int m, diff --git a/lib/mapping0.c b/lib/mapping0.c index 6339190a..0ac237fb 100644 --- a/lib/mapping0.c +++ b/lib/mapping0.c @@ -12,7 +12,7 @@ ******************************************************************** function: channel mapping 0 implementation - last mod: $Id: mapping0.c,v 1.2 2000/01/22 13:28:23 xiphmont Exp $ + last mod: $Id: mapping0.c,v 1.3 2000/01/28 09:05:13 xiphmont Exp $ ********************************************************************/ @@ -20,30 +20,43 @@ #include <string.h> #include <math.h> #include "vorbis/codec.h" +#include "vorbis/backends.h" #include "bitwise.h" #include "bookinternal.h" #include "registry.h" -#include "mapping0.h" +#include "psy.h" +#include "misc.h" -_vi_info_map *_vorbis_map0_dup(vorbis_info *vi,_vi_info_map *source){ - vorbis_info_mapping0 *d=malloc(sizeof(vorbis_info_mapping0)); - vorbis_info_mapping0 *s=(vorbis_info_mapping0 *)source; - memcpy(d,s,sizeof(vorbis_info_mapping0)); +/* simplistic, wasteful way of doing this (unique lookup for each + mode/submapping); there should be a central repository for + identical lookups. That will require minor work, so I'm putting it + off as low priority. - d->floorsubmap=malloc(sizeof(int)*vi->channels); - d->residuesubmap=malloc(sizeof(int)*vi->channels); - d->psysubmap=malloc(sizeof(int)*vi->channels); - memcpy(d->floorsubmap,s->floorsubmap,sizeof(int)*vi->channels); - memcpy(d->residuesubmap,s->residuesubmap,sizeof(int)*vi->channels); - memcpy(d->psysubmap,s->psysubmap,sizeof(int)*vi->channels); + Why a lookup for each backend in a given mode? Because the + blocksize is set by the mode, and low backend lookups may require + parameters from other areas of the mode/mapping */ - return(d); -} +typedef struct { + vorbis_info_mode *mode; + vorbis_info_mapping0 *map; + + vorbis_look_time **time_look; + vorbis_look_floor **floor_look; + vorbis_look_residue **residue_look; + vorbis_look_psy *psy_look; + + vorbis_func_time **time_func; + vorbis_func_floor **floor_func; + vorbis_func_residue **residue_func; + +} vorbis_look_mapping0; -void _vorbis_map0_free(_vi_info_map *i){ +void free_info(vorbis_info_mapping *i){ vorbis_info_mapping0 *d=(vorbis_info_mapping0 *)i; if(d){ + if(d->chmuxlist)free(d->chmuxlist); + if(d->timesubmap)free(d->timesubmap); if(d->floorsubmap)free(d->floorsubmap); if(d->residuesubmap)free(d->residuesubmap); if(d->psysubmap)free(d->psysubmap); @@ -52,80 +65,118 @@ void _vorbis_map0_free(_vi_info_map *i){ } } -void _vorbis_map0_pack(vorbis_info *vi,oggpack_buffer *opb, - _vi_info_map *source){ +void free_look(vorbis_look_mapping *look){ int i; - vorbis_info_mapping0 *d=(vorbis_info_mapping0 *)source; - - _oggpack_write(opb,d->timesubmap,8); - - /* we abbreviate the channel submappings if they all map to the same - floor/res/psy */ - for(i=1;i<vi->channels;i++)if(d->floorsubmap[i]!=d->floorsubmap[i-1])break; - if(i==vi->channels){ - _oggpack_write(opb,0,1); - _oggpack_write(opb,d->floorsubmap[0],8); - }else{ - _oggpack_write(opb,1,1); - for(i=0;i<vi->channels;i++) - _oggpack_write(opb,d->floorsubmap[i],8); + vorbis_look_mapping0 *l=(vorbis_look_mapping0 *)look; + if(l){ + for(i=0;i<l->map->submaps;i++){ + l->time_func[i]->free_look(l->time_look[i]); + l->floor_func[i]->free_look(l->floor_look[i]); + l->residue_func[i]->free_look(l->residue_look[i]); + if(l->psy_look)_vp_psy_clear(l->psy_look+i); + } + free(l->time_func); + free(l->floor_func); + free(l->residue_func); + free(l->time_look); + free(l->floor_look); + free(l->residue_look); + if(l->psy_look)free(l->psy_look); + memset(l,0,sizeof(vorbis_info_mapping0)); + free(l); + } +} + +vorbis_look_mapping *look(vorbis_info *vi,vorbis_info_mode *vm, + vorbis_info_mapping *m){ + int i; + vorbis_look_mapping0 *ret=calloc(1,sizeof(vorbis_look_mapping0)); + vorbis_info_mapping0 *map=ret->map=(vorbis_info_mapping0 *)m; + ret->mode=vm; + + ret->time_look=calloc(map->submaps,sizeof(vorbis_look_time *)); + ret->floor_look=calloc(map->submaps,sizeof(vorbis_look_floor *)); + ret->residue_look=calloc(map->submaps,sizeof(vorbis_look_residue *)); + ret->psy_look=calloc(map->submaps,sizeof(vorbis_look_psy)); + + ret->time_func=calloc(map->submaps,sizeof(vorbis_func_time *)); + ret->floor_func=calloc(map->submaps,sizeof(vorbis_func_floor *)); + ret->residue_func=calloc(map->submaps,sizeof(vorbis_func_residue *)); + + for(i=0;i<map->submaps;i++){ + int timenum=map->timesubmap[i]; + int floornum=map->floorsubmap[i]; + int resnum=map->residuesubmap[i]; + + ret->time_func[i]=_time_P[vi->time_type[timenum]]; + ret->time_look[i]=ret->time_func[i]-> + look(vi,vm,vi->time_param[timenum]); + ret->floor_func[i]=_floor_P[vi->floor_type[floornum]]; + ret->floor_look[i]=ret->floor_func[i]-> + look(vi,vm,vi->floor_param[floornum]); + ret->residue_func[i]=_residue_P[vi->residue_type[resnum]]; + ret->residue_look[i]=ret->residue_func[i]-> + look(vi,vm,vi->residue_param[resnum]); + + if(map->psysubmap){ + int psynum=map->psysubmap[i]; + _vp_psy_init(ret->psy_look+i,vi->psy_param[psynum], + vi->blocksizes[vm->blockflag],vi->rate); + } } - for(i=1;i<vi->channels;i++) - if(d->residuesubmap[i]!=d->residuesubmap[i-1])break; - if(i==vi->channels){ - /* no channel submapping */ - _oggpack_write(opb,0,1); - _oggpack_write(opb,d->residuesubmap[0],8); - }else{ - /* channel submapping */ - _oggpack_write(opb,1,1); + return(ret); +} + +void pack(vorbis_info *vi,vorbis_info_mapping *vm,oggpack_buffer *opb){ + int i; + vorbis_info_mapping0 *d=(vorbis_info_mapping0 *)vm; + + _oggpack_write(opb,d->submaps,4); + /* we don't write the channel submappings if we only have one... */ + if(d->submaps>1){ for(i=0;i<vi->channels;i++) - _oggpack_write(opb,d->residuesubmap[i],8); + _oggpack_write(opb,d->chmuxlist[i],4); + } + for(i=0;i<d->submaps;i++){ + _oggpack_write(opb,d->timesubmap[i],8); + _oggpack_write(opb,d->floorsubmap[i],8); + _oggpack_write(opb,d->residuesubmap[i],8); } } /* also responsible for range checking */ -extern _vi_info_map *_vorbis_map0_unpack(vorbis_info *vi,oggpack_buffer *opb){ +vorbis_info_mapping *unpack(vorbis_info *vi,oggpack_buffer *opb){ int i; vorbis_info_mapping0 *d=calloc(1,sizeof(vorbis_info_mapping0)); memset(d,0,sizeof(vorbis_info_mapping0)); - d->timesubmap=_oggpack_read(opb,8); - if(d->timesubmap>=vi->times)goto err_out; + d->submaps=_oggpack_read(opb,4); - d->floorsubmap=malloc(sizeof(int)*vi->channels); - if(_oggpack_read(opb,1)){ - /* channel submap */ - for(i=0;i<vi->channels;i++) - d->floorsubmap[i]=_oggpack_read(opb,8); - }else{ - int temp=_oggpack_read(opb,8); - for(i=0;i<vi->channels;i++) - d->floorsubmap[i]=temp; - } + d->chmuxlist=calloc(vi->channels,sizeof(int)); + d->timesubmap=malloc(sizeof(int)*d->submaps); + d->floorsubmap=malloc(sizeof(int)*d->submaps); + d->residuesubmap=malloc(sizeof(int)*d->submaps); - d->residuesubmap=malloc(sizeof(int)*vi->channels); - if(_oggpack_read(opb,1)){ - /* channel submap */ - for(i=0;i<vi->channels;i++) - d->residuesubmap[i]=_oggpack_read(opb,8); - }else{ - int temp=_oggpack_read(opb,8); - for(i=0;i<vi->channels;i++) - d->residuesubmap[i]=temp; + if(d->submaps>1){ + for(i=0;i<vi->channels;i++){ + d->chmuxlist[i]=_oggpack_read(opb,4); + if(d->chmuxlist[i]>=d->submaps)goto err_out; + } } - - for(i=0;i<vi->channels;i++){ - if(d->floorsubmap[i]<0 || d->floorsubmap[i]>=vi->floors)goto err_out; - if(d->residuesubmap[i]<0 || d->residuesubmap[i]>=vi->residues) - goto err_out; + for(i=0;i<d->submaps;i++){ + d->timesubmap[i]=_oggpack_read(opb,8); + if(d->timesubmap[i]>=vi->times)goto err_out; + d->floorsubmap[i]=_oggpack_read(opb,8); + if(d->floorsubmap[i]>=vi->floors)goto err_out; + d->residuesubmap[i]=_oggpack_read(opb,8); + if(d->residuesubmap[i]>=vi->residues)goto err_out; } return d; err_out: - _vorbis_map0_free(d); + free_info(d); return(NULL); } @@ -140,110 +191,144 @@ extern _vi_info_map *_vorbis_map0_unpack(vorbis_info *vi,oggpack_buffer *opb){ #include "spectrum.h" /* no time mapping implementation for now */ -int _vorbis_map0_analysis(int mode,vorbis_block *vb){ +int forward(vorbis_block *vb,vorbis_look_mapping *l){ vorbis_dsp_state *vd=vb->vd; - oggpack_buffer *opb=&vb->opb; vorbis_info *vi=vd->vi; - vorbis_info_mapping0 *map=(vorbis_info_mapping0 *)(vi->modelist[mode]); + vorbis_look_mapping0 *look=(vorbis_look_mapping0 *)l; + vorbis_info_mapping0 *map=look->map; + vorbis_info_mode *mode=look->mode; int n=vb->pcmend; int i,j; + double *window=vd->window[vb->W][vb->lW][vb->nW][mode->windowtype]; + + double **pcmbundle=alloca(sizeof(double *)*vi->channels); + int **auxbundle=alloca(sizeof(int *)*vi->channels); /* time domain pre-window: NONE IMPLEMENTED */ /* window the PCM data: takes PCM vector, vb; modifies PCM vector */ - { - double *window=vd->window[vb->W][vb->lW][vb->nW][vi->windowtypes[mode]]; - for(i=0;i<vi->channels;i++){ - double *pcm=vb->pcm[i]; - for(j=0;j<n;j++) - pcm[j]*=window[j]; - } + for(i=0;i<vi->channels;i++){ + double *pcm=vb->pcm[i]; + for(j=0;j<n;j++) + pcm[j]*=window[j]; } /* time-domain post-window: NONE IMPLEMENTED */ /* transform the PCM data; takes PCM vector, vb; modifies PCM vector */ /* only MDCT right now.... */ - { - for(i=0;i<vi->channels;i++){ - double *pcm=vb->pcm[i]; - mdct_forward(vd->transform[vb->W][0],pcm,pcm); - } + for(i=0;i<vi->channels;i++){ + double *pcm=vb->pcm[i]; + mdct_forward(vd->transform[vb->W][0],pcm,pcm); } { double *decfloor=_vorbis_block_alloc(vb,n*sizeof(double)/2); double *floor=_vorbis_block_alloc(vb,n*sizeof(double)/2); double *mask=_vorbis_block_alloc(vb,n*sizeof(double)/2); - + int **pcmaux=_vorbis_block_alloc(vb,vi->channels*sizeof(int *)); + for(i=0;i<vi->channels;i++){ double *pcm=vb->pcm[i]; - double *pcmaux=vb->pcm[i]+n/2; - int floorsub=map->floorsubmap[i]; - int ressub=map->residuesubmap[i]; - int psysub=map->psysubmap[i]; - + int submap=map->chmuxlist[i]; + + pcmaux[i]=_vorbis_block_alloc(vb,n/2*sizeof(int)); + /* perform psychoacoustics; takes PCM vector; returns two curves: the desired transform floor and the masking curve */ memset(floor,0,sizeof(double)*n/2); memset(mask,0,sizeof(double)*n/2); - _vp_mask_floor(&vd->psy[psysub],pcm,mask,floor); + _vp_mask_floor(look->psy_look+submap,pcm,mask,floor); /* perform floor encoding; takes transform floor, returns decoded floor */ - vorbis_floor_encode_P[vi->floortypes[floorsub]] - (vi->floorlist[floorsub],vd->floor[floorsub],pcm,floor,decfloor); - - /* perform residue prequantization */ - _vp_quantize(&vd->psy[psysub],pcm,mask,decfloor,pcmaux); + look->floor_func[submap]-> + forward(vb,look->floor_look[submap],floor,decfloor); + /* no iterative residue/floor tuning at the moment */ + + /* perform residue prequantization. Do it now so we have all + the values if we need them */ + _vp_quantize(look->psy_look+submap,pcm,mask,decfloor,pcmaux[i]); + + } + + /* perform residue encoding with residue mapping; this is + multiplexed. All the channels belonging to one submap are + encoded (values interleaved), then the next submap, etc */ + + for(i=0;i<map->submaps;i++){ + int ch_in_bundle=0; + for(j=0;j<vi->channels;j++){ + if(map->chmuxlist[j]==i) + pcmbundle[ch_in_bundle]=vb->pcm[j]; + auxbundle[ch_in_bundle++]=pcmaux[j]; + } + + look->residue_func[i]->forward(vb,look->residue_look[i],pcmbundle,auxbundle, + ch_in_bundle); } } - /* perform residue encoding with residue mapping; this is multiplexed */ - /* multiplexing works like this: The first - - vorbis_res_encode_P[vi->restypes[ressub]] - (vi->reslist[ressub],vd->residue[ressub],pcm,mask,decfloor); - - - return(0); } -int _vorbis_map0_synthesis(int mode,vorbis_block *vb){ - - - - window=vb->vd->window[vb->W][vb->lW][vb->nW]; - - n=vb->pcmend=vi->blocksize[vb->W]; +int inverse(vorbis_block *vb,vorbis_look_mapping *l){ + vorbis_dsp_state *vd=vb->vd; + vorbis_info *vi=vd->vi; + vorbis_look_mapping0 *look=(vorbis_look_mapping0 *)l; + vorbis_info_mapping0 *map=look->map; + vorbis_info_mode *mode=look->mode; + int i,j; + long n=vb->pcmend=vi->blocksizes[vb->W]; + + double *window=vd->window[vb->W][vb->lW][vb->nW][mode->windowtype]; + double **pcmbundle=alloca(sizeof(double *)*vi->channels); - /* No envelope encoding yet */ - _oggpack_read(opb,0,1); + /* time domain information decode (note that applying the + information would have to happen later; we'll probably add a + function entry to the harness for that later */ + /* NOT IMPLEMENTED */ + /* recover the spectral envelope; store it in the PCM vector for now */ for(i=0;i<vi->channels;i++){ - double *lpc=vb->lpc[i]; - double *lsp=vb->lsp[i]; - - /* recover the spectral envelope */ - if(_vs_spectrum_decode(vb,&vb->amp[i],lsp)<0)return(-1); - - /* recover the spectral residue */ - if(_vs_residue_decode(vb,vb->pcm[i])<0)return(-1); + double *pcm=vb->pcm[i]; + int submap=map->chmuxlist[i]; + look->floor_func[submap]->inverse(vb,look->floor_look[submap],pcm); + } - /* LSP->LPC */ - vorbis_lsp_to_lpc(lsp,lpc,vl->m); + /* recover the residue, apply directly to the spectral envelope */ + for(i=0;i<map->submaps;i++){ + int ch_in_bundle=0; + for(j=0;j<vi->channels;j++){ + if(map->chmuxlist[j]==i) + pcmbundle[ch_in_bundle++]=vb->pcm[j]; + } - /* apply envelope to residue */ - - vorbis_lpc_apply(vb->pcm[i],lpc,vb->amp[i],vl); - + look->residue_func[i]->inverse(vb,look->residue_look[i],pcmbundle,ch_in_bundle); + } - /* MDCT->time */ - mdct_backward(&vb->vd->vm[vb->W],vb->pcm[i],vb->pcm[i],window); - + /* transform the PCM data; takes PCM vector, vb; modifies PCM vector */ + /* only MDCT right now.... */ + for(i=0;i<vi->channels;i++){ + double *pcm=vb->pcm[i]; + mdct_backward(vd->transform[vb->W][0],pcm,pcm); } + + /* now apply the decoded pre-window time information */ + /* NOT IMPLEMENTED */ + + /* window the data */ + for(i=0;i<vi->channels;i++){ + double *pcm=vb->pcm[i]; + for(j=0;j<n;j++) + pcm[j]*=window[j]; + } + + /* now apply the decoded post-window time information */ + /* NOT IMPLEMENTED */ + + /* all done! */ return(0); } @@ -12,7 +12,7 @@ ******************************************************************** function: psychoacoustics not including preecho - last mod: $Id: psy.c,v 1.12 2000/01/22 13:28:27 xiphmont Exp $ + last mod: $Id: psy.c,v 1.13 2000/01/28 09:05:14 xiphmont Exp $ ********************************************************************/ @@ -43,9 +43,9 @@ static void set_curve(double *ref,double *c,int n, double crate){ } } -void _vp_psy_init(psy_lookup *p,vorbis_info_psy *vi,int n,long rate){ +void _vp_psy_init(vorbis_look_psy *p,vorbis_info_psy *vi,int n,long rate){ long i; - memset(p,0,sizeof(psy_lookup)); + memset(p,0,sizeof(vorbis_look_psy)); p->maskthresh=malloc(n*sizeof(double)); p->barknum=malloc(n*sizeof(double)); p->vi=vi; @@ -74,18 +74,18 @@ void _vp_psy_init(psy_lookup *p,vorbis_info_psy *vi,int n,long rate){ } -void _vp_psy_clear(psy_lookup *p){ +void _vp_psy_clear(vorbis_look_psy *p){ if(p){ if(p->maskthresh)free(p->maskthresh); if(p->barknum)free(p->barknum); - memset(p,0,sizeof(psy_lookup)); + memset(p,0,sizeof(vorbis_look_psy)); } } /* Masking curve: linear rolloff on a Bark/dB scale, attenuated by maskthresh */ /* right now, floor==mask */ -void _vp_mask_floor(psy_lookup *p,double *f, double *mask,double *floor){ +void _vp_mask_floor(vorbis_look_psy *p,double *f, double *mask,double *floor){ int n=p->n; double hroll=p->vi->hrolldB; double lroll=p->vi->lrolldB; @@ -140,22 +140,3 @@ static void time_convolve(double *s,double *r,int n,int m){ } } -/* for duplicating the info struct */ - -void *_vi_psy_dup(void *i){ - vorbis_info_psy *source=i; - if(source){ - vorbis_info_psy *d=malloc(sizeof(vorbis_info_psy)); - memcpy(d,source,sizeof(vorbis_info_psy)); - return(d); - }else - return(NULL); -} - -void _vi_psy_free(void *i){ - if(i){ - memset(i,0,sizeof(vorbis_info_psy)); - free(i); - } -} - @@ -12,7 +12,7 @@ ******************************************************************** function: random psychoacoustics (not including preecho) - last mod: $Id: psy.h,v 1.6 2000/01/22 13:28:28 xiphmont Exp $ + last mod: $Id: psy.h,v 1.7 2000/01/28 09:05:15 xiphmont Exp $ ********************************************************************/ @@ -26,16 +26,17 @@ typedef struct { double *maskthresh; double *barknum; -} psy_lookup; +} vorbis_look_psy; -extern void _vp_psy_init(psy_lookup *p,vorbis_info_psy *vi,int n,long rate); -extern void _vp_psy_clear(psy_lookup *p); +extern void _vp_psy_init(vorbis_look_psy *p,vorbis_info_psy *vi,int n,long rate); +extern void _vp_psy_clear(vorbis_look_psy *p); extern void *_vi_psy_dup(void *source); extern void _vi_psy_free(void *i); -extern void _vp_mask_floor(psy_lookup *p,double *pcm, +extern void _vp_mask_floor(vorbis_look_psy *p,double *pcm, double *mask,double *floor); - +extern void _vp_quantize(vorbis_look_psy *p, double *pcm, double *mask, + double *floor,int *aux); #endif @@ -12,7 +12,7 @@ ******************************************************************** function: residue backend 0 implementation - last mod: $Id: res0.c,v 1.1 2000/01/20 04:43:04 xiphmont Exp $ + last mod: $Id: res0.c,v 1.2 2000/01/28 09:05:16 xiphmont Exp $ ********************************************************************/ @@ -21,34 +21,44 @@ #include "vorbis/codec.h" #include "bitwise.h" #include "registry.h" -#include "res0.h" /* unfinished as of 20000118 */ -extern _vi_info_res *_vorbis_res0_dup(_vi_info_res *source){ - vorbis_info_res0 *d=malloc(sizeof(vorbis_info_res0)); - memcpy(d,source,sizeof(vorbis_info_res0)); - d->books=malloc(sizeof(int)*d->stages); - memcpy(d->books,((vorbis_info_res0 *)source)->books, - sizeof(int)*d->stages); - return(d); -} -extern void _vorbis_res0_free(_vi_info_res *i){ - vorbis_info_res0 *d=(vorbis_info_res0 *)i; +void free_info(vorbis_info_residue *i){ + vorbis_info_residue0 *d=(vorbis_info_residue0 *)i; if(d){ if(d->books)free(d->books); - memset(d,0,sizeof(vorbis_info_res0)); + memset(d,0,sizeof(vorbis_info_residue0)); free(d); } } +void free_look(vorbis_look_residue *i){ +} + /* not yet */ -extern void _vorbis_res0_pack(oggpack_buffer *opb, _vi_info_res *vi){ +void pack(vorbis_info_residue *vr,oggpack_buffer *opb){ +} + +/* vorbis_info is for range checking */ +vorbis_info_residue *unpack(vorbis_info *vi,oggpack_buffer *opb){ } -extern _vi_info_res *_vorbis_res0_unpack(vorbis_info *vi, - oggpack_buffer *opb){ - vorbis_info_res0 d; - memset(&d,0,sizeof(d)); - return(_vorbis_res0_dup(&d)); +vorbis_look_residue *look (vorbis_info *vi,vorbis_info_mode *vm, + vorbis_info_residue *vr){ } + +int forward(vorbis_block *vb,vorbis_look_residue *l,double **in,int **aux,int ch){ +} +int inverse(vorbis_block *vb,vorbis_look_residue *l,double **in,int ch){ +} + +vorbis_func_residue residue0_exportbundle={ + &pack, + &unpack, + &look, + &free_info, + &free_look, + &forward, + &inverse +}; diff --git a/lib/spectrum.c b/lib/spectrum.c deleted file mode 100644 index 925c8693..00000000 --- a/lib/spectrum.c +++ /dev/null @@ -1,181 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE Ogg Vorbis SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY * - * THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE. * - * PLEASE READ THESE TERMS DISTRIBUTING. * - * * - * THE OggSQUISH SOURCE CODE IS (C) COPYRIGHT 1994-2000 * - * by Monty <monty@xiph.org> and The XIPHOPHORUS Company * - * http://www.xiph.org/ * - * * - ******************************************************************** - - function: spectrum envelope and residue code/decode - last mod: $Id: spectrum.c,v 1.10 2000/01/05 03:11:03 xiphmont Exp $ - - ********************************************************************/ - -#include <stdio.h> -#include <math.h> -#include "vorbis/codec.h" - -#include "os.h" -#include "bitwise.h" -#include "spectrum.h" - -/* this code is still seriously abbreviated. I'm filling in pieces as - we go... --Monty 19991004 */ - -/* unlike other LPC-based coders, we never apply the filter but only - inspect the frequency response, thus we don't need to guard against - instability. However, two coefficients quantising to the same - value will cause the response to explode. */ - -int _vs_spectrum_encode(vorbis_block *vb,double amp,double *lsp){ - /* no real coding yet. Just write out full sized words for now - because people need bitstreams to work with */ - - int scale=vb->W; - int m=vb->vd->vi->floororder[scale]; - int n=vb->pcmend*64; - int last=0; - double dlast=0.; - double min=M_PI/n/2.; - - int bits=rint(log(n)/log(2)); - int i; - -#ifdef TRAIN - if(amp>0){ - FILE *out; - if(vb->W) - out=fopen("lspcoeff-long.vqd","a"); - else - out=fopen("lspcoeff-short.vqd","a"); - - for(i=0;i<m;i++) - fprintf(out,"%lf ",lsp[i]); - fprintf(out,"\n"); - fclose(out); - - if(vb->W) - out=fopen("lspamp-long.vqd","a"); - else - out=fopen("lspamp-short.vqd","a"); - fprintf(out,"%lf\n",amp); - fclose(out); - } -#endif - - _oggpack_write(&vb->opb,amp*32768,18); - - for(i=0;i<m;i++){ - int val=rint(lsp[i]/M_PI*n-last); - _oggpack_write(&vb->opb,val,bits); - - lsp[i]=(last+=val)*M_PI/n; - - /* Underpowered but sufficient for now. In the real spec (coming - soon), a distance of zero can't happen. */ - if(lsp[i]<dlast+min)lsp[i]=dlast+min; - dlast=lsp[i]; - } - return(0); -} - -int _vs_spectrum_decode(vorbis_block *vb,double *amp,double *lsp){ - int scale=vb->W; - int m=vb->vd->vi->floororder[scale]; - int n=vb->pcmend*64; - int last=0; - double dlast=0.; - int bits=rint(log(n)/log(2)); - int i; - double min=M_PI/n/2.; - - *amp=_oggpack_read(&vb->opb,18)/32768.; - - for(i=0;i<m;i++){ - int val=_oggpack_read(&vb->opb,bits); - lsp[i]=(last+=val)*M_PI/n; - - /* Underpowered but sufficient */ - if(lsp[i]<dlast+min)lsp[i]=dlast+min; - dlast=lsp[i]; - } - return(0); -} - -void _vs_residue_train(vorbis_block *vb,double *data,double *curve,int n){ - int i; - FILE *out; - if(vb->W) - out=fopen("residue-long.vqd","a"); - else - out=fopen("residue-short.vqd","a"); - - for(i=0;i<n;i++){ - double val=0; - if(curve[i]!=0.)val=data[i]/curve[i]; - fprintf(out,"%lf ",val); - } - fprintf(out,"\n"); - fclose(out); -} - -void _vs_residue_quantize(double *data,double *curve, - vorbis_info *vi,int n){ - - /* The following is temporary, hardwired bullshit */ - int i; - - for(i=0;i<n;i++){ - int val=0; - - if(curve[i]!=0.)val=rint(data[i]/curve[i]); - if(val>31)val=31; - if(val<-31)val=-31; - - - /*if(val==0){ - if(data[i]<0){ - val=-1; - }else{ - val=1; - } - }*/ - - data[i]=val; - - } -} - -int _vs_residue_encode(vorbis_block *vb,double *data){ - /* no real coding yet. Just write out full sized words for now - because people need bitstreams to work with */ - - int n=vb->pcmend/2; - int i; - - for(i=0;i<n;i++){ - _oggpack_write(&vb->opb,(int)(data[i]+31),6); - } - - return(0); -} - -int _vs_residue_decode(vorbis_block *vb,double *data){ - /* no real coding yet. Just write out full sized words for now - because people need bitstreams to work with */ - - int n=vb->pcmend/2; - int i; - - for(i=0;i<n;i++){ - data[i]=_oggpack_read(&vb->opb,6)-31; - /*if(data[i]>=0)data[i]+=1;*/ - } - return(0); -} - diff --git a/lib/vorbisfile.c b/lib/vorbisfile.c index a38b357a..5f812d69 100644 --- a/lib/vorbisfile.c +++ b/lib/vorbisfile.c @@ -12,7 +12,7 @@ ******************************************************************** function: stdio-based convenience library for opening/seeking/decoding - last mod: $Id: vorbisfile.c,v 1.13 2000/01/10 14:06:31 xiphmont Exp $ + last mod: $Id: vorbisfile.c,v 1.14 2000/01/28 09:05:18 xiphmont Exp $ ********************************************************************/ @@ -197,7 +197,8 @@ static void _bisect_forward_serialno(OggVorbis_File *vf, /* uses the local ogg_stream storage in vf; this is important for non-streaming input sources */ -static int _fetch_headers(OggVorbis_File *vf,vorbis_info *vi,long *serialno){ +static int _fetch_headers(OggVorbis_File *vf,vorbis_info *vi,vorbis_comment *vc, + long *serialno){ ogg_page og; ogg_packet op; int i,ret; @@ -214,8 +215,8 @@ static int _fetch_headers(OggVorbis_File *vf,vorbis_info *vi,long *serialno){ /* extract the initial header from the first page and verify that the Ogg bitstream is in fact Vorbis data */ - vorbis_info_clear(vi); vorbis_info_init(vi); + vorbis_comment_init(vc); i=0; while(i<3){ @@ -227,7 +228,7 @@ static int _fetch_headers(OggVorbis_File *vf,vorbis_info *vi,long *serialno){ fprintf(stderr,"Corrupt header in logical bitstream.\n"); goto bail_header; } - if(vorbis_info_headerin(vi,&op)){ + if(vorbis_synthesis_headerin(vi,vc,&op)){ fprintf(stderr,"Illegal header in logical bitstream.\n"); goto bail_header; } @@ -244,6 +245,7 @@ static int _fetch_headers(OggVorbis_File *vf,vorbis_info *vi,long *serialno){ bail_header: vorbis_info_clear(vi); + vorbis_comment_clear(vc); ogg_stream_clear(&vf->os); return -1; } @@ -252,7 +254,8 @@ static int _fetch_headers(OggVorbis_File *vf,vorbis_info *vi,long *serialno){ vorbis_info structs and PCM positions. Only called by the seekable initialization (local stream storage is hacked slightly; pay attention to how that's done) */ -static void _prefetch_all_headers(OggVorbis_File *vf,vorbis_info *first, +static void _prefetch_all_headers(OggVorbis_File *vf,vorbis_info *first_i, + vorbis_comment *first_c, long dataoffset){ ogg_page og; int i,ret; @@ -263,19 +266,18 @@ static void _prefetch_all_headers(OggVorbis_File *vf,vorbis_info *first, vf->serialnos=malloc(vf->links*sizeof(long)); for(i=0;i<vf->links;i++){ - if(first && i==0){ + if(first_i && first_c && i==0){ /* we already grabbed the initial header earlier. This just saves the waste of grabbing it again */ - memcpy(vf->vi+i,first,sizeof(vorbis_info)); - memset(first,0,sizeof(vorbis_info)); + memcpy(vf->vi+i,first_i,sizeof(vorbis_info)); + memcpy(vf->vc+i,first_c,sizeof(vorbis_comment)); vf->dataoffsets[i]=dataoffset; }else{ /* seek to the location of the initial header */ _seek_helper(vf,vf->offsets[i]); - if(_fetch_headers(vf,vf->vi+i,NULL)==-1){ - vorbis_info_clear(vf->vi+i); + if(_fetch_headers(vf,vf->vi+i,vf->vc+i,NULL)==-1){ fprintf(stderr,"Error opening logical bitstream #%d.\n\n",i+1); ogg_stream_clear(&vf->os); /* clear local storage. This is not @@ -301,6 +303,7 @@ static void _prefetch_all_headers(OggVorbis_File *vf,vorbis_info *first, fprintf(stderr,"Could not find last page of logical " "bitstream #%d\n\n",i); vorbis_info_clear(vf->vi+i); + vorbis_comment_clear(vf->vc+i); break; } if(ogg_page_frameno(&og)!=-1){ @@ -314,15 +317,17 @@ static void _prefetch_all_headers(OggVorbis_File *vf,vorbis_info *first, } static int _open_seekable(OggVorbis_File *vf){ - vorbis_info initial; + vorbis_info initial_i; + vorbis_comment initial_c; long serialno,end; int ret; long dataoffset; ogg_page og; /* is this even vorbis...? */ - memset(&initial,0,sizeof(vorbis_info)); - ret=_fetch_headers(vf,&initial,&serialno); + vorbis_info_init(&initial_i); + vorbis_comment_init(&initial_c); + ret=_fetch_headers(vf,&initial_i,&initial_c,&serialno); dataoffset=vf->offset; ogg_stream_clear(&vf->os); if(ret==-1)return(-1); @@ -350,7 +355,7 @@ static int _open_seekable(OggVorbis_File *vf){ } - _prefetch_all_headers(vf,&initial,dataoffset); + _prefetch_all_headers(vf,&initial_i,&initial_c,dataoffset); ov_raw_seek(vf,0); return(0); @@ -362,7 +367,7 @@ static int _open_nonseekable(OggVorbis_File *vf){ vf->vi=malloc(sizeof(vorbis_info)); /* Try to fetch the headers, maintaining all the storage */ - if(_fetch_headers(vf,vf->vi,&vf->current_serialno)==-1)return(-1); + if(_fetch_headers(vf,vf->vi,vf->vc,&vf->current_serialno)==-1)return(-1); return 0; } @@ -477,7 +482,7 @@ static int _process_packet(OggVorbis_File *vf,int readp){ /* we're streaming */ /* fetch the three header packets, build the info struct */ - _fetch_headers(vf,vf->vi,&vf->current_serialno); + _fetch_headers(vf,vf->vi,vf->vc,&vf->current_serialno); vf->current_link++; link=0; } @@ -505,8 +510,10 @@ int ov_clear(OggVorbis_File *vf){ if(vf->vi && vf->links){ int i; - for(i=0;i<vf->links;i++) + for(i=0;i<vf->links;i++){ vorbis_info_clear(vf->vi+i); + vorbis_comment_clear(vf->vc+i); + } free(vf->vi); } if(vf->dataoffsets)free(vf->dataoffsets); @@ -919,6 +926,27 @@ vorbis_info *ov_info(OggVorbis_File *vf,int link){ } } +/* grr, strong typing, grr, no templates/inheritence, grr */ +vorbis_comment *ov_comment(OggVorbis_File *vf,int link){ + if(vf->seekable){ + if(link<0) + if(vf->decode_ready) + return vf->vc+vf->current_link; + else + return NULL; + else + if(link>=vf->links) + return NULL; + else + return vf->vc+link; + }else{ + if(vf->decode_ready) + return vf->vc; + else + return NULL; + } +} + /* up to this point, everything could more or less hide the multiple logical bitstream nature of chaining from the toplevel application if the toplevel application didn't particularly care. However, at |
