Thu, 22 Jan 2015 13:21:57 +0100
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 |