diff options
author | Monty <xiphmont@xiph.org> | 2001-05-01 17:08:38 +0000 |
---|---|---|
committer | Monty <xiphmont@xiph.org> | 2001-05-01 17:08:38 +0000 |
commit | 960ced80d48ca81fe122ed1c390285df04d4ab64 (patch) | |
tree | 5ee55ab05830027dea0f823c8ffe42af83fde382 | |
parent | 2b1605de070613fa21f435844d9c5ea8a3688f19 (diff) | |
download | libvorbis-git-960ced80d48ca81fe122ed1c390285df04d4ab64.tar.gz |
Floor 1 is now functional. Time for full QA.
Monty
svn path=/branches/monty-branch-20010404/vorbis/; revision=1437
-rw-r--r-- | lib/Makefile.am | 43 | ||||
-rw-r--r-- | lib/barkmel.c | 8 | ||||
-rw-r--r-- | lib/floor1.c | 150 | ||||
-rw-r--r-- | lib/info.c | 589 | ||||
-rw-r--r-- | lib/mapping0.c | 3 | ||||
-rw-r--r-- | lib/modes/mode_A.h | 64 | ||||
-rw-r--r-- | lib/vorbisenc.c | 157 |
7 files changed, 945 insertions, 69 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am new file mode 100644 index 00000000..8751b151 --- /dev/null +++ b/lib/Makefile.am @@ -0,0 +1,43 @@ +## Process this file with automake to produce Makefile.in + +AUTOMAKE_OPTIONS = foreign + +SUBDIRS = modes books + +INCLUDES = -I$(top_srcdir)/include @OGG_CFLAGS@ + +lib_LTLIBRARIES = libvorbis.la libvorbisfile.la libvorbisenc.la + +libvorbis_la_SOURCES = mdct.c smallft.c block.c envelope.c window.c lsp.c \ + lpc.c analysis.c synthesis.c psy.c info.c time0.c \ + floor1.c floor0.c\ + res0.c mapping0.c registry.c codebook.c sharedbook.c\ + lookup.c bitbuffer.c\ + envelope.h lpc.h lsp.h codebook.h misc.h psy.h\ + masking.h iir.h os.h mdct.h smallft.h\ + registry.h scales.h window.h lookup.h lookup_data.h\ + codec_internal.h backends.h bitbuffer.h +libvorbis_la_LDFLAGS = -version-info @V_LIB_CURRENT@:@V_LIB_REVISION@:@V_LIB_AGE@ + +libvorbisfile_la_SOURCES = vorbisfile.c +libvorbisfile_la_LDFLAGS = -version-info @VF_LIB_CURRENT@:@VF_LIB_REVISION@:@VF_LIB_AGE@ + +libvorbisenc_la_SOURCES = vorbisenc.c +libvorbisenc_la_LDFLAGS = -version-info @VE_LIB_CURRENT@:@VE_LIB_REVISION@:@VE_LIB_AGE@ + +EXTRA_PROGRAMS = barkmel tone psytune +CLEANFILES = $(EXTRA_PROGRAMS) + +barkmel_SOURCES = barkmel.c +tone_SOURCES = tone.c +psytune_SOURCES = psytune.c +psytune_LDFLAGS = -static +psytune_LDADD = libvorbis.la + +EXTRA_DIST = lookups.pl iir.c + +debug: + $(MAKE) all CFLAGS="@DEBUG@" + +profile: + $(MAKE) all CFLAGS="@PROFILE@" diff --git a/lib/barkmel.c b/lib/barkmel.c index 1f3ba38c..586dee75 100644 --- a/lib/barkmel.c +++ b/lib/barkmel.c @@ -11,7 +11,7 @@ ******************************************************************** function: bark scale utility - last mod: $Id: barkmel.c,v 1.5.4.1 2001/04/29 22:21:04 xiphmont Exp $ + last mod: $Id: barkmel.c,v 1.5.4.2 2001/05/01 17:08:36 xiphmont Exp $ ********************************************************************/ @@ -54,9 +54,9 @@ int main(){ { float i; int j; - for(i=0.,j=0;i<28;i+=.816,j++){ - fprintf(stderr,"(%d) bark=%f %gHz (%d of 1024)\n", - j,i,fromBARK(i),(int)(fromBARK(i)/22050.*1024.)); + for(i=0.,j=0;i<28;i+=2.107,j++){ + fprintf(stderr,"(%d) bark=%f %gHz (%d of 128)\n", + j,i,fromBARK(i),(int)(fromBARK(i)/22050.*128.)); } } return(0); diff --git a/lib/floor1.c b/lib/floor1.c index 84128f80..57870ea6 100644 --- a/lib/floor1.c +++ b/lib/floor1.c @@ -11,7 +11,7 @@ ******************************************************************** function: floor backend 1 implementation - last mod: $Id: floor1.c,v 1.1.2.2 2001/04/29 22:21:04 xiphmont Exp $ + last mod: $Id: floor1.c,v 1.1.2.3 2001/05/01 17:08:36 xiphmont Exp $ ********************************************************************/ @@ -121,7 +121,7 @@ static void floor1_pack (vorbis_info_floor *i,oggpack_buffer *opb){ oggpack_write(opb,info->class_dim[j]-1,3); /* 1 to 8 */ oggpack_write(opb,info->class_subs[j],2); /* 0 to 3 */ if(info->class_subs[j])oggpack_write(opb,info->class_book[j],8); - for(k=0;k<info->class_subs[j];k++) + for(k=0;k<(1<<info->class_subs[j]);k++) oggpack_write(opb,info->class_subbook[j][k]+1,8); } @@ -140,7 +140,7 @@ static void floor1_pack (vorbis_info_floor *i,oggpack_buffer *opb){ static vorbis_info_floor *floor1_unpack (vorbis_info *vi,oggpack_buffer *opb){ codec_setup_info *ci=vi->codec_setup; - int j,k,count,maxclass=-1,rangebits; + int j,k,count=0,maxclass=-1,rangebits; vorbis_info_floor1 *info=_ogg_calloc(1,sizeof(vorbis_info_floor1)); /* read partitions */ @@ -159,7 +159,7 @@ static vorbis_info_floor *floor1_unpack (vorbis_info *vi,oggpack_buffer *opb){ if(info->class_subs[j])info->class_book[j]=oggpack_read(opb,8); if(info->class_book[j]<0 || info->class_book[j]>=ci->books) goto err_out; - for(k=0;k<info->class_subs[j];k++){ + for(k=0;k<(1<<info->class_subs[j]);k++){ info->class_subbook[j][k]=oggpack_read(opb,8)-1; if(info->class_subbook[j][k]<-1 || info->class_subbook[j][k]>=ci->books) goto err_out; @@ -278,7 +278,7 @@ static int render_point(int x0,int x1,int y0,int y1,int x){ return(y0+off); } -static int FLOOR_todB_LOOKUP[560]={ +static int FLOOR_quantdB_LOOKUP[560]={ 1023, 1021, 1019, 1018, 1016, 1014, 1012, 1010, 1008, 1007, 1005, 1003, 1001, 999, 997, 996, 994, 992, 990, 988, 986, 985, 983, 981, @@ -482,6 +482,22 @@ static int accumulate_fit(float *floor,int x0, int x1,lsfit_acc *a){ return(a->n); } +static int add_fit_point(float *floor,int x,lsfit_acc *a){ + long i; + + int quantized=vorbis_floor1_dBquant(floor+x); + if(quantized){ + a->xa += x; + a->ya += quantized; + a->x2a += (x*x); + a->y2a += quantized*quantized; + a->xya += x*quantized; + a->n++; + return(1); + } + return(0); +} + /* returns < 0 on too few points to fit, >=0 (meansq error) on success */ static int fit_line(lsfit_acc *a,int fits,int *y0,int *y1){ long x=0,y=0,x2=0,y2=0,xy=0,n=0,i; @@ -550,8 +566,8 @@ static int inspect_error(int x0,int x1,int y0,int y1,float *flr, ady-=abs(base*adx); if(val){ - if(y-info->maxover>val)return(1); - if(y+info->maxunder<val)return(1); + if(y+info->maxover<val)return(1); + if(y-info->maxunder>val)return(1); mse=(y-val); mse*=mse; n++; @@ -568,8 +584,8 @@ static int inspect_error(int x0,int x1,int y0,int y1,float *flr, val=vorbis_floor1_dBquant(flr+x); if(val){ - if(y-info->maxover>val)return(1); - if(y+info->maxunder<val)return(1); + if(y+info->maxover<val)return(1); + if(y-info->maxunder>val)return(1); mse+=((y-val)*(y-val)); n++; } @@ -591,6 +607,7 @@ int post_Y(int *A,int *B,int pos){ a dB scale floor, puts out linear */ static int floor1_forward(vorbis_block *vb,vorbis_look_floor *in, float *flr){ + static int seq=0; long i,j,k,l; vorbis_look_floor1 *look=(vorbis_look_floor1 *)in; vorbis_info_floor1 *info=look->vi; @@ -605,8 +622,10 @@ static int floor1_forward(vorbis_block *vb,vorbis_look_floor *in, int loneighbor[VIF_POSIT+2]; /* sorted index of range list position (+2) */ int hineighbor[VIF_POSIT+2]; int memo[VIF_POSIT+2]; - static_codebook *sbooks=vb->vd->vi->codec_setup->book_param; - codebook *books=vb->vd->backend_state->fullbooks; + codec_setup_info *ci=vb->vd->vi->codec_setup; + static_codebook **sbooks=ci->book_param; + codebook *books=((backend_lookup_state *)(vb->vd->backend_state))-> + fullbooks; memset(fit_flag,0,sizeof(fit_flag)); for(i=0;i<posts;i++)loneighbor[i]=0; /* 0 for the implicit 0 post */ @@ -618,9 +637,13 @@ static int floor1_forward(vorbis_block *vb,vorbis_look_floor *in, if(posts==0){ nonzero+=accumulate_fit(flr,0,n,fits); }else{ - for(i=0;i<posts-1;i++) + for(i=0;i<posts-2;i++){ nonzero+=accumulate_fit(flr,look->sorted_index[i], look->sorted_index[i+1],fits+i); + nonzero+=add_fit_point(flr,look->sorted_index[i+1],fits+i); + } + nonzero+=accumulate_fit(flr,look->sorted_index[i], + look->sorted_index[i+1],fits+i); } if(nonzero){ @@ -657,6 +680,7 @@ static int floor1_forward(vorbis_block *vb,vorbis_look_floor *in, /* haven't performed this error search yet */ int lsortpos=look->reverse_index[ln]; int hsortpos=look->reverse_index[hn]; + memo[ln]=hn; /* if this is an empty segment, its endpoints don't matter. Mark as such */ @@ -673,7 +697,6 @@ static int floor1_forward(vorbis_block *vb,vorbis_look_floor *in, int hx=info->postlist[hn]; int ly=post_Y(fit_valueA,fit_valueB,ln); int hy=post_Y(fit_valueA,fit_valueB,hn); - memo[ln]=hn; if(i<info->searchstart || inspect_error(lx,hx,ly,hy,flr,info)){ @@ -685,13 +708,13 @@ static int floor1_forward(vorbis_block *vb,vorbis_look_floor *in, int lmse=fit_line(fits+lsortpos,sortpos-lsortpos,&ly0,&ly1); int hmse=fit_line(fits+sortpos,hsortpos-sortpos,&hy0,&hy1); - /* Handle degeneracy */ + /* Handle degeneracy if(lmse<0 && hmse<0){ ly0=fit_valueA[ln]; hy1=fit_valueB[hn]; lmse=fit_line(fits+lsortpos,sortpos-lsortpos,&ly0,&ly1); hmse=fit_line(fits+sortpos,hsortpos-sortpos,&hy0,&hy1); - } + }*/ if(lmse<0 && hmse<0) continue; @@ -734,6 +757,34 @@ static int floor1_forward(vorbis_block *vb,vorbis_look_floor *in, } } } + + + + /* generate quantized floor equivalent to what we'd unpack in decode */ + { + int hx; + int lx=0; + int ly=(post_Y(fit_valueA,fit_valueB,0)+4)>>3; + + for(j=1;j<posts;j++){ + int current=look->forward_index[j]; + if(fit_flag[current]){ + int hy=(post_Y(fit_valueA,fit_valueB,current)+4)>>3; + hx=info->postlist[current]; + + render_line(lx,hx,ly*2,hy*2,flr); + + lx=hx; + ly=hy; + } + } + for(j=hx;j<n;j++)flr[j]=0.f; /* be certain */ + _analysis_output("infloor",seq,flr,n,0,1); + + } + + + /* quantize values to multiplier spec */ switch(info->mult){ @@ -763,8 +814,8 @@ static int floor1_forward(vorbis_block *vb,vorbis_look_floor *in, /* work backward to avoid a copy; unwind the neighbor arrays */ for(i=posts-1;i>1;i--){ int sp=look->reverse_index[i]; - int ln=loneighbor[i]; - int hn=hineighbor[i]; + int ln=loneighbor[sp]; + int hn=hineighbor[sp]; int x0=info->postlist[ln]; int x1=info->postlist[hn]; @@ -789,12 +840,12 @@ static int floor1_forward(vorbis_block *vb,vorbis_look_floor *in, if(val<-headroom) val=headroom-val-1; else - val=1-(val<<1); + val=-1-(val<<1); else if(val>=headroom) val= val+headroom; else - val>>=1; + val<<=1; fit_valueB[i]=val; @@ -840,15 +891,15 @@ static int floor1_forward(vorbis_block *vb,vorbis_look_floor *in, for(k=0;k<csub;k++){ int booknum=info->class_subbook[class][k]; if(booknum<0){ - maxval[k]=0; + maxval[k]=1; }else{ - maxval[k]=sbooks[info->class_subbook[class][k]].entries; + maxval[k]=sbooks[info->class_subbook[class][k]]->entries; } } for(k=0;k<cdim;k++){ for(l=0;l<csub;l++){ - val=fit_valueB[j+k]; - if(val<maxval[k]){ + int val=fit_valueB[j+k]; + if(val<maxval[l]){ bookas[k]=l; break; } @@ -863,7 +914,7 @@ static int floor1_forward(vorbis_block *vb,vorbis_look_floor *in, { FILE *of; char buffer[80]; - sprintf(buffer,"floor1_class%d.vqd",class); + sprintf(buffer,"line%d_class%d.vqd",vb->mode,class); of=fopen(buffer,"a"); fprintf(of,"%d\n",cval); fclose(of); @@ -877,11 +928,12 @@ static int floor1_forward(vorbis_block *vb,vorbis_look_floor *in, if(book>=0){ vorbis_book_encode(books+book, fit_valueB[j+k],&vb->opb); + #ifdef TRAIN_FLOOR1 { FILE *of; char buffer[80]; - sprintf(buffer,"floor1_class%dsub%d.vqd",class,bookas[k]); + sprintf(buffer,"line%d_%dsub%d.vqd",vb->mode,class,bookas[k]); of=fopen(buffer,"a"); fprintf(of,"%d\n",fit_valueB[j+k]); fclose(of); @@ -902,29 +954,31 @@ static int floor1_forward(vorbis_block *vb,vorbis_look_floor *in, int hy=fit_valueA[current]*info->mult; hx=info->postlist[current]; - render_line(lx,hx,ly,hy,out); + render_line(lx,hx,ly,hy,flr); lx=hx; ly=hy; } - for(j=hx;j<n;j++)out[j]=0.f; /* be certain */ + for(j=hx;j<n;j++)flr[j]=0.f; /* be certain */ } }else{ oggpack_write(&vb->opb,0,1); memset(flr,0,n*sizeof(float)); } + seq++; return(nonzero); } -static int floor1_inverse(vorbis_block *vb,vorbis_look_floor *i,float *out){ - vorbis_look_floor1 *look=(vorbis_look_floor1 *)i; +static int floor1_inverse(vorbis_block *vb,vorbis_look_floor *in,float *out){ + vorbis_look_floor1 *look=(vorbis_look_floor1 *)in; vorbis_info_floor1 *info=look->vi; codec_setup_info *ci=vb->vd->vi->codec_setup; int n=ci->blocksizes[vb->mode]/2; - int i,j; - codebook *books=vb->vd->backend_state->fullbooks; + int i,j,k; + codebook *books=((backend_lookup_state *)(vb->vd->backend_state))-> + fullbooks; /* unpack wrapped/predicted values from stream */ if(oggpack_read(&vb->opb,1)==1){ @@ -940,32 +994,30 @@ static int floor1_inverse(vorbis_block *vb,vorbis_look_floor *i,float *out){ int cdim=info->class_dim[class]; int csubbits=info->class_subs[class]; int csub=1<<csubbits; - int bookas[8]={0,0,0,0,0,0,0,0}; + int cval=0; /* decode the partition's first stage cascade value */ if(csubbits){ - int cval=vorbis_book_decode(books+info->class_book[class],&vb->opb); + cval=vorbis_book_decode(books+info->class_book[class],&vb->opb); + if(cval==-1)goto eop; + } - for(k=0;k<cdim;k++){ - int book=info->class_subbook[class][val&(csub-1)]; - cval>>=csubbits; - if(book>=0){ - if((fit_value[j+k]=vorbis_book_decode(books+book,&vb->opb))==-1) - goto eop; - }else{ - fit_value[j+k]=0; - } - } - }else{ - for(k=0;k<cdim;k++) + for(k=0;k<cdim;k++){ + int book=info->class_subbook[class][cval&(csub-1)]; + cval>>=csubbits; + if(book>=0){ + if((fit_value[j+k]=vorbis_book_decode(books+book,&vb->opb))==-1) + goto eop; + }else{ fit_value[j+k]=0; - } + } + } j+=cdim; } /* unwrap positive values and reconsitute via linear interpolation */ - for(i=2;i<posts;i++){ + for(i=2;i<look->posts;i++){ int predicted=render_point(info->postlist[look->loneighbor[i-2]], info->postlist[look->hineighbor[i-2]], fit_value[look->loneighbor[i-2]], @@ -984,7 +1036,7 @@ static int floor1_inverse(vorbis_block *vb,vorbis_look_floor *i,float *out){ } }else{ if(val&1){ - val= -1 -(val>>1); + val= -((val+1)>>1); }else{ val>>=1; } @@ -998,7 +1050,7 @@ static int floor1_inverse(vorbis_block *vb,vorbis_look_floor *i,float *out){ int hx; int lx=0; int ly=fit_value[0]*info->mult; - for(j=1;j<posts;j++){ + for(j=1;j<look->posts;j++){ int current=look->forward_index[j]; int hy=fit_value[current]*info->mult; hx=info->postlist[current]; diff --git a/lib/info.c b/lib/info.c new file mode 100644 index 00000000..8c683a1d --- /dev/null +++ b/lib/info.c @@ -0,0 +1,589 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001 * + * by the XIPHOPHORUS Company http://www.xiph.org/ * + + ******************************************************************** + + function: maintain the info structure, info <-> header packets + last mod: $Id: info.c,v 1.39.4.1 2001/05/01 17:08:36 xiphmont Exp $ + + ********************************************************************/ + +/* general handling of the header and the vorbis_info structure (and + substructures) */ + +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <ogg/ogg.h> +#include "vorbis/codec.h" +#include "backends.h" +#include "codec_internal.h" +#include "codebook.h" +#include "registry.h" +#include "window.h" +#include "psy.h" +#include "misc.h" +#include "os.h" + +/* helpers */ +static int ilog2(unsigned int v){ + int ret=0; + while(v>1){ + ret++; + v>>=1; + } + return(ret); +} + +static void _v_writestring(oggpack_buffer *o,char *s){ + while(*s){ + oggpack_write(o,*s++,8); + } +} + +static void _v_readstring(oggpack_buffer *o,char *buf,int bytes){ + while(bytes--){ + *buf++=oggpack_read(o,8); + } +} + +void vorbis_comment_init(vorbis_comment *vc){ + memset(vc,0,sizeof(vorbis_comment)); +} + +void vorbis_comment_add(vorbis_comment *vc,char *comment){ + vc->user_comments=_ogg_realloc(vc->user_comments, + (vc->comments+2)*sizeof(char *)); + vc->comment_lengths=_ogg_realloc(vc->comment_lengths, + (vc->comments+2)*sizeof(int)); + vc->user_comments[vc->comments]=strdup(comment); + vc->comment_lengths[vc->comments]=strlen(comment); + vc->comments++; + vc->user_comments[vc->comments]=NULL; +} + +void vorbis_comment_add_tag(vorbis_comment *vc, char *tag, char *contents){ + char *comment=alloca(strlen(tag)+strlen(contents)+2); /* +2 for = and \0 */ + strcpy(comment, tag); + strcat(comment, "="); + strcat(comment, contents); + vorbis_comment_add(vc, comment); +} + +/* This is more or less the same as strncasecmp - but that doesn't exist + * everywhere, and this is a fairly trivial function, so we include it */ +static int tagcompare(const char *s1, const char *s2, int n){ + int c=0; + while(c < n){ + if(toupper(s1[c]) != toupper(s2[c])) + return !0; + c++; + } + return 0; +} + +char *vorbis_comment_query(vorbis_comment *vc, char *tag, int count){ + long i; + int found = 0; + int taglen = strlen(tag)+1; /* +1 for the = we append */ + char *fulltag = alloca(taglen+ 1); + + strcpy(fulltag, tag); + strcat(fulltag, "="); + + for(i=0;i<vc->comments;i++){ + if(!tagcompare(vc->user_comments[i], fulltag, taglen)){ + if(count == found) + /* We return a pointer to the data, not a copy */ + return vc->user_comments[i] + taglen; + else + found++; + } + } + return NULL; /* didn't find anything */ +} + +int vorbis_comment_query_count(vorbis_comment *vc, char *tag){ + int i,count=0; + int taglen = strlen(tag)+1; /* +1 for the = we append */ + char *fulltag = alloca(taglen+1); + strcpy(fulltag,tag); + strcat(fulltag, "="); + + for(i=0;i<vc->comments;i++){ + if(!tagcompare(vc->user_comments[i], fulltag, taglen)) + count++; + } + + return count; +} + +void vorbis_comment_clear(vorbis_comment *vc){ + if(vc){ + long i; + for(i=0;i<vc->comments;i++) + if(vc->user_comments[i])_ogg_free(vc->user_comments[i]); + if(vc->user_comments)_ogg_free(vc->user_comments); + if(vc->comment_lengths)_ogg_free(vc->comment_lengths); + if(vc->vendor)_ogg_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)); + vi->codec_setup=_ogg_calloc(1,sizeof(codec_setup_info)); +} + +void vorbis_info_clear(vorbis_info *vi){ + codec_setup_info *ci=vi->codec_setup; + int i; + + if(ci){ + + for(i=0;i<ci->modes;i++) + if(ci->mode_param[i])_ogg_free(ci->mode_param[i]); + + for(i=0;i<ci->maps;i++) /* unpack does the range checking */ + _mapping_P[ci->map_type[i]]->free_info(ci->map_param[i]); + + for(i=0;i<ci->times;i++) /* unpack does the range checking */ + _time_P[ci->time_type[i]]->free_info(ci->time_param[i]); + + for(i=0;i<ci->floors;i++) /* unpack does the range checking */ + _floor_P[ci->floor_type[i]]->free_info(ci->floor_param[i]); + + for(i=0;i<ci->residues;i++) /* unpack does the range checking */ + _residue_P[ci->residue_type[i]]->free_info(ci->residue_param[i]); + + for(i=0;i<ci->books;i++){ + if(ci->book_param[i]){ + /* knows if the book was not alloced */ + vorbis_staticbook_destroy(ci->book_param[i]); + } + } + + for(i=0;i<ci->psys;i++) + _vi_psy_free(ci->psy_param[i]); + + _ogg_free(ci); + } + + memset(vi,0,sizeof(vorbis_info)); +} + +/* Header packing/unpacking ********************************************/ + +static int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb){ + codec_setup_info *ci=vi->codec_setup; + if(!ci)return(OV_EFAULT); + + vi->version=oggpack_read(opb,32); + if(vi->version!=0)return(OV_EVERSION); + + vi->channels=oggpack_read(opb,8); + vi->rate=oggpack_read(opb,32); + + vi->bitrate_upper=oggpack_read(opb,32); + vi->bitrate_nominal=oggpack_read(opb,32); + vi->bitrate_lower=oggpack_read(opb,32); + + ci->blocksizes[0]=1<<oggpack_read(opb,4); + ci->blocksizes[1]=1<<oggpack_read(opb,4); + + if(vi->rate<1)goto err_out; + if(vi->channels<1)goto err_out; + if(ci->blocksizes[0]<8)goto err_out; + if(ci->blocksizes[1]<ci->blocksizes[0])goto err_out; + + if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */ + + return(0); + err_out: + vorbis_info_clear(vi); + return(OV_EBADHEADER); +} + +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; + vc->vendor=_ogg_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=_ogg_calloc(vc->comments+1,sizeof(char **)); + vc->comment_lengths=_ogg_calloc(vc->comments+1, sizeof(int)); + + for(i=0;i<vc->comments;i++){ + int len=oggpack_read(opb,32); + if(len<0)goto err_out; + vc->comment_lengths[i]=len; + vc->user_comments[i]=_ogg_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_comment_clear(vc); + return(OV_EBADHEADER); +} + +/* all of the real encoding details are here. The modes, books, + everything */ +static int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb){ + codec_setup_info *ci=vi->codec_setup; + int i; + if(!ci)return(OV_EFAULT); + + /* codebooks */ + ci->books=oggpack_read(opb,8)+1; + /*ci->book_param=_ogg_calloc(ci->books,sizeof(static_codebook *));*/ + for(i=0;i<ci->books;i++){ + ci->book_param[i]=_ogg_calloc(1,sizeof(static_codebook)); + if(vorbis_staticbook_unpack(opb,ci->book_param[i]))goto err_out; + } + + /* time backend settings */ + ci->times=oggpack_read(opb,6)+1; + /*ci->time_type=_ogg_malloc(ci->times*sizeof(int));*/ + /*ci->time_param=_ogg_calloc(ci->times,sizeof(void *));*/ + for(i=0;i<ci->times;i++){ + ci->time_type[i]=oggpack_read(opb,16); + if(ci->time_type[i]<0 || ci->time_type[i]>=VI_TIMEB)goto err_out; + ci->time_param[i]=_time_P[ci->time_type[i]]->unpack(vi,opb); + if(!ci->time_param[i])goto err_out; + } + + /* floor backend settings */ + ci->floors=oggpack_read(opb,6)+1; + /*ci->floor_type=_ogg_malloc(ci->floors*sizeof(int));*/ + /*ci->floor_param=_ogg_calloc(ci->floors,sizeof(void *));*/ + for(i=0;i<ci->floors;i++){ + ci->floor_type[i]=oggpack_read(opb,16); + if(ci->floor_type[i]<0 || ci->floor_type[i]>=VI_FLOORB)goto err_out; + ci->floor_param[i]=_floor_P[ci->floor_type[i]]->unpack(vi,opb); + if(!ci->floor_param[i])goto err_out; + } + + /* residue backend settings */ + ci->residues=oggpack_read(opb,6)+1; + /*ci->residue_type=_ogg_malloc(ci->residues*sizeof(int));*/ + /*ci->residue_param=_ogg_calloc(ci->residues,sizeof(void *));*/ + for(i=0;i<ci->residues;i++){ + ci->residue_type[i]=oggpack_read(opb,16); + if(ci->residue_type[i]<0 || ci->residue_type[i]>=VI_RESB)goto err_out; + ci->residue_param[i]=_residue_P[ci->residue_type[i]]->unpack(vi,opb); + if(!ci->residue_param[i])goto err_out; + } + + /* map backend settings */ + ci->maps=oggpack_read(opb,6)+1; + /*ci->map_type=_ogg_malloc(ci->maps*sizeof(int));*/ + /*ci->map_param=_ogg_calloc(ci->maps,sizeof(void *));*/ + for(i=0;i<ci->maps;i++){ + ci->map_type[i]=oggpack_read(opb,16); + if(ci->map_type[i]<0 || ci->map_type[i]>=VI_MAPB)goto err_out; + ci->map_param[i]=_mapping_P[ci->map_type[i]]->unpack(vi,opb); + if(!ci->map_param[i])goto err_out; + } + + /* mode settings */ + ci->modes=oggpack_read(opb,6)+1; + /*vi->mode_param=_ogg_calloc(vi->modes,sizeof(void *));*/ + for(i=0;i<ci->modes;i++){ + ci->mode_param[i]=_ogg_calloc(1,sizeof(vorbis_info_mode)); + ci->mode_param[i]->blockflag=oggpack_read(opb,1); + ci->mode_param[i]->windowtype=oggpack_read(opb,16); + ci->mode_param[i]->transformtype=oggpack_read(opb,16); + ci->mode_param[i]->mapping=oggpack_read(opb,8); + + if(ci->mode_param[i]->windowtype>=VI_WINDOWB)goto err_out; + if(ci->mode_param[i]->transformtype>=VI_WINDOWB)goto err_out; + if(ci->mode_param[i]->mapping>=ci->maps)goto err_out; + } + + if(oggpack_read(opb,1)!=1)goto err_out; /* top level EOP check */ + + return(0); + err_out: + vorbis_info_clear(vi); + return(OV_EBADHEADER); +} + +/* The Vorbis header is in three packets; the initial small packet in + the first page that identifies basic parameters, a second packet + with bitstream comments and a third packet that holds the + codebook. */ + +int vorbis_synthesis_headerin(vorbis_info *vi,vorbis_comment *vc,ogg_packet *op){ + oggpack_buffer opb; + + if(op){ + oggpack_readinit(&opb,op->packet,op->bytes); + + /* Which of the three types of header is this? */ + /* Also verify header-ness, vorbis */ + { + char buffer[6]; + int packtype=oggpack_read(&opb,8); + memset(buffer,0,6); + _v_readstring(&opb,buffer,6); + if(memcmp(buffer,"vorbis",6)){ + /* not a vorbis header */ + return(OV_ENOTVORBIS); + } + switch(packtype){ + case 0x01: /* least significant *bit* is read first */ + if(!op->b_o_s){ + /* Not the initial packet */ + return(OV_EBADHEADER); + } + if(vi->rate!=0){ + /* previously initialized info header */ + return(OV_EBADHEADER); + } + + return(_vorbis_unpack_info(vi,&opb)); + + case 0x03: /* least significant *bit* is read first */ + if(vi->rate==0){ + /* um... we didn't get the initial header */ + return(OV_EBADHEADER); + } + + return(_vorbis_unpack_comment(vc,&opb)); + + case 0x05: /* least significant *bit* is read first */ + if(vi->rate==0 || vc->vendor==NULL){ + /* um... we didn;t get the initial header or comments yet */ + return(OV_EBADHEADER); + } + + return(_vorbis_unpack_books(vi,&opb)); + + default: + /* Not a valid vorbis header type */ + return(OV_EBADHEADER); + break; + } + } + } + return(OV_EBADHEADER); +} + +/* pack side **********************************************************/ + +static int _vorbis_pack_info(oggpack_buffer *opb,vorbis_info *vi){ + codec_setup_info *ci=vi->codec_setup; + if(!ci)return(OV_EFAULT); + + /* preamble */ + oggpack_write(opb,0x01,8); + _v_writestring(opb,"vorbis"); + + /* basic information about the stream */ + oggpack_write(opb,0x00,32); + oggpack_write(opb,vi->channels,8); + oggpack_write(opb,vi->rate,32); + + oggpack_write(opb,vi->bitrate_upper,32); + oggpack_write(opb,vi->bitrate_nominal,32); + oggpack_write(opb,vi->bitrate_lower,32); + + oggpack_write(opb,ilog2(ci->blocksizes[0]),4); + oggpack_write(opb,ilog2(ci->blocksizes[1]),4); + oggpack_write(opb,1,1); + + return(0); +} + +static int _vorbis_pack_comment(oggpack_buffer *opb,vorbis_comment *vc){ + char temp[]="Xiphophorus libVorbis I 20010501"; + + /* preamble */ + oggpack_write(opb,0x03,8); + _v_writestring(opb,"vorbis"); + + /* vendor */ + oggpack_write(opb,strlen(temp),32); + _v_writestring(opb,temp); + + /* comments */ + + oggpack_write(opb,vc->comments,32); + if(vc->comments){ + int i; + for(i=0;i<vc->comments;i++){ + if(vc->user_comments[i]){ + oggpack_write(opb,vc->comment_lengths[i],32); + _v_writestring(opb,vc->user_comments[i]); + }else{ + oggpack_write(opb,0,32); + } + } + } + oggpack_write(opb,1,1); + + return(0); +} + +static int _vorbis_pack_books(oggpack_buffer *opb,vorbis_info *vi){ + codec_setup_info *ci=vi->codec_setup; + int i; + if(!ci)return(OV_EFAULT); + + oggpack_write(opb,0x05,8); + _v_writestring(opb,"vorbis"); + + /* books */ + oggpack_write(opb,ci->books-1,8); + for(i=0;i<ci->books;i++) + if(vorbis_staticbook_pack(ci->book_param[i],opb))goto err_out; + + /* times */ + oggpack_write(opb,ci->times-1,6); + for(i=0;i<ci->times;i++){ + oggpack_write(opb,ci->time_type[i],16); + _time_P[ci->time_type[i]]->pack(ci->time_param[i],opb); + } + + /* floors */ + oggpack_write(opb,ci->floors-1,6); + for(i=0;i<ci->floors;i++){ + oggpack_write(opb,ci->floor_type[i],16); + _floor_P[ci->floor_type[i]]->pack(ci->floor_param[i],opb); + } + + /* residues */ + oggpack_write(opb,ci->residues-1,6); + for(i=0;i<ci->residues;i++){ + oggpack_write(opb,ci->residue_type[i],16); + _residue_P[ci->residue_type[i]]->pack(ci->residue_param[i],opb); + } + + /* maps */ + oggpack_write(opb,ci->maps-1,6); + for(i=0;i<ci->maps;i++){ + oggpack_write(opb,ci->map_type[i],16); + _mapping_P[ci->map_type[i]]->pack(vi,ci->map_param[i],opb); + } + + /* modes */ + oggpack_write(opb,ci->modes-1,6); + for(i=0;i<ci->modes;i++){ + oggpack_write(opb,ci->mode_param[i]->blockflag,1); + oggpack_write(opb,ci->mode_param[i]->windowtype,16); + oggpack_write(opb,ci->mode_param[i]->transformtype,16); + oggpack_write(opb,ci->mode_param[i]->mapping,8); + } + oggpack_write(opb,1,1); + + return(0); +err_out: + return(-1); +} + +int vorbis_commentheader_out(vorbis_comment *vc, + ogg_packet *op){ + + oggpack_buffer opb; + + oggpack_writeinit(&opb); + if(_vorbis_pack_comment(&opb,vc)) return OV_EIMPL; + + op->packet = _ogg_malloc(oggpack_bytes(&opb)); + memcpy(op->packet, opb.buffer, oggpack_bytes(&opb)); + + op->bytes=oggpack_bytes(&opb); + op->b_o_s=0; + op->e_o_s=0; + op->granulepos=0; + + return 0; +} + +int vorbis_analysis_headerout(vorbis_dsp_state *v, + vorbis_comment *vc, + ogg_packet *op, + ogg_packet *op_comm, + ogg_packet *op_code){ + int ret=OV_EIMPL; + vorbis_info *vi=v->vi; + oggpack_buffer opb; + backend_lookup_state *b=v->backend_state; + + if(!b){ + ret=OV_EFAULT; + goto err_out; + } + + /* first header packet **********************************************/ + + oggpack_writeinit(&opb); + if(_vorbis_pack_info(&opb,vi))goto err_out; + + /* build the packet */ + if(b->header)_ogg_free(b->header); + b->header=_ogg_malloc(oggpack_bytes(&opb)); + memcpy(b->header,opb.buffer,oggpack_bytes(&opb)); + op->packet=b->header; + op->bytes=oggpack_bytes(&opb); + op->b_o_s=1; + op->e_o_s=0; + op->granulepos=0; + + /* second header packet (comments) **********************************/ + + oggpack_reset(&opb); + if(_vorbis_pack_comment(&opb,vc))goto err_out; + + if(b->header1)_ogg_free(b->header1); + b->header1=_ogg_malloc(oggpack_bytes(&opb)); + memcpy(b->header1,opb.buffer,oggpack_bytes(&opb)); + op_comm->packet=b->header1; + op_comm->bytes=oggpack_bytes(&opb); + op_comm->b_o_s=0; + op_comm->e_o_s=0; + op_comm->granulepos=0; + + /* third header packet (modes/codebooks) ****************************/ + + oggpack_reset(&opb); + if(_vorbis_pack_books(&opb,vi))goto err_out; + + if(b->header2)_ogg_free(b->header2); + b->header2=_ogg_malloc(oggpack_bytes(&opb)); + memcpy(b->header2,opb.buffer,oggpack_bytes(&opb)); + op_code->packet=b->header2; + op_code->bytes=oggpack_bytes(&opb); + op_code->b_o_s=0; + op_code->e_o_s=0; + op_code->granulepos=0; + + oggpack_writeclear(&opb); + return(0); + err_out: + oggpack_writeclear(&opb); + memset(op,0,sizeof(ogg_packet)); + memset(op_comm,0,sizeof(ogg_packet)); + memset(op_code,0,sizeof(ogg_packet)); + + if(b->header)_ogg_free(b->header); + if(b->header1)_ogg_free(b->header1); + if(b->header2)_ogg_free(b->header2); + b->header=NULL; + b->header1=NULL; + b->header2=NULL; + return(ret); +} + diff --git a/lib/mapping0.c b/lib/mapping0.c index 0e02d9f1..00ef2598 100644 --- a/lib/mapping0.c +++ b/lib/mapping0.c @@ -11,7 +11,7 @@ ******************************************************************** function: channel mapping 0 implementation - last mod: $Id: mapping0.c,v 1.27.4.1 2001/04/29 22:21:04 xiphmont Exp $ + last mod: $Id: mapping0.c,v 1.27.4.2 2001/05/01 17:08:36 xiphmont Exp $ ********************************************************************/ @@ -297,7 +297,6 @@ static int mapping0_forward(vorbis_block *vb,vorbis_look_mapping *l){ #endif } - seq++; vbi->ampmax=newmax; /* perform residue encoding with residue mapping; this is diff --git a/lib/modes/mode_A.h b/lib/modes/mode_A.h index 09694c04..6b493eed 100644 --- a/lib/modes/mode_A.h +++ b/lib/modes/mode_A.h @@ -11,7 +11,7 @@ ******************************************************************** function: predefined encoding modes - last mod: $Id: mode_A.h,v 1.14.4.1 2001/04/29 22:21:06 xiphmont Exp $ + last mod: $Id: mode_A.h,v 1.14.4.2 2001/05/01 17:08:38 xiphmont Exp $ ********************************************************************/ @@ -22,10 +22,8 @@ #include "vorbis/codec.h" #include "backends.h" -#include "books/lsp12_0.vqh" -#include "books/lsp30_0.vqh" -#include "books/lsp12_1.vqh" -#include "books/lsp30_1.vqh" +#include "books/line0.vqh" +#include "books/line1.vqh" #include "books/res0_128_128aux.vqh" #include "books/res0_128_1024aux.vqh" @@ -228,10 +226,48 @@ static vorbis_info_psy _psy_set_A={ /* with GNUisms, this could be short and readable. Oh well */ static vorbis_info_time0 _time_set0A={0}; -static vorbis_info_floor0 _floor_set0A={12, 44100, 64, 10,130, 2, {0,1}, - 0.199f, .285f}; -static vorbis_info_floor0 _floor_set1A={30, 44100, 256, 12,150, 2, {2,3}, - .082f, .126f}; +/*static vorbis_info_floor0 _floor_set0A={12, 44100, 64, 10,130, 2, {0,1}, + 0.199f, .285f};*/ +/*static vorbis_info_floor0 _floor_set1A={30, 44100, 256, 12,150, 2, {2,3}, + .082f, .126f};*/ + +static vorbis_info_floor1 _floor_set0A={4, + {0,1,2,2}, + + {2,3,3}, + {1,1,1}, + {0,0,0}, + {{-1,1},{-1,1},{-1,1}}, + + 2, + {0,128, + 5,21, + + 2,1,3, + 11,7,15, + 45,30,73}, + + 40,8,200,4}; + +static vorbis_info_floor1 _floor_set1A={10, + {0,1,2,2,2,2,3,3,3,3}, + + {3,4,3,3}, + {1,1,1,1}, + {2,2,2,2}, + {{-1,3},{-1,3},{-1,3},{-1,3}}, + + 2, + {0,1024, + 88,31,243, + 14,54,143,460, + + 6,3,10, 22,18,26, 41,36,47, + 69,61,78, 112,99,126, 185,162,211, + 329,282,387, 672,553,825}, + + 40,8,200,9}; + static vorbis_info_residue0 _residue_set0A={0,96,16,6,4, {0,1,1,1,1,1}, {6,7,8,9,10}, @@ -271,14 +307,14 @@ codec_setup_info info_A={ /* times */ {0,0},{&_time_set0A}, /* floors */ - {0,0},{&_floor_set0A,&_floor_set1A}, + {1,1},{&_floor_set0A,&_floor_set1A}, /* residue */ {0,0},{&_residue_set0A,&_residue_set1A}, /* books */ - {&_vq_book_lsp12_0, /* 0 */ - &_vq_book_lsp12_1, /* 1 */ - &_vq_book_lsp30_0, /* 2 */ - &_vq_book_lsp30_1, /* 3 */ + {&_huff_book_line0, + &_huff_book_line1, + &_huff_book_line0, + &_huff_book_line1, &_huff_book_res0_128_128aux, &_huff_book_res0_128_1024aux, diff --git a/lib/vorbisenc.c b/lib/vorbisenc.c new file mode 100644 index 00000000..91f1f72e --- /dev/null +++ b/lib/vorbisenc.c @@ -0,0 +1,157 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001 * + * by the XIPHOPHORUS Company http://www.xiph.org/ * + + ******************************************************************** + + function: simple programmatic interface for encoder mode setup + last mod: $Id: vorbisenc.c,v 1.6.4.1 2001/05/01 17:08:36 xiphmont Exp $ + + ********************************************************************/ + +#include <stdlib.h> +#include <string.h> +#include <math.h> + +#include "vorbis/codec.h" +#include "vorbis/vorbisenc.h" + +#include "codec_internal.h" +#include "registry.h" +#include "modes/modes.h" + +#include "os.h" +#include "misc.h" + + +/* deepcopy all but the codebooks; in this usage, they're static + (don't copy as they could be big) */ +static void codec_setup_partialcopy(codec_setup_info *ci, + codec_setup_info *cs){ + int i; + + memcpy(ci,cs,sizeof(codec_setup_info)); /* to get the flat numbers */ + + /* codebooks */ + for(i=0;i<ci->books;i++){ + ci->book_param[i]=cs->book_param[i]; + } + + /* time backend settings */ + for(i=0;i<ci->times;i++){ + ci->time_param[i]=_time_P[ci->time_type[i]]-> + copy_info(cs->time_param[i]); + } + + /* floor backend settings */ + for(i=0;i<ci->floors;i++){ + ci->floor_param[i]=_floor_P[ci->floor_type[i]]-> + copy_info(cs->floor_param[i]); + } + + /* residue backend settings */ + for(i=0;i<ci->residues;i++){ + ci->residue_param[i]=_residue_P[ci->residue_type[i]]-> + copy_info(cs->residue_param[i]); + } + + /* map backend settings */ + for(i=0;i<ci->maps;i++){ + ci->map_param[i]=_mapping_P[ci->map_type[i]]-> + copy_info(cs->map_param[i]); + } + + /* mode settings */ + for(i=0;i<ci->modes;i++){ + ci->mode_param[i]=_ogg_calloc(1,sizeof(vorbis_info_mode)); + ci->mode_param[i]->blockflag=cs->mode_param[i]->blockflag; + ci->mode_param[i]->windowtype=cs->mode_param[i]->windowtype; + ci->mode_param[i]->transformtype=cs->mode_param[i]->transformtype; + ci->mode_param[i]->mapping=cs->mode_param[i]->mapping; + } + + /* psy settings */ + for(i=0;i<ci->psys;i++){ + ci->psy_param[i]=_vi_psy_copy(cs->psy_param[i]); + } + +} + +/* right now, this just encapsultes the old modes behind the interface + we'll be using from here on out. After beta 3, the new bitrate + tracking/modding/tuning engine will lurk inside */ +/* encoders will need to use vorbis_info_init beforehand and call + vorbis_info clear when all done */ + +int vorbis_encode_init(vorbis_info *vi, + long channels, + long rate, + + long max_bitrate, + long nominal_bitrate, + long min_bitrate){ + + long bpch; + int i,j; + codec_setup_info *ci=vi->codec_setup; + codec_setup_info *mode=NULL; + if(!ci)return(OV_EFAULT); + + vi->version=0; + vi->channels=channels; + vi->rate=rate; + + vi->bitrate_upper=max_bitrate; + vi->bitrate_nominal=nominal_bitrate; + vi->bitrate_lower=min_bitrate; + vi->bitrate_window=2; + + /* copy a mode into our allocated storage */ + bpch=nominal_bitrate/channels; + if(bpch<60000){ + /* mode A */ + mode=&info_AA; + }else if(bpch<75000){ + /* mode A */ + mode=&info_A; + }else if(bpch<90000){ + /* mode B */ + mode=&info_B; + }else if(bpch<110000){ + /* mode C */ + mode=&info_C; + }else if(bpch<160000){ + /* mode D */ + mode=&info_D; + }else{ + /* mode E */ + mode=&info_E; + } + + /* now we have to deepcopy */ + codec_setup_partialcopy(ci,mode); + + /* adjust for sample rate */ + for(i=0;i<ci->floors;i++) + if(ci->floor_type[i]==0) + ((vorbis_info_floor0 *)(ci->floor_param[i]))->rate=rate; + + /* adjust for channels; all our mappings use submap zero now */ + /* yeah, OK, _ogg_calloc did this for us. But it's a reminder/placeholder */ + for(i=0;i<ci->maps;i++) + for(j=0;j<channels;j++) + ((vorbis_info_mapping0 *)ci->map_param[i])->chmuxlist[j]=0; + + return(0); +} + +int vorbis_encode_ctl(vorbis_info *vi,int number,void *arg){ + return(OV_EIMPL); +} + |