summaryrefslogtreecommitdiff
path: root/apps/codecs/libwma/wmafixed.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/codecs/libwma/wmafixed.c')
-rw-r--r--apps/codecs/libwma/wmafixed.c350
1 files changed, 350 insertions, 0 deletions
diff --git a/apps/codecs/libwma/wmafixed.c b/apps/codecs/libwma/wmafixed.c
new file mode 100644
index 0000000000..6cb3d3c4a6
--- /dev/null
+++ b/apps/codecs/libwma/wmafixed.c
@@ -0,0 +1,350 @@
1//#include "asf.h"
2#include "wmadec.h"
3#include "wmafixed.h"
4#include <codecs.h>
5
6fixed64 IntTo64(int x){
7 fixed64 res = 0;
8 unsigned char *p = (unsigned char *)&res;
9
10#ifdef ROCKBOX_BIG_ENDIAN
11 p[5] = x & 0xff;
12 p[4] = (x & 0xff00)>>8;
13 p[3] = (x & 0xff0000)>>16;
14 p[2] = (x & 0xff000000)>>24;
15#else
16 p[2] = x & 0xff;
17 p[3] = (x & 0xff00)>>8;
18 p[4] = (x & 0xff0000)>>16;
19 p[5] = (x & 0xff000000)>>24;
20#endif
21 return res;
22}
23
24int IntFrom64(fixed64 x)
25{
26 int res = 0;
27 unsigned char *p = (unsigned char *)&x;
28
29#ifdef ROCKBOX_BIG_ENDIAN
30 res = p[5] | (p[4]<<8) | (p[3]<<16) | (p[2]<<24);
31#else
32 res = p[2] | (p[3]<<8) | (p[4]<<16) | (p[5]<<24);
33#endif
34 return res;
35}
36
37fixed32 Fixed32From64(fixed64 x)
38{
39 return x & 0xFFFFFFFF;
40}
41
42fixed64 Fixed32To64(fixed32 x)
43{
44 return (fixed64)x;
45}
46
47
48/*
49 Fixed precision multiply code.
50
51*/
52
53/*Sign-15.16 format */
54#ifdef CPU_ARM
55/* these are defines in wmafixed.h*/
56
57
58#elif defined(CPU_COLDFIRE)
59static inline int32_t fixmul32(int32_t x, int32_t y)
60{
61#if PRECISION != 16
62#warning Coldfire fixmul32() only works for PRECISION == 16
63#endif
64 int32_t t1;
65 asm (
66 "mac.l %[x], %[y], %%acc0 \n" /* multiply */
67 "mulu.l %[y], %[x] \n" /* get lower half, avoid emac stall */
68 "movclr.l %%acc0, %[t1] \n" /* get higher half */
69 "lsr.l #1, %[t1] \n"
70 "move.w %[t1], %[x] \n"
71 "swap %[x] \n"
72 : /* outputs */
73 [t1]"=&d"(t1),
74 [x] "+d" (x)
75 : /* inputs */
76 [y] "d" (y)
77 );
78 return x;
79}
80#else
81
82fixed32 fixmul32(fixed32 x, fixed32 y)
83{
84 fixed64 temp;
85 temp = x;
86 temp *= y;
87
88 temp >>= PRECISION;
89
90 return (fixed32)temp;
91}
92
93
94
95/*
96 Special fixmul32 that does a 16.16 x 1.31 multiply that returns a 16.16 value.
97 this is needed because the fft constants are all normalized to be less then 1
98 and can't fit into a 16 bit number without excessive rounding
99
100
101*/
102
103fixed32 fixmul32b(fixed32 x, fixed32 y)
104{
105 fixed64 temp;
106
107 temp = x;
108 temp *= y;
109
110 temp >>= 31; //16+31-16 = 31 bits
111
112 return (fixed32)temp;
113}
114
115#endif
116
117
118/*
119 Not performance senstitive code here
120
121*/
122
123
124fixed64 fixmul64byfixed(fixed64 x, fixed32 y)
125{
126
127 //return x * y;
128 return (x * y);
129 // return (fixed64) fixmul32(Fixed32From64(x),y);
130}
131
132
133fixed32 fixdiv32(fixed32 x, fixed32 y)
134{
135 fixed64 temp;
136
137 if(x == 0)
138 return 0;
139 if(y == 0)
140 return 0x7fffffff;
141 temp = x;
142 temp <<= PRECISION;
143 return (fixed32)(temp / y);
144}
145
146fixed64 fixdiv64(fixed64 x, fixed64 y)
147{
148 fixed64 temp;
149
150 if(x == 0)
151 return 0;
152 if(y == 0)
153 return 0x07ffffffffffffffLL;
154 temp = x;
155 temp <<= PRECISION64;
156 return (fixed64)(temp / y);
157}
158
159 fixed32 fixsqrt32(fixed32 x)
160{
161
162 unsigned long r = 0, s, v = (unsigned long)x;
163
164#define STEP(k) s = r + (1 << k * 2); r >>= 1; \
165 if (s <= v) { v -= s; r |= (1 << k * 2); }
166
167 STEP(15);
168 STEP(14);
169 STEP(13);
170 STEP(12);
171 STEP(11);
172 STEP(10);
173 STEP(9);
174 STEP(8);
175 STEP(7);
176 STEP(6);
177 STEP(5);
178 STEP(4);
179 STEP(3);
180 STEP(2);
181 STEP(1);
182 STEP(0);
183
184 return (fixed32)(r << (PRECISION / 2));
185}
186
187
188
189/* Inverse gain of circular cordic rotation in s0.31 format. */
190static const long cordic_circular_gain = 0xb2458939; /* 0.607252929 */
191
192/* Table of values of atan(2^-i) in 0.32 format fractions of pi where pi = 0xffffffff / 2 */
193static const unsigned long atan_table[] = {
194 0x1fffffff, /* +0.785398163 (or pi/4) */
195 0x12e4051d, /* +0.463647609 */
196 0x09fb385b, /* +0.244978663 */
197 0x051111d4, /* +0.124354995 */
198 0x028b0d43, /* +0.062418810 */
199 0x0145d7e1, /* +0.031239833 */
200 0x00a2f61e, /* +0.015623729 */
201 0x00517c55, /* +0.007812341 */
202 0x0028be53, /* +0.003906230 */
203 0x00145f2e, /* +0.001953123 */
204 0x000a2f98, /* +0.000976562 */
205 0x000517cc, /* +0.000488281 */
206 0x00028be6, /* +0.000244141 */
207 0x000145f3, /* +0.000122070 */
208 0x0000a2f9, /* +0.000061035 */
209 0x0000517c, /* +0.000030518 */
210 0x000028be, /* +0.000015259 */
211 0x0000145f, /* +0.000007629 */
212 0x00000a2f, /* +0.000003815 */
213 0x00000517, /* +0.000001907 */
214 0x0000028b, /* +0.000000954 */
215 0x00000145, /* +0.000000477 */
216 0x000000a2, /* +0.000000238 */
217 0x00000051, /* +0.000000119 */
218 0x00000028, /* +0.000000060 */
219 0x00000014, /* +0.000000030 */
220 0x0000000a, /* +0.000000015 */
221 0x00000005, /* +0.000000007 */
222 0x00000002, /* +0.000000004 */
223 0x00000001, /* +0.000000002 */
224 0x00000000, /* +0.000000001 */
225 0x00000000, /* +0.000000000 */
226};
227
228
229/*
230
231 Below here functions do not use standard fixed precision!
232*/
233
234
235/**
236 * Implements sin and cos using CORDIC rotation.
237 *
238 * @param phase has range from 0 to 0xffffffff, representing 0 and
239 * 2*pi respectively.
240 * @param cos return address for cos
241 * @return sin of phase, value is a signed value from LONG_MIN to LONG_MAX,
242 * representing -1 and 1 respectively.
243 *
244 * Gives at least 24 bits precision (last 2-8 bits or so are probably off)
245 */
246long fsincos(unsigned long phase, fixed32 *cos)
247{
248 int32_t x, x1, y, y1;
249 unsigned long z, z1;
250 int i;
251
252 /* Setup initial vector */
253 x = cordic_circular_gain;
254 y = 0;
255 z = phase;
256
257 /* The phase has to be somewhere between 0..pi for this to work right */
258 if (z < 0xffffffff / 4) {
259 /* z in first quadrant, z += pi/2 to correct */
260 x = -x;
261 z += 0xffffffff / 4;
262 } else if (z < 3 * (0xffffffff / 4)) {
263 /* z in third quadrant, z -= pi/2 to correct */
264 z -= 0xffffffff / 4;
265 } else {
266 /* z in fourth quadrant, z -= 3pi/2 to correct */
267 x = -x;
268 z -= 3 * (0xffffffff / 4);
269 }
270
271 /* Each iteration adds roughly 1-bit of extra precision */
272 for (i = 0; i < 31; i++) {
273 x1 = x >> i;
274 y1 = y >> i;
275 z1 = atan_table[i];
276
277 /* Decided which direction to rotate vector. Pivot point is pi/2 */
278 if (z >= 0xffffffff / 4) {
279 x -= y1;
280 y += x1;
281 z -= z1;
282 } else {
283 x += y1;
284 y -= x1;
285 z += z1;
286 }
287 }
288
289 if (cos)
290 *cos = x;
291
292 return y;
293}
294
295
296/*
297 Old trig functions. Still used in 1 place each.
298
299*/
300
301fixed32 fixsin32(fixed32 x)
302{
303
304 fixed64 x2, temp;
305 int sign = 1;
306
307 if(x < 0)
308 {
309 sign = -1;
310 x = -x;
311 }
312 while (x > 0x19220)
313 {
314 x -= M_PI_F;
315 sign = -sign;
316 }
317 if (x > 0x19220)
318 {
319 x = M_PI_F - x;
320 }
321 x2 = (fixed64)x * x;
322 x2 >>= PRECISION;
323 if(sign != 1)
324 {
325 x = -x;
326 }
327 /**
328 temp = ftofix32(-.0000000239f) * x2;
329 temp >>= PRECISION;
330 **/
331 temp = 0; // PJJ
332 //temp = (temp + 0x0) * x2; //MGG: this can't possibly do anything?
333 //temp >>= PRECISION;
334 temp = (temp - 0xd) * x2;
335 temp >>= PRECISION;
336 temp = (temp + 0x222) * x2;
337 temp >>= PRECISION;
338 temp = (temp - 0x2aab) * x2;
339 temp >>= PRECISION;
340 temp += 0x10000;
341 temp = temp * x;
342 temp >>= PRECISION;
343
344 return (fixed32)(temp);
345}
346
347fixed32 fixcos32(fixed32 x)
348{
349 return fixsin32(x - (M_PI_F>>1))*-1;
350}