summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorMonty <xiphmont@xiph.org>2000-02-23 09:24:33 +0000
committerMonty <xiphmont@xiph.org>2000-02-23 09:24:33 +0000
commitaadce85249efb25ead6b27b2a3ebbcbc61c01c6f (patch)
treee4758618201900982aa016c87b471ed36a7d2d13 /lib
parentcf8e31643849079886d4eddcb268981e7bb13e83 (diff)
downloadlibvorbis-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.c18
-rw-r--r--lib/bitwise.c4
-rw-r--r--lib/block.c51
-rw-r--r--lib/bookinternal.h4
-rw-r--r--lib/codebook.c51
-rw-r--r--lib/floor0.c92
-rw-r--r--lib/lpc.c37
-rw-r--r--lib/mapping0.c132
-rw-r--r--lib/misc.h3
-rw-r--r--lib/res0.c306
-rw-r--r--lib/time0.c4
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);
}
diff --git a/lib/lpc.c b/lib/lpc.c
index 47be644b..5b97ee26 100644
--- a/lib/lpc.c
+++ b/lib/lpc.c
@@ -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];
}
diff --git a/lib/misc.h b/lib/misc.h
index 26850bf0..bae284fa 100644
--- a/lib/misc.h
+++ b/lib/misc.h
@@ -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
diff --git a/lib/res0.c b/lib/res0.c
index 0134d7dd..d32bfbbe 100644
--- a/lib/res0.c
+++ b/lib/res0.c
@@ -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 "";
}