summaryrefslogtreecommitdiff
path: root/lib/rbcodec/codecs/libtremor/floor0.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rbcodec/codecs/libtremor/floor0.c')
-rw-r--r--lib/rbcodec/codecs/libtremor/floor0.c444
1 files changed, 444 insertions, 0 deletions
diff --git a/lib/rbcodec/codecs/libtremor/floor0.c b/lib/rbcodec/codecs/libtremor/floor0.c
new file mode 100644
index 0000000000..cd0a9f89f6
--- /dev/null
+++ b/lib/rbcodec/codecs/libtremor/floor0.c
@@ -0,0 +1,444 @@
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 "config-tremor.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 const 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
136static void 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 (void)ln;
143 /* 0 <= m < 256 */
144
145 /* set up for using all int later */
146 int i;
147 int ampoffseti=ampoffset*4096;
148 int ampi=amp;
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*/
151 for(i=0;i<m;i++){
152#ifndef _LOW_ACCURACY_
153 ogg_int32_t val=MULT32(lsp[i],0x517cc2);
154#else
155 ogg_int32_t val=((lsp[i]>>10)*0x517d)>>14;
156#endif
157
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);
161 return;
162 }
163
164 ilsp[i]=vorbis_coslook_i(val);
165 }
166
167 i=0;
168 while(i<n){
169 int j,k=map[i];
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];
174
175#ifdef _V_LSP_MATH_ASM
176 (void)shift; /* kill warnings */
177 (void)j;
178 lsp_loop_asm(&qi,&pi,&qexp,ilsp,wi,m);
179
180 pi=((pi*pi)>>16);
181 qi=((qi*qi)>>16);
182
183 if(m&1){
184 qexp= qexp*2-28*((m+1)>>1)+m;
185 pi*=(1<<14)-((wi*wi)>>14);
186 qi+=pi>>14;
187 }else{
188 qexp= qexp*2-13*m;
189
190 pi*=(1<<14)-wi;
191 qi*=(1<<14)+wi;
192
193 qi=(qi+pi)>>14;
194 }
195
196 if(qi&0xffff0000){ /* checks for 1.xxxxxxxxxxxxxxxx */
197 qi>>=1; qexp++;
198 }else
199 lsp_norm_asm(&qi,&qexp);
200
201#else
202
203 j=1;
204 if(m>1){
205 qi*=labs(ilsp[0]-wi);
206 pi*=labs(ilsp[1]-wi);
207
208 for(j+=2;j<m;j+=2){
209 if(!(shift=MLOOP_1[(pi|qi)>>25]))
210 if(!(shift=MLOOP_2[(pi|qi)>>19]))
211 shift=MLOOP_3[(pi|qi)>>16];
212 qi=(qi>>shift)*labs(ilsp[j-1]-wi);
213 pi=(pi>>shift)*labs(ilsp[j]-wi);
214 qexp+=shift;
215 }
216 }
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 /* pi,qi normalized collectively, both tracked using qexp */
222
223 if(m&1){
224 /* odd order filter; slightly assymetric */
225 /* the last coefficient */
226 qi=(qi>>shift)*labs(ilsp[j-1]-wi);
227 pi=(pi>>shift)<<14;
228 qexp+=shift;
229
230 if(!(shift=MLOOP_1[(pi|qi)>>25]))
231 if(!(shift=MLOOP_2[(pi|qi)>>19]))
232 shift=MLOOP_3[(pi|qi)>>16];
233
234 pi>>=shift;
235 qi>>=shift;
236 qexp+=shift-14*((m+1)>>1);
237
238 pi=((pi*pi)>>16);
239 qi=((qi*qi)>>16);
240 qexp=qexp*2+m;
241
242 pi*=(1<<14)-((wi*wi)>>14);
243 qi+=pi>>14;
244
245 }else{
246 /* even order filter; still symmetric */
247
248 /* p*=p(1-w), q*=q(1+w), let normalization drift because it isn't
249 worth tracking step by step */
250
251 pi>>=shift;
252 qi>>=shift;
253 qexp+=shift-7*m;
254
255 pi=((pi*pi)>>16);
256 qi=((qi*qi)>>16);
257 qexp=qexp*2+m;
258
259 pi*=(1<<14)-wi;
260 qi*=(1<<14)+wi;
261 qi=(qi+pi)>>14;
262
263 }
264
265
266 /* we've let the normalization drift because it wasn't important;
267 however, for the lookup, things must be normalized again. We
268 need at most one right shift or a number of left shifts */
269
270 if(qi&0xffff0000){ /* checks for 1.xxxxxxxxxxxxxxxx */
271 qi>>=1; qexp++;
272 }else
273 while(qi && !(qi&0x8000)){ /* checks for 0.0xxxxxxxxxxxxxxx or less*/
274 qi<<=1; qexp--;
275 }
276
277#endif
278
279 amp=vorbis_fromdBlook_i(ampi* /* n.4 */
280 vorbis_invsqlook_i(qi,qexp)-
281 /* m.8, m+n<=8 */
282 ampoffseti); /* 8.12[0] */
283
284#ifdef _LOW_ACCURACY_
285 amp>>=9;
286#endif
287 curve[i]= MULT31_SHIFT15(curve[i],amp);
288 while(map[++i]==k) curve[i]= MULT31_SHIFT15(curve[i],amp);
289 }
290}
291
292/*************** vorbis decode glue ************/
293
294static void floor0_free_info(vorbis_info_floor *i){
295 vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
296 if(info){
297 memset(info,0,sizeof(*info));
298 _ogg_free(info);
299 }
300}
301
302static void floor0_free_look(vorbis_look_floor *i){
303 vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
304 if(look){
305
306 if(look->linearmap)_ogg_free(look->linearmap);
307 if(look->lsp_look)_ogg_free(look->lsp_look);
308 memset(look,0,sizeof(*look));
309 _ogg_free(look);
310 }
311}
312
313static vorbis_info_floor *floor0_unpack (vorbis_info *vi,oggpack_buffer *opb){
314 codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
315 int j;
316
317 vorbis_info_floor0 *info=(vorbis_info_floor0 *)_ogg_malloc(sizeof(*info));
318 info->order=oggpack_read(opb,8);
319 info->rate=oggpack_read(opb,16);
320 info->barkmap=oggpack_read(opb,16);
321 info->ampbits=oggpack_read(opb,6);
322 info->ampdB=oggpack_read(opb,8);
323 info->numbooks=oggpack_read(opb,4)+1;
324
325 if(info->order<1)goto err_out;
326 if(info->rate<1)goto err_out;
327 if(info->barkmap<1)goto err_out;
328 if(info->numbooks<1)goto err_out;
329
330 for(j=0;j<info->numbooks;j++){
331 info->books[j]=oggpack_read(opb,8);
332 if(info->books[j]<0 || info->books[j]>=ci->books)goto err_out;
333 if(ci->book_param[info->books[j]]->maptype==0)goto err_out;
334 if(ci->book_param[info->books[j]]->dim<1)goto err_out;
335 }
336 return(info);
337
338 err_out:
339 floor0_free_info(info);
340 return(NULL);
341}
342
343/* initialize Bark scale and normalization lookups. We could do this
344 with static tables, but Vorbis allows a number of possible
345 combinations, so it's best to do it computationally.
346
347 The below is authoritative in terms of defining scale mapping.
348 Note that the scale depends on the sampling rate as well as the
349 linear block and mapping sizes */
350
351static vorbis_look_floor *floor0_look (vorbis_dsp_state *vd,vorbis_info_mode *mi,
352 vorbis_info_floor *i){
353 int j;
354 // ogg_int32_t scale;
355 vorbis_info *vi=vd->vi;
356 codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
357 vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
358 vorbis_look_floor0 *look=(vorbis_look_floor0 *)_ogg_calloc(1,sizeof(*look));
359 look->m=info->order;
360 look->n=ci->blocksizes[mi->blockflag]/2;
361 look->ln=info->barkmap;
362 look->vi=info;
363
364 /* the mapping from a linear scale to a smaller bark scale is
365 straightforward. We do *not* make sure that the linear mapping
366 does not skip bark-scale bins; the decoder simply skips them and
367 the encoder may do what it wishes in filling them. They're
368 necessary in some mapping combinations to keep the scale spacing
369 accurate */
370 look->linearmap=(int *)_ogg_malloc((look->n+1)*sizeof(*look->linearmap));
371 for(j=0;j<look->n;j++){
372
373 int val=(look->ln*
374 ((toBARK(info->rate/2*j/look->n)<<11)/toBARK(info->rate/2)))>>11;
375
376 if(val>=look->ln)val=look->ln-1; /* guard against the approximation */
377 look->linearmap[j]=val;
378 }
379 look->linearmap[j]=-1;
380
381 look->lsp_look=(ogg_int32_t *)_ogg_malloc(look->ln*sizeof(*look->lsp_look));
382 for(j=0;j<look->ln;j++)
383 look->lsp_look[j]=vorbis_coslook2_i(0x10000*j/look->ln);
384
385 return look;
386}
387
388static void *floor0_inverse1(vorbis_block *vb,vorbis_look_floor *i){
389 vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
390 vorbis_info_floor0 *info=look->vi;
391 int j,k;
392
393 int ampraw=oggpack_read(&vb->opb,info->ampbits);
394 if(ampraw>0){ /* also handles the -1 out of data case */
395 long maxval=(1<<info->ampbits)-1;
396 int amp=((ampraw*info->ampdB)<<4)/maxval;
397 int booknum=oggpack_read(&vb->opb,_ilog(info->numbooks));
398
399 if(booknum!=-1 && booknum<info->numbooks){ /* be paranoid */
400 codec_setup_info *ci=(codec_setup_info *)vb->vd->vi->codec_setup;
401 codebook *b=ci->fullbooks+info->books[booknum];
402 ogg_int32_t last=0;
403 ogg_int32_t *lsp=(ogg_int32_t *)_vorbis_block_alloc(vb,sizeof(*lsp)*(look->m+1));
404
405 if(vorbis_book_decodev_set(b,lsp,&vb->opb,look->m,-24)==-1)goto eop;
406 for(j=0;j<look->m;){
407 for(k=0;j<look->m && k<b->dim;k++,j++)lsp[j]+=last;
408 last=lsp[j-1];
409 }
410
411 lsp[look->m]=amp;
412 return(lsp);
413 }
414 }
415 eop:
416 return(NULL);
417}
418
419static int floor0_inverse2(vorbis_block *vb,vorbis_look_floor *i,
420 void *memo,ogg_int32_t *out){
421 vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
422 vorbis_info_floor0 *info=look->vi;
423 (void)vb;
424
425 if(memo){
426 ogg_int32_t *lsp=(ogg_int32_t *)memo;
427 ogg_int32_t amp=lsp[look->m];
428
429 /* take the coefficients back to a spectral envelope curve */
430 vorbis_lsp_to_curve(out,look->linearmap,look->n,look->ln,
431 lsp,look->m,amp,info->ampdB,look->lsp_look);
432 return(1);
433 }
434 memset(out,0,sizeof(*out)*look->n);
435 return(0);
436}
437
438/* export hooks */
439const vorbis_func_floor floor0_exportbundle ICONST_ATTR ={
440 &floor0_unpack,&floor0_look,&floor0_free_info,
441 &floor0_free_look,&floor0_inverse1,&floor0_inverse2
442};
443
444