summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMonty <xiphmont@xiph.org>2001-04-05 00:22:48 +0000
committerMonty <xiphmont@xiph.org>2001-04-05 00:22:48 +0000
commit78540c3db714ab4dda28e11659f2a69e9961bf69 (patch)
tree7599d7a89d4e259f032802ee43e95b07fc41c946
downloadlibvorbis-git-78540c3db714ab4dda28e11659f2a69e9961bf69.tar.gz
Taking Snotfish down for the move. Putting all in-progress work
(floor 1) into CVS on a branch so I can work while Snotfish is asleep on a truck. Monty svn path=/branches/monty-branch-20010404/vorbis/; revision=1425
-rw-r--r--lib/analysis.c111
-rw-r--r--lib/backends.h166
-rw-r--r--lib/floor0.c445
-rw-r--r--lib/floor1.c288
-rw-r--r--lib/psytune.c471
-rw-r--r--lib/registry.c47
-rw-r--r--lib/registry.h35
7 files changed, 1563 insertions, 0 deletions
diff --git a/lib/analysis.c b/lib/analysis.c
new file mode 100644
index 00000000..0589a1b6
--- /dev/null
+++ b/lib/analysis.c
@@ -0,0 +1,111 @@
+/********************************************************************
+ * *
+ * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
+ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
+ * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
+ * *
+ * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001 *
+ * by the XIPHOPHORUS Company http://www.xiph.org/ *
+
+ ********************************************************************
+
+ function: single-block PCM analysis mode dispatch
+ last mod: $Id: analysis.c,v 1.43.4.1 2001/04/05 00:22:48 xiphmont Exp $
+
+ ********************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <ogg/ogg.h>
+#include "vorbis/codec.h"
+#include "registry.h"
+#include "scales.h"
+#include "os.h"
+
+/* decides between modes, dispatches to the appropriate mapping. */
+int vorbis_analysis(vorbis_block *vb,ogg_packet *op){
+ vorbis_dsp_state *vd=vb->vd;
+ backend_lookup_state *b=vd->backend_state;
+ vorbis_info *vi=vd->vi;
+ codec_setup_info *ci=vi->codec_setup;
+ int type,ret;
+ int mode=0;
+
+ vb->glue_bits=0;
+ vb->time_bits=0;
+ vb->floor_bits=0;
+ vb->res_bits=0;
+
+ /* first things first. Make sure encode is ready */
+ oggpack_reset(&vb->opb);
+ /* Encode the packet type */
+ oggpack_write(&vb->opb,0,1);
+
+ /* currently lazy. Short block dispatches to 0, long to 1. */
+
+ if(vb->W &&ci->modes>1)mode=1;
+ type=ci->map_type[ci->mode_param[mode]->mapping];
+ vb->mode=mode;
+
+ /* Encode frame mode, pre,post windowsize, then dispatch */
+ oggpack_write(&vb->opb,mode,b->modebits);
+ if(vb->W){
+ oggpack_write(&vb->opb,vb->lW,1);
+ oggpack_write(&vb->opb,vb->nW,1);
+ /*fprintf(stderr,"*");
+ }else{
+ fprintf(stderr,".");*/
+ }
+
+ if((ret=_mapping_P[type]->forward(vb,b->mode[mode])))
+ return(ret);
+
+ /* set up the packet wrapper */
+
+ op->packet=oggpack_get_buffer(&vb->opb);
+ op->bytes=oggpack_bytes(&vb->opb);
+ op->b_o_s=0;
+ op->e_o_s=vb->eofflag;
+ op->granulepos=vb->granulepos;
+ op->packetno=vb->sequence; /* for sake of completeness */
+
+ return(0);
+}
+
+/* there was no great place to put this.... */
+void _analysis_output_always(char *base,int i,float *v,int n,int bark,int dB){
+ int j;
+ FILE *of;
+ char buffer[80];
+ sprintf(buffer,"%s_%d.m",base,i);
+ of=fopen(buffer,"w");
+
+ if(!of)perror("failed to open data dump file");
+
+ for(j=0;j<n;j++){
+ if(dB && v[j]==0)
+ fprintf(of,"\n\n");
+ else{
+ if(bark)
+ fprintf(of,"%g ",toBARK(22050.f*j/n));
+ else
+ fprintf(of,"%g ",(double)j);
+
+ if(dB){
+ fprintf(of,"%g\n",todB(fabs(v[j])));
+ }else{
+ fprintf(of,"%g\n",v[j]);
+ }
+ }
+ }
+ fclose(of);
+}
+
+void _analysis_output(char *base,int i,float *v,int n,int bark,int dB){
+#ifdef ANALYSIS
+ _analysis_output_always(base,i,v,n,bark,dB);
+#endif
+}
+
diff --git a/lib/backends.h b/lib/backends.h
new file mode 100644
index 00000000..72097000
--- /dev/null
+++ b/lib/backends.h
@@ -0,0 +1,166 @@
+/********************************************************************
+ * *
+ * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
+ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
+ * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
+ * *
+ * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001 *
+ * by the XIPHOPHORUS Company http://www.xiph.org/ *
+
+ ********************************************************************
+
+ function: libvorbis backend and mapping structures; needed for
+ static mode headers
+ last mod: $Id: backends.h,v 1.6.4.1 2001/04/05 00:22:48 xiphmont Exp $
+
+ ********************************************************************/
+
+/* this is exposed up here because we need it for static modes.
+ Lookups for each backend aren't exposed because there's no reason
+ to do so */
+
+#ifndef _vorbis_backend_h_
+#define _vorbis_backend_h_
+
+#include "codec_internal.h"
+
+/* this would all be simpler/shorter with templates, but.... */
+/* Transform backend generic *************************************/
+
+/* only mdct right now. Flesh it out more if we ever transcend mdct
+ in the transform domain */
+
+/* Time backend generic ******************************************/
+typedef struct{
+ void (*pack) (vorbis_info_time *,oggpack_buffer *);
+ vorbis_info_time *(*unpack)(vorbis_info *,oggpack_buffer *);
+ vorbis_look_time *(*look) (vorbis_dsp_state *,vorbis_info_mode *,
+ vorbis_info_time *);
+ vorbis_info_time *(*copy_info)(vorbis_info_time *);
+
+ void (*free_info) (vorbis_info_time *);
+ void (*free_look) (vorbis_look_time *);
+ int (*forward) (struct vorbis_block *,vorbis_look_time *,
+ float *,float *);
+ int (*inverse) (struct vorbis_block *,vorbis_look_time *,
+ float *,float *);
+} vorbis_func_time;
+
+typedef struct{
+ int dummy;
+} vorbis_info_time0;
+
+/* Floor backend generic *****************************************/
+typedef struct{
+ void (*pack) (vorbis_info_floor *,oggpack_buffer *);
+ vorbis_info_floor *(*unpack)(vorbis_info *,oggpack_buffer *);
+ vorbis_look_floor *(*look) (vorbis_dsp_state *,vorbis_info_mode *,
+ vorbis_info_floor *);
+ vorbis_info_floor *(*copy_info)(vorbis_info_floor *);
+ void (*free_info) (vorbis_info_floor *);
+ void (*free_look) (vorbis_look_floor *);
+ int (*forward) (struct vorbis_block *,vorbis_look_floor *,
+ float *, float *);
+ int (*inverse) (struct vorbis_block *,vorbis_look_floor *,
+ float *);
+} vorbis_func_floor;
+
+typedef struct{
+ int order;
+ long rate;
+ long barkmap;
+
+ int ampbits;
+ int ampdB;
+
+ int numbooks; /* <= 16 */
+ int books[16];
+
+ float lessthan; /* encode-only config setting hacks for libvorbis */
+ float greaterthan; /* encode-only config setting hacks for libvorbis */
+
+} vorbis_info_floor0;
+
+typedef struct{
+ long maxrange;
+ int rangeres; /* 6, 7 or 8 */
+
+ int ranges; /* up to 8 */
+ int rangesizes[8]; /* 1 to 8 */
+ int rangelist[64];
+
+ int positionbook[8];
+ int ampbook[8];
+
+ float maxover; /* encode side analysis parameter */
+ float maxunder; /* encode side analysis parameter */
+ float maxerr; /* encode side analysis parameter */
+
+} vorbis_info_floor1;
+
+/* Residue backend generic *****************************************/
+typedef struct{
+ void (*pack) (vorbis_info_residue *,oggpack_buffer *);
+ vorbis_info_residue *(*unpack)(vorbis_info *,oggpack_buffer *);
+ vorbis_look_residue *(*look) (vorbis_dsp_state *,vorbis_info_mode *,
+ vorbis_info_residue *);
+ vorbis_info_residue *(*copy_info)(vorbis_info_residue *);
+ void (*free_info) (vorbis_info_residue *);
+ void (*free_look) (vorbis_look_residue *);
+ int (*forward) (struct vorbis_block *,vorbis_look_residue *,
+ float **,int);
+ int (*inverse) (struct vorbis_block *,vorbis_look_residue *,
+ float **,int);
+} vorbis_func_residue;
+
+typedef struct vorbis_info_residue0{
+/* block-partitioned VQ coded straight residue */
+ long begin;
+ long end;
+
+ /* first stage (lossless partitioning) */
+ int grouping; /* group n vectors per partition */
+ int partitions; /* possible codebooks for a partition */
+ int groupbook; /* huffbook for partitioning */
+ int secondstages[64]; /* expanded out to pointers in lookup */
+ int booklist[256]; /* list of second stage books */
+
+ /* encode-only heuristic settings */
+ float entmax[64]; /* book entropy threshholds*/
+ float ampmax[64]; /* book amp threshholds*/
+ int subgrp[64]; /* book heuristic subgroup size */
+ int blimit[64]; /* subgroup position limits */
+
+} vorbis_info_residue0;
+
+/* Mapping backend generic *****************************************/
+typedef struct{
+ void (*pack) (vorbis_info *,vorbis_info_mapping *,
+ oggpack_buffer *);
+ vorbis_info_mapping *(*unpack)(vorbis_info *,oggpack_buffer *);
+ vorbis_look_mapping *(*look) (vorbis_dsp_state *,vorbis_info_mode *,
+ vorbis_info_mapping *);
+ vorbis_info_mapping *(*copy_info)(vorbis_info_mapping *);
+ void (*free_info) (vorbis_info_mapping *);
+ void (*free_look) (vorbis_look_mapping *);
+ int (*forward) (struct vorbis_block *vb,vorbis_look_mapping *);
+ int (*inverse) (struct vorbis_block *vb,vorbis_look_mapping *);
+} vorbis_func_mapping;
+
+typedef struct vorbis_info_mapping0{
+ int submaps; /* <= 16 */
+ int chmuxlist[256]; /* up to 256 channels in a Vorbis stream */
+
+ int timesubmap[16]; /* [mux] */
+ int floorsubmap[16]; /* [mux] submap to floors */
+ int residuesubmap[16]; /* [mux] submap to residue */
+ int psysubmap[16]; /* [mux]; encode only */
+} vorbis_info_mapping0;
+
+#endif
+
+
+
+
+
diff --git a/lib/floor0.c b/lib/floor0.c
new file mode 100644
index 00000000..6be7fa90
--- /dev/null
+++ b/lib/floor0.c
@@ -0,0 +1,445 @@
+/********************************************************************
+ * *
+ * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
+ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
+ * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
+ * *
+ * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001 *
+ * by the XIPHOPHORUS Company http://www.xiph.org/ *
+
+ ********************************************************************
+
+ function: floor backend 0 implementation
+ last mod: $Id: floor0.c,v 1.39.4.1 2001/04/05 00:22:48 xiphmont Exp $
+
+ ********************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <ogg/ogg.h>
+#include "vorbis/codec.h"
+#include "codec_internal.h"
+#include "registry.h"
+#include "lpc.h"
+#include "lsp.h"
+#include "codebook.h"
+#include "scales.h"
+#include "misc.h"
+#include "os.h"
+
+#include "misc.h"
+#include <stdio.h>
+
+typedef struct {
+ long n;
+ int ln;
+ int m;
+ int *linearmap;
+
+ vorbis_info_floor0 *vi;
+ lpc_lookup lpclook;
+ float *lsp_look;
+
+} vorbis_look_floor0;
+
+/* infrastructure for finding fit */
+static long _f0_fit(codebook *book,
+ float *orig,
+ float *workfit,
+ int cursor){
+ int dim=book->dim;
+ float norm,base=0.f;
+ int i,best=0;
+ float *lsp=workfit+cursor;
+
+ if(cursor)base=workfit[cursor-1];
+ norm=orig[cursor+dim-1]-base;
+
+ for(i=0;i<dim;i++)
+ lsp[i]=(orig[i+cursor]-base);
+ best=_best(book,lsp,1);
+
+ memcpy(lsp,book->valuelist+best*dim,dim*sizeof(float));
+ for(i=0;i<dim;i++)
+ lsp[i]+=base;
+ return(best);
+}
+
+/***********************************************/
+
+static vorbis_info_floor *floor0_copy_info (vorbis_info_floor *i){
+ vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
+ vorbis_info_floor0 *ret=_ogg_malloc(sizeof(vorbis_info_floor0));
+ memcpy(ret,info,sizeof(vorbis_info_floor0));
+ return(ret);
+}
+
+static void floor0_free_info(vorbis_info_floor *i){
+ if(i){
+ memset(i,0,sizeof(vorbis_info_floor0));
+ _ogg_free(i);
+ }
+}
+
+static void floor0_free_look(vorbis_look_floor *i){
+ vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
+ if(i){
+ if(look->linearmap)_ogg_free(look->linearmap);
+ if(look->lsp_look)_ogg_free(look->lsp_look);
+ lpc_clear(&look->lpclook);
+ memset(look,0,sizeof(vorbis_look_floor0));
+ _ogg_free(look);
+ }
+}
+
+static void floor0_pack (vorbis_info_floor *i,oggpack_buffer *opb){
+ vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
+ int j;
+ 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->numbooks-1,4);
+ for(j=0;j<info->numbooks;j++)
+ oggpack_write(opb,info->books[j],8);
+}
+
+static vorbis_info_floor *floor0_unpack (vorbis_info *vi,oggpack_buffer *opb){
+ codec_setup_info *ci=vi->codec_setup;
+ int j;
+
+ vorbis_info_floor0 *info=_ogg_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->numbooks=oggpack_read(opb,4)+1;
+
+ if(info->order<1)goto err_out;
+ if(info->rate<1)goto err_out;
+ if(info->barkmap<1)goto err_out;
+ if(info->numbooks<1)goto err_out;
+
+ for(j=0;j<info->numbooks;j++){
+ info->books[j]=oggpack_read(opb,8);
+ if(info->books[j]<0 || info->books[j]>=ci->books)goto err_out;
+ }
+ return(info);
+
+ err_out:
+ floor0_free_info(info);
+ return(NULL);
+}
+
+/* initialize Bark scale and normalization lookups. We could do this
+ with static tables, but Vorbis allows a number of possible
+ combinations, so it's best to do it computationally.
+
+ The below is authoritative in terms of defining scale mapping.
+ Note that the scale depends on the sampling rate as well as the
+ linear block and mapping sizes */
+
+static vorbis_look_floor *floor0_look (vorbis_dsp_state *vd,vorbis_info_mode *mi,
+ vorbis_info_floor *i){
+ int j;
+ float scale;
+ vorbis_info *vi=vd->vi;
+ codec_setup_info *ci=vi->codec_setup;
+ vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
+ vorbis_look_floor0 *look=_ogg_calloc(1,sizeof(vorbis_look_floor0));
+ look->m=info->order;
+ look->n=ci->blocksizes[mi->blockflag]/2;
+ look->ln=info->barkmap;
+ look->vi=info;
+
+ if(vd->analysisp)
+ lpc_init(&look->lpclook,look->ln,look->m);
+
+ /* we choose a scaling constant so that:
+ floor(bark(rate/2-1)*C)=mapped-1
+ floor(bark(rate/2)*C)=mapped */
+ scale=look->ln/toBARK(info->rate/2.f);
+
+ /* the mapping from a linear scale to a smaller bark scale is
+ straightforward. We do *not* make sure that the linear mapping
+ does not skip bark-scale bins; the decoder simply skips them and
+ the encoder may do what it wishes in filling them. They're
+ necessary in some mapping combinations to keep the scale spacing
+ accurate */
+ look->linearmap=_ogg_malloc((look->n+1)*sizeof(int));
+ for(j=0;j<look->n;j++){
+ int val=floor( toBARK((info->rate/2.f)/look->n*j)
+ *scale); /* bark numbers represent band edges */
+ if(val>=look->ln)val=look->ln; /* guard against the approximation */
+ look->linearmap[j]=val;
+ }
+ look->linearmap[j]=-1;
+
+ look->lsp_look=_ogg_malloc(look->ln*sizeof(float));
+ for(j=0;j<look->ln;j++)
+ look->lsp_look[j]=2*cos(M_PI/look->ln*j);
+
+ return look;
+}
+
+/* less efficient than the decode side (written for clarity). We're
+ not bottlenecked here anyway */
+
+float _curve_to_lpc(float *curve,float *lpc,
+ vorbis_look_floor0 *l){
+ /* map the input curve to a bark-scale curve for encoding */
+
+ int mapped=l->ln;
+ float *work=alloca(sizeof(float)*mapped);
+ int i,j,last=0;
+ int bark=0;
+ static int seq=0;
+
+ memset(work,0,sizeof(float)*mapped);
+
+ /* Only the decode side is behavior-specced; for now in the encoder,
+ we select the maximum value of each band as representative (this
+ helps make sure peaks don't go out of range. In error terms,
+ selecting min would make more sense, but the codebook is trained
+ numerically, so we don't actually lose. We'd still want to
+ use the original curve for error and noise estimation */
+
+ for(i=0;i<l->n;i++){
+ bark=l->linearmap[i];
+ if(work[bark]<curve[i])work[bark]=curve[i];
+ if(bark>last+1){
+ /* If the bark scale is climbing rapidly, some bins may end up
+ going unused. This isn't a waste actually; it keeps the
+ scale resolution even so that the LPC generator has an easy
+ time. However, if we leave the bins empty we lose energy.
+ So, fill 'em in. The decoder does not do anything with he
+ unused bins, so we can fill them anyway we like to end up
+ with a better spectral curve */
+
+ /* we'll always have a bin zero, so we don't need to guard init */
+ long span=bark-last;
+ for(j=1;j<span;j++){
+ float del=(float)j/span;
+ work[j+last]=work[bark]*del+work[last]*(1.f-del);
+ }
+ }
+ last=bark;
+ }
+
+ /* If we're over-ranged to avoid edge effects, fill in the end of spectrum gap */
+ for(i=bark+1;i<mapped;i++)
+ work[i]=work[i-1];
+
+
+ /**********************/
+
+ for(i=0;i<l->n;i++)
+ curve[i]-=150;
+
+ _analysis_output_always("barkfloor",seq,work,bark,0,0);
+ _analysis_output_always("barkcurve",seq++,curve,l->n,1,0);
+
+ for(i=0;i<l->n;i++)
+ curve[i]+=150;
+
+ /**********************/
+
+ return vorbis_lpc_from_curve(work,lpc,&(l->lpclook));
+}
+
+/* generate the whole freq response curve of an LSP IIR filter */
+/* didn't need in->out seperation, modifies the flr[] vector; takes in
+ a dB scale floor, puts out linear */
+static int floor0_forward(vorbis_block *vb,vorbis_look_floor *i,
+ float *flr,float *dummy){
+ long j;
+ vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
+ vorbis_info_floor0 *info=look->vi;
+ float amp;
+ long bits=0;
+ long val=0;
+ static int seq=0;
+
+#ifdef TRAIN_LSP
+ FILE *of;
+ FILE *ef;
+ char buffer[80];
+
+#if 1
+ sprintf(buffer,"lsp0coeff_%d.vqd",vb->mode);
+ of=fopen(buffer,"a");
+#endif
+#endif
+
+ seq++;
+
+
+ /* our floor comes in on a [-Inf...0] dB scale. The curve has to be
+ positive, so we offset it. */
+
+ for(j=0;j<look->n;j++)
+ flr[j]+=info->ampdB;
+
+ /* use 'out' as temp storage */
+ /* Convert our floor to a set of lpc coefficients */
+ amp=sqrt(_curve_to_lpc(flr,flr,look));
+
+ /* amp is in the range (0. to ampdB]. Encode that range using
+ ampbits bits */
+
+ {
+ long maxval=(1L<<info->ampbits)-1;
+
+ val=rint(amp/info->ampdB*maxval);
+
+ if(val<0)val=0; /* likely */
+ if(val>maxval)val=maxval; /* not bloody likely */
+
+ if(val>0)
+ amp=(float)val/maxval*info->ampdB;
+ else
+ amp=0;
+ }
+
+ if(val){
+ /* LSP <-> LPC is orthogonal and LSP quantizes more stably */
+ _analysis_output("lpc",seq-1,flr,look->m,0,0);
+ if(vorbis_lpc_to_lsp(flr,flr,look->m))
+ val=0;
+
+ }
+
+ oggpack_write(&vb->opb,val,info->ampbits);
+
+ if(val){
+ float *lspwork=alloca(look->m*sizeof(float));
+
+ /* the spec supports using one of a number of codebooks. Right
+ now, encode using this lib supports only one */
+ backend_lookup_state *be=vb->vd->backend_state;
+ codebook *b;
+ int booknum;
+
+ _analysis_output("lsp",seq-1,flr,look->m,0,0);
+
+ /* which codebook to use? We do it only by range right now. */
+ if(info->numbooks>1){
+ float last=0.;
+ for(j=0;j<look->m;j++){
+ float val=flr[j]-last;
+ if(val<info->lessthan || val>info->greaterthan)break;
+ last=flr[j];
+ }
+ if(j<look->m)
+ booknum=0;
+ else
+ booknum=1;
+ }else
+ booknum=0;
+
+ b=be->fullbooks+info->books[booknum];
+ oggpack_write(&vb->opb,booknum,_ilog(info->numbooks));
+
+
+#ifdef TRAIN_LSP
+ {
+ float last=0.f;
+ for(j=0;j<look->m;j++){
+ fprintf(of,"%.12g, ",flr[j]-last);
+ last=flr[j];
+ }
+ }
+ fprintf(of,"\n");
+ fclose(of);
+
+ sprintf(buffer,"lsp0ent_m%d_b%d.vqd",vb->mode,booknum);
+ ef=fopen(buffer,"a");
+
+#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. */
+
+ for(j=0;j<look->m;j+=b->dim){
+ int entry=_f0_fit(b,flr,lspwork,j);
+ bits+=vorbis_book_encode(b,entry,&vb->opb);
+
+#ifdef TRAIN_LSP
+ fprintf(ef,"%d,\n",entry);
+#endif
+
+ }
+
+#ifdef TRAIN_LSP
+ fclose(ef);
+#endif
+
+ _analysis_output("lsp2",seq-1,lspwork,look->m,0,0);
+
+ /* take the coefficients back to a spectral envelope curve */
+ vorbis_lsp_to_curve(flr,look->linearmap,look->n,look->ln,
+ lspwork,look->m,amp,info->ampdB);
+
+ _analysis_output_always("barklsp",seq-1,flr,look->n,1,1);
+ _analysis_output("lsp3",seq-1,flr,look->n,0,1);
+ return(val);
+ }
+
+#ifdef TRAIN_LSP
+ fclose(of);
+#endif
+
+ memset(flr,0,sizeof(float)*look->n);
+ return(val);
+}
+
+static int floor0_inverse(vorbis_block *vb,vorbis_look_floor *i,float *out){
+ vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
+ vorbis_info_floor0 *info=look->vi;
+ int j,k;
+
+ int ampraw=oggpack_read(&vb->opb,info->ampbits);
+ if(ampraw>0){ /* also handles the -1 out of data case */
+ long maxval=(1<<info->ampbits)-1;
+ float amp=(float)ampraw/maxval*info->ampdB;
+ int booknum=oggpack_read(&vb->opb,_ilog(info->numbooks));
+ float *lsp=alloca(sizeof(float)*look->m);
+
+ if(booknum!=-1 && booknum<info->numbooks){ /* be paranoid */
+ backend_lookup_state *be=vb->vd->backend_state;
+ codebook *b=be->fullbooks+info->books[booknum];
+ float last=0.f;
+
+ memset(out,0,sizeof(float)*look->m);
+
+ for(j=0;j<look->m;j+=b->dim)
+ if(vorbis_book_decodevs(b,lsp+j,&vb->opb,1,-1)==-1)goto eop;
+ for(j=0;j<look->m;){
+ for(k=0;k<b->dim;k++,j++)lsp[j]+=last;
+ last=lsp[j-1];
+ }
+
+ /* take the coefficients back to a spectral envelope curve */
+ vorbis_lsp_to_curve(out,look->linearmap,look->n,look->ln,
+ lsp,look->m,amp,info->ampdB);
+ return(1);
+ }
+ }
+
+ eop:
+ memset(out,0,sizeof(float)*look->n);
+ return(0);
+}
+
+/* export hooks */
+vorbis_func_floor floor0_exportbundle={
+ &floor0_pack,&floor0_unpack,&floor0_look,&floor0_copy_info,&floor0_free_info,
+ &floor0_free_look,&floor0_forward,&floor0_inverse
+};
+
+
diff --git a/lib/floor1.c b/lib/floor1.c
new file mode 100644
index 00000000..6457f506
--- /dev/null
+++ b/lib/floor1.c
@@ -0,0 +1,288 @@
+/********************************************************************
+ * *
+ * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
+ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
+ * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
+ * *
+ * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001 *
+ * by the XIPHOPHORUS Company http://www.xiph.org/ *
+ * *
+ ********************************************************************
+
+ function: floor backend 1 implementation
+ last mod: $Id: floor1.c,v 1.1.2.1 2001/04/05 00:22:48 xiphmont Exp $
+
+ ********************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <ogg/ogg.h>
+#include "vorbis/codec.h"
+#include "codec_internal.h"
+#include "registry.h"
+#include "codebook.h"
+#include "misc.h"
+
+#include <stdio.h>
+
+#define floor1_rangedB 140 /* floor 0 fixed at -140dB to 0dB range */
+
+
+typedef struct {
+ int lo_neighbor[66];
+ int hi_neighbor[66];
+ int n;
+ vorbis_info_floor1 *vi;
+} vorbis_look_floor1;
+
+/***********************************************/
+
+static vorbis_info_floor *floor1_copy_info (vorbis_info_floor *i){
+ vorbis_info_floor1 *info=(vorbis_info_floor1 *)i;
+ vorbis_info_floor1 *ret=_ogg_malloc(sizeof(vorbis_info_floor1));
+ memcpy(ret,info,sizeof(vorbis_info_floor1));
+ return(ret);
+}
+
+static void floor1_free_info(vorbis_info_floor *i){
+ if(i){
+ memset(i,0,sizeof(vorbis_info_floor1));
+ _ogg_free(i);
+ }
+}
+
+static void floor1_free_look(vorbis_look_floor *i){
+ vorbis_look_floor1 *look=(vorbis_look_floor1 *)i;
+ if(i){
+ memset(look,0,sizeof(vorbis_look_floor1));
+ free(i);
+ }
+}
+
+static int ilog2(unsigned int v){
+ int ret=0;
+ while(v>1){
+ ret++;
+ v>>=1;
+ }
+ return(ret);
+}
+
+static void floor1_pack (vorbis_info_floor *i,oggpack_buffer *opb){
+ vorbis_info_floor1 *info=(vorbis_info_floor1 *)i;
+ int j,k;
+ int count=0;
+ int rangebits;
+
+ oggpack_write(opb,info->maxrange,24);
+ rangebits=ilog2(info->maxrange);
+
+ oggpack_write(opb,info->ranges,4); /* only 0 to 8 legal now */
+ oggpack_write(opb,info->rangeres-1,3); /* only 6,7 or 8 legal now */
+ for(j=0,k=0;j<info->ranges;j++){
+ oggpack_write(opb,info->rangesizes[j]-1,3);
+ oggpack_write(opb,info->positionbook[j],8);
+ oggpack_write(opb,info->ampbook[j],8);
+ count+=info->rangesizes[j];
+ for(;k<count;k++)
+ oggpack_write(opb,info->rangelist[k],rangebits);
+ }
+}
+
+static vorbis_info_floor *floor1_unpack (vorbis_info *vi,oggpack_buffer *opb){
+ codec_setup_info *ci=vi->codec_setup;
+ int j,k,count;
+
+ vorbis_info_floor1 *info=_ogg_malloc(sizeof(vorbis_info_floor1));
+ int rangebits;
+
+ info->maxrange=oggpack_read(opb,24);
+ rangebits=ilog2(info->maxrange);
+
+ info->ranges=oggpack_read(opb,4);
+ if(info->ranges>8)goto err_out;
+
+ info->rangeres=oggpack_read(opb,3)+1;
+ if(info->rangeres<6)goto err_out;
+ if(info->rangeres>8)goto err_out;
+
+ for(j=0,k=0;j<info->ranges;j++){
+ info->rangesizes[j]=oggpack_read(opb,3)+1;
+ info->positionbook[j]=oggpack_read(opb,8);
+ if(info->positionbook[j]<0 || info->positionbook[j]>=ci->books)
+ goto err_out;
+
+ info->ampbook[j]=oggpack_read(opb,8);
+ if(info->ampbook[j]<0 || info->ampbook[j]>=ci->books)
+ goto err_out;
+ count+=info->rangesizes[j];
+ for(;k<count;k++){
+ info->rangelist[k]=oggpack_read(opb,rangebits);
+ if(info->rangelist[k]<0 || info->rangelist[k]>=maxrange)
+ goto err_out;
+ }
+ }
+
+ err_out:
+ floor1_free_info(info);
+ return(NULL);
+}
+
+static vorbis_look_floor *floor1_look(vorbis_dsp_state *vd,vorbis_info_mode *mi,
+ vorbis_info_floor *i){
+
+ vorbis_info *vi=vd->vi;
+ codec_setup_info *ci=vi->codec_setup;
+ vorbis_info_floor1 *info=(vorbis_info_floor1 *)i;
+ vorbis_look_floor1 *look=_ogg_calloc(1,sizeof(vorbis_look_floor1));
+ int i,j,n=0;
+
+ look->vi=vi;
+ look->n=ci->blocksizes[mi->blockflag]/2;
+
+ /* we drop each position value in-between already decoded values,
+ and use linear interpolation to predict each new value past the
+ edges. The positions are read in the order of the position
+ list... we precompute the bounding positions in the lookup. Of
+ course, the neighbors can change (if a position is declined), but
+ this is an initial mapping */
+
+ for(i=0;i<info->ranges;i++)n+=info->rangesizes[j];
+ for(i=0;i<info->ranges;i++){
+ int hi=-1;
+ int lo=-1;
+ for(j=0;j<i;j++){
+ if(info->rangelist[j]<info->rangelist[i] &&
+ (lo==-1 || info->rangelist[j]>info->rangelist[lo]))
+ lo=j;
+ if(info->rangelist[j]>info->rangelist[i] &&
+ (hi==-1 || info->rangelist[j]<info->rangelist[hi]))
+ hi=j;
+ }
+ look->lo_neighbor[i]=lo;
+ look->hi_neighbor[i]=hi;
+ }
+
+ return(look);
+}
+
+static int render_point_dB(int x0,int x1,int y0,int y1,int x){
+ int dy=y1-y0;
+ int adx=x1-x0;
+ int ady=abs(dy);
+ int err=(ady>>1)+ady*(x-x0);
+
+ int off=err%adx;
+ if(dy<0)return(y0-off);
+ return(y0+off);
+}
+
+static int render_line_dB(int x0,int x1,int y0,int y1,int *d){
+ int dy=y1-y0;
+ int adx=x1-x0;
+ int ady=abs(dy);
+ int base=dy/adx;
+ int sy=(dy<0?base-1:base+1);
+ int x=x0;
+ int y=y0;
+ int err;
+
+ ady-=base*adx;
+ err=ady>>1;
+
+ d[x]=y;
+ while(++x<x1){
+ err=err+ady;
+ if(err>adx){
+ err-=adx;
+ y+=sy;
+ }else{
+ y+=base;
+ }
+ d[x]=y;
+ }
+}
+
+/* the floor has already been filtered to only include relevant sections */
+static int fit_line(int *floor,int x0, int x1,int *y0, int *y1){
+ long i,n=0;
+ long x=0,y=0,x2=0,y2=0,xy=0;
+
+ if(*y0>-900){ /* hint used to break degenerate cases */
+ x+=x0;
+ y+=*y0;
+ x2+=(x0*x0);
+ y2+= *y0 * *y0;
+ xy= *y0*x0;
+ n++;
+ }
+
+ if(*y1>-900){ /* hint used to break degenerate cases */
+ x+=x1;
+ y+=*y1;
+ x2+=(x1*x1);
+ y2+= *y1 * *y1;
+ xy= *y1*x1;
+ n++;
+ }
+
+ for(i=x0;i<x1;i++)
+ if(floor[i]>-900){
+ x+=i;
+ y+=floor[i];
+ x2+=(i*i);
+ y2+=floor[i]*floor[i];
+ xy=i*floor[i];
+ n++;
+ }
+ if(n<2)return(-1);
+
+ {
+ float a=(float)(y*x2-xy*x)/(n*x2-x*x);
+ float b=(float)(n*xy-x*y)/(n*x2-x*x);
+ *y0=rint(a+b*x0);
+ *y1=rint(a+b*x1);
+ }
+ return(0);
+}
+
+
+/* didn't need in->out seperation, modifies the flr[] vector; takes in
+ a dB scale floor, puts out linear */
+static int floor1_forward(vorbis_block *vb,vorbis_look_floor *i,
+ float *flr,float *mdct){
+ long i,j;
+ vorbis_look_floor1 *look=(vorbis_look_floor1 *)i;
+ vorbis_info_floor1 *info=look->vi;
+ long n=look->n;
+ /* first, quantize the floor into the units we're using,
+ silmultaneously weeding out values for x positions where the
+ residue will likely quantize to zero */
+ int workfloor=alloca(sizeof(int)*n);
+ memset(workfloor,0,sizeof(int)*n);
+ for(i=0;i<n;i++){
+ if
+
+
+ return(val);
+}
+
+static int floor1_inverse(vorbis_block *vb,vorbis_look_floor *i,float *out){
+ vorbis_look_floor1 *look=(vorbis_look_floor1 *)i;
+ vorbis_info_floor1 *info=look->vi;
+
+
+ eop:
+ memset(out,0,sizeof(float)*look->n);
+ return(0);
+}
+
+/* export hooks */
+vorbis_func_floor floor1_exportbundle={
+ &floor1_pack,&floor1_unpack,&floor1_look,&floor1_copy_info,&floor1_free_info,
+ &floor1_free_look,&floor1_forward,&floor1_inverse
+};
+
+
diff --git a/lib/psytune.c b/lib/psytune.c
new file mode 100644
index 00000000..16a8f82b
--- /dev/null
+++ b/lib/psytune.c
@@ -0,0 +1,471 @@
+/********************************************************************
+ * *
+ * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
+ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
+ * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
+ * *
+ * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001 *
+ * by the XIPHOPHORUS Company http://www.xiph.org/ *
+
+ ********************************************************************
+
+ function: simple utility that runs audio through the psychoacoustics
+ without encoding
+ last mod: $Id: psytune.c,v 1.14.4.1 2001/04/05 00:22:48 xiphmont Exp $
+
+ ********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "vorbis/codec.h"
+#include "os.h"
+#include "psy.h"
+#include "mdct.h"
+#include "smallft.h"
+#include "window.h"
+#include "scales.h"
+#include "lpc.h"
+#include "lsp.h"
+
+static vorbis_info_psy _psy_set0={
+ 1,/*athp*/
+ 1,/*decayp*/
+
+ -100.f,
+ -140.f,
+
+ 8,
+
+ /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 */
+ /* x: 63 88 125 175 250 350 500 700 1k 1.4k 2k 2.8k 4k 5.6k 8k 11.5k 16k Hz */
+ /* y: 0 10 20 30 40 50 60 70 80 90 100 dB */
+ 1,/* tonemaskp */
+ /* 0 10 20 30 40 50 60 70 80 90 100 */
+ {
+ {-999.f,-999.f,-999.f,-999.f,-999.f,-999.f,-999.f,-999.f,-999.f,-999.f,-999.f
+}, /*63*/
+ {-999.f,-999.f,-999.f,-999.f,-999.f,-999.f,-999.f,-999.f,-999.f,-999.f,-999.f
+}, /*88*/
+ {-999.f,-999.f,-999.f,-999.f,-999.f,-999.f,-999.f,-999.f,-999.f,-999.f,-999.f
+}, /*125*/
+
+ {-35.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*175*/
+ {-35.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*250*/
+ {-35.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*350*/
+ {-35.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*500*/
+ {-35.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*700*/
+
+ {-35.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*1000*/
+ {-35.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*1400*/
+ {-40.f,-40.f,-40.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*2000*/
+ {-40.f,-40.f,-40.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*2800*/
+ {-35.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*4000*/
+ {-35.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*5600*/
+
+ {-30.f,-30.f,-33.f,-35.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*8000*/
+ {-30.f,-30.f,-33.f,-35.f,-35.f,-45.f,-50.f,-60.f,-70.f,-90.f,-100.f}, /*11500*/
+ {-24.f,-24.f,-26.f,-32.f,-32.f,-42.f,-50.f,-60.f,-70.f,-90.f,-100.f}, /*16000*/
+
+ },
+
+ 1,/* peakattp */
+ {{-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-24.f,-24.f,-24.f},/*63*/
+ {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-24.f,-24.f,-24.f},/*88*/
+ {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-24.f,-24.f,-24.f},/*125*/
+ {-10.f,-10.f,-10.f,-10.f,-16.f,-16.f,-18.f,-20.f,-24.f,-24.f,-24.f},/*175*/
+ {-10.f,-10.f,-10.f,-10.f,-16.f,-16.f,-18.f,-20.f,-24.f,-24.f,-24.f},/*250*/
+ {-10.f,-10.f,-10.f,-10.f,-16.f,-16.f,-18.f,-20.f,-22.f,-24.f,-24.f},/*350*/
+ {-10.f,-10.f,-10.f,-10.f,-16.f,-16.f,-18.f,-20.f,-22.f,-24.f,-24.f},/*500*/
+ {-10.f,-10.f,-10.f,-10.f,-14.f,-14.f,-16.f,-20.f,-22.f,-24.f,-24.f},/*700*/
+ {-10.f,-10.f,-10.f,-10.f,-14.f,-14.f,-16.f,-20.f,-22.f,-24.f,-24.f},/*1000*/
+ {-10.f,-10.f,-10.f,-10.f,-14.f,-14.f,-16.f,-20.f,-22.f,-24.f,-24.f},/*1400*/
+ {-10.f,-10.f,-10.f,-10.f,-14.f,-14.f,-16.f,-20.f,-22.f,-24.f,-24.f},/*2000*/
+ {-10.f,-10.f,-10.f,-12.f,-16.f,-16.f,-16.f,-20.f,-22.f,-24.f,-24.f},/*2400*/
+ {-10.f,-10.f,-10.f,-12.f,-16.f,-16.f,-16.f,-20.f,-22.f,-24.f,-24.f},/*4000*/
+ {-10.f,-10.f,-10.f,-12.f,-12.f,-14.f,-16.f,-18.f,-22.f,-24.f,-24.f},/*5600*/
+ {-10.f,-10.f,-10.f,-10.f,-10.f,-14.f,-16.f,-18.f,-22.f,-24.f,-24.f},/*8000*/
+ {-10.f,-10.f,-10.f,-10.f,-10.f,-14.f,-16.f,-18.f,-22.f,-24.f,-24.f},/*11500*/
+ {-10.f,-10.f,-10.f,-10.f,-10.f,-12.f,-16.f,-18.f,-22.f,-24.f,-24.f},/*16000*/
+ },
+
+ 1,/*noisemaskp */
+ -24.f, /* suppress any noise curve over maxspec+n */
+ .5f, /* low window */
+ .5f, /* high window */
+ 25,
+ 25,
+ {.000f, 0.f, /*63*/
+ .000f, 0.f, /*88*/
+ .000f, 0.f, /*125*/
+ .000f, 0.f, /*175*/
+ .000f, 0.f, /*250*/
+ .000f, 0.f, /*350*/
+ .000f, 0.f, /*500*/
+ .200f, 0.f, /*700*/
+ .300f, 0.f, /*1000*/
+ .400f, 0.f, /*1400*/
+ .400f, 0.f, /*2000*/
+ .400f, 0.f, /*2800*/
+ .700f, 0.f, /*4000*/
+ .850f, 0.f, /*5600*/
+ .900f, 0.f, /*8000*/
+ .900f, 0.f, /*11500*/
+ .900f, 1.f, /*16000*/
+ },
+
+ 95.f, /* even decade + 5 is important; saves an rint() later in a
+ tight loop) */
+ -28.,
+
+ -0.f, -.004f, /* attack/decay control */
+
+};
+
+static int noisy=0;
+void analysis(char *base,int i,float *v,int n,int bark,int dB){
+ if(noisy){
+ int j;
+ FILE *of;
+ char buffer[80];
+ sprintf(buffer,"%s_%d.m",base,i);
+ of=fopen(buffer,"w");
+
+ for(j=0;j<n;j++){
+ if(dB && v[j]==0)
+ fprintf(of,"\n\n");
+ else{
+ if(bark)
+ fprintf(of,"%g ",toBARK(22050.f*j/n));
+ else
+ fprintf(of,"%g ",(float)j);
+
+ if(dB){
+ fprintf(of,"%g\n",todB(fabs(v[j])));
+ }else{
+ fprintf(of,"%g\n",v[j]);
+ }
+ }
+ }
+ fclose(of);
+ }
+}
+
+typedef struct {
+ long n;
+ int ln;
+ int m;
+ int *linearmap;
+
+ void *vi;
+ lpc_lookup lpclook;
+ float *lsp_look;
+
+} vorbis_look_floor0;
+
+extern float _curve_to_lpc(float *curve,float *lpc,
+ vorbis_look_floor0 *l);
+
+long frameno=0;
+
+/* hacked from floor0.c */
+static void floorinit(vorbis_look_floor0 *look,int n,int m,int ln){
+ int j;
+ float scale;
+ look->m=m;
+ look->n=n;
+ look->ln=ln;
+ lpc_init(&look->lpclook,look->ln,look->m);
+
+ scale=look->ln/toBARK(22050.f);
+
+ look->linearmap=_ogg_malloc(look->n*sizeof(int));
+ for(j=0;j<look->n;j++){
+ int val=floor( toBARK(22050.f/n*j) *scale);
+ if(val>look->ln)val=look->ln;
+ look->linearmap[j]=val;
+ }
+}
+
+/*****************************************************************/
+/* fine floor partitioner */
+
+static char amplitude_split[8000];
+static char frequency_split[8000];
+
+/* brute force it for now */
+void partition_split(float *floor,int f0,int f1,int a0,int a1,char *list,int d){
+ int i;
+ for(i=f0;i<f1;i++)
+ if(floor[i]>=a0 && floor[i]<a1)break;
+
+ if(i<f1)
+ strcat(list,"1");
+ else{
+ strcat(list,"0");
+ return;
+ }
+
+ if(f1-f0 >= a1-a0){
+ if(f1-f0==2)return;
+
+ partition_split(floor,f0,(f1+f0)/2,a0,a1,frequency_split,d+1);
+ partition_split(floor,(f1+f0)/2,f1,a0,a1,frequency_split,d+1);
+
+ }else{
+
+ partition_split(floor,f0,f1,a0,(a1+a0)/2,amplitude_split,d+1);
+ partition_split(floor,f0,f1,(a1+a0)/2,a1,amplitude_split,d+1);
+
+ }
+}
+
+
+void partition_setup(float *floor,float *data,int n){
+ int i;
+ float foo[n];
+ amplitude_split[0]='\0';
+ frequency_split[0]='\0';
+
+ for(i=0;i<n;i++){
+ if(data[i]>0){
+ if(data[i]/fromdB(floor[i])>.5){
+ foo[i]=todB(data[i]);
+ data[i]=fromdB(rint(todB(data[i])));
+ }else{
+ foo[i]=-999;
+ data[i]=0.;
+ }
+ }else{
+ if(data[i]/fromdB(floor[i])<-.5){
+ foo[i]=todB(data[i]);
+ data[i]=-fromdB(rint(todB(data[i])));
+ }else{
+ foo[i]=-999;
+ data[i]=0.;
+ }
+ }
+ }
+
+ partition_split(foo,0,n,-128,0,frequency_split,0);
+
+ fprintf(stderr,"%d:%d, ",strlen(frequency_split),strlen(amplitude_split));
+}
+
+
+
+/****************************************************************/
+
+int main(int argc,char *argv[]){
+ int eos=0;
+ float nonz=0.f;
+ float acc=0.f;
+ float tot=0.f;
+ float ampmax=-9999,newmax;
+
+ int framesize=2048;
+ int order=30;
+ int map=256;
+ float ampmax_att_per_sec=-10.;
+
+ float *pcm[2],*out[2],*window,*lpc,*flr,*mask;
+ signed char *buffer,*buffer2;
+ mdct_lookup m_look;
+ drft_lookup f_look;
+ vorbis_look_psy p_look;
+ long i,j,k;
+
+ vorbis_look_floor0 floorlook;
+
+ int ath=0;
+ int decayp=0;
+
+ argv++;
+ while(*argv){
+ if(*argv[0]=='-'){
+ /* option */
+ if(argv[0][1]=='v'){
+ noisy=0;
+ }
+ if(argv[0][1]=='o'){
+ order=atoi(argv[0]+2);
+ }
+ if(argv[0][1]=='m'){
+ map=atoi(argv[0]+2);
+ }
+ }else
+ if(*argv[0]=='+'){
+ /* option */
+ if(argv[0][1]=='v'){
+ noisy=1;
+ }
+ if(argv[0][1]=='o'){
+ order=atoi(argv[0]+2);
+ }
+ if(argv[0][1]=='m'){
+ map=atoi(argv[0]+2);
+ }
+ }else
+ framesize=atoi(argv[0]);
+ argv++;
+ }
+
+ mask=_ogg_malloc(framesize*sizeof(float));
+ pcm[0]=_ogg_malloc(framesize*sizeof(float));
+ pcm[1]=_ogg_malloc(framesize*sizeof(float));
+ out[0]=_ogg_calloc(framesize/2,sizeof(float));
+ out[1]=_ogg_calloc(framesize/2,sizeof(float));
+ flr=_ogg_malloc(framesize*sizeof(float));
+ lpc=_ogg_malloc(order*sizeof(float));
+ buffer=_ogg_malloc(framesize*4);
+ buffer2=buffer+framesize*2;
+ window=_vorbis_window(0,framesize,framesize/2,framesize/2);
+ mdct_init(&m_look,framesize);
+ drft_init(&f_look,framesize);
+ _vp_psy_init(&p_look,&_psy_set0,framesize/2,44100);
+ floorinit(&floorlook,framesize/2,order,map);
+
+ for(i=0;i<P_BANDS;i++)
+ for(j=0;j<P_LEVELS;j++)
+ analysis("Ptonecurve",i*100+j,p_look.tonecurves[i][j],EHMER_MAX,0,0);
+
+ /* we cheat on the WAV header; we just bypass 44 bytes and never
+ verify that it matches 16bit/stereo/44.1kHz. */
+
+ fread(buffer,1,44,stdin);
+ fwrite(buffer,1,44,stdout);
+ memset(buffer,0,framesize*2);
+
+ analysis("window",0,window,framesize,0,0);
+
+ fprintf(stderr,"Processing for frame size %d...\n",framesize);
+
+ while(!eos){
+ long bytes=fread(buffer2,1,framesize*2,stdin);
+ if(bytes<framesize*2)
+ memset(buffer2+bytes,0,framesize*2-bytes);
+
+ if(bytes!=0){
+
+ /* uninterleave samples */
+ for(i=0;i<framesize;i++){
+ pcm[0][i]=((buffer[i*4+1]<<8)|
+ (0x00ff&(int)buffer[i*4]))/32768.f;
+ pcm[1][i]=((buffer[i*4+3]<<8)|
+ (0x00ff&(int)buffer[i*4+2]))/32768.f;
+ }
+
+ {
+ float secs=framesize/44100.;
+
+ ampmax+=secs*ampmax_att_per_sec;
+ if(ampmax<-9999)ampmax=-9999;
+ }
+ newmax=ampmax;
+
+ for(i=0;i<2;i++){
+ float amp;
+
+ analysis("pre",frameno,pcm[i],framesize,0,0);
+ memcpy(mask,pcm[i],sizeof(float)*framesize);
+
+ /* do the psychacoustics */
+ for(j=0;j<framesize;j++)
+ mask[j]=pcm[i][j]*=window[j];
+
+ drft_forward(&f_look,mask);
+
+ mask[0]/=(framesize/4.);
+ for(j=1;j<framesize-1;j+=2)
+ mask[(j+1)>>1]=4*hypot(mask[j],mask[j+1])/framesize;
+
+ mdct_forward(&m_look,pcm[i],pcm[i]);
+ memcpy(mask+framesize/2,pcm[i],sizeof(float)*framesize/2);
+ analysis("mdct",frameno,pcm[i],framesize/2,0,1);
+ analysis("fft",frameno,mask,framesize/2,0,1);
+
+ {
+ float ret;
+ ret=_vp_compute_mask(&p_look,mask,mask+framesize/2,flr,NULL,ampmax);
+ if(ret>newmax)newmax=ret;
+ }
+
+ analysis("mask",frameno,flr,framesize/2,0,0);
+
+ partition_setup(flr,pcm[i],framesize/2);
+
+ /*
+ for(j=0;j<framesize/2;j++)
+ mask[j]=flr[j]+140.;
+
+ amp=sqrt(_curve_to_lpc(mask,mask,&floorlook));
+ vorbis_lpc_to_lsp(mask,mask,floorlook.m);
+ vorbis_lsp_to_curve(flr,floorlook.linearmap,floorlook.n,floorlook.ln,
+ mask,floorlook.m,amp,140.);
+
+ analysis("floor",frameno,flr,framesize/2,0,1);
+
+ _vp_apply_floor(&p_look,pcm[i],flr);
+
+
+ analysis("quant",frameno,pcm[i],framesize/2,0,0);
+
+ for(j=0;j<framesize/2;j++){
+ float val=rint(pcm[i][j]);
+ tot++;
+ if(val){
+ nonz++;
+ acc+=log(fabs(val)*2.f+1.f)/log(2);
+ pcm[i][j]=val*flr[j];
+ }else{
+ pcm[i][j]=0.f;
+ }
+ }
+ */
+
+ analysis("final",frameno,pcm[i],framesize/2,0,1);
+
+ /* take it back to time */
+ mdct_backward(&m_look,pcm[i],pcm[i]);
+ for(j=0;j<framesize/2;j++)
+ out[i][j]+=pcm[i][j]*window[j];
+
+ frameno++;
+ }
+ ampmax=newmax;
+
+ /* write data. Use the part of buffer we're about to shift out */
+ for(i=0;i<2;i++){
+ char *ptr=buffer+i*2;
+ float *mono=out[i];
+ for(j=0;j<framesize/2;j++){
+ int val=mono[j]*32767.;
+ /* might as well guard against clipping */
+ if(val>32767)val=32767;
+ if(val<-32768)val=-32768;
+ ptr[0]=val&0xff;
+ ptr[1]=(val>>8)&0xff;
+ ptr+=4;
+ }
+ }
+
+ fprintf(stderr,"*");
+ fwrite(buffer,1,framesize*2,stdout);
+ memmove(buffer,buffer2,framesize*2);
+
+ for(i=0;i<2;i++){
+ for(j=0,k=framesize/2;j<framesize/2;j++,k++)
+ out[i][j]=pcm[i][k]*window[k];
+ }
+ }else
+ eos=1;
+ }
+ fprintf(stderr,"average raw bits of entropy: %.03g/sample\n",acc/tot);
+ fprintf(stderr,"average nonzero samples: %.03g/%d\n",nonz/tot*framesize/2,
+ framesize/2);
+ fprintf(stderr,"Done\n\n");
+ return 0;
+}
diff --git a/lib/registry.c b/lib/registry.c
new file mode 100644
index 00000000..5cd4d373
--- /dev/null
+++ b/lib/registry.c
@@ -0,0 +1,47 @@
+/********************************************************************
+ * *
+ * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
+ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
+ * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
+ * *
+ * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001 *
+ * by the XIPHOPHORUS Company http://www.xiph.org/ *
+
+ ********************************************************************
+
+ function: registry for time, floor, res backends and channel mappings
+ last mod: $Id: registry.c,v 1.6.4.1 2001/04/05 00:22:48 xiphmont Exp $
+
+ ********************************************************************/
+
+#include "vorbis/codec.h"
+#include "registry.h"
+#include "misc.h"
+
+/* seems like major overkill now; the backend numbers will grow into
+ the infrastructure soon enough */
+
+extern vorbis_func_time time0_exportbundle;
+extern vorbis_func_floor floor0_exportbundle;
+extern vorbis_func_floor floor1_exportbundle;
+extern vorbis_func_residue residue0_exportbundle;
+extern vorbis_func_mapping mapping0_exportbundle;
+
+vorbis_func_time *_time_P[]={
+ &time0_exportbundle,
+};
+
+vorbis_func_floor *_floor_P[]={
+ &floor0_exportbundle,
+ &floor1_exportbundle,
+};
+
+vorbis_func_residue *_residue_P[]={
+ &residue0_exportbundle,
+};
+
+vorbis_func_mapping *_mapping_P[]={
+ &mapping0_exportbundle,
+};
+
diff --git a/lib/registry.h b/lib/registry.h
new file mode 100644
index 00000000..af0f2434
--- /dev/null
+++ b/lib/registry.h
@@ -0,0 +1,35 @@
+/********************************************************************
+ * *
+ * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
+ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
+ * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
+ * *
+ * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001 *
+ * by the XIPHOPHORUS Company http://www.xiph.org/ *
+
+ ********************************************************************
+
+ function: registry for time, floor, res backends and channel mappings
+ last mod: $Id: registry.h,v 1.5.4.1 2001/04/05 00:22:48 xiphmont Exp $
+
+ ********************************************************************/
+
+#ifndef _V_REG_H_
+#define _V_REG_H_
+
+#include "backends.h"
+
+#define VI_TRANSFORMB 1
+#define VI_WINDOWB 1
+#define VI_TIMEB 1
+#define VI_FLOORB 2
+#define VI_RESB 1
+#define VI_MAPB 1
+
+extern vorbis_func_time *_time_P[];
+extern vorbis_func_floor *_floor_P[];
+extern vorbis_func_residue *_residue_P[];
+extern vorbis_func_mapping *_mapping_P[];
+
+#endif