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