summaryrefslogtreecommitdiff
path: root/apps/codecs/libcook/cook_fixpoint.h
diff options
context:
space:
mode:
Diffstat (limited to 'apps/codecs/libcook/cook_fixpoint.h')
-rw-r--r--apps/codecs/libcook/cook_fixpoint.h65
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
76static inline FIXP fixp_mult_su(FIXP a, FIXPU b) 77static 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)
101static 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
112static 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
86static inline int av_log2(unsigned int v) 127static 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
188static inline void imlt_math(COOKContext *q, FIXP *in) 230static 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}