diff options
Diffstat (limited to 'apps/codecs/libcook/cook_fixpoint.h')
-rw-r--r-- | apps/codecs/libcook/cook_fixpoint.h | 65 |
1 files changed, 56 insertions, 9 deletions
diff --git a/apps/codecs/libcook/cook_fixpoint.h b/apps/codecs/libcook/cook_fixpoint.h index 2e7f68913b..c2ab9299c6 100644 --- a/apps/codecs/libcook/cook_fixpoint.h +++ b/apps/codecs/libcook/cook_fixpoint.h | |||
@@ -73,14 +73,55 @@ static inline FIXP fixp_pow2(FIXP x, int i) | |||
73 | * @param a fix point value | 73 | * @param a fix point value |
74 | * @param b fix point fraction, 0 <= b < 1 | 74 | * @param b fix point fraction, 0 <= b < 1 |
75 | */ | 75 | */ |
76 | |||
76 | static inline FIXP fixp_mult_su(FIXP a, FIXPU b) | 77 | static inline FIXP fixp_mult_su(FIXP a, FIXPU b) |
77 | { | 78 | { |
79 | |||
78 | int32_t hb = (a >> 16) * b; | 80 | int32_t hb = (a >> 16) * b; |
79 | uint32_t lb = (a & 0xffff) * b; | 81 | uint32_t lb = (a & 0xffff) * b; |
80 | 82 | ||
81 | return hb + (lb >> 16) + ((lb & 0x8000) >> 15); | 83 | return hb + (lb >> 16) + ((lb & 0x8000) >> 15); |
82 | } | 84 | } |
83 | 85 | ||
86 | /* Faster version of the above using 32x32=64 bit multiply */ | ||
87 | #ifdef CPU_ARM | ||
88 | #define fixmul31(x, y) \ | ||
89 | ({ int32_t __hi; \ | ||
90 | uint32_t __lo; \ | ||
91 | int32_t __result; \ | ||
92 | asm ("smull %0, %1, %3, %4\n\t" \ | ||
93 | "movs %2, %1, lsl #1" \ | ||
94 | : "=&r" (__lo), "=&r" (__hi), "=r" (__result) \ | ||
95 | : "%r" (x), "r" (y) \ | ||
96 | : "cc"); \ | ||
97 | __result; \ | ||
98 | }) | ||
99 | |||
100 | #elif defined(CPU_COLDFIRE) | ||
101 | static inline int32_t fixmul31(int32_t x, int32_t y) | ||
102 | { | ||
103 | asm ( | ||
104 | "mac.l %[x], %[y], %%acc0 \n" /* multiply */ | ||
105 | "movclr.l %%acc0, %[x] \n" /* get higher half */ | ||
106 | : [x] "+d" (x) | ||
107 | : [y] "d" (y) | ||
108 | ); | ||
109 | return x; | ||
110 | } | ||
111 | #else | ||
112 | static inline int32_t fixmul31(int32_t x, int32_t y) | ||
113 | { | ||
114 | int64_t temp; | ||
115 | |||
116 | temp = x; | ||
117 | temp *= y; | ||
118 | |||
119 | temp >>= 31; //16+31-16 = 31 bits | ||
120 | |||
121 | return (int32_t)temp; | ||
122 | } | ||
123 | #endif | ||
124 | |||
84 | /* math functions taken from libavutil/common.h */ | 125 | /* math functions taken from libavutil/common.h */ |
85 | 126 | ||
86 | static inline int av_log2(unsigned int v) | 127 | static inline int av_log2(unsigned int v) |
@@ -162,7 +203,7 @@ static inline void imlt_math(COOKContext *q, FIXP *in) | |||
162 | const int n = q->samples_per_channel; | 203 | const int n = q->samples_per_channel; |
163 | const int step = 4 << (10 - av_log2(n)); | 204 | const int step = 4 << (10 - av_log2(n)); |
164 | int i = 0, j = step>>1; | 205 | int i = 0, j = step>>1; |
165 | 206 | ||
166 | cook_mdct_backward(2 * n, in, q->mono_mdct_output); | 207 | cook_mdct_backward(2 * n, in, q->mono_mdct_output); |
167 | 208 | ||
168 | do { | 209 | do { |
@@ -184,30 +225,35 @@ static inline void imlt_math(COOKContext *q, FIXP *in) | |||
184 | } | 225 | } |
185 | #else | 226 | #else |
186 | #include <codecs/lib/codeclib.h> | 227 | #include <codecs/lib/codeclib.h> |
228 | #include <codecs/lib/mdct_lookup.h> | ||
187 | 229 | ||
188 | static inline void imlt_math(COOKContext *q, FIXP *in) | 230 | static inline void imlt_math(COOKContext *q, FIXP *in) |
189 | { | 231 | { |
190 | const int n = q->samples_per_channel; | 232 | const int n = q->samples_per_channel; |
191 | const int step = 4 << (10 - av_log2(n)); | 233 | const int step = 2 << (10 - av_log2(n)); |
192 | int i = 0, j = step>>1; | 234 | int i = 0, j = 0; |
193 | 235 | ||
194 | mdct_backward(2 * n, in, q->mono_mdct_output); | 236 | mdct_backward(2 * n, in, q->mono_mdct_output); |
195 | 237 | ||
196 | do { | 238 | do { |
197 | FIXP tmp = q->mono_mdct_output[i]; | 239 | FIXP tmp = q->mono_mdct_output[i]; |
198 | 240 | ||
199 | q->mono_mdct_output[i] = | 241 | q->mono_mdct_output[i] = |
200 | fixp_mult_su(-q->mono_mdct_output[n + i], sincos_lookup[j]); | 242 | fixmul31(-q->mono_mdct_output[n + i], (sincos_lookup0[j])); |
201 | q->mono_mdct_output[n + i] = fixp_mult_su(tmp, sincos_lookup[j+1]); | 243 | |
244 | q->mono_mdct_output[n + i] = fixmul31(tmp, (sincos_lookup0[j+1]) ); | ||
245 | |||
202 | j += step; | 246 | j += step; |
247 | |||
203 | } while (++i < n/2); | 248 | } while (++i < n/2); |
249 | |||
204 | do { | 250 | do { |
205 | FIXP tmp = q->mono_mdct_output[i]; | 251 | FIXP tmp = q->mono_mdct_output[i]; |
206 | 252 | ||
207 | j -= step; | 253 | j -= step; |
208 | q->mono_mdct_output[i] = | 254 | q->mono_mdct_output[i] = |
209 | fixp_mult_su(-q->mono_mdct_output[n + i], sincos_lookup[j+1]); | 255 | fixmul31(-q->mono_mdct_output[n + i], (sincos_lookup0[j+1]) ); |
210 | q->mono_mdct_output[n + i] = fixp_mult_su(tmp, sincos_lookup[j]); | 256 | q->mono_mdct_output[n + i] = fixmul31(tmp, (sincos_lookup0[j]) ); |
211 | } while (++i < n); | 257 | } while (++i < n); |
212 | } | 258 | } |
213 | #endif | 259 | #endif |
@@ -291,6 +337,7 @@ static inline void output_math(COOKContext *q, int16_t *out, int chan) | |||
291 | int j; | 337 | int j; |
292 | 338 | ||
293 | for (j = 0; j < q->samples_per_channel; j++) { | 339 | for (j = 0; j < q->samples_per_channel; j++) { |
294 | out[chan + q->nb_channels * j] = fixp_pow2(q->mono_mdct_output[j], -11); | 340 | out[chan + q->nb_channels * j] = |
341 | av_clip(fixp_pow2(q->mono_mdct_output[j], -11), -32768, 32767); | ||
295 | } | 342 | } |
296 | } | 343 | } |