diff options
author | Monty <xiphmont@xiph.org> | 2001-04-05 00:22:48 +0000 |
---|---|---|
committer | Monty <xiphmont@xiph.org> | 2001-04-05 00:22:48 +0000 |
commit | 78540c3db714ab4dda28e11659f2a69e9961bf69 (patch) | |
tree | 7599d7a89d4e259f032802ee43e95b07fc41c946 | |
download | libvorbis-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.c | 111 | ||||
-rw-r--r-- | lib/backends.h | 166 | ||||
-rw-r--r-- | lib/floor0.c | 445 | ||||
-rw-r--r-- | lib/floor1.c | 288 | ||||
-rw-r--r-- | lib/psytune.c | 471 | ||||
-rw-r--r-- | lib/registry.c | 47 | ||||
-rw-r--r-- | lib/registry.h | 35 |
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 |