1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/libtremor/lib/tremor_floor0.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,438 @@ 1.4 +/******************************************************************** 1.5 + * * 1.6 + * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * 1.7 + * * 1.8 + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * 1.9 + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * 1.10 + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * 1.11 + * * 1.12 + * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * 1.13 + * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * 1.14 + * * 1.15 + ******************************************************************** 1.16 + 1.17 + function: floor backend 0 implementation 1.18 + 1.19 + ********************************************************************/ 1.20 + 1.21 +#include <stdlib.h> 1.22 +#include <string.h> 1.23 +#include <math.h> 1.24 +#include <ogg/ogg.h> 1.25 +#include "ivorbiscodec.h" 1.26 +#include "codec_internal.h" 1.27 +#include "registry.h" 1.28 +#include "codebook.h" 1.29 +#include "misc.h" 1.30 +#include "block.h" 1.31 + 1.32 +#define LSP_FRACBITS 14 1.33 + 1.34 +typedef struct { 1.35 + long n; 1.36 + int ln; 1.37 + int m; 1.38 + int *linearmap; 1.39 + 1.40 + vorbis_info_floor0 *vi; 1.41 + ogg_int32_t *lsp_look; 1.42 + 1.43 +} vorbis_look_floor0; 1.44 + 1.45 +/*************** LSP decode ********************/ 1.46 + 1.47 +#include "lsp_lookup.h" 1.48 + 1.49 +/* interpolated 1./sqrt(p) where .5 <= a < 1. (.100000... to .111111...) in 1.50 + 16.16 format 1.51 + returns in m.8 format */ 1.52 + 1.53 +static long ADJUST_SQRT2[2]={8192,5792}; 1.54 +STIN ogg_int32_t vorbis_invsqlook_i(long a,long e){ 1.55 + long i=(a&0x7fff)>>(INVSQ_LOOKUP_I_SHIFT-1); 1.56 + long d=a&INVSQ_LOOKUP_I_MASK; /* 0.10 */ 1.57 + long val=INVSQ_LOOKUP_I[i]- /* 1.16 */ 1.58 + ((INVSQ_LOOKUP_IDel[i]*d)>>INVSQ_LOOKUP_I_SHIFT); /* result 1.16 */ 1.59 + val*=ADJUST_SQRT2[e&1]; 1.60 + e=(e>>1)+21; 1.61 + return(val>>e); 1.62 +} 1.63 + 1.64 +/* interpolated lookup based fromdB function, domain -140dB to 0dB only */ 1.65 +/* a is in n.12 format */ 1.66 +STIN ogg_int32_t vorbis_fromdBlook_i(long a){ 1.67 + int i=(-a)>>(12-FROMdB2_SHIFT); 1.68 + if(i<0) return 0x7fffffff; 1.69 + if(i>=(FROMdB_LOOKUP_SZ<<FROMdB_SHIFT))return 0; 1.70 + 1.71 + return FROMdB_LOOKUP[i>>FROMdB_SHIFT] * FROMdB2_LOOKUP[i&FROMdB2_MASK]; 1.72 +} 1.73 + 1.74 +/* interpolated lookup based cos function, domain 0 to PI only */ 1.75 +/* a is in 0.16 format, where 0==0, 2^^16-1==PI, return 0.14 */ 1.76 +STIN ogg_int32_t vorbis_coslook_i(long a){ 1.77 + int i=a>>COS_LOOKUP_I_SHIFT; 1.78 + int d=a&COS_LOOKUP_I_MASK; 1.79 + return COS_LOOKUP_I[i]- ((d*(COS_LOOKUP_I[i]-COS_LOOKUP_I[i+1]))>> 1.80 + COS_LOOKUP_I_SHIFT); 1.81 +} 1.82 + 1.83 +/* interpolated lookup based cos function */ 1.84 +/* a is in 0.16 format, where 0==0, 2^^16==PI, return .LSP_FRACBITS */ 1.85 +STIN ogg_int32_t vorbis_coslook2_i(long a){ 1.86 + a=a&0x1ffff; 1.87 + 1.88 + if(a>0x10000)a=0x20000-a; 1.89 + { 1.90 + int i=a>>COS_LOOKUP_I_SHIFT; 1.91 + int d=a&COS_LOOKUP_I_MASK; 1.92 + a=((COS_LOOKUP_I[i]<<COS_LOOKUP_I_SHIFT)- 1.93 + d*(COS_LOOKUP_I[i]-COS_LOOKUP_I[i+1]))>> 1.94 + (COS_LOOKUP_I_SHIFT-LSP_FRACBITS+14); 1.95 + } 1.96 + 1.97 + return(a); 1.98 +} 1.99 + 1.100 +static const int barklook[28]={ 1.101 + 0,100,200,301, 405,516,635,766, 1.102 + 912,1077,1263,1476, 1720,2003,2333,2721, 1.103 + 3184,3742,4428,5285, 6376,7791,9662,12181, 1.104 + 15624,20397,27087,36554 1.105 +}; 1.106 + 1.107 +/* used in init only; interpolate the long way */ 1.108 +STIN ogg_int32_t toBARK(int n){ 1.109 + int i; 1.110 + for(i=0;i<27;i++) 1.111 + if(n>=barklook[i] && n<barklook[i+1])break; 1.112 + 1.113 + if(i==27){ 1.114 + return 27<<15; 1.115 + }else{ 1.116 + int gap=barklook[i+1]-barklook[i]; 1.117 + int del=n-barklook[i]; 1.118 + 1.119 + return((i<<15)+((del<<15)/gap)); 1.120 + } 1.121 +} 1.122 + 1.123 +static const unsigned char MLOOP_1[64]={ 1.124 + 0,10,11,11, 12,12,12,12, 13,13,13,13, 13,13,13,13, 1.125 + 14,14,14,14, 14,14,14,14, 14,14,14,14, 14,14,14,14, 1.126 + 15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15, 1.127 + 15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15, 1.128 +}; 1.129 + 1.130 +static const unsigned char MLOOP_2[64]={ 1.131 + 0,4,5,5, 6,6,6,6, 7,7,7,7, 7,7,7,7, 1.132 + 8,8,8,8, 8,8,8,8, 8,8,8,8, 8,8,8,8, 1.133 + 9,9,9,9, 9,9,9,9, 9,9,9,9, 9,9,9,9, 1.134 + 9,9,9,9, 9,9,9,9, 9,9,9,9, 9,9,9,9, 1.135 +}; 1.136 + 1.137 +static const unsigned char MLOOP_3[8]={0,1,2,2,3,3,3,3}; 1.138 + 1.139 +void vorbis_lsp_to_curve(ogg_int32_t *curve,int *map,int n,int ln, 1.140 + ogg_int32_t *lsp,int m, 1.141 + ogg_int32_t amp, 1.142 + ogg_int32_t ampoffset, 1.143 + ogg_int32_t *icos){ 1.144 + 1.145 + /* 0 <= m < 256 */ 1.146 + 1.147 + /* set up for using all int later */ 1.148 + int i; 1.149 + int ampoffseti=ampoffset*4096; 1.150 + int ampi=amp; 1.151 + ogg_int32_t *ilsp=(ogg_int32_t *)alloca(m*sizeof(*ilsp)); 1.152 + /* lsp is in 8.24, range 0 to PI; coslook wants it in .16 0 to 1*/ 1.153 + for(i=0;i<m;i++){ 1.154 +#ifndef _LOW_ACCURACY_ 1.155 + ogg_int32_t val=MULT32(lsp[i],0x517cc2); 1.156 +#else 1.157 + ogg_int32_t val=((lsp[i]>>10)*0x517d)>>14; 1.158 +#endif 1.159 + 1.160 + /* safeguard against a malicious stream */ 1.161 + if(val<0 || (val>>COS_LOOKUP_I_SHIFT)>=COS_LOOKUP_I_SZ){ 1.162 + memset(curve,0,sizeof(*curve)*n); 1.163 + return; 1.164 + } 1.165 + 1.166 + ilsp[i]=vorbis_coslook_i(val); 1.167 + } 1.168 + 1.169 + i=0; 1.170 + while(i<n){ 1.171 + int j,k=map[i]; 1.172 + ogg_uint32_t pi=46341; /* 2**-.5 in 0.16 */ 1.173 + ogg_uint32_t qi=46341; 1.174 + ogg_int32_t qexp=0,shift; 1.175 + ogg_int32_t wi=icos[k]; 1.176 + 1.177 +#ifdef _V_LSP_MATH_ASM 1.178 + lsp_loop_asm(&qi,&pi,&qexp,ilsp,wi,m); 1.179 + 1.180 + pi=((pi*pi)>>16); 1.181 + qi=((qi*qi)>>16); 1.182 + 1.183 + if(m&1){ 1.184 + qexp= qexp*2-28*((m+1)>>1)+m; 1.185 + pi*=(1<<14)-((wi*wi)>>14); 1.186 + qi+=pi>>14; 1.187 + }else{ 1.188 + qexp= qexp*2-13*m; 1.189 + 1.190 + pi*=(1<<14)-wi; 1.191 + qi*=(1<<14)+wi; 1.192 + 1.193 + qi=(qi+pi)>>14; 1.194 + } 1.195 + 1.196 + if(qi&0xffff0000){ /* checks for 1.xxxxxxxxxxxxxxxx */ 1.197 + qi>>=1; qexp++; 1.198 + }else 1.199 + lsp_norm_asm(&qi,&qexp); 1.200 + 1.201 +#else 1.202 + 1.203 + j=1; 1.204 + if(m>1){ 1.205 + qi*=labs(ilsp[0]-wi); 1.206 + pi*=labs(ilsp[1]-wi); 1.207 + 1.208 + for(j+=2;j<m;j+=2){ 1.209 + if(!(shift=MLOOP_1[(pi|qi)>>25])) 1.210 + if(!(shift=MLOOP_2[(pi|qi)>>19])) 1.211 + shift=MLOOP_3[(pi|qi)>>16]; 1.212 + qi=(qi>>shift)*labs(ilsp[j-1]-wi); 1.213 + pi=(pi>>shift)*labs(ilsp[j]-wi); 1.214 + qexp+=shift; 1.215 + } 1.216 + } 1.217 + if(!(shift=MLOOP_1[(pi|qi)>>25])) 1.218 + if(!(shift=MLOOP_2[(pi|qi)>>19])) 1.219 + shift=MLOOP_3[(pi|qi)>>16]; 1.220 + 1.221 + /* pi,qi normalized collectively, both tracked using qexp */ 1.222 + 1.223 + if(m&1){ 1.224 + /* odd order filter; slightly assymetric */ 1.225 + /* the last coefficient */ 1.226 + qi=(qi>>shift)*labs(ilsp[j-1]-wi); 1.227 + pi=(pi>>shift)<<14; 1.228 + qexp+=shift; 1.229 + 1.230 + if(!(shift=MLOOP_1[(pi|qi)>>25])) 1.231 + if(!(shift=MLOOP_2[(pi|qi)>>19])) 1.232 + shift=MLOOP_3[(pi|qi)>>16]; 1.233 + 1.234 + pi>>=shift; 1.235 + qi>>=shift; 1.236 + qexp+=shift-14*((m+1)>>1); 1.237 + 1.238 + pi=((pi*pi)>>16); 1.239 + qi=((qi*qi)>>16); 1.240 + qexp=qexp*2+m; 1.241 + 1.242 + pi*=(1<<14)-((wi*wi)>>14); 1.243 + qi+=pi>>14; 1.244 + 1.245 + }else{ 1.246 + /* even order filter; still symmetric */ 1.247 + 1.248 + /* p*=p(1-w), q*=q(1+w), let normalization drift because it isn't 1.249 + worth tracking step by step */ 1.250 + 1.251 + pi>>=shift; 1.252 + qi>>=shift; 1.253 + qexp+=shift-7*m; 1.254 + 1.255 + pi=((pi*pi)>>16); 1.256 + qi=((qi*qi)>>16); 1.257 + qexp=qexp*2+m; 1.258 + 1.259 + pi*=(1<<14)-wi; 1.260 + qi*=(1<<14)+wi; 1.261 + qi=(qi+pi)>>14; 1.262 + 1.263 + } 1.264 + 1.265 + 1.266 + /* we've let the normalization drift because it wasn't important; 1.267 + however, for the lookup, things must be normalized again. We 1.268 + need at most one right shift or a number of left shifts */ 1.269 + 1.270 + if(qi&0xffff0000){ /* checks for 1.xxxxxxxxxxxxxxxx */ 1.271 + qi>>=1; qexp++; 1.272 + }else 1.273 + while(qi && !(qi&0x8000)){ /* checks for 0.0xxxxxxxxxxxxxxx or less*/ 1.274 + qi<<=1; qexp--; 1.275 + } 1.276 + 1.277 +#endif 1.278 + 1.279 + amp=vorbis_fromdBlook_i(ampi* /* n.4 */ 1.280 + vorbis_invsqlook_i(qi,qexp)- 1.281 + /* m.8, m+n<=8 */ 1.282 + ampoffseti); /* 8.12[0] */ 1.283 + 1.284 +#ifdef _LOW_ACCURACY_ 1.285 + amp>>=9; 1.286 +#endif 1.287 + curve[i]= MULT31_SHIFT15(curve[i],amp); 1.288 + while(map[++i]==k) curve[i]= MULT31_SHIFT15(curve[i],amp); 1.289 + } 1.290 +} 1.291 + 1.292 +/*************** vorbis decode glue ************/ 1.293 + 1.294 +static void floor0_free_info(vorbis_info_floor *i){ 1.295 + vorbis_info_floor0 *info=(vorbis_info_floor0 *)i; 1.296 + if(info){ 1.297 + memset(info,0,sizeof(*info)); 1.298 + _ogg_free(info); 1.299 + } 1.300 +} 1.301 + 1.302 +static void floor0_free_look(vorbis_look_floor *i){ 1.303 + vorbis_look_floor0 *look=(vorbis_look_floor0 *)i; 1.304 + if(look){ 1.305 + 1.306 + if(look->linearmap)_ogg_free(look->linearmap); 1.307 + if(look->lsp_look)_ogg_free(look->lsp_look); 1.308 + memset(look,0,sizeof(*look)); 1.309 + _ogg_free(look); 1.310 + } 1.311 +} 1.312 + 1.313 +static vorbis_info_floor *floor0_unpack (vorbis_info *vi,oggpack_buffer *opb){ 1.314 + codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; 1.315 + int j; 1.316 + 1.317 + vorbis_info_floor0 *info=(vorbis_info_floor0 *)_ogg_malloc(sizeof(*info)); 1.318 + info->order=oggpack_read(opb,8); 1.319 + info->rate=oggpack_read(opb,16); 1.320 + info->barkmap=oggpack_read(opb,16); 1.321 + info->ampbits=oggpack_read(opb,6); 1.322 + info->ampdB=oggpack_read(opb,8); 1.323 + info->numbooks=oggpack_read(opb,4)+1; 1.324 + 1.325 + if(info->order<1)goto err_out; 1.326 + if(info->rate<1)goto err_out; 1.327 + if(info->barkmap<1)goto err_out; 1.328 + if(info->numbooks<1)goto err_out; 1.329 + 1.330 + for(j=0;j<info->numbooks;j++){ 1.331 + info->books[j]=oggpack_read(opb,8); 1.332 + if(info->books[j]<0 || info->books[j]>=ci->books)goto err_out; 1.333 + if(ci->book_param[info->books[j]]->maptype==0)goto err_out; 1.334 + } 1.335 + return(info); 1.336 + 1.337 + err_out: 1.338 + floor0_free_info(info); 1.339 + return(NULL); 1.340 +} 1.341 + 1.342 +/* initialize Bark scale and normalization lookups. We could do this 1.343 + with static tables, but Vorbis allows a number of possible 1.344 + combinations, so it's best to do it computationally. 1.345 + 1.346 + The below is authoritative in terms of defining scale mapping. 1.347 + Note that the scale depends on the sampling rate as well as the 1.348 + linear block and mapping sizes */ 1.349 + 1.350 +static vorbis_look_floor *floor0_look (vorbis_dsp_state *vd,vorbis_info_mode *mi, 1.351 + vorbis_info_floor *i){ 1.352 + int j; 1.353 + vorbis_info *vi=vd->vi; 1.354 + codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; 1.355 + vorbis_info_floor0 *info=(vorbis_info_floor0 *)i; 1.356 + vorbis_look_floor0 *look=(vorbis_look_floor0 *)_ogg_calloc(1,sizeof(*look)); 1.357 + look->m=info->order; 1.358 + look->n=ci->blocksizes[mi->blockflag]/2; 1.359 + look->ln=info->barkmap; 1.360 + look->vi=info; 1.361 + 1.362 + /* the mapping from a linear scale to a smaller bark scale is 1.363 + straightforward. We do *not* make sure that the linear mapping 1.364 + does not skip bark-scale bins; the decoder simply skips them and 1.365 + the encoder may do what it wishes in filling them. They're 1.366 + necessary in some mapping combinations to keep the scale spacing 1.367 + accurate */ 1.368 + look->linearmap=(int *)_ogg_malloc((look->n+1)*sizeof(*look->linearmap)); 1.369 + for(j=0;j<look->n;j++){ 1.370 + 1.371 + int val=(look->ln* 1.372 + ((toBARK(info->rate/2*j/look->n)<<11)/toBARK(info->rate/2)))>>11; 1.373 + 1.374 + if(val>=look->ln)val=look->ln-1; /* guard against the approximation */ 1.375 + look->linearmap[j]=val; 1.376 + } 1.377 + look->linearmap[j]=-1; 1.378 + 1.379 + look->lsp_look=(ogg_int32_t *)_ogg_malloc(look->ln*sizeof(*look->lsp_look)); 1.380 + for(j=0;j<look->ln;j++) 1.381 + look->lsp_look[j]=vorbis_coslook2_i(0x10000*j/look->ln); 1.382 + 1.383 + return look; 1.384 +} 1.385 + 1.386 +static void *floor0_inverse1(vorbis_block *vb,vorbis_look_floor *i){ 1.387 + vorbis_look_floor0 *look=(vorbis_look_floor0 *)i; 1.388 + vorbis_info_floor0 *info=look->vi; 1.389 + int j,k; 1.390 + 1.391 + int ampraw=oggpack_read(&vb->opb,info->ampbits); 1.392 + if(ampraw>0){ /* also handles the -1 out of data case */ 1.393 + long maxval=(1<<info->ampbits)-1; 1.394 + int amp=((ampraw*info->ampdB)<<4)/maxval; 1.395 + int booknum=oggpack_read(&vb->opb,_ilog(info->numbooks)); 1.396 + 1.397 + if(booknum!=-1 && booknum<info->numbooks){ /* be paranoid */ 1.398 + codec_setup_info *ci=(codec_setup_info *)vb->vd->vi->codec_setup; 1.399 + codebook *b=ci->fullbooks+info->books[booknum]; 1.400 + ogg_int32_t last=0; 1.401 + ogg_int32_t *lsp=(ogg_int32_t *)_vorbis_block_alloc(vb,sizeof(*lsp)*(look->m+1)); 1.402 + 1.403 + if(vorbis_book_decodev_set(b,lsp,&vb->opb,look->m,-24)==-1)goto eop; 1.404 + for(j=0;j<look->m;){ 1.405 + for(k=0;j<look->m && k<b->dim;k++,j++)lsp[j]+=last; 1.406 + last=lsp[j-1]; 1.407 + } 1.408 + 1.409 + lsp[look->m]=amp; 1.410 + return(lsp); 1.411 + } 1.412 + } 1.413 + eop: 1.414 + return(NULL); 1.415 +} 1.416 + 1.417 +static int floor0_inverse2(vorbis_block *vb,vorbis_look_floor *i, 1.418 + void *memo,ogg_int32_t *out){ 1.419 + vorbis_look_floor0 *look=(vorbis_look_floor0 *)i; 1.420 + vorbis_info_floor0 *info=look->vi; 1.421 + 1.422 + if(memo){ 1.423 + ogg_int32_t *lsp=(ogg_int32_t *)memo; 1.424 + ogg_int32_t amp=lsp[look->m]; 1.425 + 1.426 + /* take the coefficients back to a spectral envelope curve */ 1.427 + vorbis_lsp_to_curve(out,look->linearmap,look->n,look->ln, 1.428 + lsp,look->m,amp,info->ampdB,look->lsp_look); 1.429 + return(1); 1.430 + } 1.431 + memset(out,0,sizeof(*out)*look->n); 1.432 + return(0); 1.433 +} 1.434 + 1.435 +/* export hooks */ 1.436 +vorbis_func_floor floor0_exportbundle={ 1.437 + &floor0_unpack,&floor0_look,&floor0_free_info, 1.438 + &floor0_free_look,&floor0_inverse1,&floor0_inverse2 1.439 +}; 1.440 + 1.441 +