SHOW:
|
|
- or go back to the newest paste.
1 | So I was scrolling through twinvq_tables.h and almost all of it is just a shitload of VQ tables and yes the spec really DOES explicitly define each and every single one of them. However, if you get to the very end, you'll notice a surprise: | |
2 | ||
3 | #include <stdint.h> | |
4 | static inline unsigned int av_log2(unsigned int x) { | |
5 | unsigned int ret; | |
6 | x |= 1; | |
7 | __asm__ volatile("bsr %1, %0 \n\t" :"=a"(ret) :"r"(x)); | |
8 | return ret; | |
9 | } | |
10 | ||
11 | static const uint8_t tab7[][35] = { | |
12 | {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0}, | |
13 | {0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0}, | |
14 | {0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, | |
15 | {0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0}, | |
16 | {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0}, | |
17 | {0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0}, | |
18 | {0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, | |
19 | {0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0}, | |
20 | {0,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,1}, | |
21 | {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0}, | |
22 | {0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0} | |
23 | }; | |
24 | ||
25 | static const uint8_t tab8[][5] = { | |
26 | {0, 0, 0, 1, 1}, | |
27 | {0, 1, 0, 0, 1}, | |
28 | {1, 1, 0, 0, 0}, | |
29 | {1, 0, 0, 1, 0}, | |
30 | {0, 0, 0, 1, 1}, | |
31 | {0, 1, 0, 0, 1}, | |
32 | {1, 1, 0, 0, 0}, | |
33 | {1, 0, 0, 1, 0}, | |
34 | {0, 0, 0, 1, 1}, | |
35 | {0, 1, 0, 0, 1}, | |
36 | {1, 1, 0, 0, 0}, | |
37 | {0, 0, 0, 0, 0}, | |
38 | {0, 1, 0, 1, 0} | |
39 | }; | |
40 | ||
41 | static const uint8_t tab9[][45] = { | |
42 | { | |
43 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
44 | 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 | |
45 | },{ | |
46 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
47 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 | |
48 | },{ | |
49 | 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
50 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
51 | },{ | |
52 | 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
53 | 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
54 | },{ | |
55 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
56 | 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 | |
57 | },{ | |
58 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
59 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 | |
60 | },{ | |
61 | 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
62 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
63 | },{ | |
64 | 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
65 | 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
66 | },{ | |
67 | 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, | |
68 | 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0 | |
69 | },{ | |
70 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, | |
71 | 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
72 | } | |
73 | }; | |
74 | ||
75 | static const uint8_t tab10[][25] = | |
76 | { | |
77 | {1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0}, | |
78 | {1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0}, | |
79 | {1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0}, | |
80 | {1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0}, | |
81 | {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, | |
82 | {0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1}, | |
83 | {0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1}, | |
84 | {1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0}, | |
85 | {0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1} | |
86 | }; | |
87 | ||
88 | static const uint8_t tab11[][55] = { | |
89 | { | |
90 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
91 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, | |
92 | 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0 | |
93 | },{ | |
94 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, | |
95 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
96 | 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, | |
97 | },{ | |
98 | 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, | |
99 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
100 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
101 | },{ | |
102 | 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
103 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, | |
104 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
105 | }, { | |
106 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
107 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, | |
108 | 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, | |
109 | },{ | |
110 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, | |
111 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
112 | 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, | |
113 | },{ | |
114 | 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, | |
115 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
116 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
117 | },{ | |
118 | 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
119 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, | |
120 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
121 | },{ | |
122 | 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, | |
123 | 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
124 | 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, | |
125 | } | |
126 | }; | |
127 | ||
128 | static const uint8_t tab12[][15] = { | |
129 | {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0}, | |
130 | {0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0}, | |
131 | {0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, | |
132 | {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}, | |
133 | {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0}, | |
134 | {0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0}, | |
135 | {0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, | |
136 | {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}, | |
137 | {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0}, | |
138 | {0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0}, | |
139 | {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1}, | |
140 | }; | |
141 | ||
142 | static const struct { | |
143 | int size; | |
144 | const uint8_t *tab; | |
145 | } tabs[] = { | |
146 | {0 , NULL}, | |
147 | {5 , &tab8 [0][0]},{5 , &tab8 [0][0]}, {15, &tab12[0][0]}, | |
148 | {5 , &tab8 [0][0]},{25, &tab10[0][0]}, {15, &tab12[0][0]}, | |
149 | {35, &tab7 [0][0]},{5 , &tab8 [0][0]}, {45, &tab9 [0][0]}, | |
150 | {25, &tab10[0][0]},{55, &tab11[0][0]}, {15, &tab12[0][0]} | |
151 | }; | |
152 | ||
153 | - | In twinqv.c |
153 | + | /* In twinqv.c */ |
154 | /** | |
155 | * Evaluate a*b/400 rounded to the nearest integer. When, for example, | |
156 | * a*b == 200 and the nearest integer is ill-defined, use a table to emulate | |
157 | * the following broken float-based implementation used by the binary decoder: | |
158 | * | |
159 | * \code | |
160 | * static int very_broken_op(int a, int b) | |
161 | * { | |
162 | * static float test; // Ugh, force gcc to do the division first... | |
163 | * | |
164 | * test = a/400.; | |
165 | * return b * test + 0.5; | |
166 | * } | |
167 | * \endcode | |
168 | * | |
169 | * @note if this function is replaced by just ROUNDED_DIV(a*b,400.), the stddev | |
170 | * between the original file (before encoding with Yamaha encoder) and the | |
171 | * decoded output increases, which leads one to believe that the encoder expects | |
172 | * exactly this broken calculation. | |
173 | */ | |
174 | int very_broken_op(int a, int b) | |
175 | { | |
176 | int x = a*b + 200; | |
177 | int size; | |
178 | const uint8_t *rtab; | |
179 | ||
180 | if (x%400 || b%5) | |
181 | return x/400; | |
182 | ||
183 | x /= 400; | |
184 | ||
185 | size = tabs[b/5].size; | |
186 | rtab = tabs[b/5].tab; | |
187 | return x - rtab[size*av_log2(2*(x - 1)/size)+(x - 1)%size]; | |
188 | } |