media/libtremor/lib/tremor_floor0.c

changeset 0
6474c204b198
     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 +

mercurial