blob: 8a09b611f509a89d4a48146a4bd71cfff806f4d6 [file] [log] [blame]
Gloria Wang37fe1582010-03-12 14:53:20 -08001/************************************************************************
2 * Copyright (C) 2010, The Android Open Source Project
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
14 * distribution.
15 * * Neither the name of the Android Open Source Project nor the
16 * names of its contributors may be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 ************************************************************************
Gloria Wang79130732010-02-08 14:41:04 -080031
32 function: floor backend 0 implementation
33
Gloria Wang37fe1582010-03-12 14:53:20 -080034 ************************************************************************/
Gloria Wang79130732010-02-08 14:41:04 -080035
36#include <stdlib.h>
37#include <string.h>
38#include <math.h>
39#include "ogg.h"
40#include "ivorbiscodec.h"
41#include "codec_internal.h"
42#include "codebook.h"
43#include "misc.h"
44#include "os.h"
45
46#define LSP_FRACBITS 14
47extern const ogg_int32_t FLOOR_fromdB_LOOKUP[];
48
49/*************** LSP decode ********************/
50
51#include "lsp_lookup.h"
52
53/* interpolated 1./sqrt(p) where .5 <= a < 1. (.100000... to .111111...) in
54 16.16 format
55 returns in m.8 format */
56
57static long ADJUST_SQRT2[2]={8192,5792};
58static inline ogg_int32_t vorbis_invsqlook_i(long a,long e){
59 long i=(a&0x7fff)>>(INVSQ_LOOKUP_I_SHIFT-1);
60 long d=a&INVSQ_LOOKUP_I_MASK; /* 0.10 */
61 long val=INVSQ_LOOKUP_I[i]- /* 1.16 */
62 ((INVSQ_LOOKUP_IDel[i]*d)>>INVSQ_LOOKUP_I_SHIFT); /* result 1.16 */
63 val*=ADJUST_SQRT2[e&1];
64 e=(e>>1)+21;
65 return(val>>e);
66}
67
68/* interpolated lookup based fromdB function, domain -140dB to 0dB only */
69/* a is in n.12 format */
70#ifdef _LOW_ACCURACY_
71static inline ogg_int32_t vorbis_fromdBlook_i(long a){
72 if(a>0) return 0x7fffffff;
73 if(a<(-140<<12)) return 0;
74 return FLOOR_fromdB_LOOKUP[((a+140)*467)>>20]<<9;
75}
76#else
77static inline ogg_int32_t vorbis_fromdBlook_i(long a){
78 if(a>0) return 0x7fffffff;
79 if(a<(-140<<12)) return 0;
80 return FLOOR_fromdB_LOOKUP[((a+(140<<12))*467)>>20];
81}
82#endif
83
84/* interpolated lookup based cos function, domain 0 to PI only */
85/* a is in 0.16 format, where 0==0, 2^^16-1==PI, return 0.14 */
86static inline ogg_int32_t vorbis_coslook_i(long a){
87 int i=a>>COS_LOOKUP_I_SHIFT;
88 int d=a&COS_LOOKUP_I_MASK;
89 return COS_LOOKUP_I[i]- ((d*(COS_LOOKUP_I[i]-COS_LOOKUP_I[i+1]))>>
90 COS_LOOKUP_I_SHIFT);
91}
92
93/* interpolated half-wave lookup based cos function */
94/* a is in 0.16 format, where 0==0, 2^^16==PI, return .LSP_FRACBITS */
95static inline ogg_int32_t vorbis_coslook2_i(long a){
96 int i=a>>COS_LOOKUP_I_SHIFT;
97 int d=a&COS_LOOKUP_I_MASK;
98 return ((COS_LOOKUP_I[i]<<COS_LOOKUP_I_SHIFT)-
99 d*(COS_LOOKUP_I[i]-COS_LOOKUP_I[i+1]))>>
100 (COS_LOOKUP_I_SHIFT-LSP_FRACBITS+14);
101}
102
103static const ogg_uint16_t barklook[54]={
104 0,51,102,154, 206,258,311,365,
105 420,477,535,594, 656,719,785,854,
106 926,1002,1082,1166, 1256,1352,1454,1564,
107 1683,1812,1953,2107, 2276,2463,2670,2900,
108 3155,3440,3756,4106, 4493,4919,5387,5901,
109 6466,7094,7798,8599, 9528,10623,11935,13524,
110 15453,17775,20517,23667, 27183,31004
111};
112
113/* used in init only; interpolate the long way */
114static inline ogg_int32_t toBARK(int n){
115 int i;
116 for(i=0;i<54;i++)
117 if(n>=barklook[i] && n<barklook[i+1])break;
118
119 if(i==54){
120 return 54<<14;
121 }else{
122 return (i<<14)+(((n-barklook[i])*
123 ((1UL<<31)/(barklook[i+1]-barklook[i])))>>17);
124 }
125}
126
127static const unsigned char MLOOP_1[64]={
128 0,10,11,11, 12,12,12,12, 13,13,13,13, 13,13,13,13,
129 14,14,14,14, 14,14,14,14, 14,14,14,14, 14,14,14,14,
130 15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15,
131 15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15,
132};
133
134static const unsigned char MLOOP_2[64]={
135 0,4,5,5, 6,6,6,6, 7,7,7,7, 7,7,7,7,
136 8,8,8,8, 8,8,8,8, 8,8,8,8, 8,8,8,8,
137 9,9,9,9, 9,9,9,9, 9,9,9,9, 9,9,9,9,
138 9,9,9,9, 9,9,9,9, 9,9,9,9, 9,9,9,9,
139};
140
141static const unsigned char MLOOP_3[8]={0,1,2,2,3,3,3,3};
142
143void vorbis_lsp_to_curve(ogg_int32_t *curve,int n,int ln,
144 ogg_int32_t *lsp,int m,
145 ogg_int32_t amp,
146 ogg_int32_t ampoffset,
147 ogg_int32_t nyq){
148
149 /* 0 <= m < 256 */
150
151 /* set up for using all int later */
152 int i;
153 int ampoffseti=ampoffset*4096;
154 int ampi=amp;
155 ogg_int32_t *ilsp=(ogg_int32_t *)alloca(m*sizeof(*ilsp));
156
157 ogg_uint32_t inyq= (1UL<<31) / toBARK(nyq);
158 ogg_uint32_t imap= (1UL<<31) / ln;
159 ogg_uint32_t tBnyq1 = toBARK(nyq)<<1;
160
161 /* Besenham for frequency scale to avoid a division */
162 int f=0;
163 int fdx=n;
164 int fbase=nyq/fdx;
165 int ferr=0;
166 int fdy=nyq-fbase*fdx;
167 int map=0;
168
169#ifdef _LOW_ACCURACY_
170 ogg_uint32_t nextbark=((tBnyq1<<11)/ln)>>12;
171#else
172 ogg_uint32_t nextbark=MULT31(imap>>1,tBnyq1);
173#endif
174 int nextf=barklook[nextbark>>14]+(((nextbark&0x3fff)*
175 (barklook[(nextbark>>14)+1]-barklook[nextbark>>14]))>>14);
176
177 /* lsp is in 8.24, range 0 to PI; coslook wants it in .16 0 to 1*/
178 for(i=0;i<m;i++){
179#ifndef _LOW_ACCURACY_
180 ogg_int32_t val=MULT32(lsp[i],0x517cc2);
181#else
182 ogg_int32_t val=((lsp[i]>>10)*0x517d)>>14;
183#endif
184
185 /* safeguard against a malicious stream */
186 if(val<0 || (val>>COS_LOOKUP_I_SHIFT)>=COS_LOOKUP_I_SZ){
187 memset(curve,0,sizeof(*curve)*n);
188 return;
189 }
190
191 ilsp[i]=vorbis_coslook_i(val);
192 }
193
194 i=0;
195 while(i<n){
196 int j;
197 ogg_uint32_t pi=46341; /* 2**-.5 in 0.16 */
198 ogg_uint32_t qi=46341;
199 ogg_int32_t qexp=0,shift;
200 ogg_int32_t wi;
201
202 wi=vorbis_coslook2_i((map*imap)>>15);
203
204
205#ifdef _V_LSP_MATH_ASM
206 lsp_loop_asm(&qi,&pi,&qexp,ilsp,wi,m);
207
208 pi=((pi*pi)>>16);
209 qi=((qi*qi)>>16);
210
211 if(m&1){
212 qexp= qexp*2-28*((m+1)>>1)+m;
213 pi*=(1<<14)-((wi*wi)>>14);
214 qi+=pi>>14;
215 }else{
216 qexp= qexp*2-13*m;
217
218 pi*=(1<<14)-wi;
219 qi*=(1<<14)+wi;
220
221 qi=(qi+pi)>>14;
222 }
223
224 if(qi&0xffff0000){ /* checks for 1.xxxxxxxxxxxxxxxx */
225 qi>>=1; qexp++;
226 }else
227 lsp_norm_asm(&qi,&qexp);
228
229#else
230
231 qi*=labs(ilsp[0]-wi);
232 pi*=labs(ilsp[1]-wi);
233
234 for(j=3;j<m;j+=2){
235 if(!(shift=MLOOP_1[(pi|qi)>>25]))
236 if(!(shift=MLOOP_2[(pi|qi)>>19]))
237 shift=MLOOP_3[(pi|qi)>>16];
238
239 qi=(qi>>shift)*labs(ilsp[j-1]-wi);
240 pi=(pi>>shift)*labs(ilsp[j]-wi);
241 qexp+=shift;
242 }
243 if(!(shift=MLOOP_1[(pi|qi)>>25]))
244 if(!(shift=MLOOP_2[(pi|qi)>>19]))
245 shift=MLOOP_3[(pi|qi)>>16];
246
247 /* pi,qi normalized collectively, both tracked using qexp */
248
249 if(m&1){
250 /* odd order filter; slightly assymetric */
251 /* the last coefficient */
252 qi=(qi>>shift)*labs(ilsp[j-1]-wi);
253 pi=(pi>>shift)<<14;
254 qexp+=shift;
255
256 if(!(shift=MLOOP_1[(pi|qi)>>25]))
257 if(!(shift=MLOOP_2[(pi|qi)>>19]))
258 shift=MLOOP_3[(pi|qi)>>16];
259
260 pi>>=shift;
261 qi>>=shift;
262 qexp+=shift-14*((m+1)>>1);
263
264 pi=((pi*pi)>>16);
265 qi=((qi*qi)>>16);
266 qexp=qexp*2+m;
267
268 pi*=(1<<14)-((wi*wi)>>14);
269 qi+=pi>>14;
270
271 }else{
272 /* even order filter; still symmetric */
273
274 /* p*=p(1-w), q*=q(1+w), let normalization drift because it isn't
275 worth tracking step by step */
276
277 pi>>=shift;
278 qi>>=shift;
279 qexp+=shift-7*m;
280
281 pi=((pi*pi)>>16);
282 qi=((qi*qi)>>16);
283 qexp=qexp*2+m;
284
285 pi*=(1<<14)-wi;
286 qi*=(1<<14)+wi;
287 qi=(qi+pi)>>14;
288
289 }
290
291
292 /* we've let the normalization drift because it wasn't important;
293 however, for the lookup, things must be normalized again. We
294 need at most one right shift or a number of left shifts */
295
296 if(qi&0xffff0000){ /* checks for 1.xxxxxxxxxxxxxxxx */
297 qi>>=1; qexp++;
298 }else
299 while(qi && !(qi&0x8000)){ /* checks for 0.0xxxxxxxxxxxxxxx or less*/
300 qi<<=1; qexp--;
301 }
302
303#endif
304
305 amp=vorbis_fromdBlook_i(ampi* /* n.4 */
306 vorbis_invsqlook_i(qi,qexp)-
307 /* m.8, m+n<=8 */
308 ampoffseti); /* 8.12[0] */
309
310#ifdef _LOW_ACCURACY_
311 amp>>=9;
312#endif
313 curve[i]= MULT31_SHIFT15(curve[i],amp);
314
315 while(++i<n){
316
317 /* line plot to get new f */
318 ferr+=fdy;
319 if(ferr>=fdx){
320 ferr-=fdx;
321 f++;
322 }
323 f+=fbase;
324
325 if(f>=nextf)break;
326
327 curve[i]= MULT31_SHIFT15(curve[i],amp);
328 }
329
330 while(1){
331 map++;
332
333 if(map+1<ln){
334
335#ifdef _LOW_ACCURACY_
336 nextbark=((tBnyq1<<11)/ln*(map+1))>>12;
337#else
338 nextbark=MULT31((map+1)*(imap>>1),tBnyq1);
339#endif
340 nextf=barklook[nextbark>>14]+
341 (((nextbark&0x3fff)*
342 (barklook[(nextbark>>14)+1]-barklook[nextbark>>14]))>>14);
343 if(f<=nextf)break;
344
345 }else{
346 nextf=9999999;
347 break;
348 }
349 }
350 if(map>=ln){
351 map=ln-1; /* guard against the approximation */
352 nextf=9999999;
353 }
354 }
355}
356
357/*************** vorbis decode glue ************/
358
359void floor0_free_info(vorbis_info_floor *i){
360 vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
361 if(info)_ogg_free(info);
362}
363
364vorbis_info_floor *floor0_info_unpack (vorbis_info *vi,oggpack_buffer *opb){
365 codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
366 int j;
367
368 vorbis_info_floor0 *info=(vorbis_info_floor0 *)_ogg_malloc(sizeof(*info));
369 info->order=oggpack_read(opb,8);
370 info->rate=oggpack_read(opb,16);
371 info->barkmap=oggpack_read(opb,16);
372 info->ampbits=oggpack_read(opb,6);
373 info->ampdB=oggpack_read(opb,8);
374 info->numbooks=oggpack_read(opb,4)+1;
375
376 if(info->order<1)goto err_out;
377 if(info->rate<1)goto err_out;
378 if(info->barkmap<1)goto err_out;
379
380 for(j=0;j<info->numbooks;j++){
381 info->books[j]=(char)oggpack_read(opb,8);
382 if(info->books[j]>=ci->books)goto err_out;
383 }
384
385 if(oggpack_eop(opb))goto err_out;
386 return(info);
387
388 err_out:
389 floor0_free_info(info);
390 return(NULL);
391}
392
393int floor0_memosize(vorbis_info_floor *i){
394 vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
395 return info->order+1;
396}
397
398ogg_int32_t *floor0_inverse1(vorbis_dsp_state *vd,vorbis_info_floor *i,
399 ogg_int32_t *lsp){
400 vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
401 int j,k;
402
403 int ampraw=oggpack_read(&vd->opb,info->ampbits);
404 if(ampraw>0){ /* also handles the -1 out of data case */
405 long maxval=(1<<info->ampbits)-1;
406 int amp=((ampraw*info->ampdB)<<4)/maxval;
407 int booknum=oggpack_read(&vd->opb,_ilog(info->numbooks));
408
409 if(booknum!=-1 && booknum<info->numbooks){ /* be paranoid */
410 codec_setup_info *ci=(codec_setup_info *)vd->vi->codec_setup;
411 codebook *b=ci->book_param+info->books[booknum];
412 ogg_int32_t last=0;
413
414 for(j=0;j<info->order;j+=b->dim)
415 if(vorbis_book_decodev_set(b,lsp+j,&vd->opb,b->dim,-24)==-1)goto eop;
416 for(j=0;j<info->order;){
417 for(k=0;k<b->dim;k++,j++)lsp[j]+=last;
418 last=lsp[j-1];
419 }
420
421 lsp[info->order]=amp;
422 return(lsp);
423 }
424 }
425 eop:
426 return(NULL);
427}
428
429int floor0_inverse2(vorbis_dsp_state *vd,vorbis_info_floor *i,
430 ogg_int32_t *lsp,ogg_int32_t *out){
431 vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
432 codec_setup_info *ci=(codec_setup_info *)vd->vi->codec_setup;
433
434 if(lsp){
435 ogg_int32_t amp=lsp[info->order];
436
437 /* take the coefficients back to a spectral envelope curve */
438 vorbis_lsp_to_curve(out,ci->blocksizes[vd->W]/2,info->barkmap,
439 lsp,info->order,amp,info->ampdB,
440 info->rate>>1);
441 return(1);
442 }
443 memset(out,0,sizeof(*out)*ci->blocksizes[vd->W]/2);
444 return(0);
445}
446