summaryrefslogtreecommitdiff
path: root/apps/codecs/libmusepack/math.h
diff options
context:
space:
mode:
authorThom Johansen <thomj@rockbox.org>2007-08-30 11:41:05 +0000
committerThom Johansen <thomj@rockbox.org>2007-08-30 11:41:05 +0000
commit953348f1ba4845984980ad71b05c17d4ded84b30 (patch)
tree728605bcacc89b221e71065d0d092d1b06132799 /apps/codecs/libmusepack/math.h
parentc7b3f8be9b1ea505463c3d8ba17740af36c6df2c (diff)
downloadrockbox-953348f1ba4845984980ad71b05c17d4ded84b30.tar.gz
rockbox-953348f1ba4845984980ad71b05c17d4ded84b30.zip
FS #7166. Musepack optimizations and cleanups. Huge speedup on ARM. Note that all ARM (Ipod/Sansa/Gigabeat) targets will now play back Musepack files with somewhat reduced accuracy. Please get in touch via forums or Flyspray if you've got sample files where this is very apparent. Most users should hear no difference.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@14531 a1c6a512-1295-4272-9138-f99709370657
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