summaryrefslogtreecommitdiff
path: root/lib/rbcodec/codecs/libtremor/floor1.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rbcodec/codecs/libtremor/floor1.c')
-rw-r--r--lib/rbcodec/codecs/libtremor/floor1.c426
1 files changed, 426 insertions, 0 deletions
diff --git a/lib/rbcodec/codecs/libtremor/floor1.c b/lib/rbcodec/codecs/libtremor/floor1.c
new file mode 100644
index 0000000000..d2268db121
--- /dev/null
+++ b/lib/rbcodec/codecs/libtremor/floor1.c
@@ -0,0 +1,426 @@
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 1 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 "ffmpeg_stuff.h"
28
29#define floor1_rangedB 140 /* floor 1 fixed at -140dB to 0dB range */
30
31typedef struct {
32 int forward_index[VIF_POSIT+2];
33
34 int hineighbor[VIF_POSIT];
35 int loneighbor[VIF_POSIT];
36 int posts;
37
38 int n;
39 int quant_q;
40 vorbis_info_floor1 *vi;
41
42} vorbis_look_floor1;
43
44/***********************************************/
45
46static void floor1_free_info(vorbis_info_floor *i){
47 vorbis_info_floor1 *info=(vorbis_info_floor1 *)i;
48 if(info){
49 //memset(info,0,sizeof(*info));
50 _ogg_free(info);
51 }
52}
53
54static void floor1_free_look(vorbis_look_floor *i){
55 vorbis_look_floor1 *look=(vorbis_look_floor1 *)i;
56 if(look){
57 //memset(look,0,sizeof(*look));
58 _ogg_free(look);
59 }
60}
61
62static inline int ilog(register unsigned int v){
63 register int ret=0;
64 while(v){
65 ret++;
66 v>>=1;
67 }
68 return(ret);
69}
70
71static int icomp(const void *a,const void *b){
72 return(**(int **)a-**(int **)b);
73}
74
75static vorbis_info_floor *floor1_unpack (vorbis_info *vi,oggpack_buffer *opb){
76 codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
77 int j,k,count=0,maxclass=-1,rangebits;
78
79 vorbis_info_floor1 *info=(vorbis_info_floor1 *)_ogg_calloc(1,sizeof(*info));
80 /* read partitions */
81 info->partitions=oggpack_read(opb,5); /* only 0 to 31 legal */
82 for(j=0;j<info->partitions;j++){
83 info->partitionclass[j]=oggpack_read(opb,4); /* only 0 to 15 legal */
84 if(info->partitionclass[j]<0)goto err_out;
85 if(maxclass<info->partitionclass[j])maxclass=info->partitionclass[j];
86 }
87
88 /* read partition classes */
89 for(j=0;j<maxclass+1;j++){
90 info->class_dim[j]=oggpack_read(opb,3)+1; /* 1 to 8 */
91 info->class_subs[j]=oggpack_read(opb,2); /* 0,1,2,3 bits */
92 if(info->class_subs[j]<0)
93 goto err_out;
94 if(info->class_subs[j])info->class_book[j]=oggpack_read(opb,8);
95 if(info->class_book[j]<0 || info->class_book[j]>=ci->books)
96 goto err_out;
97 for(k=0;k<(1<<info->class_subs[j]);k++){
98 info->class_subbook[j][k]=oggpack_read(opb,8)-1;
99 if(info->class_subbook[j][k]<-1 || info->class_subbook[j][k]>=ci->books)
100 goto err_out;
101 }
102 }
103
104 /* read the post list */
105 info->mult=oggpack_read(opb,2)+1; /* only 1,2,3,4 legal now */
106 rangebits=oggpack_read(opb,4);
107 if(rangebits<0)goto err_out;
108
109 for(j=0,k=0;j<info->partitions;j++){
110 count+=info->class_dim[info->partitionclass[j]];
111 for(;k<count;k++){
112 int t=info->postlist[k+2]=oggpack_read(opb,rangebits);
113 if(t<0 || t>=(1<<rangebits))
114 goto err_out;
115 }
116 }
117 info->postlist[0]=0;
118 info->postlist[1]=1<<rangebits;
119
120 /* don't allow repeated values in post list as they'd result in
121 zero-length segments */
122 {
123 int *sortpointer[VIF_POSIT+2];
124 for(j=0;j<count+2;j++)sortpointer[j]=info->postlist+j;
125 qsort(sortpointer,count+2,sizeof(*sortpointer),icomp);
126
127 for(j=1;j<count+2;j++)
128 if(*sortpointer[j-1]==*sortpointer[j])goto err_out;
129 }
130
131 return(info);
132
133 err_out:
134 floor1_free_info(info);
135 return(NULL);
136}
137
138static vorbis_look_floor *floor1_look(vorbis_dsp_state *vd,vorbis_info_mode *mi,
139 vorbis_info_floor *in){
140
141 int *sortpointer[VIF_POSIT+2];
142 vorbis_info_floor1 *info=(vorbis_info_floor1 *)in;
143 vorbis_look_floor1 *look=(vorbis_look_floor1 *)_ogg_calloc(1,sizeof(*look));
144 int i,j,n=0;
145
146 (void)vd;
147 (void)mi;
148 look->vi=info;
149 look->n=info->postlist[1];
150
151 /* we drop each position value in-between already decoded values,
152 and use linear interpolation to predict each new value past the
153 edges. The positions are read in the order of the position
154 list... we precompute the bounding positions in the lookup. Of
155 course, the neighbors can change (if a position is declined), but
156 this is an initial mapping */
157
158 for(i=0;i<info->partitions;i++)n+=info->class_dim[info->partitionclass[i]];
159 n+=2;
160 look->posts=n;
161
162 /* also store a sorted position index */
163 for(i=0;i<n;i++)sortpointer[i]=info->postlist+i;
164 qsort(sortpointer,n,sizeof(*sortpointer),icomp);
165
166 /* points from sort order back to range number */
167 for(i=0;i<n;i++)look->forward_index[i]=sortpointer[i]-info->postlist;
168
169 /* quantize values to multiplier spec */
170 switch(info->mult){
171 case 1: /* 1024 -> 256 */
172 look->quant_q=256;
173 break;
174 case 2: /* 1024 -> 128 */
175 look->quant_q=128;
176 break;
177 case 3: /* 1024 -> 86 */
178 look->quant_q=86;
179 break;
180 case 4: /* 1024 -> 64 */
181 look->quant_q=64;
182 break;
183 }
184
185 /* discover our neighbors for decode where we don't use fit flags
186 (that would push the neighbors outward) */
187 for(i=0;i<n-2;i++){
188 int lo=0;
189 int hi=1;
190 int lx=0;
191 int hx=look->n;
192 int currentx=info->postlist[i+2];
193 for(j=0;j<i+2;j++){
194 int x=info->postlist[j];
195 if(x>lx && x<currentx){
196 lo=j;
197 lx=x;
198 }
199 if(x<hx && x>currentx){
200 hi=j;
201 hx=x;
202 }
203 }
204 look->loneighbor[i]=lo;
205 look->hineighbor[i]=hi;
206 }
207
208 return(look);
209}
210
211static int render_point(int x0,int x1,int y0,int y1,int x){
212 y0&=0x7fff; /* mask off flag */
213 y1&=0x7fff;
214 return y0+((y1-y0)*(x-x0))/(x1-x0);
215}
216
217#ifdef _LOW_ACCURACY_
218# define XdB(n) ((((n)>>8)+1)>>1)
219#else
220# define XdB(n) (n)
221#endif
222
223/* keep the floor lookup table in fast IRAM */
224static const ogg_int32_t FLOOR_fromdB_LOOKUP[256] ICONST_ATTR = {
225 XdB(0x000000e5), XdB(0x000000f4), XdB(0x00000103), XdB(0x00000114),
226 XdB(0x00000126), XdB(0x00000139), XdB(0x0000014e), XdB(0x00000163),
227 XdB(0x0000017a), XdB(0x00000193), XdB(0x000001ad), XdB(0x000001c9),
228 XdB(0x000001e7), XdB(0x00000206), XdB(0x00000228), XdB(0x0000024c),
229 XdB(0x00000272), XdB(0x0000029b), XdB(0x000002c6), XdB(0x000002f4),
230 XdB(0x00000326), XdB(0x0000035a), XdB(0x00000392), XdB(0x000003cd),
231 XdB(0x0000040c), XdB(0x00000450), XdB(0x00000497), XdB(0x000004e4),
232 XdB(0x00000535), XdB(0x0000058c), XdB(0x000005e8), XdB(0x0000064a),
233 XdB(0x000006b3), XdB(0x00000722), XdB(0x00000799), XdB(0x00000818),
234 XdB(0x0000089e), XdB(0x0000092e), XdB(0x000009c6), XdB(0x00000a69),
235 XdB(0x00000b16), XdB(0x00000bcf), XdB(0x00000c93), XdB(0x00000d64),
236 XdB(0x00000e43), XdB(0x00000f30), XdB(0x0000102d), XdB(0x0000113a),
237 XdB(0x00001258), XdB(0x0000138a), XdB(0x000014cf), XdB(0x00001629),
238 XdB(0x0000179a), XdB(0x00001922), XdB(0x00001ac4), XdB(0x00001c82),
239 XdB(0x00001e5c), XdB(0x00002055), XdB(0x0000226f), XdB(0x000024ac),
240 XdB(0x0000270e), XdB(0x00002997), XdB(0x00002c4b), XdB(0x00002f2c),
241 XdB(0x0000323d), XdB(0x00003581), XdB(0x000038fb), XdB(0x00003caf),
242 XdB(0x000040a0), XdB(0x000044d3), XdB(0x0000494c), XdB(0x00004e10),
243 XdB(0x00005323), XdB(0x0000588a), XdB(0x00005e4b), XdB(0x0000646b),
244 XdB(0x00006af2), XdB(0x000071e5), XdB(0x0000794c), XdB(0x0000812e),
245 XdB(0x00008993), XdB(0x00009283), XdB(0x00009c09), XdB(0x0000a62d),
246 XdB(0x0000b0f9), XdB(0x0000bc79), XdB(0x0000c8b9), XdB(0x0000d5c4),
247 XdB(0x0000e3a9), XdB(0x0000f274), XdB(0x00010235), XdB(0x000112fd),
248 XdB(0x000124dc), XdB(0x000137e4), XdB(0x00014c29), XdB(0x000161bf),
249 XdB(0x000178bc), XdB(0x00019137), XdB(0x0001ab4a), XdB(0x0001c70e),
250 XdB(0x0001e4a1), XdB(0x0002041f), XdB(0x000225aa), XdB(0x00024962),
251 XdB(0x00026f6d), XdB(0x000297f0), XdB(0x0002c316), XdB(0x0002f109),
252 XdB(0x000321f9), XdB(0x00035616), XdB(0x00038d97), XdB(0x0003c8b4),
253 XdB(0x000407a7), XdB(0x00044ab2), XdB(0x00049218), XdB(0x0004de23),
254 XdB(0x00052f1e), XdB(0x0005855c), XdB(0x0005e135), XdB(0x00064306),
255 XdB(0x0006ab33), XdB(0x00071a24), XdB(0x0007904b), XdB(0x00080e20),
256 XdB(0x00089422), XdB(0x000922da), XdB(0x0009bad8), XdB(0x000a5cb6),
257 XdB(0x000b091a), XdB(0x000bc0b1), XdB(0x000c8436), XdB(0x000d5471),
258 XdB(0x000e3233), XdB(0x000f1e5f), XdB(0x001019e4), XdB(0x001125c1),
259 XdB(0x00124306), XdB(0x001372d5), XdB(0x0014b663), XdB(0x00160ef7),
260 XdB(0x00177df0), XdB(0x001904c1), XdB(0x001aa4f9), XdB(0x001c603d),
261 XdB(0x001e384f), XdB(0x00202f0f), XdB(0x0022467a), XdB(0x002480b1),
262 XdB(0x0026dff7), XdB(0x002966b3), XdB(0x002c1776), XdB(0x002ef4fc),
263 XdB(0x0032022d), XdB(0x00354222), XdB(0x0038b828), XdB(0x003c67c2),
264 XdB(0x004054ae), XdB(0x004482e8), XdB(0x0048f6af), XdB(0x004db488),
265 XdB(0x0052c142), XdB(0x005821ff), XdB(0x005ddc33), XdB(0x0063f5b0),
266 XdB(0x006a74a7), XdB(0x00715faf), XdB(0x0078bdce), XdB(0x0080967f),
267 XdB(0x0088f1ba), XdB(0x0091d7f9), XdB(0x009b5247), XdB(0x00a56a41),
268 XdB(0x00b02a27), XdB(0x00bb9ce2), XdB(0x00c7ce12), XdB(0x00d4ca17),
269 XdB(0x00e29e20), XdB(0x00f15835), XdB(0x0101074b), XdB(0x0111bb4e),
270 XdB(0x01238531), XdB(0x01367704), XdB(0x014aa402), XdB(0x016020a7),
271 XdB(0x017702c3), XdB(0x018f6190), XdB(0x01a955cb), XdB(0x01c4f9cf),
272 XdB(0x01e269a8), XdB(0x0201c33b), XdB(0x0223265a), XdB(0x0246b4ea),
273 XdB(0x026c9302), XdB(0x0294e716), XdB(0x02bfda13), XdB(0x02ed9793),
274 XdB(0x031e4e09), XdB(0x03522ee4), XdB(0x03896ed0), XdB(0x03c445e2),
275 XdB(0x0402efd6), XdB(0x0445ac4b), XdB(0x048cbefc), XdB(0x04d87013),
276 XdB(0x05290c67), XdB(0x057ee5ca), XdB(0x05da5364), XdB(0x063bb204),
277 XdB(0x06a36485), XdB(0x0711d42b), XdB(0x0787710e), XdB(0x0804b299),
278 XdB(0x088a17ef), XdB(0x0918287e), XdB(0x09af747c), XdB(0x0a50957e),
279 XdB(0x0afc2f19), XdB(0x0bb2ef7f), XdB(0x0c759034), XdB(0x0d44d6ca),
280 XdB(0x0e2195bc), XdB(0x0f0cad0d), XdB(0x10070b62), XdB(0x1111aeea),
281 XdB(0x122da66c), XdB(0x135c120f), XdB(0x149e24d9), XdB(0x15f525b1),
282 XdB(0x176270e3), XdB(0x18e7794b), XdB(0x1a85c9ae), XdB(0x1c3f06d1),
283 XdB(0x1e14f07d), XdB(0x200963d7), XdB(0x221e5ccd), XdB(0x2455f870),
284 XdB(0x26b2770b), XdB(0x29363e2b), XdB(0x2be3db5c), XdB(0x2ebe06b6),
285 XdB(0x31c7a55b), XdB(0x3503ccd4), XdB(0x3875c5aa), XdB(0x3c210f44),
286 XdB(0x4009632b), XdB(0x4432b8cf), XdB(0x48a149bc), XdB(0x4d59959e),
287 XdB(0x52606733), XdB(0x57bad899), XdB(0x5d6e593a), XdB(0x6380b298),
288 XdB(0x69f80e9a), XdB(0x70dafda8), XdB(0x78307d76), XdB(0x7fffffff),
289};
290
291static void *floor1_inverse1(vorbis_block *vb,vorbis_look_floor *in)
292 ICODE_ATTR_TREMOR_NOT_MDCT;
293static void *floor1_inverse1(vorbis_block *vb,vorbis_look_floor *in){
294 vorbis_look_floor1 *look=(vorbis_look_floor1 *)in;
295 vorbis_info_floor1 *info=look->vi;
296 codec_setup_info *ci=(codec_setup_info *)vb->vd->vi->codec_setup;
297 int i,j,k;
298 codebook *books=ci->fullbooks;
299
300 /* unpack wrapped/predicted values from stream */
301 if(oggpack_read(&vb->opb,1)==1){
302 int *fit_value=(int *)_vorbis_block_alloc(vb,(look->posts)*sizeof(*fit_value));
303 int ilg = ilog(look->quant_q-1);
304 fit_value[0]=oggpack_read(&vb->opb,ilg);
305 fit_value[1]=oggpack_read(&vb->opb,ilg);
306
307 /* partition by partition */
308 /* partition by partition */
309 for(i=0,j=2;i<info->partitions;i++){
310 int classv=info->partitionclass[i];
311 int cdim=info->class_dim[classv];
312 int csubbits=info->class_subs[classv];
313 int csub=1<<csubbits;
314 int cval=0;
315
316 /* decode the partition's first stage cascade value */
317 if(csubbits){
318 cval=vorbis_book_decode(books+info->class_book[classv],&vb->opb);
319
320 if(cval==-1)goto eop;
321 }
322
323 for(k=0;k<cdim;k++){
324 int book=info->class_subbook[classv][cval&(csub-1)];
325 cval>>=csubbits;
326 if(book>=0){
327 if((fit_value[j+k]=vorbis_book_decode(books+book,&vb->opb))==-1)
328 goto eop;
329 }else{
330 fit_value[j+k]=0;
331 }
332 }
333 j+=cdim;
334 }
335
336 /* unwrap positive values and reconsitute via linear interpolation */
337 for(i=2;i<look->posts;i++){
338 int predicted=render_point(info->postlist[look->loneighbor[i-2]],
339 info->postlist[look->hineighbor[i-2]],
340 fit_value[look->loneighbor[i-2]],
341 fit_value[look->hineighbor[i-2]],
342 info->postlist[i]);
343 int hiroom=look->quant_q-predicted;
344 int loroom=predicted;
345 int room=(hiroom<loroom?hiroom:loroom)<<1;
346 int val=fit_value[i];
347
348 if(val){
349 if(val>=room){
350 if(hiroom>loroom){
351 val = val-loroom;
352 }else{
353 val = -1-(val-hiroom);
354 }
355 }else{
356 if(val&1){
357 val= -((val+1)>>1);
358 }else{
359 val>>=1;
360 }
361 }
362
363 fit_value[i]=(val+predicted)&0x7fff;;
364 fit_value[look->loneighbor[i-2]]&=0x7fff;
365 fit_value[look->hineighbor[i-2]]&=0x7fff;
366
367 }else{
368 fit_value[i]=predicted|0x8000;
369 }
370 }
371
372 return(fit_value);
373 }
374 eop:
375 return(NULL);
376}
377
378static int floor1_inverse2(vorbis_block *vb,vorbis_look_floor *in,void *memo,
379 ogg_int32_t *out) ICODE_ATTR_TREMOR_NOT_MDCT;
380static int floor1_inverse2(vorbis_block *vb,vorbis_look_floor *in,void *memo,
381 ogg_int32_t *out){
382 vorbis_look_floor1 *look=(vorbis_look_floor1 *)in;
383 vorbis_info_floor1 *info=look->vi;
384
385 codec_setup_info *ci=(codec_setup_info *)vb->vd->vi->codec_setup;
386 int n=ci->blocksizes[vb->W]/2;
387 int j;
388
389 if(memo){
390 /* render the lines */
391 int *fit_value=(int *)memo;
392 int hx=0;
393 int lx=0;
394 int ly=fit_value[0]*info->mult;
395 /* guard lookup against out-of-range values */
396 ly=(ly<0?0:ly>255?255:ly);
397
398 for(j=1;j<look->posts;j++){
399 int current=look->forward_index[j];
400 int hy=fit_value[current]&0x7fff;
401 if(hy==fit_value[current]){
402
403 hx=info->postlist[current];
404 hy*=info->mult;
405 /* guard lookup against out-of-range values */
406 hy=(hy<0?0:hy>255?255:hy);
407
408 render_line(lx, ly, hx, hy, FLOOR_fromdB_LOOKUP, out);
409
410 lx=hx;
411 ly=hy;
412 }
413 }
414 for(j=hx;j<n;j++)out[j]*=ly; /* be certain */
415 return(1);
416 }
417 memset(out,0,sizeof(*out)*n);
418 return(0);
419}
420
421/* export hooks */
422const vorbis_func_floor floor1_exportbundle ICONST_ATTR = {
423 &floor1_unpack,&floor1_look,&floor1_free_info,
424 &floor1_free_look,&floor1_inverse1,&floor1_inverse2
425};
426