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