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"
30 #define LSP_FRACBITS 14
38 vorbis_info_floor0
*vi
;
39 ogg_int32_t
*lsp_look
;
43 /*************** LSP decode ********************/
45 #include "lsp_lookup.h"
47 /* interpolated 1./sqrt(p) where .5 <= a < 1. (.100000... to .111111...) in
49 returns in m.8 format */
51 static long ADJUST_SQRT2
[2]={8192,5792};
52 static inline ogg_int32_t
vorbis_invsqlook_i(long a
,long e
){
53 long i
=(a
&0x7fff)>>(INVSQ_LOOKUP_I_SHIFT
-1);
54 long d
=a
&INVSQ_LOOKUP_I_MASK
; /* 0.10 */
55 long val
=INVSQ_LOOKUP_I
[i
]- /* 1.16 */
56 ((INVSQ_LOOKUP_IDel
[i
]*d
)>>INVSQ_LOOKUP_I_SHIFT
); /* result 1.16 */
57 val
*=ADJUST_SQRT2
[e
&1];
62 /* interpolated lookup based fromdB function, domain -140dB to 0dB only */
63 /* a is in n.12 format */
64 static inline ogg_int32_t
vorbis_fromdBlook_i(long a
){
65 int i
=(-a
)>>(12-FROMdB2_SHIFT
);
66 if(i
<0) return 0x7fffffff;
67 if(i
>=(FROMdB_LOOKUP_SZ
<<FROMdB_SHIFT
))return 0;
69 return FROMdB_LOOKUP
[i
>>FROMdB_SHIFT
] * FROMdB2_LOOKUP
[i
&FROMdB2_MASK
];
72 /* interpolated lookup based cos function, domain 0 to PI only */
73 /* a is in 0.16 format, where 0==0, 2^^16-1==PI, return 0.14 */
74 static inline ogg_int32_t
vorbis_coslook_i(long a
){
75 int i
=a
>>COS_LOOKUP_I_SHIFT
;
76 int d
=a
&COS_LOOKUP_I_MASK
;
77 return COS_LOOKUP_I
[i
]- ((d
*(COS_LOOKUP_I
[i
]-COS_LOOKUP_I
[i
+1]))>>
81 /* interpolated lookup based cos function */
82 /* a is in 0.16 format, where 0==0, 2^^16==PI, return .LSP_FRACBITS */
83 static inline ogg_int32_t
vorbis_coslook2_i(long a
){
86 if(a
>0x10000)a
=0x20000-a
;
88 int i
=a
>>COS_LOOKUP_I_SHIFT
;
89 int d
=a
&COS_LOOKUP_I_MASK
;
90 a
=((COS_LOOKUP_I
[i
]<<COS_LOOKUP_I_SHIFT
)-
91 d
*(COS_LOOKUP_I
[i
]-COS_LOOKUP_I
[i
+1]))>>
92 (COS_LOOKUP_I_SHIFT
-LSP_FRACBITS
+14);
98 static const int barklook
[28]={
99 0,100,200,301, 405,516,635,766,
100 912,1077,1263,1476, 1720,2003,2333,2721,
101 3184,3742,4428,5285, 6376,7791,9662,12181,
102 15624,20397,27087,36554
105 /* used in init only; interpolate the long way */
106 static inline ogg_int32_t
toBARK(int n
){
109 if(n
>=barklook
[i
] && n
<barklook
[i
+1])break;
114 int gap
=barklook
[i
+1]-barklook
[i
];
115 int del
=n
-barklook
[i
];
117 return((i
<<15)+((del
<<15)/gap
));
121 static const unsigned char MLOOP_1
[64]={
122 0,10,11,11, 12,12,12,12, 13,13,13,13, 13,13,13,13,
123 14,14,14,14, 14,14,14,14, 14,14,14,14, 14,14,14,14,
124 15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15,
125 15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15,
128 static const unsigned char MLOOP_2
[64]={
129 0,4,5,5, 6,6,6,6, 7,7,7,7, 7,7,7,7,
130 8,8,8,8, 8,8,8,8, 8,8,8,8, 8,8,8,8,
131 9,9,9,9, 9,9,9,9, 9,9,9,9, 9,9,9,9,
132 9,9,9,9, 9,9,9,9, 9,9,9,9, 9,9,9,9,
135 static const unsigned char MLOOP_3
[8]={0,1,2,2,3,3,3,3};
137 void vorbis_lsp_to_curve(ogg_int32_t
*curve
,int *map
,int n
,int ln
,
138 ogg_int32_t
*lsp
,int m
,
140 ogg_int32_t ampoffset
,
145 /* set up for using all int later */
147 int ampoffseti
=ampoffset
*4096;
149 ogg_int32_t
*ilsp
=(ogg_int32_t
*)alloca(m
*sizeof(*ilsp
));
150 /* lsp is in 8.24, range 0 to PI; coslook wants it in .16 0 to 1*/
152 #ifndef _LOW_ACCURACY_
153 ogg_int32_t val
=MULT32(lsp
[i
],0x517cc2);
155 ogg_int32_t val
=((lsp
[i
]>>10)*0x517d)>>14;
158 /* safeguard against a malicious stream */
159 if(val
<0 || (val
>>COS_LOOKUP_I_SHIFT
)>=COS_LOOKUP_I_SZ
){
160 memset(curve
,0,sizeof(*curve
)*n
);
164 ilsp
[i
]=vorbis_coslook_i(val
);
170 ogg_uint32_t pi
=46341; /* 2**-.5 in 0.16 */
171 ogg_uint32_t qi
=46341;
172 ogg_int32_t qexp
=0,shift
;
173 ogg_int32_t wi
=icos
[k
];
175 #ifdef _V_LSP_MATH_ASM
176 lsp_loop_asm(&qi
,&pi
,&qexp
,ilsp
,wi
,m
);
182 qexp
= qexp
*2-28*((m
+1)>>1)+m
;
183 pi
*=(1<<14)-((wi
*wi
)>>14);
194 if(qi
&0xffff0000){ /* checks for 1.xxxxxxxxxxxxxxxx */
197 lsp_norm_asm(&qi
,&qexp
);
201 qi
*=labs(ilsp
[0]-wi
);
202 pi
*=labs(ilsp
[1]-wi
);
205 if(!(shift
=MLOOP_1
[(pi
|qi
)>>25]))
206 if(!(shift
=MLOOP_2
[(pi
|qi
)>>19]))
207 shift
=MLOOP_3
[(pi
|qi
)>>16];
208 qi
=(qi
>>shift
)*labs(ilsp
[j
-1]-wi
);
209 pi
=(pi
>>shift
)*labs(ilsp
[j
]-wi
);
212 if(!(shift
=MLOOP_1
[(pi
|qi
)>>25]))
213 if(!(shift
=MLOOP_2
[(pi
|qi
)>>19]))
214 shift
=MLOOP_3
[(pi
|qi
)>>16];
216 /* pi,qi normalized collectively, both tracked using qexp */
219 /* odd order filter; slightly assymetric */
220 /* the last coefficient */
221 qi
=(qi
>>shift
)*labs(ilsp
[j
-1]-wi
);
225 if(!(shift
=MLOOP_1
[(pi
|qi
)>>25]))
226 if(!(shift
=MLOOP_2
[(pi
|qi
)>>19]))
227 shift
=MLOOP_3
[(pi
|qi
)>>16];
231 qexp
+=shift
-14*((m
+1)>>1);
237 pi
*=(1<<14)-((wi
*wi
)>>14);
241 /* even order filter; still symmetric */
243 /* p*=p(1-w), q*=q(1+w), let normalization drift because it isn't
244 worth tracking step by step */
261 /* we've let the normalization drift because it wasn't important;
262 however, for the lookup, things must be normalized again. We
263 need at most one right shift or a number of left shifts */
265 if(qi
&0xffff0000){ /* checks for 1.xxxxxxxxxxxxxxxx */
268 while(qi
&& !(qi
&0x8000)){ /* checks for 0.0xxxxxxxxxxxxxxx or less*/
274 amp
=vorbis_fromdBlook_i(ampi
* /* n.4 */
275 vorbis_invsqlook_i(qi
,qexp
)-
277 ampoffseti
); /* 8.12[0] */
279 #ifdef _LOW_ACCURACY_
282 curve
[i
]= MULT31_SHIFT15(curve
[i
],amp
);
283 while(map
[++i
]==k
) curve
[i
]= MULT31_SHIFT15(curve
[i
],amp
);
287 /*************** vorbis decode glue ************/
289 static void floor0_free_info(vorbis_info_floor
*i
){
290 vorbis_info_floor0
*info
=(vorbis_info_floor0
*)i
;
292 memset(info
,0,sizeof(*info
));
297 static void floor0_free_look(vorbis_look_floor
*i
){
298 vorbis_look_floor0
*look
=(vorbis_look_floor0
*)i
;
301 if(look
->linearmap
)_ogg_free(look
->linearmap
);
302 if(look
->lsp_look
)_ogg_free(look
->lsp_look
);
303 memset(look
,0,sizeof(*look
));
308 static vorbis_info_floor
*floor0_unpack (vorbis_info
*vi
,oggpack_buffer
*opb
){
309 codec_setup_info
*ci
=(codec_setup_info
*)vi
->codec_setup
;
312 vorbis_info_floor0
*info
=(vorbis_info_floor0
*)_ogg_malloc(sizeof(*info
));
313 info
->order
=oggpack_read(opb
,8);
314 info
->rate
=oggpack_read(opb
,16);
315 info
->barkmap
=oggpack_read(opb
,16);
316 info
->ampbits
=oggpack_read(opb
,6);
317 info
->ampdB
=oggpack_read(opb
,8);
318 info
->numbooks
=oggpack_read(opb
,4)+1;
320 if(info
->order
<1)goto err_out
;
321 if(info
->rate
<1)goto err_out
;
322 if(info
->barkmap
<1)goto err_out
;
323 if(info
->numbooks
<1)goto err_out
;
325 for(j
=0;j
<info
->numbooks
;j
++){
326 info
->books
[j
]=oggpack_read(opb
,8);
327 if(info
->books
[j
]<0 || info
->books
[j
]>=ci
->books
)goto err_out
;
332 floor0_free_info(info
);
336 /* initialize Bark scale and normalization lookups. We could do this
337 with static tables, but Vorbis allows a number of possible
338 combinations, so it's best to do it computationally.
340 The below is authoritative in terms of defining scale mapping.
341 Note that the scale depends on the sampling rate as well as the
342 linear block and mapping sizes */
344 static vorbis_look_floor
*floor0_look (vorbis_dsp_state
*vd
,vorbis_info_mode
*mi
,
345 vorbis_info_floor
*i
){
348 vorbis_info
*vi
=vd
->vi
;
349 codec_setup_info
*ci
=(codec_setup_info
*)vi
->codec_setup
;
350 vorbis_info_floor0
*info
=(vorbis_info_floor0
*)i
;
351 vorbis_look_floor0
*look
=(vorbis_look_floor0
*)_ogg_calloc(1,sizeof(*look
));
353 look
->n
=ci
->blocksizes
[mi
->blockflag
]/2;
354 look
->ln
=info
->barkmap
;
357 /* the mapping from a linear scale to a smaller bark scale is
358 straightforward. We do *not* make sure that the linear mapping
359 does not skip bark-scale bins; the decoder simply skips them and
360 the encoder may do what it wishes in filling them. They're
361 necessary in some mapping combinations to keep the scale spacing
363 look
->linearmap
=(int *)_ogg_malloc((look
->n
+1)*sizeof(*look
->linearmap
));
364 for(j
=0;j
<look
->n
;j
++){
367 ((toBARK(info
->rate
/2*j
/look
->n
)<<11)/toBARK(info
->rate
/2)))>>11;
369 if(val
>=look
->ln
)val
=look
->ln
-1; /* guard against the approximation */
370 look
->linearmap
[j
]=val
;
372 look
->linearmap
[j
]=-1;
374 look
->lsp_look
=(ogg_int32_t
*)_ogg_malloc(look
->ln
*sizeof(*look
->lsp_look
));
375 for(j
=0;j
<look
->ln
;j
++)
376 look
->lsp_look
[j
]=vorbis_coslook2_i(0x10000*j
/look
->ln
);
381 static void *floor0_inverse1(vorbis_block
*vb
,vorbis_look_floor
*i
){
382 vorbis_look_floor0
*look
=(vorbis_look_floor0
*)i
;
383 vorbis_info_floor0
*info
=look
->vi
;
386 int ampraw
=oggpack_read(&vb
->opb
,info
->ampbits
);
387 if(ampraw
>0){ /* also handles the -1 out of data case */
388 long maxval
=(1<<info
->ampbits
)-1;
389 int amp
=((ampraw
*info
->ampdB
)<<4)/maxval
;
390 int booknum
=oggpack_read(&vb
->opb
,_ilog(info
->numbooks
));
392 if(booknum
!=-1 && booknum
<info
->numbooks
){ /* be paranoid */
393 codec_setup_info
*ci
=(codec_setup_info
*)vb
->vd
->vi
->codec_setup
;
394 codebook
*b
=ci
->fullbooks
+info
->books
[booknum
];
396 ogg_int32_t
*lsp
=(ogg_int32_t
*)_vorbis_block_alloc(vb
,sizeof(*lsp
)*(look
->m
+1));
398 for(j
=0;j
<look
->m
;j
+=b
->dim
)
399 if(vorbis_book_decodev_set(b
,lsp
+j
,&vb
->opb
,b
->dim
,-24)==-1)goto eop
;
401 for(k
=0;k
<b
->dim
;k
++,j
++)lsp
[j
]+=last
;
413 static int floor0_inverse2(vorbis_block
*vb
,vorbis_look_floor
*i
,
414 void *memo
,ogg_int32_t
*out
){
415 vorbis_look_floor0
*look
=(vorbis_look_floor0
*)i
;
416 vorbis_info_floor0
*info
=look
->vi
;
419 ogg_int32_t
*lsp
=(ogg_int32_t
*)memo
;
420 ogg_int32_t amp
=lsp
[look
->m
];
422 /* take the coefficients back to a spectral envelope curve */
423 vorbis_lsp_to_curve(out
,look
->linearmap
,look
->n
,look
->ln
,
424 lsp
,look
->m
,amp
,info
->ampdB
,look
->lsp_look
);
427 memset(out
,0,sizeof(*out
)*look
->n
);
432 vorbis_func_floor floor0_exportbundle
={
433 &floor0_unpack
,&floor0_look
,&floor0_free_info
,
434 &floor0_free_look
,&floor0_inverse1
,&floor0_inverse2