summaryrefslogtreecommitdiff
path: root/apps/codecs/libmusepack/math.h
diff options
context:
space:
mode:
Diffstat (limited to 'apps/codecs/libmusepack/math.h')
-rw-r--r--apps/codecs/libmusepack/math.h350
1 files changed, 184 insertions, 166 deletions
diff --git a/apps/codecs/libmusepack/math.h b/apps/codecs/libmusepack/math.h
index f9e9d08b08..a015d45cbb 100644
--- a/apps/codecs/libmusepack/math.h
+++ b/apps/codecs/libmusepack/math.h
@@ -44,174 +44,192 @@
44 44
45#ifdef MPC_FIXED_POINT 45#ifdef MPC_FIXED_POINT
46 46
47 #ifdef _WIN32_WCE
48 #include <cmnintrin.h>
49 #define MPC_HAVE_MULHIGH
50 #endif
51
52 #define MPC_FIXED_POINT_SCALE_SHIFT (MPC_FIXED_POINT_SHIFT + MPC_FIXED_POINT_FRACTPART)
53 #define MPC_FIXED_POINT_SCALE (1 << (MPC_FIXED_POINT_SCALE_SHIFT - 1))
54 //in fixedpoint mode, results in decode output buffer are in -MPC_FIXED_POINT_SCALE ... MPC_FIXED_POINT_SCALE range
55
56 #define MPC_FIXED_POINT_FRACTPART 14
57 typedef mpc_int32_t MPC_SAMPLE_FORMAT;
58 typedef mpc_int64_t MPC_SAMPLE_FORMAT_MULTIPLY;
59
60 #define MAKE_MPC_SAMPLE(X) (MPC_SAMPLE_FORMAT)((double)(X) * (double)(((mpc_int64_t)1)<<MPC_FIXED_POINT_FRACTPART))
61 #define MAKE_MPC_SAMPLE_EX(X,Y) (MPC_SAMPLE_FORMAT)((double)(X) * (double)(((mpc_int64_t)1)<<(Y)))
62
63 #define MPC_SHR_RND(X, Y) ((X+(1<<(Y-1)))>>Y)
64
65 #if defined(CPU_COLDFIRE)
66
67 #define MPC_MULTIPLY(X,Y) mpc_multiply((X), (Y))
68 #define MPC_MULTIPLY_EX(X,Y,Z) mpc_multiply_ex((X), (Y), (Z))
69
70 static inline MPC_SAMPLE_FORMAT mpc_multiply(MPC_SAMPLE_FORMAT x,
71 MPC_SAMPLE_FORMAT y)
72 {
73 MPC_SAMPLE_FORMAT t1, t2;
74 asm volatile (
75 "mac.l %[x],%[y],%%acc0\n" /* multiply */
76 "mulu.l %[y],%[x] \n" /* get lower half, avoid emac stall */
77 "movclr.l %%acc0,%[t1] \n" /* get higher half */
78 "moveq.l #17,%[t2] \n"
79 "asl.l %[t2],%[t1] \n" /* hi <<= 17, plus one free */
80 "moveq.l #14,%[t2] \n"
81 "lsr.l %[t2],%[x] \n" /* (unsigned)lo >>= 14 */
82 "or.l %[x],%[t1] \n" /* combine result */
83 : /* outputs */
84 [t1]"=&d"(t1),
85 [t2]"=&d"(t2),
86 [x] "+d" (x)
87 : /* inputs */
88 [y] "d" (y)
89 );
90 return t1;
91 }
92
93 static inline MPC_SAMPLE_FORMAT mpc_multiply_ex(MPC_SAMPLE_FORMAT x,
94 MPC_SAMPLE_FORMAT y,
95 unsigned shift)
96 {
97 MPC_SAMPLE_FORMAT t1, t2;
98 asm volatile (
99 "mac.l %[x],%[y],%%acc0\n" /* multiply */
100 "mulu.l %[y],%[x] \n" /* get lower half, avoid emac stall */
101 "movclr.l %%acc0,%[t1] \n" /* get higher half */
102 "moveq.l #31,%[t2] \n"
103 "sub.l %[sh],%[t2] \n" /* t2 = 31 - shift */
104 "ble.s 1f \n"
105 "asl.l %[t2],%[t1] \n" /* hi <<= 31 - shift */
106 "lsr.l %[sh],%[x] \n" /* (unsigned)lo >>= shift */
107 "or.l %[x],%[t1] \n" /* combine result */
108 "bra.s 2f \n"
109 "1: \n"
110 "neg.l %[t2] \n" /* t2 = shift - 31 */
111 "asr.l %[t2],%[t1] \n" /* hi >>= t2 */
112 "2: \n"
113 : /* outputs */
114 [t1]"=&d"(t1),
115 [t2]"=&d"(t2),
116 [x] "+d" (x)
117 : /* inputs */
118 [y] "d" (y),
119 [sh]"d" (shift)
120 );
121 return t1;
122 }
123 #elif defined(CPU_ARM)
124 // borrowed and adapted from libMAD
125 #define MPC_MULTIPLY(X,Y) \
126 ({ \
127 MPC_SAMPLE_FORMAT low; \
128 MPC_SAMPLE_FORMAT high; \
129 asm volatile ( /* will calculate: result = (X*Y)>>14 */ \
130 "smull %0,%1,%2,%3 \n\t" /* multiply with result %0 [0..31], %1 [32..63] */ \
131 "mov %0, %0, lsr #14 \n\t" /* %0 = %0 >> 14 */ \
132 "orr %0, %0, %1, lsl #18 \n\t"/* result = %0 OR (%1 << 18) */ \
133 : "=&r"(low), "=&r" (high) \
134 : "r"(X),"r"(Y)); \
135 low; \
136 })
137
138 // borrowed and adapted from libMAD
139 #define MPC_MULTIPLY_EX(X,Y,Z) \
140 ({ \
141 MPC_SAMPLE_FORMAT low; \
142 MPC_SAMPLE_FORMAT high; \
143 asm volatile ( /* will calculate: result = (X*Y)>>Z */ \
144 "smull %0,%1,%2,%3 \n\t" /* multiply with result %0 [0..31], %1 [32..63] */ \
145 "mov %0, %0, lsr %4 \n\t" /* %0 = %0 >> Z */ \
146 "orr %0, %0, %1, lsl %5 \n\t" /* result = %0 OR (%1 << (32-Z)) */ \
147 : "=&r"(low), "=&r" (high) \
148 : "r"(X),"r"(Y),"r"(Z),"r"(32-Z)); \
149 low; \
150 })
151 #else /* libmusepack standard */
152
153 #define MPC_MULTIPLY_NOTRUNCATE(X,Y) \
154 (((MPC_SAMPLE_FORMAT_MULTIPLY)(X) * (MPC_SAMPLE_FORMAT_MULTIPLY)(Y)) >> MPC_FIXED_POINT_FRACTPART)
155
156 #define MPC_MULTIPLY_EX_NOTRUNCATE(X,Y,Z) \
157 (((MPC_SAMPLE_FORMAT_MULTIPLY)(X) * (MPC_SAMPLE_FORMAT_MULTIPLY)(Y)) >> (Z))
158
159 #ifdef _DEBUG
160 static inline MPC_SAMPLE_FORMAT MPC_MULTIPLY(MPC_SAMPLE_FORMAT item1,MPC_SAMPLE_FORMAT item2)
161 {
162 MPC_SAMPLE_FORMAT_MULTIPLY temp = MPC_MULTIPLY_NOTRUNCATE(item1,item2);
163 assert(temp == (MPC_SAMPLE_FORMAT_MULTIPLY)(MPC_SAMPLE_FORMAT)temp);
164 return (MPC_SAMPLE_FORMAT)temp;
165 }
166
167 static inline MPC_SAMPLE_FORMAT MPC_MULTIPLY_EX(MPC_SAMPLE_FORMAT item1,MPC_SAMPLE_FORMAT item2,unsigned shift)
168 {
169 MPC_SAMPLE_FORMAT_MULTIPLY temp = MPC_MULTIPLY_EX_NOTRUNCATE(item1,item2,shift);
170 assert(temp == (MPC_SAMPLE_FORMAT_MULTIPLY)(MPC_SAMPLE_FORMAT)temp);
171 return (MPC_SAMPLE_FORMAT)temp;
172 }
173 #else
174 #define MPC_MULTIPLY(X,Y) ((MPC_SAMPLE_FORMAT)MPC_MULTIPLY_NOTRUNCATE(X,Y))
175 #define MPC_MULTIPLY_EX(X,Y,Z) ((MPC_SAMPLE_FORMAT)MPC_MULTIPLY_EX_NOTRUNCATE(X,Y,Z))
176 #endif
177
178 #endif
179
180 #ifdef MPC_HAVE_MULHIGH
181 #define MPC_MULTIPLY_FRACT(X,Y) _MulHigh(X,Y)
182 #else
183 #if defined(CPU_COLDFIRE)
184 /* loses one bit of accuracy. The rest of the macros won't be as easy as this... */
185 #define MPC_MULTIPLY_FRACT(X,Y) \
186 ({ \
187 MPC_SAMPLE_FORMAT t; \
188 asm volatile ( \
189 "mac.l %[A], %[B], %%acc0\n\t" \
190 "movclr.l %%acc0, %[t]\n\t" \
191 "asr.l #1, %[t]\n\t" \
192 : [t] "=d" (t) \
193 : [A] "r" ((X)), [B] "r" ((Y))); \
194 t; \
195 })
196 #elif defined(CPU_ARM)
197 // borrowed and adapted from libMAD
198 #define MPC_MULTIPLY_FRACT(X,Y) \
199 ({ \
200 MPC_SAMPLE_FORMAT low; \
201 MPC_SAMPLE_FORMAT high; \
202 asm volatile ( /* will calculate: result = (X*Y)>>32 */ \
203 "smull %0,%1,%2,%3 \n\t" /* multiply with result %0 [0..31], %1 [32..63] */ \
204 : "=&r"(low), "=&r" (high) /* result = %1 [32..63], saves the >>32 */ \
205 : "r"(X),"r"(Y)); \
206 high; \
207 })
208 #else
209 #define MPC_MULTIPLY_FRACT(X,Y) MPC_MULTIPLY_EX(X,Y,32)
210 #endif
211 #endif
212
213 #define MPC_MAKE_FRACT_CONST(X) (MPC_SAMPLE_FORMAT)((X) * (double)(((mpc_int64_t)1)<<32) )
214
215 #define MPC_MULTIPLY_FLOAT_INT(X,Y) ((X)*(Y))
47 216
48#ifdef _WIN32_WCE
49
50#include <cmnintrin.h>
51
52#define MPC_HAVE_MULHIGH
53
54#endif
55
56
57#define MPC_FIXED_POINT_SCALE_SHIFT (MPC_FIXED_POINT_SHIFT + MPC_FIXED_POINT_FRACTPART)
58#define MPC_FIXED_POINT_SCALE (1 << (MPC_FIXED_POINT_SCALE_SHIFT - 1))
59
60
61//in fixedpoint mode, results in decode output buffer are in -MPC_FIXED_POINT_SCALE ... MPC_FIXED_POINT_SCALE range
62
63#define MPC_FIXED_POINT_FRACTPART 14
64typedef mpc_int32_t MPC_SAMPLE_FORMAT;
65
66typedef mpc_int64_t MPC_SAMPLE_FORMAT_MULTIPLY;
67
68#define MAKE_MPC_SAMPLE(X) (MPC_SAMPLE_FORMAT)((double)(X) * (double)(((mpc_int64_t)1)<<MPC_FIXED_POINT_FRACTPART))
69#define MAKE_MPC_SAMPLE_EX(X,Y) (MPC_SAMPLE_FORMAT)((double)(X) * (double)(((mpc_int64_t)1)<<(Y)))
70
71#if defined(CPU_COLDFIRE)
72
73#define MPC_MULTIPLY(X,Y) mpc_multiply((X), (Y))
74#define MPC_MULTIPLY_EX(X,Y,Z) mpc_multiply_ex((X), (Y), (Z))
75
76static inline MPC_SAMPLE_FORMAT mpc_multiply(MPC_SAMPLE_FORMAT x,
77 MPC_SAMPLE_FORMAT y)
78{
79 MPC_SAMPLE_FORMAT t1, t2;
80 asm volatile (
81 "mac.l %[x],%[y],%%acc0\n" /* multiply */
82 "mulu.l %[y],%[x] \n" /* get lower half, avoid emac stall */
83 "movclr.l %%acc0,%[t1] \n" /* get higher half */
84 "moveq.l #17,%[t2] \n"
85 "asl.l %[t2],%[t1] \n" /* hi <<= 17, plus one free */
86 "moveq.l #14,%[t2] \n"
87 "lsr.l %[t2],%[x] \n" /* (unsigned)lo >>= 14 */
88 "or.l %[x],%[t1] \n" /* combine result */
89 : /* outputs */
90 [t1]"=&d"(t1),
91 [t2]"=&d"(t2),
92 [x] "+d" (x)
93 : /* inputs */
94 [y] "d" (y)
95 );
96 return t1;
97}
98
99static inline MPC_SAMPLE_FORMAT mpc_multiply_ex(MPC_SAMPLE_FORMAT x,
100 MPC_SAMPLE_FORMAT y,
101 unsigned shift)
102{
103 MPC_SAMPLE_FORMAT t1, t2;
104 asm volatile (
105 "mac.l %[x],%[y],%%acc0\n" /* multiply */
106 "mulu.l %[y],%[x] \n" /* get lower half, avoid emac stall */
107 "movclr.l %%acc0,%[t1] \n" /* get higher half */
108 "moveq.l #31,%[t2] \n"
109 "sub.l %[sh],%[t2] \n" /* t2 = 31 - shift */
110 "ble.s 1f \n"
111 "asl.l %[t2],%[t1] \n" /* hi <<= 31 - shift */
112 "lsr.l %[sh],%[x] \n" /* (unsigned)lo >>= shift */
113 "or.l %[x],%[t1] \n" /* combine result */
114 "bra.s 2f \n"
115 "1: \n"
116 "neg.l %[t2] \n" /* t2 = shift - 31 */
117 "asr.l %[t2],%[t1] \n" /* hi >>= t2 */
118 "2: \n"
119 : /* outputs */
120 [t1]"=&d"(t1),
121 [t2]"=&d"(t2),
122 [x] "+d" (x)
123 : /* inputs */
124 [y] "d" (y),
125 [sh]"d" (shift)
126 );
127 return t1;
128}
129#else /* libmusepack standard */
130
131#define MPC_MULTIPLY_NOTRUNCATE(X,Y) \
132 (((MPC_SAMPLE_FORMAT_MULTIPLY)(X) * (MPC_SAMPLE_FORMAT_MULTIPLY)(Y)) >> MPC_FIXED_POINT_FRACTPART)
133
134#define MPC_MULTIPLY_EX_NOTRUNCATE(X,Y,Z) \
135 (((MPC_SAMPLE_FORMAT_MULTIPLY)(X) * (MPC_SAMPLE_FORMAT_MULTIPLY)(Y)) >> (Z))
136
137#ifdef _DEBUG
138static inline MPC_SAMPLE_FORMAT MPC_MULTIPLY(MPC_SAMPLE_FORMAT item1,MPC_SAMPLE_FORMAT item2)
139{
140 MPC_SAMPLE_FORMAT_MULTIPLY temp = MPC_MULTIPLY_NOTRUNCATE(item1,item2);
141 assert(temp == (MPC_SAMPLE_FORMAT_MULTIPLY)(MPC_SAMPLE_FORMAT)temp);
142 return (MPC_SAMPLE_FORMAT)temp;
143}
144
145static inline MPC_SAMPLE_FORMAT MPC_MULTIPLY_EX(MPC_SAMPLE_FORMAT item1,MPC_SAMPLE_FORMAT item2,unsigned shift)
146{
147 MPC_SAMPLE_FORMAT_MULTIPLY temp = MPC_MULTIPLY_EX_NOTRUNCATE(item1,item2,shift);
148 assert(temp == (MPC_SAMPLE_FORMAT_MULTIPLY)(MPC_SAMPLE_FORMAT)temp);
149 return (MPC_SAMPLE_FORMAT)temp;
150}
151#else
152#define MPC_MULTIPLY(X,Y) ((MPC_SAMPLE_FORMAT)MPC_MULTIPLY_NOTRUNCATE(X,Y))
153#define MPC_MULTIPLY_EX(X,Y,Z) ((MPC_SAMPLE_FORMAT)MPC_MULTIPLY_EX_NOTRUNCATE(X,Y,Z))
154#endif
155
156#endif
157
158#ifdef MPC_HAVE_MULHIGH
159#define MPC_MULTIPLY_FRACT(X,Y) _MulHigh(X,Y)
160#else
161#if defined(CPU_COLDFIRE)
162/* loses one bit of accuracy.
163 the rest of the macros won't be as easy as this... */
164#define MPC_MULTIPLY_FRACT(X,Y) \
165 ({ \
166 MPC_SAMPLE_FORMAT t; \
167 asm volatile ( \
168 "mac.l %[A], %[B], %%acc0\n\t" \
169 "movclr.l %%acc0, %[t]\n\t" \
170 "asr.l #1, %[t]\n\t" \
171 : [t] "=d" (t) \
172 : [A] "r" ((X)), [B] "r" ((Y))); \
173 t; \
174 })
175#else 217#else
176#define MPC_MULTIPLY_FRACT(X,Y) MPC_MULTIPLY_EX(X,Y,32) 218 //in floating-point mode, decoded samples are in -1...1 range
177#endif 219
178#endif 220 typedef float MPC_SAMPLE_FORMAT;
179 221
180#define MPC_MAKE_FRACT_CONST(X) (MPC_SAMPLE_FORMAT)((X) * (double)(((mpc_int64_t)1)<<32) ) 222 #define MAKE_MPC_SAMPLE(X) ((MPC_SAMPLE_FORMAT)(X))
181#define MPC_MULTIPLY_FRACT_CONST(X,Y) MPC_MULTIPLY_FRACT(X,MPC_MAKE_FRACT_CONST(Y)) 223 #define MAKE_MPC_SAMPLE_EX(X,Y) ((MPC_SAMPLE_FORMAT)(X))
182#define MPC_MULTIPLY_FRACT_CONST_FIX(X,Y,Z) ( MPC_MULTIPLY_FRACT(X,MPC_MAKE_FRACT_CONST( Y / (1<<(Z)) )) << (Z) ) 224
183#define MPC_MULTIPLY_FRACT_CONST_SHR(X,Y,Z) MPC_MULTIPLY_FRACT(X,MPC_MAKE_FRACT_CONST( Y / (1<<(Z)) )) 225 #define MPC_MULTIPLY_FRACT(X,Y) ((X)*(Y))
184 226 #define MPC_MAKE_FRACT_CONST(X) (X)
185#define MPC_MULTIPLY_FLOAT_INT(X,Y) ((X)*(Y)) 227
186#define MPC_SCALE_CONST(X,Y,Z) MPC_MULTIPLY_EX(X,MAKE_MPC_SAMPLE_EX(Y,Z),(Z)) 228 #define MPC_MULTIPLY_FLOAT_INT(X,Y) ((X)*(Y))
187#define MPC_SCALE_CONST_SHL(X,Y,Z,S) MPC_MULTIPLY_EX(X,MAKE_MPC_SAMPLE_EX(Y,Z),(Z)-(S)) 229 #define MPC_MULTIPLY(X,Y) ((X)*(Y))
188#define MPC_SCALE_CONST_SHR(X,Y,Z,S) MPC_MULTIPLY_EX(X,MAKE_MPC_SAMPLE_EX(Y,Z),(Z)+(S)) 230 #define MPC_MULTIPLY_EX(X,Y,Z) ((X)*(Y))
189#define MPC_SHR(X,Y) ((X)>>(Y)) 231
190#define MPC_SHL(X,Y) ((X)<<(Y)) 232 #define MPC_SHR_RND(X, Y) (X)
191
192#else
193
194//in floating-point mode, decoded samples are in -1...1 range
195
196typedef float MPC_SAMPLE_FORMAT;
197
198#define MAKE_MPC_SAMPLE(X) ((MPC_SAMPLE_FORMAT)(X))
199#define MAKE_MPC_SAMPLE_EX(X,Y) ((MPC_SAMPLE_FORMAT)(X))
200
201#define MPC_MULTIPLY_FRACT(X,Y) ((X)*(Y))
202#define MPC_MAKE_FRACT_CONST(X) (X)
203#define MPC_MULTIPLY_FRACT_CONST(X,Y) MPC_MULTPLY_FRACT(X,MPC_MAKE_FRACT_CONST(Y))
204#define MPC_MULTIPLY_FRACT_CONST_SHR(X,Y,Z) MPC_MULTIPLY_FRACT(X,MPC_MAKE_FRACT_CONST( Y ))
205#define MPC_MULTIPLY_FRACT_CONST_FIX(X,Y,Z) MPC_MULTIPLY_FRACT(X,MPC_MAKE_FRACT_CONST( Y ))
206
207#define MPC_MULTIPLY_FLOAT_INT(X,Y) ((X)*(Y))
208#define MPC_MULTIPLY(X,Y) ((X)*(Y))
209#define MPC_MULTIPLY_EX(X,Y,Z) ((X)*(Y))
210#define MPC_SCALE_CONST(X,Y,Z) ((X)*(Y))
211#define MPC_SCALE_CONST_SHL(X,Y,Z,S) ((X)*(Y))
212#define MPC_SCALE_CONST_SHR(X,Y,Z,S) ((X)*(Y))
213#define MPC_SHR(X,Y) (X)
214#define MPC_SHL(X,Y) (X)
215 233
216#endif 234#endif
217 235