From 69c07b4904ace8a29154e6da0fcf4fea3f409f8a Mon Sep 17 00:00:00 2001 From: Monty Date: Sat, 12 Feb 2000 08:33:10 +0000 Subject: [PATCH] Collect training data from the lib when compiled with -DTRAIN Added staging to floor0.c Added first work toward residue partitioning and huff builder Monty x svn path=/trunk/vorbis/; revision=257 --- Makefile.in | 4 +- configure | 4 +- configure.in | 4 +- examples/Makefile.in | 4 +- include/vorbis/backends.h | 12 ++- include/vorbis/codec.h | 3 +- include/vorbis/modes.h | 9 +- lib/analysis.c | 3 +- lib/floor0.c | 16 +++- lib/mapping0.c | 40 +++++--- lib/psy.c | 39 ++------ lib/psy.h | 16 +--- lib/res0.c | 74 ++++++++++++++- lib/synthesis.c | 3 +- vq/residuesplit.c | 230 ++++++++++++++++++++++++++++++++++++++++++++++ 15 files changed, 379 insertions(+), 82 deletions(-) create mode 100644 vq/residuesplit.c diff --git a/Makefile.in b/Makefile.in index 9dd4b1d..b2fea18 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,6 +1,6 @@ # vorbis makefile configured for use with gcc on any platform -# $Id: Makefile.in,v 1.4 1999/12/30 07:26:22 xiphmont Exp $ +# $Id: Makefile.in,v 1.5 2000/02/12 08:32:57 xiphmont Exp $ ############################################################################### # # @@ -17,7 +17,7 @@ @SET_MAKE@ -SUBDIRS = lib vq examples # cmdline xmms +SUBDIRS = lib vq huff examples # cmdline xmms all debug profile selftest target clean: @for dir in $(SUBDIRS); do (cd $$dir && $(MAKE) $(MFLAGS) $@) || exit 1; done diff --git a/configure b/configure index 71c1d7d..cdefa9e 100755 --- a/configure +++ b/configure @@ -2117,7 +2117,7 @@ done ac_given_srcdir=$srcdir -trap 'rm -fr `echo "Makefile lib/Makefile examples/Makefile vq/Makefile cmdline/Makefile xmms/Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +trap 'rm -fr `echo "Makefile lib/Makefile examples/Makefile vq/Makefile huff/Makefile cmdline/Makefile xmms/Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 EOF cat >> $CONFIG_STATUS <> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then diff --git a/configure.in b/configure.in index d330830..42d7b2c 100644 --- a/configure.in +++ b/configure.in @@ -1,4 +1,4 @@ -# $Id: configure.in,v 1.9 2000/01/12 11:34:34 xiphmont Exp $ +# $Id: configure.in,v 1.10 2000/02/12 08:32:59 xiphmont Exp $ AC_INIT(lib/mdct.c) #AC_CONFIG_HEADER(config.h) @@ -180,4 +180,4 @@ AC_SUBST(RANLIB) #AC_SUBST(LIBGTKDIR) AC_SUBST(pthread_lib) -AC_OUTPUT(Makefile lib/Makefile examples/Makefile vq/Makefile cmdline/Makefile xmms/Makefile) +AC_OUTPUT(Makefile lib/Makefile examples/Makefile vq/Makefile huff/Makefile cmdline/Makefile xmms/Makefile) diff --git a/examples/Makefile.in b/examples/Makefile.in index b80ab68..6183a1b 100644 --- a/examples/Makefile.in +++ b/examples/Makefile.in @@ -1,6 +1,6 @@ # vorbis makefile configured for use with gcc on any platform -# $Id: Makefile.in,v 1.4 2000/01/28 09:04:57 xiphmont Exp $ +# $Id: Makefile.in,v 1.5 2000/02/12 08:33:00 xiphmont Exp $ ############################################################################### # # @@ -44,6 +44,8 @@ profile: target: $(BINFILES) +encoder_example.o: ../include/vorbis/modes.h + encoder_example: $(OFILES) ../lib/libvorbis.a $(CC) $(CFLAGS) $(LDFLAGS) encoder_example.o ../lib/libvorbis.a -o \ encoder_example -lm diff --git a/include/vorbis/backends.h b/include/vorbis/backends.h index 5030de5..d24a364 100644 --- a/include/vorbis/backends.h +++ b/include/vorbis/backends.h @@ -13,7 +13,7 @@ function: libvorbis backend and mapping structures; needed for static mode headers - last mod: $Id: backends.h,v 1.5 2000/02/09 22:04:09 xiphmont Exp $ + last mod: $Id: backends.h,v 1.6 2000/02/12 08:33:01 xiphmont Exp $ ********************************************************************/ @@ -83,7 +83,7 @@ typedef struct{ void (*free_info) (vorbis_info_residue *); void (*free_look) (vorbis_look_residue *); int (*forward) (struct vorbis_block *,vorbis_look_residue *, - double **,int **,int); + double **,int); int (*inverse) (struct vorbis_block *,vorbis_look_residue *, double **,int); } vorbis_func_residue; @@ -93,7 +93,13 @@ typedef struct vorbis_info_residue0{ long begin; long end; - /* way unfinished, just so you know while poking around CVS ;-) */ + /* first stage (lossless partitioning) */ + int grouping; /* group n vectors */ + int partitions; /* partition entries (per group) */ + int groupspercode; /* groups per codeword */ + int groupbook; /* huffbook for partitioning */ + int secondstages[64]; /* expanded out to pointers in lookup */ + int booklist[256]; /* list of second stage books */ } vorbis_info_residue0; diff --git a/include/vorbis/codec.h b/include/vorbis/codec.h index aa05234..703da9f 100644 --- a/include/vorbis/codec.h +++ b/include/vorbis/codec.h @@ -12,7 +12,7 @@ ******************************************************************** function: libvorbis codec headers - last mod: $Id: codec.h,v 1.8 2000/02/06 13:39:37 xiphmont Exp $ + last mod: $Id: codec.h,v 1.9 2000/02/12 08:33:02 xiphmont Exp $ ********************************************************************/ @@ -269,6 +269,7 @@ typedef struct vorbis_block{ long W; long nW; int pcmend; + int mode; int eofflag; int frameno; diff --git a/include/vorbis/modes.h b/include/vorbis/modes.h index 06ee1af..b213666 100644 --- a/include/vorbis/modes.h +++ b/include/vorbis/modes.h @@ -12,7 +12,7 @@ ******************************************************************** function: predefined encoding modes - last mod: $Id: modes.h,v 1.5 2000/02/09 22:04:10 xiphmont Exp $ + last mod: $Id: modes.h,v 1.6 2000/02/12 08:33:03 xiphmont Exp $ ********************************************************************/ @@ -46,9 +46,10 @@ static vorbis_info_psy _psy_set0={ static vorbis_info_time0 _time_set0={0}; static vorbis_info_floor0 _floor_set0={20, 44100, 64, 12,140, 1, {0} }; static vorbis_info_floor0 _floor_set1={32, 44100, 256, 12,140, 1, {1} }; -static vorbis_info_residue0 _residue_set0={0,0}; +static vorbis_info_residue0 _residue_set0={0, 128, 32,4,4,3,{0,1,1,1},{0,0,0}}; +static vorbis_info_residue0 _residue_set1={0,1024, 32,4,4,3,{0,1,1,1},{0,0,0}}; static vorbis_info_mapping0 _mapping_set0={1, {0,0}, {0}, {0}, {0}, {0}}; -static vorbis_info_mapping0 _mapping_set1={1, {0,0}, {0}, {1}, {0}, {0}}; +static vorbis_info_mapping0 _mapping_set1={1, {0,0}, {0}, {1}, {1}, {0}}; static vorbis_info_mode _mode_set0={0,0,0,0}; static vorbis_info_mode _mode_set1={1,0,0,1}; @@ -69,7 +70,7 @@ vorbis_info info_A={ /* floors */ {0,0},{&_floor_set0,&_floor_set1}, /* residue */ - {0,0},{&_residue_set0}, + {0,0},{&_residue_set0,&_residue_set1}, /* books */ {&_vq_book_lsp20_0,&_vq_book_lsp32_0}, /* psy */ diff --git a/lib/analysis.c b/lib/analysis.c index faceac3..c6fd420 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.22 2000/01/22 13:28:14 xiphmont Exp $ + last mod: $Id: analysis.c,v 1.23 2000/02/12 08:33:04 xiphmont Exp $ ********************************************************************/ @@ -44,6 +44,7 @@ int vorbis_analysis(vorbis_block *vb,ogg_packet *op){ if(vb->W &&vi->modes>1)mode=1; type=vi->map_type[vi->mode_param[mode]->mapping]; + vb->mode=mode; /* Encode frame mode, pre,post windowsize, then dispatch */ _oggpack_write(&vb->opb,mode,vd->modebits); diff --git a/lib/floor0.c b/lib/floor0.c index 56ef805..eff41a4 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.8 2000/02/09 22:04:12 xiphmont Exp $ + last mod: $Id: floor0.c,v 1.9 2000/02/12 08:33:05 xiphmont Exp $ ********************************************************************/ @@ -143,6 +143,20 @@ static int forward(vorbis_block *vb,vorbis_look_floor *i, vorbis_lpc_to_lsp(out,out,look->m); memcpy(work,out,sizeof(double)*look->m); +#ifdef TRAIN + { + int j; + FILE *of; + char buffer[80]; + sprintf(buffer,"lsp0coeff_%d.vqd",vb->mode); + of=fopen(buffer,"a"); + for(j=0;jm;j++) + fprintf(of,"%g, ",out[j]); + fprintf(of,"\n"); + fclose(of); + } +#endif + /* code the spectral envelope, and keep track of the actual quantized values; we don't want creeping error as each block is nailed to the last quantized value of the previous block. */ diff --git a/lib/mapping0.c b/lib/mapping0.c index 58f6f13..df36ce5 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.8 2000/02/09 22:04:14 xiphmont Exp $ + last mod: $Id: mapping0.c,v 1.9 2000/02/12 08:33:06 xiphmont Exp $ ********************************************************************/ @@ -190,7 +190,6 @@ static int forward(vorbis_block *vb,vorbis_look_mapping *l){ double *window=vd->window[vb->W][vb->lW][vb->nW][mode->windowtype]; double **pcmbundle=alloca(sizeof(double *)*vi->channels); - int **auxbundle=alloca(sizeof(int *)*vi->channels); int *nonzero=alloca(sizeof(int)*vi->channels); /* time domain pre-window: NONE IMPLEMENTED */ @@ -216,19 +215,17 @@ 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 *mask=_vorbis_block_alloc(vb,n*sizeof(double)/2); - int **pcmaux=_vorbis_block_alloc(vb,vi->channels*sizeof(int *)); for(i=0;ichannels;i++){ double *pcm=vb->pcm[i]; int submap=map->chmuxlist[i]; - pcmaux[i]=_vorbis_block_alloc(vb,n/2*sizeof(int)); - /* perform psychoacoustics; takes PCM vector; returns two curves: the desired transform floor and the masking curve */ memset(floor,0,sizeof(double)*n/2); memset(mask,0,sizeof(double)*n/2); - _vp_mask_floor(look->psy_look+submap,pcm,mask,floor); + _vp_mask_floor(look->psy_look+submap,pcm,floor,0); + _vp_mask_floor(look->psy_look+submap,pcm,mask,1); /* perform floor encoding; takes transform floor, returns decoded floor */ nonzero[i]=look->floor_func[submap]-> @@ -236,12 +233,28 @@ static int forward(vorbis_block *vb,vorbis_look_mapping *l){ /* no iterative residue/floor tuning at the moment */ - /* perform residue prequantization. Do it now so we have all - the values if we need them */ - _vp_quantize(look->psy_look+submap,pcm,mask,decfloor,pcmaux[i],0,n/2,n/2); - +#ifdef TRAIN + if(nonzero[i]){ + FILE *of; + char buffer[80]; + + sprintf(buffer,"masked_%d.vqd",vb->mode); + of=fopen(buffer,"a"); + for(i=0;imode); + of=fopen(buffer,"a"); + for(i=0;ichannels;j++){ if(map->chmuxlist[j]==i && nonzero[j]==1){ pcmbundle[ch_in_bundle]=vb->pcm[j]; - auxbundle[ch_in_bundle++]=pcmaux[j]; } } - look->residue_func[i]->forward(vb,look->residue_look[i],pcmbundle,auxbundle, - ch_in_bundle); + look->residue_func[i]->forward(vb,look->residue_look[i], + pcmbundle,ch_in_bundle); } } diff --git a/lib/psy.c b/lib/psy.c index 1b9b5fb..dd6a10e 100644 --- a/lib/psy.c +++ b/lib/psy.c @@ -12,7 +12,7 @@ ******************************************************************** function: psychoacoustics not including preecho - last mod: $Id: psy.c,v 1.15 2000/02/06 13:39:44 xiphmont Exp $ + last mod: $Id: psy.c,v 1.16 2000/02/12 08:33:07 xiphmont Exp $ ********************************************************************/ @@ -84,18 +84,18 @@ void _vp_psy_clear(vorbis_look_psy *p){ /* Masking curve: linear rolloff on a Bark/dB scale, attenuated by maskthresh */ -/* right now, floor==mask */ -void _vp_mask_floor(vorbis_look_psy *p,double *f, double *mask,double *floor){ + +void _vp_mask_floor(vorbis_look_psy *p,double *f, double *floor,int attp){ int n=p->n; double hroll=p->vi->hrolldB; double lroll=p->vi->lrolldB; - double curmask=todB(f[0])+p->maskthresh[0]; + double curmask=todB(f[0])+(attp?p->maskthresh[0]:0); double curoc=0.; long i; /* run mask forward then backward */ for(i=0;imaskthresh[i]; + double newmask=todB(f[i])+(attp?p->maskthresh[i]:0); double newoc=p->barknum[i]; double roll=curmask-(newoc-curoc)*hroll; double troll; @@ -104,14 +104,13 @@ void _vp_mask_floor(vorbis_look_psy *p,double *f, double *mask,double *floor){ curoc=newoc; } troll=fromdB(roll); - if(mask[i]maskthresh[n-1]; + curmask=todB(f[n-1])+(attp?p->maskthresh[n-1]:0); curoc=p->barknum[n-1]; for(i=n-1;i>=0;i--){ - double newmask=todB(f[i])+p->maskthresh[i]; + double newmask=todB(f[i])+(attp?p->maskthresh[i]:0); double newoc=p->barknum[i]; double roll=curmask-(curoc-newoc)*lroll; double troll; @@ -120,34 +119,10 @@ void _vp_mask_floor(vorbis_look_psy *p,double *f, double *mask,double *floor){ curoc=newoc; } troll=fromdB(roll); - if(mask[i]15)value=15; - if(value<-15)value=-15; - pcm[i]=value; - } - -} - /* s must be padded at the end with m-1 zeroes */ static void time_convolve(double *s,double *r,int n,int m){ int i; diff --git a/lib/psy.h b/lib/psy.h index 6426f94..5f41163 100644 --- a/lib/psy.h +++ b/lib/psy.h @@ -12,7 +12,7 @@ ******************************************************************** function: random psychoacoustics (not including preecho) - last mod: $Id: psy.h,v 1.10 2000/02/06 13:39:45 xiphmont Exp $ + last mod: $Id: psy.h,v 1.11 2000/02/12 08:33:08 xiphmont Exp $ ********************************************************************/ @@ -26,13 +26,6 @@ typedef struct { double *maskthresh; double *barknum; - int framebegin; - int frameend; - int subframelen; - int elements[4]; - double cutoffs[4]; - int quantval[4]; - } vorbis_look_psy; extern void _vp_psy_init(vorbis_look_psy *p,vorbis_info_psy *vi,int n,long rate); @@ -40,11 +33,8 @@ extern void _vp_psy_clear(vorbis_look_psy *p); extern void *_vi_psy_dup(void *source); extern void _vi_psy_free(vorbis_info_psy *i); -extern void _vp_mask_floor(vorbis_look_psy *p,double *pcm, - double *mask,double *floor); -extern void _vp_quantize(vorbis_look_psy *p, double *pcm, double *mask, - double *floor,int *aux, - long begin,long n, long subn); +extern void _vp_mask_floor(vorbis_look_psy *p,double *pcm,double *floor, + int attp); #endif diff --git a/lib/res0.c b/lib/res0.c index 65012fd..ec0b27c 100644 --- a/lib/res0.c +++ b/lib/res0.c @@ -12,42 +12,106 @@ ******************************************************************** function: residue backend 0 implementation - last mod: $Id: res0.c,v 1.4 2000/02/06 13:39:46 xiphmont Exp $ + last mod: $Id: res0.c,v 1.5 2000/02/12 08:33:09 xiphmont Exp $ ********************************************************************/ #include #include #include +#include #include "vorbis/codec.h" #include "bitwise.h" #include "registry.h" +#include "scales.h" -/* unfinished as of 20000118 */ +typedef struct { + vorbis_info_residue0 *info; + int bookpointers[64]; +} vorbis_look_residue0; void free_info(vorbis_info_residue *i){ + if(i){ + memset(i,0,sizeof(vorbis_info_residue0)); + free(i); + } } void free_look(vorbis_look_residue *i){ + if(i){ + memset(i,0,sizeof(vorbis_look_residue0)); + free(i); + } } /* not yet */ void pack(vorbis_info_residue *vr,oggpack_buffer *opb){ + vorbis_info_residue0 *info=(vorbis_info_residue0 *)vr; + int j,acc=0; + _oggpack_write(opb,info->begin,24); + _oggpack_write(opb,info->end,24); + + _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;jpartitions;j++){ + _oggpack_write(opb,info->secondstages[j],4); /* zero *is* a valid choice */ + acc+=info->secondstages[j]; + } + for(j=0;jbooklist[j],8); + } /* vorbis_info is for range checking */ vorbis_info_residue *unpack(vorbis_info *vi,oggpack_buffer *opb){ - return ""; + 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;jpartitions;j++) + acc+=ret->secondstages[j]=_oggpack_read(opb,4); + for(j=0;jbooklist[j]=_oggpack_read(opb,8); + + if(ret->groupbook>=vi->books)goto errout; + for(j=0;jbooklist[j]>=vi->books)goto errout; + + return(ret); + errout: + free_info(ret); + return(NULL); } vorbis_look_residue *look (vorbis_info *vi,vorbis_info_mode *vm, vorbis_info_residue *vr){ - return ""; + vorbis_info_residue0 *info=(vorbis_info_residue0 *)vr; + vorbis_look_residue0 *look=calloc(1,sizeof(vorbis_look_residue0)); + int j,acc=0; + look->info=info; + for(j=0;jpartitions;j++){ + look->bookpointers[j]=acc; + acc+=info->secondstages[j]; + } + + return(look); } int forward(vorbis_block *vb,vorbis_look_residue *l, - double **in,int **aux,int ch){ + double **in,int ch){ long i,j; + vorbis_look_residue0 *look=(vorbis_look_residue0 *)l; + vorbis_info_residue0 *info=look->info; for(i=0;ipcmend/2;j++) _oggpack_write(&vb->opb,rint(in[i][j])+16,5); diff --git a/lib/synthesis.c b/lib/synthesis.c index 3947f23..031d6cd 100644 --- a/lib/synthesis.c +++ b/lib/synthesis.c @@ -12,7 +12,7 @@ ******************************************************************** function: single-block PCM synthesis - last mod: $Id: synthesis.c,v 1.14 2000/01/22 13:28:33 xiphmont Exp $ + last mod: $Id: synthesis.c,v 1.15 2000/02/12 08:33:10 xiphmont Exp $ ********************************************************************/ @@ -40,6 +40,7 @@ int vorbis_synthesis(vorbis_block *vb,ogg_packet *op){ /* read our mode and pre/post windowsize */ mode=_oggpack_read(opb,vd->modebits); + vb->mode=mode; vb->W=vi->mode_param[mode]->blockflag; if(vb->W){ vb->lW=_oggpack_read(opb,1); diff --git a/vq/residuesplit.c b/vq/residuesplit.c new file mode 100644 index 0000000..28205f1 --- /dev/null +++ b/vq/residuesplit.c @@ -0,0 +1,230 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE Ogg Vorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY * + * THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE. * + * PLEASE READ THESE TERMS DISTRIBUTING. * + * * + * THE OggSQUISH SOURCE CODE IS (C) COPYRIGHT 1994-2000 * + * by Monty and The XIPHOPHORUS Company * + * http://www.xiph.org/ * + * * + ******************************************************************** + + function: residue backend 0 partitioner + last mod: $Id: residuesplit.c,v 1.1 2000/02/12 08:33:01 xiphmont Exp $ + + ********************************************************************/ + +#include +#include +#include +#include +#include "../lib/scales.h" +#include "../vq/bookutil.h" + +/* take a masking curve and raw residue; eliminate the inaduble and + quantize to the final form handed to the VQ. All and any tricks to + squeeze out bits given knowledge of the encoding mode should go + here too */ + +/* modifies the pcm vector, returns book membership in aux */ + +/* This is currently a bit specific to/hardwired for mapping 0; things + will need to change in the future when we het real multichannel + mappings */ + +static double _maxval(double *v,int n){ + int i; + double acc=0.; + for(i=0;i []...\n" + " where begin,n,group is first scalar, \n" + " number of scalars of each in line,\n" + " number of scalars in a group\n" + " m,a,f are the boundary conditions for each group\n" + "eg: residuesplit mask.vqd floor.vqd 0,1024,32 res .5 2.5,1.5 ,,.25\n" + "produces resaux.vqd and res_0...n.vqd\n\n"); + exit(1); +} + +int main(int argc, char *argv[]){ + char *buffer; + char *base; + int i,parts,begin,n,subn; + FILE *mask; + FILE *floor; + double *maskmbound,*maskabound,*maskvec; + double *floorbound,*floorvec; + + if(argc<6)usage(); + + base=strdup(argv[4]); + buffer=alloca(strlen(base)+20); + { + char *pos=strchr(argv[3],','); + begin=atoi(argv[3]); + if(!pos) + usage(); + else + n=atoi(pos+1); + pos=strchr(pos+1,','); + if(!pos) + usage(); + else + subn=atoi(pos+1); + if(n/subn*subn != n){ + fprintf(stderr,"n must be divisible by group\n"); + exit(1); + } + } + + /* how many parts? Need to scan m,f... */ + parts=argc-4; /* yes, one past */ + maskmbound=malloc(sizeof(double)*parts); + maskabound=malloc(sizeof(double)*parts); + floorbound=malloc(sizeof(double)*parts); + + for(i=0;i