summaryrefslogtreecommitdiff
path: root/core/multimedia/opieplayer/vorbis/tremor/floor0.c
Unidiff
Diffstat (limited to 'core/multimedia/opieplayer/vorbis/tremor/floor0.c') (more/less context) (ignore whitespace changes)
-rw-r--r--core/multimedia/opieplayer/vorbis/tremor/floor0.c436
1 files changed, 436 insertions, 0 deletions
diff --git a/core/multimedia/opieplayer/vorbis/tremor/floor0.c b/core/multimedia/opieplayer/vorbis/tremor/floor0.c
new file mode 100644
index 0000000..3ed57a5
--- a/dev/null
+++ b/core/multimedia/opieplayer/vorbis/tremor/floor0.c
@@ -0,0 +1,436 @@
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.h"
22#include "ivorbiscodec.h"
23#include "codec_internal.h"
24#include "registry.h"
25#include "codebook.h"
26#include "misc.h"
27#include "os.h"
28
29#define LSP_FRACBITS 14
30
31typedef 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
50static long ADJUST_SQRT2[2]={8192,5792};
51static inline ogg_int32_t vorbis_invsqlook_i(long a,long e){
52 long i=(a&0x7fff)>>(INVSQ_LOOKUP_I_SHIFT-1);
53 long d=a&INVSQ_LOOKUP_I_MASK; /* 0.10 */
54 long val=INVSQ_LOOKUP_I[i]- /* 1.16 */
55 ((INVSQ_LOOKUP_IDel[i]*d)>>INVSQ_LOOKUP_I_SHIFT); /* result 1.16 */
56 val*=ADJUST_SQRT2[e&1];
57 e=(e>>1)+21;
58 return(val>>e);
59}
60
61/* interpolated lookup based fromdB function, domain -140dB to 0dB only */
62/* a is in n.12 format */
63static inline ogg_int32_t vorbis_fromdBlook_i(long a){
64 int i=(-a)>>(12-FROMdB2_SHIFT);
65 if(i<0) return 0x7fffffff;
66 if(i>=(FROMdB_LOOKUP_SZ<<FROMdB_SHIFT))return 0;
67
68 return FROMdB_LOOKUP[i>>FROMdB_SHIFT] * FROMdB2_LOOKUP[i&FROMdB2_MASK];
69}
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 */
73static inline ogg_int32_t vorbis_coslook_i(long a){
74 int i=a>>COS_LOOKUP_I_SHIFT;
75 int d=a&COS_LOOKUP_I_MASK;
76 return COS_LOOKUP_I[i]- ((d*(COS_LOOKUP_I[i]-COS_LOOKUP_I[i+1]))>>
77 COS_LOOKUP_I_SHIFT);
78}
79
80/* interpolated lookup based cos function */
81/* a is in 0.16 format, where 0==0, 2^^16==PI, return .LSP_FRACBITS */
82static inline ogg_int32_t vorbis_coslook2_i(long a){
83 a=a&0x1ffff;
84
85 if(a>0x10000)a=0x20000-a;
86 {
87 int i=a>>COS_LOOKUP_I_SHIFT;
88 int d=a&COS_LOOKUP_I_MASK;
89 a=((COS_LOOKUP_I[i]<<COS_LOOKUP_I_SHIFT)-
90 d*(COS_LOOKUP_I[i]-COS_LOOKUP_I[i+1]))>>
91 (COS_LOOKUP_I_SHIFT-LSP_FRACBITS+14);
92 }
93
94 return(a);
95}
96
97static 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 */
105static inline ogg_int32_t toBARK(int n){
106 int i;
107 for(i=0;i<27;i++)
108 if(n>=barklook[i] && n<barklook[i+1])break;
109
110 if(i==27){
111 return 27<<15;
112 }else{
113 int gap=barklook[i+1]-barklook[i];
114 int del=n-barklook[i];
115
116 return((i<<15)+((del<<15)/gap));
117 }
118}
119
120static 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
127static 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
134static const unsigned char MLOOP_3[8]={0,1,2,2,3,3,3,3};
135
136void 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 ogg_int32_t *icos){
141
142 /* 0 <= m < 256 */
143
144 /* set up for using all int later */
145 int i;
146 int ampoffseti=ampoffset*4096;
147 int ampi=amp;
148 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 for(i=0;i<m;i++){
151#ifndef _LOW_ACCURACY_
152 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 if(val<0 || (val>>COS_LOOKUP_I_SHIFT)>=COS_LOOKUP_I_SZ){
159 memset(curve,0,sizeof(*curve)*n);
160 return;
161 }
162
163 ilsp[i]=vorbis_coslook_i(val);
164 }
165
166 i=0;
167 while(i<n){
168 int j,k=map[i];
169 ogg_uint32_t pi=46341; /* 2**-.5 in 0.16 */
170 ogg_uint32_t qi=46341;
171 ogg_int32_t qexp=0,shift;
172 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 qi*=labs(ilsp[0]-wi);
201 pi*=labs(ilsp[1]-wi);
202
203 for(j=3;j<m;j+=2){
204 if(!(shift=MLOOP_1[(pi|qi)>>25]))
205 if(!(shift=MLOOP_2[(pi|qi)>>19]))
206 shift=MLOOP_3[(pi|qi)>>16];
207 qi=(qi>>shift)*labs(ilsp[j-1]-wi);
208 pi=(pi>>shift)*labs(ilsp[j]-wi);
209 qexp+=shift;
210 }
211 if(!(shift=MLOOP_1[(pi|qi)>>25]))
212 if(!(shift=MLOOP_2[(pi|qi)>>19]))
213 shift=MLOOP_3[(pi|qi)>>16];
214
215 /* pi,qi normalized collectively, both tracked using qexp */
216
217 if(m&1){
218 /* odd order filter; slightly assymetric */
219 /* the last coefficient */
220 qi=(qi>>shift)*labs(ilsp[j-1]-wi);
221 pi=(pi>>shift)<<14;
222 qexp+=shift;
223
224 if(!(shift=MLOOP_1[(pi|qi)>>25]))
225 if(!(shift=MLOOP_2[(pi|qi)>>19]))
226 shift=MLOOP_3[(pi|qi)>>16];
227
228 pi>>=shift;
229 qi>>=shift;
230 qexp+=shift-14*((m+1)>>1);
231
232 pi=((pi*pi)>>16);
233 qi=((qi*qi)>>16);
234 qexp=qexp*2+m;
235
236 pi*=(1<<14)-((wi*wi)>>14);
237 qi+=pi>>14;
238
239 }else{
240 /* even order filter; still symmetric */
241
242 /* p*=p(1-w), q*=q(1+w), let normalization drift because it isn't
243 worth tracking step by step */
244
245 pi>>=shift;
246 qi>>=shift;
247 qexp+=shift-7*m;
248
249 pi=((pi*pi)>>16);
250 qi=((qi*qi)>>16);
251 qexp=qexp*2+m;
252
253 pi*=(1<<14)-wi;
254 qi*=(1<<14)+wi;
255 qi=(qi+pi)>>14;
256
257 }
258
259
260 /* we've let the normalization drift because it wasn't important;
261 however, for the lookup, things must be normalized again. We
262 need at most one right shift or a number of left shifts */
263
264 if(qi&0xffff0000){ /* checks for 1.xxxxxxxxxxxxxxxx */
265 qi>>=1; qexp++;
266 }else
267 while(qi && !(qi&0x8000)){ /* checks for 0.0xxxxxxxxxxxxxxx or less*/
268 qi<<=1; qexp--;
269 }
270
271#endif
272
273 amp=vorbis_fromdBlook_i(ampi* /* n.4 */
274 vorbis_invsqlook_i(qi,qexp)-
275 /* m.8, m+n<=8 */
276 ampoffseti); /* 8.12[0] */
277
278#ifdef _LOW_ACCURACY_
279 amp>>=9;
280#endif
281 curve[i]= MULT31_SHIFT15(curve[i],amp);
282 while(map[++i]==k) curve[i]= MULT31_SHIFT15(curve[i],amp);
283 }
284}
285
286/*************** vorbis decode glue ************/
287
288static void floor0_free_info(vorbis_info_floor *i){
289 vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
290 if(info){
291 memset(info,0,sizeof(*info));
292 _ogg_free(info);
293 }
294}
295
296static void floor0_free_look(vorbis_look_floor *i){
297 vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
298 if(look){
299
300 if(look->linearmap)_ogg_free(look->linearmap);
301 if(look->lsp_look)_ogg_free(look->lsp_look);
302 memset(look,0,sizeof(*look));
303 _ogg_free(look);
304 }
305}
306
307static vorbis_info_floor *floor0_unpack (vorbis_info *vi,oggpack_buffer *opb){
308 codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
309 int j;
310
311 vorbis_info_floor0 *info=(vorbis_info_floor0 *)_ogg_malloc(sizeof(*info));
312 info->order=oggpack_read(opb,8);
313 info->rate=oggpack_read(opb,16);
314 info->barkmap=oggpack_read(opb,16);
315 info->ampbits=oggpack_read(opb,6);
316 info->ampdB=oggpack_read(opb,8);
317 info->numbooks=oggpack_read(opb,4)+1;
318
319 if(info->order<1)goto err_out;
320 if(info->rate<1)goto err_out;
321 if(info->barkmap<1)goto err_out;
322 if(info->numbooks<1)goto err_out;
323
324 for(j=0;j<info->numbooks;j++){
325 info->books[j]=oggpack_read(opb,8);
326 if(info->books[j]<0 || info->books[j]>=ci->books)goto err_out;
327 }
328 return(info);
329
330 err_out:
331 floor0_free_info(info);
332 return(NULL);
333}
334
335/* initialize Bark scale and normalization lookups. We could do this
336 with static tables, but Vorbis allows a number of possible
337 combinations, so it's best to do it computationally.
338
339 The below is authoritative in terms of defining scale mapping.
340 Note that the scale depends on the sampling rate as well as the
341 linear block and mapping sizes */
342
343static vorbis_look_floor *floor0_look (vorbis_dsp_state *vd,vorbis_info_mode *mi,
344 vorbis_info_floor *i){
345 int j;
346 ogg_int32_t scale;
347 vorbis_info *vi=vd->vi;
348 codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
349 vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
350 vorbis_look_floor0 *look=(vorbis_look_floor0 *)_ogg_calloc(1,sizeof(*look));
351 look->m=info->order;
352 look->n=ci->blocksizes[mi->blockflag]/2;
353 look->ln=info->barkmap;
354 look->vi=info;
355
356 /* the mapping from a linear scale to a smaller bark scale is
357 straightforward. We do *not* make sure that the linear mapping
358 does not skip bark-scale bins; the decoder simply skips them and
359 the encoder may do what it wishes in filling them. They're
360 necessary in some mapping combinations to keep the scale spacing
361 accurate */
362 look->linearmap=(int *)_ogg_malloc((look->n+1)*sizeof(*look->linearmap));
363 for(j=0;j<look->n;j++){
364
365 int val=(look->ln*
366 ((toBARK(info->rate/2*j/look->n)<<11)/toBARK(info->rate/2)))>>11;
367
368 if(val>=look->ln)val=look->ln-1; /* guard against the approximation */
369 look->linearmap[j]=val;
370 }
371 look->linearmap[j]=-1;
372
373 look->lsp_look=(ogg_int32_t *)_ogg_malloc(look->ln*sizeof(*look->lsp_look));
374 for(j=0;j<look->ln;j++)
375 look->lsp_look[j]=vorbis_coslook2_i(0x10000*j/look->ln);
376
377 return look;
378}
379
380static void *floor0_inverse1(vorbis_block *vb,vorbis_look_floor *i){
381 vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
382 vorbis_info_floor0 *info=look->vi;
383 int j,k;
384
385 int ampraw=oggpack_read(&vb->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(&vb->opb,_ilog(info->numbooks));
390
391 if(booknum!=-1 && booknum<info->numbooks){ /* be paranoid */
392 codec_setup_info *ci=(codec_setup_info *)vb->vd->vi->codec_setup;
393 codebook *b=ci->fullbooks+info->books[booknum];
394 ogg_int32_t last=0;
395 ogg_int32_t *lsp=(ogg_int32_t *)_vorbis_block_alloc(vb,sizeof(*lsp)*(look->m+1));
396
397 for(j=0;j<look->m;j+=b->dim)
398 if(vorbis_book_decodev_set(b,lsp+j,&vb->opb,b->dim,-24)==-1)goto eop;
399 for(j=0;j<look->m;){
400 for(k=0;k<b->dim;k++,j++)lsp[j]+=last;
401 last=lsp[j-1];
402 }
403
404 lsp[look->m]=amp;
405 return(lsp);
406 }
407 }
408 eop:
409 return(NULL);
410}
411
412static int floor0_inverse2(vorbis_block *vb,vorbis_look_floor *i,
413 void *memo,ogg_int32_t *out){
414 vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
415 vorbis_info_floor0 *info=look->vi;
416
417 if(memo){
418 ogg_int32_t *lsp=(ogg_int32_t *)memo;
419 ogg_int32_t amp=lsp[look->m];
420
421 /* take the coefficients back to a spectral envelope curve */
422 vorbis_lsp_to_curve(out,look->linearmap,look->n,look->ln,
423 lsp,look->m,amp,info->ampdB,look->lsp_look);
424 return(1);
425 }
426 memset(out,0,sizeof(*out)*look->n);
427 return(0);
428}
429
430/* export hooks */
431vorbis_func_floor floor0_exportbundle={
432 &floor0_unpack,&floor0_look,&floor0_free_info,
433 &floor0_free_look,&floor0_inverse1,&floor0_inverse2
434};
435
436