X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=lib%2Ffloor0.c;h=adc2bcffba99260f77a85706e1d1afb6ef5f18ec;hb=baa60cc70e72d398bcff8d26ac00825ce8f16be9;hp=1654ba496ce3578f8b8440aab8ccbc60bc019060;hpb=67f833635368a912b53f68ec55840e4f7cdd69c5;p=platform%2Fupstream%2Flibvorbis.git diff --git a/lib/floor0.c b/lib/floor0.c index 1654ba4..adc2bcf 100644 --- a/lib/floor0.c +++ b/lib/floor0.c @@ -1,104 +1,101 @@ /******************************************************************** * * - * 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. * + * 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 OggSQUISH SOURCE CODE IS (C) COPYRIGHT 1994-2000 * - * by Monty and The XIPHOPHORUS Company * - * http://www.xiph.org/ * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * * * ******************************************************************** function: floor backend 0 implementation - last mod: $Id: floor0.c,v 1.15 2000/06/14 01:38:31 xiphmont Exp $ + last mod: $Id$ ********************************************************************/ #include #include #include +#include #include "vorbis/codec.h" -#include "bitwise.h" +#include "codec_internal.h" #include "registry.h" #include "lpc.h" #include "lsp.h" -#include "bookinternal.h" -#include "sharedbook.h" +#include "codebook.h" #include "scales.h" #include "misc.h" #include "os.h" +#include "misc.h" +#include + typedef struct { - long n; int ln; int m; - int *linearmap; + int **linearmap; + int n[2]; vorbis_info_floor0 *vi; - lpc_lookup lpclook; + + long bits; + long frames; } vorbis_look_floor0; -typedef struct { - long *codewords; - double *curve; - long frameno; - long codes; -} vorbis_echstate_floor0; - -static void free_info(vorbis_info_floor *i){ - if(i){ - memset(i,0,sizeof(vorbis_info_floor0)); - free(i); + +/***********************************************/ + +static void floor0_free_info(vorbis_info_floor *i){ + vorbis_info_floor0 *info=(vorbis_info_floor0 *)i; + if(info){ + memset(info,0,sizeof(*info)); + _ogg_free(info); } } -static void free_look(vorbis_look_floor *i){ +static void floor0_free_look(vorbis_look_floor *i){ vorbis_look_floor0 *look=(vorbis_look_floor0 *)i; - if(i){ - if(look->linearmap)free(look->linearmap); - lpc_clear(&look->lpclook); - memset(look,0,sizeof(vorbis_look_floor0)); - free(look); + if(look){ + + if(look->linearmap){ + + if(look->linearmap[0])_ogg_free(look->linearmap[0]); + if(look->linearmap[1])_ogg_free(look->linearmap[1]); + + _ogg_free(look->linearmap); + } + memset(look,0,sizeof(*look)); + _ogg_free(look); } } -static void pack (vorbis_info_floor *i,oggpack_buffer *opb){ - vorbis_info_floor0 *info=(vorbis_info_floor0 *)i; +static vorbis_info_floor *floor0_unpack (vorbis_info *vi,oggpack_buffer *opb){ + codec_setup_info *ci=vi->codec_setup; 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;jnumbooks;j++) - _oggpack_write(opb,info->books[j],8); -} -static vorbis_info_floor *unpack (vorbis_info *vi,oggpack_buffer *opb){ - int j; - vorbis_info_floor0 *info=malloc(sizeof(vorbis_info_floor0)); - info->order=_oggpack_read(opb,8); - info->rate=_oggpack_read(opb,16); - info->barkmap=_oggpack_read(opb,16); - info->ampbits=_oggpack_read(opb,6); - info->ampdB=_oggpack_read(opb,8); - info->numbooks=_oggpack_read(opb,4)+1; - + vorbis_info_floor0 *info=_ogg_malloc(sizeof(*info)); + 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;jnumbooks;j++){ - info->books[j]=_oggpack_read(opb,8); - if(info->books[j]<0 || info->books[j]>=vi->books)goto err_out; + info->books[j]=oggpack_read(opb,8); + if(info->books[j]<0 || info->books[j]>=ci->books)goto err_out; } - return(info); + return(info); + err_out: - free_info(info); + floor0_free_info(info); return(NULL); } @@ -110,344 +107,114 @@ static vorbis_info_floor *unpack (vorbis_info *vi,oggpack_buffer *opb){ Note that the scale depends on the sampling rate as well as the linear block and mapping sizes */ -static vorbis_look_floor *look (vorbis_dsp_state *vd,vorbis_info_mode *mi, - vorbis_info_floor *i){ - int j; - double scale; - vorbis_info *vi=vd->vi; - vorbis_info_floor0 *info=(vorbis_info_floor0 *)i; - vorbis_look_floor0 *look=malloc(sizeof(vorbis_look_floor0)); - look->m=info->order; - look->n=vi->blocksizes[mi->blockflag]/2; - look->ln=info->barkmap; - look->vi=info; - lpc_init(&look->lpclook,look->ln,look->m); - - /* we choose a scaling constant so that: - floor(bark(rate/2-1)*C)=mapped-1 +static void floor0_map_lazy_init(vorbis_block *vb, + vorbis_info_floor *infoX, + vorbis_look_floor0 *look){ + if(!look->linearmap[vb->W]){ + vorbis_dsp_state *vd=vb->vd; + vorbis_info *vi=vd->vi; + codec_setup_info *ci=vi->codec_setup; + vorbis_info_floor0 *info=(vorbis_info_floor0 *)infoX; + int W=vb->W; + int n=ci->blocksizes[W]/2,j; + + /* 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.); - - /* 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=malloc(look->n*sizeof(int)); - for(j=0;jn;j++){ - int val=floor( toBARK((info->rate/2.)/look->n*j) - *scale); /* bark numbers represent band edges */ - if(val>look->ln)val=look->ln; /* guard against the approximation */ - look->linearmap[j]=val; - } - return look; -} - -static vorbis_echstate_floor *state (vorbis_info_floor *i){ - vorbis_echstate_floor0 *state=calloc(1,sizeof(vorbis_echstate_floor0)); - vorbis_info_floor0 *info=(vorbis_info_floor0 *)i; - - /* a safe size if usually too big (dim==1) */ - state->codewords=malloc(info->order*sizeof(long)); - state->curve=malloc(info->barkmap*sizeof(double)); - state->frameno=-1; - return(state); -} - -static void free_state (vorbis_echstate_floor *vs){ - vorbis_echstate_floor0 *state=(vorbis_echstate_floor0 *)vs; - if(state){ - free(state->codewords); - free(state->curve); - memset(state,0,sizeof(vorbis_echstate_floor0)); - free(state); - } -} - -#include - -double _curve_error(double *curve1,double *curve2,long n){ - double acc=0.; - long i; - for(i=0;iln; - double *work=alloca(sizeof(double)*mapped); - int i,j,last=0; - int bark=0; - - memset(work,0,sizeof(double)*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;in;i++){ - bark=l->linearmap[i]; - if(work[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;jln/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[W]=_ogg_malloc((n+1)*sizeof(**look->linearmap)); + for(j=0;jrate/2.f)/n*j) + *scale); /* bark numbers represent band edges */ + if(val>=look->ln)val=look->ln-1; /* guard against the approximation */ + look->linearmap[W][j]=val; } - last=bark; + look->linearmap[W][j]=-1; + look->n[W]=n; } - - /* If we're over-ranged to avoid edge effects, fill in the end of spectrum gap */ - for(i=bark+1;ilpclook)); } -/* generate the whole freq response curve of an LPC IIR filter */ - -void _lpc_to_curve(double *curve,double *lpc,double amp, - vorbis_look_floor0 *l,char *name,long frameno){ - /* l->m+1 must be less than l->ln, but guard in case we get a bad stream */ - double *lcurve=alloca(sizeof(double)*max(l->ln*2,l->m*2+2)); - int i; - - if(amp==0){ - memset(curve,0,sizeof(double)*l->n); - return; - } - vorbis_lpc_to_curve(lcurve,lpc,amp,&(l->lpclook)); - -#if 0 - { /******************/ - FILE *of; - char buffer[80]; - int i; - - sprintf(buffer,"%s_%d.m",name,frameno); - of=fopen(buffer,"w"); - for(i=0;iln;i++) - fprintf(of,"%g\n",lcurve[i]); - fclose(of); - } -#endif +static vorbis_look_floor *floor0_look(vorbis_dsp_state *vd, + vorbis_info_floor *i){ + vorbis_info_floor0 *info=(vorbis_info_floor0 *)i; + vorbis_look_floor0 *look=_ogg_calloc(1,sizeof(*look)); + look->m=info->order; + look->ln=info->barkmap; + look->vi=info; - for(i=0;in;i++)curve[i]=lcurve[l->linearmap[i]]; + look->linearmap=_ogg_calloc(2,sizeof(*look->linearmap)); + return look; } -static long seq=0; -static int forward(vorbis_block *vb,vorbis_look_floor *i, - double *in,double *out,vorbis_echstate_floor *vs){ - long j,k,l; +static void *floor0_inverse1(vorbis_block *vb,vorbis_look_floor *i){ vorbis_look_floor0 *look=(vorbis_look_floor0 *)i; vorbis_info_floor0 *info=look->vi; - vorbis_echstate_floor0 *state=(vorbis_echstate_floor0 *)vs; - double *work=alloca(look->n*sizeof(double)); - double amp; - long bits=0; - - /* our floor comes in on a linear scale; go to a [-Inf...0] dB - scale. The curve has to be positive, so we offset it. */ - - for(j=0;jn;j++)work[j]=todB(in[j])+info->ampdB; - - /* use 'out' as temp storage */ - /* Convert our floor to a set of lpc coefficients */ - amp=sqrt(_curve_to_lpc(work,out,look,seq)); - - /* amp is in the range (0. to ampdB]. Encode that range using - ampbits bits */ - - { - long maxval=(1L<ampbits)-1; - - long val=rint(amp/info->ampdB*maxval); - - if(val<0)val=0; /* likely */ - if(val>maxval)val=maxval; /* not bloody likely */ - - _oggpack_write(&vb->opb,val,info->ampbits); - if(val>0) - amp=(float)val/maxval*info->ampdB; - else - amp=0; - } + int j,k; - if(amp>0){ - double *refcurve=alloca(sizeof(double)*max(look->ln*2,look->m*2+2)); - double *newcurve=alloca(sizeof(double)*max(look->ln*2,look->m*2+2)); - long *codelist=alloca(sizeof(long)*look->m); - int codes=0; + int ampraw=oggpack_read(&vb->opb,info->ampbits); + if(ampraw>0){ /* also handles the -1 out of data case */ + long maxval=(1<ampbits)-1; + float amp=(float)ampraw/maxval*info->ampdB; + int booknum=oggpack_read(&vb->opb,_ilog(info->numbooks)); + if(booknum!=-1 && booknumnumbooks){ /* be paranoid */ + codec_setup_info *ci=vb->vd->vi->codec_setup; + codebook *b=ci->fullbooks+info->books[booknum]; + float last=0.f; - if(state->frameno == vb->sequence){ - /* generate a reference curve for testing */ - vorbis_lpc_to_curve(refcurve,out,1,&(look->lpclook)); - } + /* the additional b->dim is a guard against any possible stack + smash; b->dim is provably more than we can overflow the + vector */ + float *lsp=_vorbis_block_alloc(vb,sizeof(*lsp)*(look->m+b->dim+1)); - /* LSP <-> LPC is orthogonal and LSP quantizes more stably */ - vorbis_lpc_to_lsp(out,out,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,"%.12g, ",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. */ - - /* A new development: the code selection is based on error against - the LSP coefficients and not the curve it produces. Because - the coefficient error is not linearly related to the curve - error, the fit we select is usually nonoptimal (but - sufficient). This is fine, but flailing about causes a problem - in generally consistent spectra... so we add hysterisis. */ - - /* select a new fit, but don't code it. Just grab it for testing */ - { - /* the spec supports using one of a number of codebooks. Right - now, encode using this lib supports only one */ - codebook *b=vb->vd->fullbooks+info->books[0]; - double last=0.; - + for(j=0;jm;j+=b->dim) + if(vorbis_book_decodev_set(b,lsp+j,&vb->opb,b->dim)==-1)goto eop; for(j=0;jm;){ - for(k=0;kdim;k++)out[j+k]-=last; - codelist[codes++]=vorbis_book_errorv(b,out+j); - for(k=0;kdim;k++,j++)out[j]+=last; - last=out[j-1]; + for(k=0;kdim;k++,j++)lsp[j]+=last; + last=lsp[j-1]; } - } - vorbis_lsp_to_lpc(out,out,look->m); - vorbis_lpc_to_curve(newcurve,out,1,&(look->lpclook)); - - /* if we're out of sequence, no hysterisis this frame, else check it */ - if(state->frameno != vb->sequence || - _curve_error(refcurve,newcurve,look->ln)< - _curve_error(refcurve,state->curve,look->ln)){ - /* new curve is the fit to use. replace the state */ - memcpy(state->curve,newcurve,sizeof(double)*look->ln); - memcpy(state->codewords,codelist,sizeof(long)*codes); - state->codes=codes; - }else{ - /* use state */ - /*fprintf(stderr,"X");*/ - codelist=state->codewords; - codes=state->codes; - } - state->frameno=vb->sequence+1; - - /* the spec supports using one of a number of codebooks. Right - now, encode using this lib supports only one */ - _oggpack_write(&vb->opb,0,_ilog(info->numbooks)); - - { - codebook *b=vb->vd->fullbooks+info->books[0]; - double last=0.; - for(l=0,j=0;lopb); - for(k=0;kdim;k++,j++)out[j]+=last; - last=out[j-1]; - } + lsp[look->m]=amp; + return(lsp); } - - /* take the coefficients back to a spectral envelope curve */ - vorbis_lsp_to_lpc(out,out,look->m); - _lpc_to_curve(out,out,amp,look,"Ffloor",seq); - for(j=0;jn;j++)out[j]= fromdB(out[j]-info->ampdB); - return(1); } - - memset(out,0,sizeof(double)*look->n); - seq++; - return(0); + eop: + return(NULL); } -static int inverse(vorbis_block *vb,vorbis_look_floor *i,double *out){ +static int floor0_inverse2(vorbis_block *vb,vorbis_look_floor *i, + void *memo,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){ - long maxval=(1<ampbits)-1; - double amp=(float)ampraw/maxval*info->ampdB; - int booknum=_oggpack_read(&vb->opb,_ilog(info->numbooks)); - codebook *b=vb->vd->fullbooks+info->books[booknum]; - double last=0.; - - memset(out,0,sizeof(double)*look->m); - - for(j=0;jm;j+=b->dim) - vorbis_book_decodevs(b,out+j,&vb->opb,1,-1); - for(j=0;jm;){ - for(k=0;kdim;k++,j++)out[j]+=last; - last=out[j-1]; - } - /* take the coefficients back to a spectral envelope curve */ - vorbis_lsp_to_lpc(out,out,look->m); - _lpc_to_curve(out,out,amp,look,"",0); + floor0_map_lazy_init(vb,info,look); - for(j=0;jn;j++)out[j]= fromdB(out[j]-info->ampdB); - return(1); - }else - memset(out,0,sizeof(double)*look->n); + if(memo){ + float *lsp=(float *)memo; + float amp=lsp[look->m]; + /* take the coefficients back to a spectral envelope curve */ + vorbis_lsp_to_curve(out, + look->linearmap[vb->W], + look->n[vb->W], + look->ln, + lsp,look->m,amp,(float)info->ampdB); + return(1); + } + memset(out,0,sizeof(*out)*look->n[vb->W]); return(0); } /* export hooks */ -vorbis_func_floor floor0_exportbundle={ - &pack,&unpack,&look,&state,&free_info,&free_look,&free_state,&forward,&inverse +const vorbis_func_floor floor0_exportbundle={ + NULL,&floor0_unpack,&floor0_look,&floor0_free_info, + &floor0_free_look,&floor0_inverse1,&floor0_inverse2 }; - -