diff -r 775a72905708 -r a12155461b34 misc/libtremor/tremor/floor0.c --- a/misc/libtremor/tremor/floor0.c Sun Oct 28 03:48:37 2012 +0100 +++ b/misc/libtremor/tremor/floor0.c Sun Oct 28 04:00:07 2012 +0100 @@ -6,7 +6,7 @@ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * - * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2003 * + * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * * * ******************************************************************** @@ -21,12 +21,23 @@ #include "ogg.h" #include "ivorbiscodec.h" #include "codec_internal.h" +#include "registry.h" #include "codebook.h" #include "misc.h" -#include "os.h" +#include "block.h" #define LSP_FRACBITS 14 -extern const ogg_int32_t FLOOR_fromdB_LOOKUP[]; + +typedef struct { + long n; + int ln; + int m; + int *linearmap; + + vorbis_info_floor0 *vi; + ogg_int32_t *lsp_look; + +} vorbis_look_floor0; /*************** LSP decode ********************/ @@ -37,7 +48,7 @@ returns in m.8 format */ static long ADJUST_SQRT2[2]={8192,5792}; -static inline ogg_int32_t vorbis_invsqlook_i(long a,long e){ +STIN ogg_int32_t vorbis_invsqlook_i(long a,long e){ long i=(a&0x7fff)>>(INVSQ_LOOKUP_I_SHIFT-1); long d=a&INVSQ_LOOKUP_I_MASK; /* 0.10 */ long val=INVSQ_LOOKUP_I[i]- /* 1.16 */ @@ -49,60 +60,60 @@ /* interpolated lookup based fromdB function, domain -140dB to 0dB only */ /* a is in n.12 format */ -#ifdef _LOW_ACCURACY_ -static inline ogg_int32_t vorbis_fromdBlook_i(long a){ - if(a>0) return 0x7fffffff; - if(a<(-140<<12)) return 0; - return FLOOR_fromdB_LOOKUP[((a+140)*467)>>20]<<9; +STIN ogg_int32_t vorbis_fromdBlook_i(long a){ + int i=(-a)>>(12-FROMdB2_SHIFT); + if(i<0) return 0x7fffffff; + if(i>=(FROMdB_LOOKUP_SZ<>FROMdB_SHIFT] * FROMdB2_LOOKUP[i&FROMdB2_MASK]; } -#else -static inline ogg_int32_t vorbis_fromdBlook_i(long a){ - if(a>0) return 0x7fffffff; - if(a<(-140<<12)) return 0; - return FLOOR_fromdB_LOOKUP[((a+(140<<12))*467)>>20]; -} -#endif /* interpolated lookup based cos function, domain 0 to PI only */ /* a is in 0.16 format, where 0==0, 2^^16-1==PI, return 0.14 */ -static inline ogg_int32_t vorbis_coslook_i(long a){ +STIN ogg_int32_t vorbis_coslook_i(long a){ int i=a>>COS_LOOKUP_I_SHIFT; int d=a&COS_LOOKUP_I_MASK; return COS_LOOKUP_I[i]- ((d*(COS_LOOKUP_I[i]-COS_LOOKUP_I[i+1]))>> COS_LOOKUP_I_SHIFT); } -/* interpolated half-wave lookup based cos function */ +/* interpolated lookup based cos function */ /* a is in 0.16 format, where 0==0, 2^^16==PI, return .LSP_FRACBITS */ -static inline ogg_int32_t vorbis_coslook2_i(long a){ - int i=a>>COS_LOOKUP_I_SHIFT; - int d=a&COS_LOOKUP_I_MASK; - return ((COS_LOOKUP_I[i]<> - (COS_LOOKUP_I_SHIFT-LSP_FRACBITS+14); +STIN ogg_int32_t vorbis_coslook2_i(long a){ + a=a&0x1ffff; + + if(a>0x10000)a=0x20000-a; + { + int i=a>>COS_LOOKUP_I_SHIFT; + int d=a&COS_LOOKUP_I_MASK; + a=((COS_LOOKUP_I[i]<> + (COS_LOOKUP_I_SHIFT-LSP_FRACBITS+14); + } + + return(a); } -static const ogg_uint16_t barklook[54]={ - 0,51,102,154, 206,258,311,365, - 420,477,535,594, 656,719,785,854, - 926,1002,1082,1166, 1256,1352,1454,1564, - 1683,1812,1953,2107, 2276,2463,2670,2900, - 3155,3440,3756,4106, 4493,4919,5387,5901, - 6466,7094,7798,8599, 9528,10623,11935,13524, - 15453,17775,20517,23667, 27183,31004 +static const int barklook[28]={ + 0,100,200,301, 405,516,635,766, + 912,1077,1263,1476, 1720,2003,2333,2721, + 3184,3742,4428,5285, 6376,7791,9662,12181, + 15624,20397,27087,36554 }; /* used in init only; interpolate the long way */ -static inline ogg_int32_t toBARK(int n){ +STIN ogg_int32_t toBARK(int n){ int i; - for(i=0;i<54;i++) + for(i=0;i<27;i++) if(n>=barklook[i] && n>17); + int gap=barklook[i+1]-barklook[i]; + int del=n-barklook[i]; + + return((i<<15)+((del<<15)/gap)); } } @@ -122,11 +133,11 @@ static const unsigned char MLOOP_3[8]={0,1,2,2,3,3,3,3}; -void vorbis_lsp_to_curve(ogg_int32_t *curve,int n,int ln, +void vorbis_lsp_to_curve(ogg_int32_t *curve,int *map,int n,int ln, ogg_int32_t *lsp,int m, ogg_int32_t amp, ogg_int32_t ampoffset, - ogg_int32_t nyq){ + ogg_int32_t *icos){ /* 0 <= m < 256 */ @@ -135,27 +146,6 @@ int ampoffseti=ampoffset*4096; int ampi=amp; ogg_int32_t *ilsp=(ogg_int32_t *)alloca(m*sizeof(*ilsp)); - - ogg_uint32_t inyq= (1UL<<31) / toBARK(nyq); - ogg_uint32_t imap= (1UL<<31) / ln; - ogg_uint32_t tBnyq1 = toBARK(nyq)<<1; - - /* Besenham for frequency scale to avoid a division */ - int f=0; - int fdx=n; - int fbase=nyq/fdx; - int ferr=0; - int fdy=nyq-fbase*fdx; - int map=0; - -#ifdef _LOW_ACCURACY_ - ogg_uint32_t nextbark=((tBnyq1<<11)/ln)>>12; -#else - ogg_uint32_t nextbark=MULT31(imap>>1,tBnyq1); -#endif - int nextf=barklook[nextbark>>14]+(((nextbark&0x3fff)* - (barklook[(nextbark>>14)+1]-barklook[nextbark>>14]))>>14); - /* lsp is in 8.24, range 0 to PI; coslook wants it in .16 0 to 1*/ for(i=0;i>15); - + ogg_int32_t wi=icos[k]; #ifdef _V_LSP_MATH_ASM lsp_loop_asm(&qi,&pi,&qexp,ilsp,wi,m); @@ -215,9 +202,8 @@ for(j=3;j>25])) - if(!(shift=MLOOP_2[(pi|qi)>>19])) - shift=MLOOP_3[(pi|qi)>>16]; - + if(!(shift=MLOOP_2[(pi|qi)>>19])) + shift=MLOOP_3[(pi|qi)>>16]; qi=(qi>>shift)*labs(ilsp[j-1]-wi); pi=(pi>>shift)*labs(ilsp[j]-wi); qexp+=shift; @@ -225,7 +211,7 @@ if(!(shift=MLOOP_1[(pi|qi)>>25])) if(!(shift=MLOOP_2[(pi|qi)>>19])) shift=MLOOP_3[(pi|qi)>>16]; - + /* pi,qi normalized collectively, both tracked using qexp */ if(m&1){ @@ -293,57 +279,32 @@ amp>>=9; #endif curve[i]= MULT31_SHIFT15(curve[i],amp); - - while(++i=fdx){ - ferr-=fdx; - f++; - } - f+=fbase; - - if(f>=nextf)break; - - curve[i]= MULT31_SHIFT15(curve[i],amp); - } - - while(1){ - map++; - - if(map+1>12; -#else - nextbark=MULT31((map+1)*(imap>>1),tBnyq1); -#endif - nextf=barklook[nextbark>>14]+ - (((nextbark&0x3fff)* - (barklook[(nextbark>>14)+1]-barklook[nextbark>>14]))>>14); - if(f<=nextf)break; - - }else{ - nextf=9999999; - break; - } - } - if(map>=ln){ - map=ln-1; /* guard against the approximation */ - nextf=9999999; - } + while(map[++i]==k) curve[i]= MULT31_SHIFT15(curve[i],amp); } } /*************** vorbis decode glue ************/ -void floor0_free_info(vorbis_info_floor *i){ +static void floor0_free_info(vorbis_info_floor *i){ vorbis_info_floor0 *info=(vorbis_info_floor0 *)i; - if(info)_ogg_free(info); + if(info){ + memset(info,0,sizeof(*info)); + _ogg_free(info); + } } -vorbis_info_floor *floor0_info_unpack (vorbis_info *vi,oggpack_buffer *opb){ +static void floor0_free_look(vorbis_look_floor *i){ + vorbis_look_floor0 *look=(vorbis_look_floor0 *)i; + if(look){ + + if(look->linearmap)_ogg_free(look->linearmap); + if(look->lsp_look)_ogg_free(look->lsp_look); + memset(look,0,sizeof(*look)); + _ogg_free(look); + } +} + +static vorbis_info_floor *floor0_unpack (vorbis_info *vi,oggpack_buffer *opb){ codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; int j; @@ -358,13 +319,12 @@ 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]>=ci->books)goto err_out; + if(info->books[j]<0 || info->books[j]>=ci->books)goto err_out; } - - if(oggpack_eop(opb))goto err_out; return(info); err_out: @@ -372,35 +332,75 @@ return(NULL); } -int floor0_memosize(vorbis_info_floor *i){ +/* 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; + vorbis_info *vi=vd->vi; + codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; vorbis_info_floor0 *info=(vorbis_info_floor0 *)i; - return info->order+1; + vorbis_look_floor0 *look=(vorbis_look_floor0 *)_ogg_calloc(1,sizeof(*look)); + look->m=info->order; + look->n=ci->blocksizes[mi->blockflag]/2; + look->ln=info->barkmap; + look->vi=info; + + /* 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=(int *)_ogg_malloc((look->n+1)*sizeof(*look->linearmap)); + for(j=0;jn;j++){ + + int val=(look->ln* + ((toBARK(info->rate/2*j/look->n)<<11)/toBARK(info->rate/2)))>>11; + + if(val>=look->ln)val=look->ln-1; /* guard against the approximation */ + look->linearmap[j]=val; + } + look->linearmap[j]=-1; + + look->lsp_look=(ogg_int32_t *)_ogg_malloc(look->ln*sizeof(*look->lsp_look)); + for(j=0;jln;j++) + look->lsp_look[j]=vorbis_coslook2_i(0x10000*j/look->ln); + + return look; } -ogg_int32_t *floor0_inverse1(vorbis_dsp_state *vd,vorbis_info_floor *i, - ogg_int32_t *lsp){ - vorbis_info_floor0 *info=(vorbis_info_floor0 *)i; +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; int j,k; - int ampraw=oggpack_read(&vd->opb,info->ampbits); + int ampraw=oggpack_read(&vb->opb,info->ampbits); if(ampraw>0){ /* also handles the -1 out of data case */ long maxval=(1<ampbits)-1; int amp=((ampraw*info->ampdB)<<4)/maxval; - int booknum=oggpack_read(&vd->opb,_ilog(info->numbooks)); + int booknum=oggpack_read(&vb->opb,_ilog(info->numbooks)); if(booknum!=-1 && booknumnumbooks){ /* be paranoid */ - codec_setup_info *ci=(codec_setup_info *)vd->vi->codec_setup; - codebook *b=ci->book_param+info->books[booknum]; + codec_setup_info *ci=(codec_setup_info *)vb->vd->vi->codec_setup; + codebook *b=ci->fullbooks+info->books[booknum]; ogg_int32_t last=0; + ogg_int32_t *lsp=(ogg_int32_t *)_vorbis_block_alloc(vb,sizeof(*lsp)*(look->m+1)); - for(j=0;jorder;j+=b->dim) - if(vorbis_book_decodev_set(b,lsp+j,&vd->opb,b->dim,-24)==-1)goto eop; - for(j=0;jorder;){ + for(j=0;jm;j+=b->dim) + if(vorbis_book_decodev_set(b,lsp+j,&vb->opb,b->dim,-24)==-1)goto eop; + for(j=0;jm;){ for(k=0;kdim;k++,j++)lsp[j]+=last; last=lsp[j-1]; } - lsp[info->order]=amp; + lsp[look->m]=amp; return(lsp); } } @@ -408,21 +408,28 @@ return(NULL); } -int floor0_inverse2(vorbis_dsp_state *vd,vorbis_info_floor *i, - ogg_int32_t *lsp,ogg_int32_t *out){ - vorbis_info_floor0 *info=(vorbis_info_floor0 *)i; - codec_setup_info *ci=(codec_setup_info *)vd->vi->codec_setup; +static int floor0_inverse2(vorbis_block *vb,vorbis_look_floor *i, + void *memo,ogg_int32_t *out){ + vorbis_look_floor0 *look=(vorbis_look_floor0 *)i; + vorbis_info_floor0 *info=look->vi; - if(lsp){ - ogg_int32_t amp=lsp[info->order]; + if(memo){ + ogg_int32_t *lsp=(ogg_int32_t *)memo; + ogg_int32_t amp=lsp[look->m]; /* take the coefficients back to a spectral envelope curve */ - vorbis_lsp_to_curve(out,ci->blocksizes[vd->W]/2,info->barkmap, - lsp,info->order,amp,info->ampdB, - info->rate>>1); + vorbis_lsp_to_curve(out,look->linearmap,look->n,look->ln, + lsp,look->m,amp,info->ampdB,look->lsp_look); return(1); } - memset(out,0,sizeof(*out)*ci->blocksizes[vd->W]/2); + memset(out,0,sizeof(*out)*look->n); return(0); } +/* export hooks */ +vorbis_func_floor floor0_exportbundle={ + &floor0_unpack,&floor0_look,&floor0_free_info, + &floor0_free_look,&floor0_inverse1,&floor0_inverse2 +}; + +