diff options
| author | Monty <xiphmont@xiph.org> | 2000-02-23 09:24:33 +0000 |
|---|---|---|
| committer | Monty <xiphmont@xiph.org> | 2000-02-23 09:24:33 +0000 |
| commit | aadce85249efb25ead6b27b2a3ebbcbc61c01c6f (patch) | |
| tree | e4758618201900982aa016c87b471ed36a7d2d13 /lib | |
| parent | cf8e31643849079886d4eddcb268981e7bb13e83 (diff) | |
| download | libvorbis-git-aadce85249efb25ead6b27b2a3ebbcbc61c01c6f.tar.gz | |
Incremental update toward first cut. The full engine is in place.
Monty
svn path=/trunk/vorbis/; revision=269
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/analysis.c | 18 | ||||
| -rw-r--r-- | lib/bitwise.c | 4 | ||||
| -rw-r--r-- | lib/block.c | 51 | ||||
| -rw-r--r-- | lib/bookinternal.h | 4 | ||||
| -rw-r--r-- | lib/codebook.c | 51 | ||||
| -rw-r--r-- | lib/floor0.c | 92 | ||||
| -rw-r--r-- | lib/lpc.c | 37 | ||||
| -rw-r--r-- | lib/mapping0.c | 132 | ||||
| -rw-r--r-- | lib/misc.h | 3 | ||||
| -rw-r--r-- | lib/res0.c | 306 | ||||
| -rw-r--r-- | lib/time0.c | 4 |
11 files changed, 464 insertions, 238 deletions
diff --git a/lib/analysis.c b/lib/analysis.c index c6fd420e..f25f4517 100644 --- a/lib/analysis.c +++ b/lib/analysis.c @@ -12,7 +12,7 @@ ******************************************************************** function: single-block PCM analysis mode dispatch - last mod: $Id: analysis.c,v 1.23 2000/02/12 08:33:04 xiphmont Exp $ + last mod: $Id: analysis.c,v 1.24 2000/02/23 09:24:21 xiphmont Exp $ ********************************************************************/ @@ -67,3 +67,19 @@ int vorbis_analysis(vorbis_block *vb,ogg_packet *op){ return(0); } + +/* there was no great place to put this.... */ +void _analysis_output(char *base,int i,double *v,int n){ +#ifdef ANALYSIS + int j; + FILE *of; + char buffer[80]; + sprintf(buffer,"%s_%d.m",base,i); + of=fopen(buffer,"w"); + for(j=0;j<n;j++) + fprintf(of,"%g\n",v[j]); + fclose(of); +#endif +} + + diff --git a/lib/bitwise.c b/lib/bitwise.c index 77b38e2b..821647f6 100644 --- a/lib/bitwise.c +++ b/lib/bitwise.c @@ -12,7 +12,7 @@ ******************************************************************** function: packing variable sized words into an octet stream - last mod: $Id: bitwise.c,v 1.8 2000/02/05 23:31:49 xiphmont Exp $ + last mod: $Id: bitwise.c,v 1.9 2000/02/23 09:24:22 xiphmont Exp $ ********************************************************************/ @@ -228,7 +228,7 @@ oggpack_buffer o; oggpack_buffer r; void report(char *in){ - fprintf(stderr,in); + fprintf(stderr,"%s",in); exit(1); } diff --git a/lib/block.c b/lib/block.c index 609b9c28..471de547 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.25 2000/02/06 13:39:38 xiphmont Exp $ + last mod: $Id: block.c,v 1.26 2000/02/23 09:24:23 xiphmont Exp $ Handle windowing, overlap-add, etc of the PCM vectors. This is made more amusing by Vorbis' current two allowed block sizes. @@ -161,7 +161,7 @@ int vorbis_block_clear(vorbis_block *vb){ here and not in analysis.c (which is for analysis transforms only). The init is here because some of it is shared */ -static int _vds_shared_init(vorbis_dsp_state *v,vorbis_info *vi){ +static int _vds_shared_init(vorbis_dsp_state *v,vorbis_info *vi,int encp){ int i; memset(v,0,sizeof(vorbis_dsp_state)); @@ -200,13 +200,17 @@ static int _vds_shared_init(vorbis_dsp_state *v,vorbis_info *vi){ _vorbis_window(i,vi->blocksizes[1],vi->blocksizes[1]/2,vi->blocksizes[1]/2); } - /* initialize all the mapping/backend lookups */ - v->mode=calloc(vi->modes,sizeof(vorbis_look_mapping *)); - for(i=0;i<vi->modes;i++){ - int mapnum=vi->mode_param[i]->mapping; - int maptype=vi->map_type[mapnum]; - v->mode[i]=_mapping_P[maptype]->look(vi,vi->mode_param[i], - vi->map_param[mapnum]); + if(encp){ /* encode/decode differ here */ + /* 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]); + v->analysisp=1; + }else{ + /* 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]); } /* initialize the storage vectors to a decent size greater than the @@ -232,18 +236,22 @@ static int _vds_shared_init(vorbis_dsp_state *v,vorbis_info *vi){ v->centerW=vi->blocksizes[1]/2; v->pcm_current=v->centerW; + + /* initialize all the mapping/backend lookups */ + v->mode=calloc(vi->modes,sizeof(vorbis_look_mapping *)); + for(i=0;i<vi->modes;i++){ + int mapnum=vi->mode_param[i]->mapping; + int maptype=vi->map_type[mapnum]; + v->mode[i]=_mapping_P[maptype]->look(v,vi->mode_param[i], + vi->map_param[mapnum]); + } + return(0); } /* 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]); + _vds_shared_init(v,vi,1); /* Initialize the envelope multiplier storage */ @@ -251,9 +259,6 @@ int vorbis_analysis_init(vorbis_dsp_state *v,vorbis_info *vi){ v->multipliers=calloc(v->envelope_storage,sizeof(double)); _ve_envelope_init(&v->ve,vi->envelopesa); - /* the coder init is different for read/write */ - v->analysisp=1; - v->envelope_current=v->centerW/vi->envelopesa; return(0); } @@ -528,13 +533,7 @@ 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]); + _vds_shared_init(v,vi,0); /* Adjust centerW to allow an easier mechanism for determining output */ v->pcm_returned=v->centerW; diff --git a/lib/bookinternal.h b/lib/bookinternal.h index e5e7b7ab..0c25f8b9 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.5 2000/01/28 09:05:07 xiphmont Exp $ + last mod: $Id: bookinternal.h,v 1.6 2000/02/23 09:24:25 xiphmont Exp $ ********************************************************************/ @@ -32,6 +32,8 @@ extern void vorbis_book_clear(codebook *b); extern int vorbis_book_encode(codebook *book, int a, oggpack_buffer *b); extern int vorbis_book_encodev(codebook *book, double *a, oggpack_buffer *b); +extern int vorbis_book_encodevE(codebook *book, double *a, oggpack_buffer *b); +extern double vorbis_book_vE(codebook *book, double *a); extern long vorbis_book_decode(codebook *book, oggpack_buffer *b); extern long vorbis_book_decodev(codebook *book, double *a, oggpack_buffer *b); diff --git a/lib/codebook.c b/lib/codebook.c index 4e6118d3..cb45348d 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.10 2000/02/21 13:09:34 xiphmont Exp $ + last mod: $Id: codebook.c,v 1.11 2000/02/23 09:24:26 xiphmont Exp $ ********************************************************************/ @@ -371,42 +371,23 @@ int vorbis_book_encode(codebook *book, int a, oggpack_buffer *b){ static int _best(codebook *book, double *a){ encode_aux *t=book->c->encode_tree; int dim=book->dim; - int trees=t->ptr0[0]; - double bestmetric; - long best=-1; - - while(trees-->0){ - int ptr=t->ptr0[trees],k; - /* optimized, using the decision tree */ - while(1){ - double c=0.; - double *p=book->valuelist+t->p[ptr]; - double *q=book->valuelist+t->q[ptr]; - - for(k=0;k<dim;k++) - c+=(p[k]-q[k])*(a[k]-(p[k]+q[k])*.5); - - if(c>0.) /* in A */ - ptr= -t->ptr0[ptr]; - else /* in B */ - ptr= -t->ptr1[ptr]; - if(ptr<=0)break; - } + int ptr=0,k; + /* optimized, using the decision tree */ + while(1){ + double c=0.; + double *p=book->valuelist+t->p[ptr]; + double *q=book->valuelist+t->q[ptr]; - { - double dist=0.; - double *v=book->valuelist-ptr*dim; - for(k=0;k<book->dim;k++){ - double one=a[k]-v[k]; - dist+=one*one; - } - if(best==-1 || dist<bestmetric){ - best=-ptr; - bestmetric=dist; - } - } + for(k=0;k<dim;k++) + c+=(p[k]-q[k])*(a[k]-(p[k]+q[k])*.5); + + if(c>0.) /* in A */ + ptr= -t->ptr0[ptr]; + else /* in B */ + ptr= -t->ptr1[ptr]; + if(ptr<=0)break; } - return(best); + return(-ptr); } /* returns the number of bits and *modifies a* to the quantization value *****/ diff --git a/lib/floor0.c b/lib/floor0.c index eff41a4c..155a6e00 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.9 2000/02/12 08:33:05 xiphmont Exp $ + last mod: $Id: floor0.c,v 1.10 2000/02/23 09:24:27 xiphmont Exp $ ********************************************************************/ @@ -46,62 +46,63 @@ static void free_info(vorbis_info_floor *i){ } static void free_look(vorbis_look_floor *i){ - vorbis_look_floor0 *f=(vorbis_look_floor0 *)i; + vorbis_look_floor0 *look=(vorbis_look_floor0 *)i; if(i){ - lpc_clear(&f->lpclook); - memset(f,0,sizeof(vorbis_look_floor0)); - free(f); + lpc_clear(&look->lpclook); + memset(look,0,sizeof(vorbis_look_floor0)); + free(look); } } static void pack (vorbis_info_floor *i,oggpack_buffer *opb){ - vorbis_info_floor0 *d=(vorbis_info_floor0 *)i; + vorbis_info_floor0 *info=(vorbis_info_floor0 *)i; int j; - _oggpack_write(opb,d->order,8); - _oggpack_write(opb,d->rate,16); - _oggpack_write(opb,d->barkmap,16); - _oggpack_write(opb,d->ampbits,6); - _oggpack_write(opb,d->ampdB,8); - _oggpack_write(opb,d->stages-1,4); - for(j=0;j<d->stages;j++) - _oggpack_write(opb,d->books[j],8); + _oggpack_write(opb,info->order,8); + _oggpack_write(opb,info->rate,16); + _oggpack_write(opb,info->barkmap,16); + _oggpack_write(opb,info->ampbits,6); + _oggpack_write(opb,info->ampdB,8); + _oggpack_write(opb,info->stages-1,4); + for(j=0;j<info->stages;j++) + _oggpack_write(opb,info->books[j],8); } static vorbis_info_floor *unpack (vorbis_info *vi,oggpack_buffer *opb){ int j; - vorbis_info_floor0 *d=malloc(sizeof(vorbis_info_floor0)); - d->order=_oggpack_read(opb,8); - d->rate=_oggpack_read(opb,16); - d->barkmap=_oggpack_read(opb,16); - d->ampbits=_oggpack_read(opb,6); - d->ampdB=_oggpack_read(opb,8); - d->stages=_oggpack_read(opb,4)+1; + vorbis_info_floor0 *info=malloc(sizeof(vorbis_info_floor0)); + info->order=_oggpack_read(opb,8); + info->rate=_oggpack_read(opb,16); + info->barkmap=_oggpack_read(opb,16); + info->ampbits=_oggpack_read(opb,6); + info->ampdB=_oggpack_read(opb,8); + info->stages=_oggpack_read(opb,4)+1; - if(d->order<1)goto err_out; - if(d->rate<1)goto err_out; - if(d->barkmap<1)goto err_out; - if(d->stages<1)goto err_out; - - for(j=0;j<d->stages;j++){ - d->books[j]=_oggpack_read(opb,8); - if(d->books[j]<0 || d->books[j]>=vi->books)goto err_out; + if(info->order<1)goto err_out; + if(info->rate<1)goto err_out; + if(info->barkmap<1)goto err_out; + if(info->stages<1)goto err_out; + + for(j=0;j<info->stages;j++){ + info->books[j]=_oggpack_read(opb,8); + if(info->books[j]<0 || info->books[j]>=vi->books)goto err_out; } - return(d); + return(info); err_out: - free_info(d); + free_info(info); return(NULL); } -static vorbis_look_floor *look (vorbis_info *vi,vorbis_info_mode *mi, +static vorbis_look_floor *look (vorbis_dsp_state *vd,vorbis_info_mode *mi, vorbis_info_floor *i){ - vorbis_info_floor0 *d=(vorbis_info_floor0 *)i; - vorbis_look_floor0 *ret=malloc(sizeof(vorbis_look_floor0)); - ret->m=d->order; - ret->n=vi->blocksizes[mi->blockflag]/2; - ret->vi=d; - lpc_init(&ret->lpclook,ret->n,d->barkmap,d->rate,ret->m); - - return ret; + vorbis_info *vi=vd->vi; + vorbis_info_floor0 *info=(vorbis_info_floor0 *)i; + vorbis_look_floor0 *look=malloc(sizeof(vorbis_look_floor0)); + look->m=info->order; + look->n=vi->blocksizes[mi->blockflag]/2; + look->vi=info; + lpc_init(&look->lpclook,look->n,info->barkmap,info->rate,look->m); + + return look; } #include <stdio.h> @@ -111,10 +112,12 @@ static int forward(vorbis_block *vb,vorbis_look_floor *i, long j,k,stage; vorbis_look_floor0 *look=(vorbis_look_floor0 *)i; vorbis_info_floor0 *info=look->vi; + double amp; + long bits=0; /* use 'out' as temp storage */ /* Convert our floor to a set of lpc coefficients */ - double amp=sqrt(vorbis_curve_to_lpc(in,out,&look->lpclook)); + amp=sqrt(vorbis_curve_to_lpc(in,out,&look->lpclook)); /* amp is in the range 0. to 1. (well, more like .7). Log scale it */ @@ -170,7 +173,7 @@ static int forward(vorbis_block *vb,vorbis_look_floor *i, double last=0.; for(j=0;j<look->m;){ for(k=0;k<b->dim;k++)out[j+k]-=last; - vorbis_book_encodev(b,out+j,&vb->opb); + bits+=vorbis_book_encodev(b,out+j,&vb->opb); for(k=0;k<b->dim;k++,j++){ out[j]+=last; work[j]-=out[j]; @@ -180,7 +183,7 @@ static int forward(vorbis_block *vb,vorbis_look_floor *i, }else{ memcpy(out,work,sizeof(double)*look->m); for(j=0;j<look->m;){ - vorbis_book_encodev(b,out+j,&vb->opb); + bits+=vorbis_book_encodev(b,out+j,&vb->opb); for(k=0;k<b->dim;k++,j++)work[j]-=out[j]; } } @@ -188,9 +191,12 @@ static int forward(vorbis_block *vb,vorbis_look_floor *i, /* take the coefficients back to a spectral envelope curve */ vorbis_lsp_to_lpc(out,out,look->m); vorbis_lpc_to_curve(out,out,amp,&look->lpclook); + fprintf(stderr,"Encoded %d LSP coefficients in %d bits\n",look->m,bits); return(1); } + fprintf(stderr,"Encoded %d LSP coefficients in %d bits\n",look->m,bits); + memset(out,0,sizeof(double)*look->n); return(0); } @@ -12,7 +12,7 @@ ******************************************************************** function: LPC low level routines - last mod: $Id: lpc.c,v 1.17 2000/02/09 22:04:13 xiphmont Exp $ + last mod: $Id: lpc.c,v 1.18 2000/02/23 09:24:28 xiphmont Exp $ ********************************************************************/ @@ -51,7 +51,7 @@ Carsten Bormann #include "smallft.h" #include "lpc.h" #include "scales.h" - +#include "misc.h" /* Autocorrelation LPC coeff generation algorithm invented by N. Levinson in 1947, modified by J. Durbin in 1959. */ @@ -219,6 +219,7 @@ void lpc_clear(lpc_lookup *l){ /* less efficient than the decode side (written for clarity). We're not bottlenecked here anyway */ +static int frameno=-1; double vorbis_curve_to_lpc(double *curve,double *lpc,lpc_lookup *l){ /* map the input curve to a bark-scale curve for encoding */ @@ -227,6 +228,9 @@ double vorbis_curve_to_lpc(double *curve,double *lpc,lpc_lookup *l){ double *work=alloca(sizeof(double)*mapped); int i,j,last=0; + frameno++; + _analysis_output("lpc_pre",frameno,curve,l->n); + memset(work,0,sizeof(double)*mapped); /* Only the decode side is behavior-specced; for now in the encoder, @@ -257,7 +261,9 @@ double vorbis_curve_to_lpc(double *curve,double *lpc,lpc_lookup *l){ } last=bark; } + _analysis_output("lpc_prelog",frameno,work,l->ln); for(i=0;i<mapped;i++)work[i]*=l->barknorm[i]; + _analysis_output("lpc_prelognorm",frameno,work,l->ln); return vorbis_lpc_from_spectrum(work,lpc,l); } @@ -306,34 +312,13 @@ void vorbis_lpc_to_curve(double *curve,double *lpc,double amp,lpc_lookup *l){ return; } _vlpc_de_helper(lcurve,lpc,amp,l); - -#ifdef ANALYSIS - { - static int frameno=0; - int j; - FILE *out; - char buffer[80]; - - sprintf(buffer,"loglpc%d.m",frameno++); - out=fopen(buffer,"w+"); - for(j=0;j<l->ln;j++) - fprintf(out,"%g\n",lcurve[j]); - fclose(out); - -#endif + _analysis_output("lpc_lognorm",frameno,lcurve,l->ln); for(i=0;i<l->ln;i++)lcurve[i]/=l->barknorm[i]; + _analysis_output("lpc_log",frameno,lcurve,l->ln); for(i=0;i<l->n;i++)curve[i]=lcurve[l->linearmap[i]]; + _analysis_output("lpc",frameno,curve,l->n); -#ifdef ANALYSIS - - sprintf(buffer,"lpc%d.m",frameno-1); - out=fopen(buffer,"w+"); - for(j=0;j<l->n;j++) - fprintf(out,"%g\n",curve[j]); - fclose(out); - } -#endif } /* subtract or add an lpc filter to data. Vorbis doesn't actually use this. */ diff --git a/lib/mapping0.c b/lib/mapping0.c index 5a1eb748..6cb36bb2 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.10 2000/02/13 11:53:46 xiphmont Exp $ + last mod: $Id: mapping0.c,v 1.11 2000/02/23 09:24:29 xiphmont Exp $ ********************************************************************/ @@ -80,91 +80,92 @@ static void free_look(vorbis_look_mapping *look){ } } -static vorbis_look_mapping *look(vorbis_info *vi,vorbis_info_mode *vm, +static vorbis_look_mapping *look(vorbis_dsp_state *vd,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; + vorbis_info *vi=vd->vi; + vorbis_look_mapping0 *look=calloc(1,sizeof(vorbis_look_mapping0)); + vorbis_info_mapping0 *info=look->map=(vorbis_info_mapping0 *)m; + look->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 *)); - if(vi->psys)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 *)); + look->time_look=calloc(info->submaps,sizeof(vorbis_look_time *)); + look->floor_look=calloc(info->submaps,sizeof(vorbis_look_floor *)); + look->residue_look=calloc(info->submaps,sizeof(vorbis_look_residue *)); + if(vi->psys)look->psy_look=calloc(info->submaps,sizeof(vorbis_look_psy)); + + look->time_func=calloc(info->submaps,sizeof(vorbis_func_time *)); + look->floor_func=calloc(info->submaps,sizeof(vorbis_func_floor *)); + look->residue_func=calloc(info->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]); + for(i=0;i<info->submaps;i++){ + int timenum=info->timesubmap[i]; + int floornum=info->floorsubmap[i]; + int resnum=info->residuesubmap[i]; + + look->time_func[i]=_time_P[vi->time_type[timenum]]; + look->time_look[i]=look->time_func[i]-> + look(vd,vm,vi->time_param[timenum]); + look->floor_func[i]=_floor_P[vi->floor_type[floornum]]; + look->floor_look[i]=look->floor_func[i]-> + look(vd,vm,vi->floor_param[floornum]); + look->residue_func[i]=_residue_P[vi->residue_type[resnum]]; + look->residue_look[i]=look->residue_func[i]-> + look(vd,vm,vi->residue_param[resnum]); if(vi->psys){ - int psynum=map->psysubmap[i]; - _vp_psy_init(ret->psy_look+i,vi->psy_param[psynum], + int psynum=info->psysubmap[i]; + _vp_psy_init(look->psy_look+i,vi->psy_param[psynum], vi->blocksizes[vm->blockflag]/2,vi->rate); } } - return(ret); + return(look); } static void pack(vorbis_info *vi,vorbis_info_mapping *vm,oggpack_buffer *opb){ int i; - vorbis_info_mapping0 *d=(vorbis_info_mapping0 *)vm; + vorbis_info_mapping0 *info=(vorbis_info_mapping0 *)vm; - _oggpack_write(opb,d->submaps-1,4); + _oggpack_write(opb,info->submaps-1,4); /* we don't write the channel submappings if we only have one... */ - if(d->submaps>1){ + if(info->submaps>1){ for(i=0;i<vi->channels;i++) - _oggpack_write(opb,d->chmuxlist[i],4); + _oggpack_write(opb,info->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); + for(i=0;i<info->submaps;i++){ + _oggpack_write(opb,info->timesubmap[i],8); + _oggpack_write(opb,info->floorsubmap[i],8); + _oggpack_write(opb,info->residuesubmap[i],8); } } /* also responsible for range checking */ static 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)); + vorbis_info_mapping0 *info=calloc(1,sizeof(vorbis_info_mapping0)); + memset(info,0,sizeof(vorbis_info_mapping0)); - d->submaps=_oggpack_read(opb,4)+1; + info->submaps=_oggpack_read(opb,4)+1; - if(d->submaps>1){ + if(info->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; + info->chmuxlist[i]=_oggpack_read(opb,4); + if(info->chmuxlist[i]>=info->submaps)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; + for(i=0;i<info->submaps;i++){ + info->timesubmap[i]=_oggpack_read(opb,8); + if(info->timesubmap[i]>=vi->times)goto err_out; + info->floorsubmap[i]=_oggpack_read(opb,8); + if(info->floorsubmap[i]>=vi->floors)goto err_out; + info->residuesubmap[i]=_oggpack_read(opb,8); + if(info->residuesubmap[i]>=vi->residues)goto err_out; } - return d; + return info; err_out: - free_info(d); + free_info(info); return(NULL); } @@ -183,7 +184,7 @@ static int forward(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_mapping0 *info=look->map; vorbis_info_mode *mode=look->mode; int n=vb->pcmend; int i,j; @@ -213,18 +214,19 @@ static int forward(vorbis_block *vb,vorbis_look_mapping *l){ { double *decfloor=_vorbis_block_alloc(vb,n*sizeof(double)/2); - double *floor=_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); for(i=0;i<vi->channels;i++){ double *pcm=vb->pcm[i]; - int submap=map->chmuxlist[i]; + int submap=info->chmuxlist[i]; /* perform psychoacoustics; takes PCM vector; returns two curves: the desired transform floor and the masking curve */ - memset(floor,0,sizeof(double)*n/2); + /*memset(floor,0,sizeof(double)*n/2);*/ memset(mask,0,sizeof(double)*n/2); - _vp_mask_floor(look->psy_look+submap,pcm,floor,0); + /*_vp_mask_floor(look->psy_look+submap,pcm,floor,0); we use + unnormalized masks as floors for now */ _vp_mask_floor(look->psy_look+submap,pcm,mask,1); /* perform floor encoding; takes transform floor, returns decoded floor */ @@ -248,7 +250,7 @@ static int forward(vorbis_block *vb,vorbis_look_mapping *l){ sprintf(buffer,"floored_%d.vqd",vb->mode); of=fopen(buffer,"a"); for(i=0;i<n/2;i++) - fprintf(of,"%g, ",pcm[i]/floor[i]); + fprintf(of,"%g, ",pcm[i]/decfloor[i]); fprintf(of,"\n"); fclose(of); } @@ -263,10 +265,10 @@ static int forward(vorbis_block *vb,vorbis_look_mapping *l){ multiplexed. All the channels belonging to one submap are encoded (values interleaved), then the next submap, etc */ - for(i=0;i<map->submaps;i++){ + for(i=0;i<info->submaps;i++){ int ch_in_bundle=0; for(j=0;j<vi->channels;j++){ - if(map->chmuxlist[j]==i && nonzero[j]==1){ + if(info->chmuxlist[j]==i && nonzero[j]==1){ pcmbundle[ch_in_bundle++]=vb->pcm[j]; } } @@ -283,7 +285,7 @@ static 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_mapping0 *info=look->map; vorbis_info_mode *mode=look->mode; int i,j; long n=vb->pcmend=vi->blocksizes[vb->W]; @@ -300,17 +302,17 @@ static int inverse(vorbis_block *vb,vorbis_look_mapping *l){ /* recover the spectral envelope; store it in the PCM vector for now */ for(i=0;i<vi->channels;i++){ double *pcm=vb->pcm[i]; - int submap=map->chmuxlist[i]; + int submap=info->chmuxlist[i]; nonzero[i]=look->floor_func[submap]-> inverse(vb,look->floor_look[submap],pcm); } /* recover the residue, apply directly to the spectral envelope */ - for(i=0;i<map->submaps;i++){ + for(i=0;i<info->submaps;i++){ int ch_in_bundle=0; for(j=0;j<vi->channels;j++){ - if(map->chmuxlist[j]==i && nonzero[j]) + if(info->chmuxlist[j]==i && nonzero[j]) pcmbundle[ch_in_bundle++]=vb->pcm[j]; } @@ -12,7 +12,7 @@ ******************************************************************** function: miscellaneous prototypes - last mod: $Id: misc.h,v 1.1 2000/01/22 13:28:27 xiphmont Exp $ + last mod: $Id: misc.h,v 1.2 2000/02/23 09:24:30 xiphmont Exp $ ********************************************************************/ @@ -21,5 +21,6 @@ extern void *_vorbis_block_alloc(vorbis_block *vb,long bytes); extern void _vorbis_block_ripcord(vorbis_block *vb); +extern void _analysis_output(char *base,int i,double *v,int n); #endif @@ -12,10 +12,15 @@ ******************************************************************** function: residue backend 0 implementation - last mod: $Id: res0.c,v 1.6 2000/02/13 11:53:48 xiphmont Exp $ + last mod: $Id: res0.c,v 1.7 2000/02/23 09:24:31 xiphmont Exp $ ********************************************************************/ +/* Slow, slow, slow, simpleminded and did I mention it was slow? The + encode/decode loops are coded for clarity and performance is not + yet even a nagging little idea lurking in the shadows. Oh and BTW, + it's slow. */ + #include <stdlib.h> #include <string.h> #include <math.h> @@ -24,10 +29,20 @@ #include "bitwise.h" #include "registry.h" #include "scales.h" +#include "bookinternal.h" +#include "misc.h" typedef struct { vorbis_info_residue0 *info; - int bookpointers[64]; + + int parts; + codebook *phrasebook; + + codebook ***partbooks; + int *partstages; + + int partvals; + int **decodemap; } vorbis_look_residue0; void free_info(vorbis_info_residue *i){ @@ -38,7 +53,16 @@ void free_info(vorbis_info_residue *i){ } void free_look(vorbis_look_residue *i){ + int j; if(i){ + vorbis_look_residue0 *look=(vorbis_look_residue0 *)i; + for(j=0;j<look->parts;j++) + if(look->partbooks[j])free(look->partbooks[j]); + free(look->partbooks); + for(j=0;j<look->partvals;j++) + free(look->decodemap[j]); + free(look->decodemap); + if(look->partstages)free(look->partstages); memset(i,0,sizeof(vorbis_look_residue0)); free(i); } @@ -54,9 +78,6 @@ void pack(vorbis_info_residue *vr,oggpack_buffer *opb){ _oggpack_write(opb,info->grouping-1,24); /* residue vectors to group and code with a partitioned book */ _oggpack_write(opb,info->partitions-1,6); /* possible partition choices */ - _oggpack_write(opb,info->groupspercode-1,6); /* partitioned group - codes to encode at - once */ _oggpack_write(opb,info->groupbook,8); /* group huffman book */ for(j=0;j<info->partitions;j++){ _oggpack_write(opb,info->secondstages[j],4); /* zero *is* a valid choice */ @@ -70,59 +91,272 @@ 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){ int j,acc=0; - vorbis_info_residue0 *ret=calloc(1,sizeof(vorbis_info_residue0)); - - ret->begin=_oggpack_read(opb,24); - ret->end=_oggpack_read(opb,24); - ret->grouping=_oggpack_read(opb,24)+1; - ret->partitions=_oggpack_read(opb,6)+1; - ret->groupspercode=_oggpack_read(opb,6)+1; - ret->groupbook=_oggpack_read(opb,8); - for(j=0;j<ret->partitions;j++) - acc+=ret->secondstages[j]=_oggpack_read(opb,4); + vorbis_info_residue0 *info=calloc(1,sizeof(vorbis_info_residue0)); + + info->begin=_oggpack_read(opb,24); + info->end=_oggpack_read(opb,24); + info->grouping=_oggpack_read(opb,24)+1; + info->partitions=_oggpack_read(opb,6)+1; + info->groupbook=_oggpack_read(opb,8); + for(j=0;j<info->partitions;j++) + acc+=info->secondstages[j]=_oggpack_read(opb,4); for(j=0;j<acc;j++) - ret->booklist[j]=_oggpack_read(opb,8); + info->booklist[j]=_oggpack_read(opb,8); - if(ret->groupbook>=vi->books)goto errout; + if(info->groupbook>=vi->books)goto errout; for(j=0;j<acc;j++) - if(ret->booklist[j]>=vi->books)goto errout; + if(info->booklist[j]>=vi->books)goto errout; - return(ret); + return(info); errout: - free_info(ret); + free_info(info); return(NULL); } -vorbis_look_residue *look (vorbis_info *vi,vorbis_info_mode *vm, +vorbis_look_residue *look (vorbis_dsp_state *vd,vorbis_info_mode *vm, vorbis_info_residue *vr){ vorbis_info_residue0 *info=(vorbis_info_residue0 *)vr; vorbis_look_residue0 *look=calloc(1,sizeof(vorbis_look_residue0)); - int j,acc=0; + int j,k,acc=0; + int dim; look->info=info; - for(j=0;j<info->partitions;j++){ - look->bookpointers[j]=acc; - acc+=info->secondstages[j]; + + look->parts=info->partitions; + look->phrasebook=vd->fullbooks+info->groupbook; + dim=look->phrasebook->dim; + + look->partbooks=calloc(look->parts,sizeof(codebook **)); + look->partstages=calloc(look->parts,sizeof(int)); + + for(j=0;j<look->parts;j++){ + int stages=info->secondstages[j]; + if(stages){ + look->partbooks[j]=malloc(stages*sizeof(codebook *)); + for(k=0;k<stages;k++) + look->partbooks[j][k]=vd->fullbooks+info->booklist[acc++]; + } + look->partstages[j]=stages; + } + + look->partvals=pow(look->parts,dim); + look->decodemap=malloc(look->partvals*sizeof(int *)); + for(j=0;j<look->partvals;j++){ + long val=j; + long mult=look->partvals/look->parts; + look->decodemap[j]=malloc(dim*sizeof(int)); + for(k=0;k<dim;k++){ + long deco=val/mult; + val-=deco*mult; + mult/=look->parts; + look->decodemap[j][k]=deco; + } } return(look); } -int forward(vorbis_block *vb,vorbis_look_residue *l, +/* returns the distance error from encoding with this book set */ +static double _testpart(double *vec,int n, int stages, codebook **books){ + int i,j; + + double *work=alloca(n*sizeof(double)),acc=0.; + memcpy(work,vec,n*sizeof(double)); + + if(stages==0){ + /* a mild hack. We want partitions with samples values under + fabs(.5) to be fully zeroed; if this case is met, we return an + error of -1 (which cannot be beaten). If the samples values + don't meet this criteria, return the real error */ + for(i=0;i<n;i++) + if(fabs(vec[i])>.5)break; + if(i==n)return(-1.); + + /* real (squared) error */ + for(i=0;i<n;i++) + acc+=vec[i]*vec[i]; + + }else{ + for(j=0;j<stages;j++){ + acc=0.; + for(i=0;i<n;i+=books[j]->dim) + acc+=vorbis_book_vE(books[j],work+i); + } + } + + return(acc); +} + +static int _testhack(double *vec,int n){ + int i; + double acc=0.; + double max=0.; + for(i=0;i<n;i++) + acc+=todB(fabs(vec[i])); + acc=fromdB(acc/n); + for(i=0;i<n;i++) + max=(fabs(vec[i])>max?fabs(vec[i]):max); + + if(max<.5)return(0); + if(max<2.5 && acc<1.5)return(1); + if(max<6.)return(2); + return(3); +} + +static int _encodepart(oggpack_buffer *opb,double *vec, int n, + int stages, codebook **books){ + int i,j,bits=0; + + double *work=alloca(n*sizeof(double)); + memcpy(work,vec,n*sizeof(double)); + + for(j=0;j<stages;j++) + for(i=0;i<n;i+=books[j]->dim) + bits+=vorbis_book_encodevE(books[j],work+i,opb); + + return(bits); +} + +static int _decodepart(oggpack_buffer *opb,double *work,double *vec, int n, + int stages, codebook **books){ + int i,j; + + memset(work,0,n*sizeof(double)); + for(j=0;j<stages;j++) + for(i=0;i<n;i+=books[j]->dim) + vorbis_book_decodev(books[j],work+i,opb); + + for(i=0;i<n;i++) + vec[i]*=work[i]; + + return(0); +} + +int forward(vorbis_block *vb,vorbis_look_residue *vl, double **in,int ch){ - long i,j; - vorbis_look_residue0 *look=(vorbis_look_residue0 *)l; + long i,j,k,l; + vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl; vorbis_info_residue0 *info=look->info; - for(i=0;i<ch;i++) - for(j=0;j<vb->pcmend/2;j++) - _oggpack_write(&vb->opb,rint(in[i][j])+32,6); + + /* move all this setup out later */ + int samples_per_partition=info->grouping; + int possible_partitions=info->partitions; + int partitions_per_word=look->phrasebook->dim; + int n=info->end-info->begin; + long phrasebits=0,resbitsT=0; + long *resbits=alloca(sizeof(long)*possible_partitions); + long *resvals=alloca(sizeof(long)*possible_partitions); + + int partvals=n/samples_per_partition; + int partwords=(partvals+partitions_per_word-1)/partitions_per_word; + long **partword=_vorbis_block_alloc(vb,ch*sizeof(long *)); + partvals=partwords*partitions_per_word; + + /* we find/encode the patition type for each partition of each + channel. We'll go back and do the interleaved encoding in a + bit. For now, clarity */ + + if(ch)_analysis_output("a_res",vb->sequence,in[0],n); + memset(resbits,0,sizeof(long)*possible_partitions); + memset(resvals,0,sizeof(long)*possible_partitions); + + for(i=0;i<ch;i++){ + partword[i]=_vorbis_block_alloc(vb,n/samples_per_partition*sizeof(long)); + memset(partword[i],0,n/samples_per_partition*sizeof(long)); + } + + for(i=info->begin,l=0;i<info->end;i+=samples_per_partition,l++){ + for(j=0;j<ch;j++){ + + /* find the best encoding for the partition using each possible + book. Use the book that had lowest error (we arrange the + books to make optimal choice very obvious and not even think + about bits) */ + partword[j][l]=_testhack(in[j]+i,samples_per_partition); + +#if 0 + double best=_testpart(in[j]+i,samples_per_partition, + look->partstages[0],look->partbooks[0]); + for(k=1;k<info->partitions;k++){ + double this=_testpart(in[j]+i,samples_per_partition, + look->partstages[k],look->partbooks[k]); + if(this<best){ + best=this; + partword[j][l]=k; + } + } +#endif + } + } + + /* we code the partition words for each channel, then the residual + words for a partition per channel until we've written all the + partitions for that partition word. Then write the next parition + channel words... */ + + for(i=info->begin,l=0;i<info->end;){ + /* first we encode a partition codeword for each channel */ + for(j=0;j<ch;j++){ + long val=partword[j][l]; + for(k=1;k<partitions_per_word;k++) + val= val*possible_partitions+partword[j][l+k]; + phrasebits+=vorbis_book_encode(look->phrasebook,val,&vb->opb); + } + /* now we encode interleaved residual values for the partitions */ + for(k=0;k<partitions_per_word;k++,l++,i+=samples_per_partition) + for(j=0;j<ch;j++){ + resbits[partword[j][l]]+= + _encodepart(&vb->opb,in[j]+i,samples_per_partition, + look->partstages[partword[j][l]], + look->partbooks[partword[j][l]]); + resvals[partword[j][l]]+=samples_per_partition; + } + + } + + for(i=0;i<possible_partitions;i++)resbitsT+=resbits[i]; + fprintf(stderr,"Encoded %ld res vectors in %d phrasing and %d res bits\n\t", + ch*(info->end-info->begin),phrasebits,resbitsT); + for(i=0;i<possible_partitions;i++) + fprintf(stderr,"%ld(%ld):%ld ",i,resvals[i],resbits[i]); + fprintf(stderr,"\n"); + return(0); } -int inverse(vorbis_block *vb,vorbis_look_residue *l,double **in,int ch){ - long i,j; - for(i=0;i<ch;i++) - for(j=0;j<vb->pcmend/2;j++) - in[i][j]*=_oggpack_read(&vb->opb,6)-32; +int inverse(vorbis_block *vb,vorbis_look_residue *vl,double **in,int ch){ + long i,j,k,l; + vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl; + vorbis_info_residue0 *info=look->info; + + /* move all this setup out later */ + int samples_per_partition=info->grouping; + int partitions_per_word=look->phrasebook->dim; + int n=info->end-info->begin; + + int partvals=n/samples_per_partition; + int partwords=(partvals+partitions_per_word-1)/partitions_per_word; + int **partword=alloca(ch*sizeof(long *)); + double *work=alloca(sizeof(double)*samples_per_partition); + partvals=partwords*partitions_per_word; + + for(i=info->begin,l=0;i<info->end;){ + /* fetch the partition word for each channel */ + for(j=0;j<ch;j++) + partword[j]=look->decodemap[vorbis_book_decode(look->phrasebook, + &vb->opb)]; + + /* now we encode interleaved residual values for the partitions */ + for(k=0;k<partitions_per_word;k++,l++,i+=samples_per_partition) + for(j=0;j<ch;j++){ + int part=partword[j][k]; + _decodepart(&vb->opb,work,in[j]+i,samples_per_partition, + look->partstages[part], + look->partbooks[part]); + } + } + + if(ch)_analysis_output("s_res",vb->sequence,in[0],n); + return(0); } diff --git a/lib/time0.c b/lib/time0.c index 973afd5f..e0ec1f02 100644 --- a/lib/time0.c +++ b/lib/time0.c @@ -12,7 +12,7 @@ ******************************************************************** function: time backend 0 (dummy) - last mod: $Id: time0.c,v 1.3 2000/02/06 13:39:47 xiphmont Exp $ + last mod: $Id: time0.c,v 1.4 2000/02/23 09:24:32 xiphmont Exp $ ********************************************************************/ @@ -27,7 +27,7 @@ static vorbis_info_time *unpack (vorbis_info *vi,oggpack_buffer *opb){ return ""; } -static vorbis_look_time *look (vorbis_info *vi,vorbis_info_mode *mi, +static vorbis_look_time *look (vorbis_dsp_state *vd,vorbis_info_mode *mi, vorbis_info_time *i){ return ""; } |
