1 /********************************************************************
3 * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. *
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. *
9 * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 *
10 * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ *
12 ********************************************************************
14 function: floor backend 0 implementation
16 ********************************************************************/
22 #include "ivorbiscodec.h"
23 #include "codec_internal.h"
29 #define LSP_FRACBITS 14
37 vorbis_info_floor0
*vi
;
38 ogg_int32_t
*lsp_look
;
42 /*************** LSP decode ********************/
44 #include "lsp_lookup.h"
46 /* interpolated 1./sqrt(p) where .5 <= a < 1. (.100000... to .111111...) in
48 returns in m.8 format */
50 static long ADJUST_SQRT2
[2]={8192,5792};
51 static 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];
61 /* interpolated lookup based fromdB function, domain -140dB to 0dB only */
62 /* a is in n.12 format */
63 static 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;
68 return FROMdB_LOOKUP
[i
>>FROMdB_SHIFT
] * FROMdB2_LOOKUP
[i
&FROMdB2_MASK
];
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 static 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]))>>
80 /* interpolated lookup based cos function */
81 /* a is in 0.16 format, where 0==0, 2^^16==PI, return .LSP_FRACBITS */
82 static inline ogg_int32_t
vorbis_coslook2_i(long a
){
85 if(a
>0x10000)a
=0x20000-a
;
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);
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
104 /* used in init only; interpolate the long way */
105 static inline ogg_int32_t
toBARK(int n
){
108 if(n
>=barklook
[i
] && n
<barklook
[i
+1])break;
113 int gap
=barklook
[i
+1]-barklook
[i
];
114 int del
=n
-barklook
[i
];
116 return((i
<<15)+((del
<<15)/gap
));
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,
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,
134 static const unsigned char MLOOP_3
[8]={0,1,2,2,3,3,3,3};
136 void vorbis_lsp_to_curve(ogg_int32_t
*curve
,int *map
,int n
,int ln
,
137 ogg_int32_t
*lsp
,int m
,
139 ogg_int32_t ampoffset
,
144 /* set up for using all int later */
146 int ampoffseti
=ampoffset
*4096;
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*/
151 #ifndef _LOW_ACCURACY_
152 ogg_int32_t val
=MULT32(lsp
[i
],0x517cc2);
154 ogg_int32_t val
=((lsp
[i
]>>10)*0x517d)>>14;
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
);
163 ilsp
[i
]=vorbis_coslook_i(val
);
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
];
174 #ifdef _V_LSP_MATH_ASM
175 lsp_loop_asm(&qi
,&pi
,&qexp
,ilsp
,wi
,m
);
181 qexp
= qexp
*2-28*((m
+1)>>1)+m
;
182 pi
*=(1<<14)-((wi
*wi
)>>14);
193 if(qi
&0xffff0000){ /* checks for 1.xxxxxxxxxxxxxxxx */
196 lsp_norm_asm(&qi
,&qexp
);
200 qi
*=labs(ilsp
[0]-wi
);
201 pi
*=labs(ilsp
[1]-wi
);
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
);
211 if(!(shift
=MLOOP_1
[(pi
|qi
)>>25]))
212 if(!(shift
=MLOOP_2
[(pi
|qi
)>>19]))
213 shift
=MLOOP_3
[(pi
|qi
)>>16];
215 /* pi,qi normalized collectively, both tracked using qexp */
218 /* odd order filter; slightly assymetric */
219 /* the last coefficient */
220 qi
=(qi
>>shift
)*labs(ilsp
[j
-1]-wi
);
224 if(!(shift
=MLOOP_1
[(pi
|qi
)>>25]))
225 if(!(shift
=MLOOP_2
[(pi
|qi
)>>19]))
226 shift
=MLOOP_3
[(pi
|qi
)>>16];
230 qexp
+=shift
-14*((m
+1)>>1);
236 pi
*=(1<<14)-((wi
*wi
)>>14);
240 /* even order filter; still symmetric */
242 /* p*=p(1-w), q*=q(1+w), let normalization drift because it isn't
243 worth tracking step by step */
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 */
264 if(qi
&0xffff0000){ /* checks for 1.xxxxxxxxxxxxxxxx */
267 while(qi
&& !(qi
&0x8000)){ /* checks for 0.0xxxxxxxxxxxxxxx or less*/
273 amp
=vorbis_fromdBlook_i(ampi
* /* n.4 */
274 vorbis_invsqlook_i(qi
,qexp
)-
276 ampoffseti
); /* 8.12[0] */
278 #ifdef _LOW_ACCURACY_
281 curve
[i
]= MULT31_SHIFT15(curve
[i
],amp
);
282 while(map
[++i
]==k
) curve
[i
]= MULT31_SHIFT15(curve
[i
],amp
);
286 /*************** vorbis decode glue ************/
288 static void floor0_free_info(vorbis_info_floor
*i
){
289 vorbis_info_floor0
*info
=(vorbis_info_floor0
*)i
;
291 memset(info
,0,sizeof(*info
));
296 static void floor0_free_look(vorbis_look_floor
*i
){
297 vorbis_look_floor0
*look
=(vorbis_look_floor0
*)i
;
300 if(look
->linearmap
)_ogg_free(look
->linearmap
);
301 if(look
->lsp_look
)_ogg_free(look
->lsp_look
);
302 memset(look
,0,sizeof(*look
));
307 static vorbis_info_floor
*floor0_unpack (vorbis_info
*vi
,oggpack_buffer
*opb
){
308 codec_setup_info
*ci
=(codec_setup_info
*)vi
->codec_setup
;
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;
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
;
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
;
331 floor0_free_info(info
);
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.
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 */
343 static vorbis_look_floor
*floor0_look (vorbis_dsp_state
*vd
,vorbis_info_mode
*mi
,
344 vorbis_info_floor
*i
){
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
));
352 look
->n
=ci
->blocksizes
[mi
->blockflag
]/2;
353 look
->ln
=info
->barkmap
;
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
362 look
->linearmap
=(int *)_ogg_malloc((look
->n
+1)*sizeof(*look
->linearmap
));
363 for(j
=0;j
<look
->n
;j
++){
366 ((toBARK(info
->rate
/2*j
/look
->n
)<<11)/toBARK(info
->rate
/2)))>>11;
368 if(val
>=look
->ln
)val
=look
->ln
-1; /* guard against the approximation */
369 look
->linearmap
[j
]=val
;
371 look
->linearmap
[j
]=-1;
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
);
380 static 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
;
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
));
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
];
395 ogg_int32_t
*lsp
=(ogg_int32_t
*)_vorbis_block_alloc(vb
,sizeof(*lsp
)*(look
->m
+1));
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
;
400 for(k
=0;k
<b
->dim
;k
++,j
++)lsp
[j
]+=last
;
412 static 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
;
418 ogg_int32_t
*lsp
=(ogg_int32_t
*)memo
;
419 ogg_int32_t amp
=lsp
[look
->m
];
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
);
426 memset(out
,0,sizeof(*out
)*look
->n
);
431 vorbis_func_floor floor0_exportbundle
={
432 &floor0_unpack
,&floor0_look
,&floor0_free_info
,
433 &floor0_free_look
,&floor0_inverse1
,&floor0_inverse2