media/libtremor/lib/tremor_floor0.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /********************************************************************
michael@0 2 * *
michael@0 3 * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. *
michael@0 4 * *
michael@0 5 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
michael@0 6 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
michael@0 7 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
michael@0 8 * *
michael@0 9 * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 *
michael@0 10 * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ *
michael@0 11 * *
michael@0 12 ********************************************************************
michael@0 13
michael@0 14 function: floor backend 0 implementation
michael@0 15
michael@0 16 ********************************************************************/
michael@0 17
michael@0 18 #include <stdlib.h>
michael@0 19 #include <string.h>
michael@0 20 #include <math.h>
michael@0 21 #include <ogg/ogg.h>
michael@0 22 #include "ivorbiscodec.h"
michael@0 23 #include "codec_internal.h"
michael@0 24 #include "registry.h"
michael@0 25 #include "codebook.h"
michael@0 26 #include "misc.h"
michael@0 27 #include "block.h"
michael@0 28
michael@0 29 #define LSP_FRACBITS 14
michael@0 30
michael@0 31 typedef struct {
michael@0 32 long n;
michael@0 33 int ln;
michael@0 34 int m;
michael@0 35 int *linearmap;
michael@0 36
michael@0 37 vorbis_info_floor0 *vi;
michael@0 38 ogg_int32_t *lsp_look;
michael@0 39
michael@0 40 } vorbis_look_floor0;
michael@0 41
michael@0 42 /*************** LSP decode ********************/
michael@0 43
michael@0 44 #include "lsp_lookup.h"
michael@0 45
michael@0 46 /* interpolated 1./sqrt(p) where .5 <= a < 1. (.100000... to .111111...) in
michael@0 47 16.16 format
michael@0 48 returns in m.8 format */
michael@0 49
michael@0 50 static long ADJUST_SQRT2[2]={8192,5792};
michael@0 51 STIN ogg_int32_t vorbis_invsqlook_i(long a,long e){
michael@0 52 long i=(a&0x7fff)>>(INVSQ_LOOKUP_I_SHIFT-1);
michael@0 53 long d=a&INVSQ_LOOKUP_I_MASK; /* 0.10 */
michael@0 54 long val=INVSQ_LOOKUP_I[i]- /* 1.16 */
michael@0 55 ((INVSQ_LOOKUP_IDel[i]*d)>>INVSQ_LOOKUP_I_SHIFT); /* result 1.16 */
michael@0 56 val*=ADJUST_SQRT2[e&1];
michael@0 57 e=(e>>1)+21;
michael@0 58 return(val>>e);
michael@0 59 }
michael@0 60
michael@0 61 /* interpolated lookup based fromdB function, domain -140dB to 0dB only */
michael@0 62 /* a is in n.12 format */
michael@0 63 STIN ogg_int32_t vorbis_fromdBlook_i(long a){
michael@0 64 int i=(-a)>>(12-FROMdB2_SHIFT);
michael@0 65 if(i<0) return 0x7fffffff;
michael@0 66 if(i>=(FROMdB_LOOKUP_SZ<<FROMdB_SHIFT))return 0;
michael@0 67
michael@0 68 return FROMdB_LOOKUP[i>>FROMdB_SHIFT] * FROMdB2_LOOKUP[i&FROMdB2_MASK];
michael@0 69 }
michael@0 70
michael@0 71 /* interpolated lookup based cos function, domain 0 to PI only */
michael@0 72 /* a is in 0.16 format, where 0==0, 2^^16-1==PI, return 0.14 */
michael@0 73 STIN ogg_int32_t vorbis_coslook_i(long a){
michael@0 74 int i=a>>COS_LOOKUP_I_SHIFT;
michael@0 75 int d=a&COS_LOOKUP_I_MASK;
michael@0 76 return COS_LOOKUP_I[i]- ((d*(COS_LOOKUP_I[i]-COS_LOOKUP_I[i+1]))>>
michael@0 77 COS_LOOKUP_I_SHIFT);
michael@0 78 }
michael@0 79
michael@0 80 /* interpolated lookup based cos function */
michael@0 81 /* a is in 0.16 format, where 0==0, 2^^16==PI, return .LSP_FRACBITS */
michael@0 82 STIN ogg_int32_t vorbis_coslook2_i(long a){
michael@0 83 a=a&0x1ffff;
michael@0 84
michael@0 85 if(a>0x10000)a=0x20000-a;
michael@0 86 {
michael@0 87 int i=a>>COS_LOOKUP_I_SHIFT;
michael@0 88 int d=a&COS_LOOKUP_I_MASK;
michael@0 89 a=((COS_LOOKUP_I[i]<<COS_LOOKUP_I_SHIFT)-
michael@0 90 d*(COS_LOOKUP_I[i]-COS_LOOKUP_I[i+1]))>>
michael@0 91 (COS_LOOKUP_I_SHIFT-LSP_FRACBITS+14);
michael@0 92 }
michael@0 93
michael@0 94 return(a);
michael@0 95 }
michael@0 96
michael@0 97 static const int barklook[28]={
michael@0 98 0,100,200,301, 405,516,635,766,
michael@0 99 912,1077,1263,1476, 1720,2003,2333,2721,
michael@0 100 3184,3742,4428,5285, 6376,7791,9662,12181,
michael@0 101 15624,20397,27087,36554
michael@0 102 };
michael@0 103
michael@0 104 /* used in init only; interpolate the long way */
michael@0 105 STIN ogg_int32_t toBARK(int n){
michael@0 106 int i;
michael@0 107 for(i=0;i<27;i++)
michael@0 108 if(n>=barklook[i] && n<barklook[i+1])break;
michael@0 109
michael@0 110 if(i==27){
michael@0 111 return 27<<15;
michael@0 112 }else{
michael@0 113 int gap=barklook[i+1]-barklook[i];
michael@0 114 int del=n-barklook[i];
michael@0 115
michael@0 116 return((i<<15)+((del<<15)/gap));
michael@0 117 }
michael@0 118 }
michael@0 119
michael@0 120 static const unsigned char MLOOP_1[64]={
michael@0 121 0,10,11,11, 12,12,12,12, 13,13,13,13, 13,13,13,13,
michael@0 122 14,14,14,14, 14,14,14,14, 14,14,14,14, 14,14,14,14,
michael@0 123 15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15,
michael@0 124 15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15,
michael@0 125 };
michael@0 126
michael@0 127 static const unsigned char MLOOP_2[64]={
michael@0 128 0,4,5,5, 6,6,6,6, 7,7,7,7, 7,7,7,7,
michael@0 129 8,8,8,8, 8,8,8,8, 8,8,8,8, 8,8,8,8,
michael@0 130 9,9,9,9, 9,9,9,9, 9,9,9,9, 9,9,9,9,
michael@0 131 9,9,9,9, 9,9,9,9, 9,9,9,9, 9,9,9,9,
michael@0 132 };
michael@0 133
michael@0 134 static const unsigned char MLOOP_3[8]={0,1,2,2,3,3,3,3};
michael@0 135
michael@0 136 void vorbis_lsp_to_curve(ogg_int32_t *curve,int *map,int n,int ln,
michael@0 137 ogg_int32_t *lsp,int m,
michael@0 138 ogg_int32_t amp,
michael@0 139 ogg_int32_t ampoffset,
michael@0 140 ogg_int32_t *icos){
michael@0 141
michael@0 142 /* 0 <= m < 256 */
michael@0 143
michael@0 144 /* set up for using all int later */
michael@0 145 int i;
michael@0 146 int ampoffseti=ampoffset*4096;
michael@0 147 int ampi=amp;
michael@0 148 ogg_int32_t *ilsp=(ogg_int32_t *)alloca(m*sizeof(*ilsp));
michael@0 149 /* lsp is in 8.24, range 0 to PI; coslook wants it in .16 0 to 1*/
michael@0 150 for(i=0;i<m;i++){
michael@0 151 #ifndef _LOW_ACCURACY_
michael@0 152 ogg_int32_t val=MULT32(lsp[i],0x517cc2);
michael@0 153 #else
michael@0 154 ogg_int32_t val=((lsp[i]>>10)*0x517d)>>14;
michael@0 155 #endif
michael@0 156
michael@0 157 /* safeguard against a malicious stream */
michael@0 158 if(val<0 || (val>>COS_LOOKUP_I_SHIFT)>=COS_LOOKUP_I_SZ){
michael@0 159 memset(curve,0,sizeof(*curve)*n);
michael@0 160 return;
michael@0 161 }
michael@0 162
michael@0 163 ilsp[i]=vorbis_coslook_i(val);
michael@0 164 }
michael@0 165
michael@0 166 i=0;
michael@0 167 while(i<n){
michael@0 168 int j,k=map[i];
michael@0 169 ogg_uint32_t pi=46341; /* 2**-.5 in 0.16 */
michael@0 170 ogg_uint32_t qi=46341;
michael@0 171 ogg_int32_t qexp=0,shift;
michael@0 172 ogg_int32_t wi=icos[k];
michael@0 173
michael@0 174 #ifdef _V_LSP_MATH_ASM
michael@0 175 lsp_loop_asm(&qi,&pi,&qexp,ilsp,wi,m);
michael@0 176
michael@0 177 pi=((pi*pi)>>16);
michael@0 178 qi=((qi*qi)>>16);
michael@0 179
michael@0 180 if(m&1){
michael@0 181 qexp= qexp*2-28*((m+1)>>1)+m;
michael@0 182 pi*=(1<<14)-((wi*wi)>>14);
michael@0 183 qi+=pi>>14;
michael@0 184 }else{
michael@0 185 qexp= qexp*2-13*m;
michael@0 186
michael@0 187 pi*=(1<<14)-wi;
michael@0 188 qi*=(1<<14)+wi;
michael@0 189
michael@0 190 qi=(qi+pi)>>14;
michael@0 191 }
michael@0 192
michael@0 193 if(qi&0xffff0000){ /* checks for 1.xxxxxxxxxxxxxxxx */
michael@0 194 qi>>=1; qexp++;
michael@0 195 }else
michael@0 196 lsp_norm_asm(&qi,&qexp);
michael@0 197
michael@0 198 #else
michael@0 199
michael@0 200 j=1;
michael@0 201 if(m>1){
michael@0 202 qi*=labs(ilsp[0]-wi);
michael@0 203 pi*=labs(ilsp[1]-wi);
michael@0 204
michael@0 205 for(j+=2;j<m;j+=2){
michael@0 206 if(!(shift=MLOOP_1[(pi|qi)>>25]))
michael@0 207 if(!(shift=MLOOP_2[(pi|qi)>>19]))
michael@0 208 shift=MLOOP_3[(pi|qi)>>16];
michael@0 209 qi=(qi>>shift)*labs(ilsp[j-1]-wi);
michael@0 210 pi=(pi>>shift)*labs(ilsp[j]-wi);
michael@0 211 qexp+=shift;
michael@0 212 }
michael@0 213 }
michael@0 214 if(!(shift=MLOOP_1[(pi|qi)>>25]))
michael@0 215 if(!(shift=MLOOP_2[(pi|qi)>>19]))
michael@0 216 shift=MLOOP_3[(pi|qi)>>16];
michael@0 217
michael@0 218 /* pi,qi normalized collectively, both tracked using qexp */
michael@0 219
michael@0 220 if(m&1){
michael@0 221 /* odd order filter; slightly assymetric */
michael@0 222 /* the last coefficient */
michael@0 223 qi=(qi>>shift)*labs(ilsp[j-1]-wi);
michael@0 224 pi=(pi>>shift)<<14;
michael@0 225 qexp+=shift;
michael@0 226
michael@0 227 if(!(shift=MLOOP_1[(pi|qi)>>25]))
michael@0 228 if(!(shift=MLOOP_2[(pi|qi)>>19]))
michael@0 229 shift=MLOOP_3[(pi|qi)>>16];
michael@0 230
michael@0 231 pi>>=shift;
michael@0 232 qi>>=shift;
michael@0 233 qexp+=shift-14*((m+1)>>1);
michael@0 234
michael@0 235 pi=((pi*pi)>>16);
michael@0 236 qi=((qi*qi)>>16);
michael@0 237 qexp=qexp*2+m;
michael@0 238
michael@0 239 pi*=(1<<14)-((wi*wi)>>14);
michael@0 240 qi+=pi>>14;
michael@0 241
michael@0 242 }else{
michael@0 243 /* even order filter; still symmetric */
michael@0 244
michael@0 245 /* p*=p(1-w), q*=q(1+w), let normalization drift because it isn't
michael@0 246 worth tracking step by step */
michael@0 247
michael@0 248 pi>>=shift;
michael@0 249 qi>>=shift;
michael@0 250 qexp+=shift-7*m;
michael@0 251
michael@0 252 pi=((pi*pi)>>16);
michael@0 253 qi=((qi*qi)>>16);
michael@0 254 qexp=qexp*2+m;
michael@0 255
michael@0 256 pi*=(1<<14)-wi;
michael@0 257 qi*=(1<<14)+wi;
michael@0 258 qi=(qi+pi)>>14;
michael@0 259
michael@0 260 }
michael@0 261
michael@0 262
michael@0 263 /* we've let the normalization drift because it wasn't important;
michael@0 264 however, for the lookup, things must be normalized again. We
michael@0 265 need at most one right shift or a number of left shifts */
michael@0 266
michael@0 267 if(qi&0xffff0000){ /* checks for 1.xxxxxxxxxxxxxxxx */
michael@0 268 qi>>=1; qexp++;
michael@0 269 }else
michael@0 270 while(qi && !(qi&0x8000)){ /* checks for 0.0xxxxxxxxxxxxxxx or less*/
michael@0 271 qi<<=1; qexp--;
michael@0 272 }
michael@0 273
michael@0 274 #endif
michael@0 275
michael@0 276 amp=vorbis_fromdBlook_i(ampi* /* n.4 */
michael@0 277 vorbis_invsqlook_i(qi,qexp)-
michael@0 278 /* m.8, m+n<=8 */
michael@0 279 ampoffseti); /* 8.12[0] */
michael@0 280
michael@0 281 #ifdef _LOW_ACCURACY_
michael@0 282 amp>>=9;
michael@0 283 #endif
michael@0 284 curve[i]= MULT31_SHIFT15(curve[i],amp);
michael@0 285 while(map[++i]==k) curve[i]= MULT31_SHIFT15(curve[i],amp);
michael@0 286 }
michael@0 287 }
michael@0 288
michael@0 289 /*************** vorbis decode glue ************/
michael@0 290
michael@0 291 static void floor0_free_info(vorbis_info_floor *i){
michael@0 292 vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
michael@0 293 if(info){
michael@0 294 memset(info,0,sizeof(*info));
michael@0 295 _ogg_free(info);
michael@0 296 }
michael@0 297 }
michael@0 298
michael@0 299 static void floor0_free_look(vorbis_look_floor *i){
michael@0 300 vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
michael@0 301 if(look){
michael@0 302
michael@0 303 if(look->linearmap)_ogg_free(look->linearmap);
michael@0 304 if(look->lsp_look)_ogg_free(look->lsp_look);
michael@0 305 memset(look,0,sizeof(*look));
michael@0 306 _ogg_free(look);
michael@0 307 }
michael@0 308 }
michael@0 309
michael@0 310 static vorbis_info_floor *floor0_unpack (vorbis_info *vi,oggpack_buffer *opb){
michael@0 311 codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
michael@0 312 int j;
michael@0 313
michael@0 314 vorbis_info_floor0 *info=(vorbis_info_floor0 *)_ogg_malloc(sizeof(*info));
michael@0 315 info->order=oggpack_read(opb,8);
michael@0 316 info->rate=oggpack_read(opb,16);
michael@0 317 info->barkmap=oggpack_read(opb,16);
michael@0 318 info->ampbits=oggpack_read(opb,6);
michael@0 319 info->ampdB=oggpack_read(opb,8);
michael@0 320 info->numbooks=oggpack_read(opb,4)+1;
michael@0 321
michael@0 322 if(info->order<1)goto err_out;
michael@0 323 if(info->rate<1)goto err_out;
michael@0 324 if(info->barkmap<1)goto err_out;
michael@0 325 if(info->numbooks<1)goto err_out;
michael@0 326
michael@0 327 for(j=0;j<info->numbooks;j++){
michael@0 328 info->books[j]=oggpack_read(opb,8);
michael@0 329 if(info->books[j]<0 || info->books[j]>=ci->books)goto err_out;
michael@0 330 if(ci->book_param[info->books[j]]->maptype==0)goto err_out;
michael@0 331 }
michael@0 332 return(info);
michael@0 333
michael@0 334 err_out:
michael@0 335 floor0_free_info(info);
michael@0 336 return(NULL);
michael@0 337 }
michael@0 338
michael@0 339 /* initialize Bark scale and normalization lookups. We could do this
michael@0 340 with static tables, but Vorbis allows a number of possible
michael@0 341 combinations, so it's best to do it computationally.
michael@0 342
michael@0 343 The below is authoritative in terms of defining scale mapping.
michael@0 344 Note that the scale depends on the sampling rate as well as the
michael@0 345 linear block and mapping sizes */
michael@0 346
michael@0 347 static vorbis_look_floor *floor0_look (vorbis_dsp_state *vd,vorbis_info_mode *mi,
michael@0 348 vorbis_info_floor *i){
michael@0 349 int j;
michael@0 350 vorbis_info *vi=vd->vi;
michael@0 351 codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
michael@0 352 vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
michael@0 353 vorbis_look_floor0 *look=(vorbis_look_floor0 *)_ogg_calloc(1,sizeof(*look));
michael@0 354 look->m=info->order;
michael@0 355 look->n=ci->blocksizes[mi->blockflag]/2;
michael@0 356 look->ln=info->barkmap;
michael@0 357 look->vi=info;
michael@0 358
michael@0 359 /* the mapping from a linear scale to a smaller bark scale is
michael@0 360 straightforward. We do *not* make sure that the linear mapping
michael@0 361 does not skip bark-scale bins; the decoder simply skips them and
michael@0 362 the encoder may do what it wishes in filling them. They're
michael@0 363 necessary in some mapping combinations to keep the scale spacing
michael@0 364 accurate */
michael@0 365 look->linearmap=(int *)_ogg_malloc((look->n+1)*sizeof(*look->linearmap));
michael@0 366 for(j=0;j<look->n;j++){
michael@0 367
michael@0 368 int val=(look->ln*
michael@0 369 ((toBARK(info->rate/2*j/look->n)<<11)/toBARK(info->rate/2)))>>11;
michael@0 370
michael@0 371 if(val>=look->ln)val=look->ln-1; /* guard against the approximation */
michael@0 372 look->linearmap[j]=val;
michael@0 373 }
michael@0 374 look->linearmap[j]=-1;
michael@0 375
michael@0 376 look->lsp_look=(ogg_int32_t *)_ogg_malloc(look->ln*sizeof(*look->lsp_look));
michael@0 377 for(j=0;j<look->ln;j++)
michael@0 378 look->lsp_look[j]=vorbis_coslook2_i(0x10000*j/look->ln);
michael@0 379
michael@0 380 return look;
michael@0 381 }
michael@0 382
michael@0 383 static void *floor0_inverse1(vorbis_block *vb,vorbis_look_floor *i){
michael@0 384 vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
michael@0 385 vorbis_info_floor0 *info=look->vi;
michael@0 386 int j,k;
michael@0 387
michael@0 388 int ampraw=oggpack_read(&vb->opb,info->ampbits);
michael@0 389 if(ampraw>0){ /* also handles the -1 out of data case */
michael@0 390 long maxval=(1<<info->ampbits)-1;
michael@0 391 int amp=((ampraw*info->ampdB)<<4)/maxval;
michael@0 392 int booknum=oggpack_read(&vb->opb,_ilog(info->numbooks));
michael@0 393
michael@0 394 if(booknum!=-1 && booknum<info->numbooks){ /* be paranoid */
michael@0 395 codec_setup_info *ci=(codec_setup_info *)vb->vd->vi->codec_setup;
michael@0 396 codebook *b=ci->fullbooks+info->books[booknum];
michael@0 397 ogg_int32_t last=0;
michael@0 398 ogg_int32_t *lsp=(ogg_int32_t *)_vorbis_block_alloc(vb,sizeof(*lsp)*(look->m+1));
michael@0 399
michael@0 400 if(vorbis_book_decodev_set(b,lsp,&vb->opb,look->m,-24)==-1)goto eop;
michael@0 401 for(j=0;j<look->m;){
michael@0 402 for(k=0;j<look->m && k<b->dim;k++,j++)lsp[j]+=last;
michael@0 403 last=lsp[j-1];
michael@0 404 }
michael@0 405
michael@0 406 lsp[look->m]=amp;
michael@0 407 return(lsp);
michael@0 408 }
michael@0 409 }
michael@0 410 eop:
michael@0 411 return(NULL);
michael@0 412 }
michael@0 413
michael@0 414 static int floor0_inverse2(vorbis_block *vb,vorbis_look_floor *i,
michael@0 415 void *memo,ogg_int32_t *out){
michael@0 416 vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
michael@0 417 vorbis_info_floor0 *info=look->vi;
michael@0 418
michael@0 419 if(memo){
michael@0 420 ogg_int32_t *lsp=(ogg_int32_t *)memo;
michael@0 421 ogg_int32_t amp=lsp[look->m];
michael@0 422
michael@0 423 /* take the coefficients back to a spectral envelope curve */
michael@0 424 vorbis_lsp_to_curve(out,look->linearmap,look->n,look->ln,
michael@0 425 lsp,look->m,amp,info->ampdB,look->lsp_look);
michael@0 426 return(1);
michael@0 427 }
michael@0 428 memset(out,0,sizeof(*out)*look->n);
michael@0 429 return(0);
michael@0 430 }
michael@0 431
michael@0 432 /* export hooks */
michael@0 433 vorbis_func_floor floor0_exportbundle={
michael@0 434 &floor0_unpack,&floor0_look,&floor0_free_info,
michael@0 435 &floor0_free_look,&floor0_inverse1,&floor0_inverse2
michael@0 436 };
michael@0 437
michael@0 438

mercurial