summaryrefslogtreecommitdiff
path: root/apps/dsp.h
diff options
context:
space:
mode:
authorThom Johansen <thomj@rockbox.org>2007-02-05 01:01:15 +0000
committerThom Johansen <thomj@rockbox.org>2007-02-05 01:01:15 +0000
commit5f48e1590f16049aaaf916ad72d6016a4e7ffa5c (patch)
tree4438397a1a44cf301f0f4675388f92ee1e8ddb38 /apps/dsp.h
parent7170a00daad917993d3fed460f1122f543d2b0ea (diff)
downloadrockbox-5f48e1590f16049aaaf916ad72d6016a4e7ffa5c.zip
rockbox-5f48e1590f16049aaaf916ad72d6016a4e7ffa5c.tar.gz
rockbox-5f48e1590f16049aaaf916ad72d6016a4e7ffa5c.tar.bz2
rockbox-5f48e1590f16049aaaf916ad72d6016a4e7ffa5c.tar.xz
Optimise EQ coef calculation routines for both speed and size. Move now unneeded fsqrt function to plugin fixed point library in case it'll be needed. Move all fixed point helper macros to dsp.h. Added FRACMUL_SHL macro to facilitate high-precision shifting of 64 bit multiplies and remove rounding from macsr in main thread to make this work as intended.
Tested quite thorougly, but as always, be careful with your ears. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@12203 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/dsp.h')
-rw-r--r--apps/dsp.h159
1 files changed, 159 insertions, 0 deletions
diff --git a/apps/dsp.h b/apps/dsp.h
index 1a2b878..ccea8cb 100644
--- a/apps/dsp.h
+++ b/apps/dsp.h
@@ -47,6 +47,165 @@ enum {
DSP_CROSSFEED
};
+/* A bunch of fixed point assembler helper macros */
+#if defined(CPU_COLDFIRE) && !defined(SIMULATOR)
+
+/* Multiply two S.31 fractional integers and return the sign bit and the
+ * 31 most significant bits of the result.
+ */
+#define FRACMUL(x, y) \
+({ \
+ long t; \
+ asm volatile ("mac.l %[a], %[b], %%acc0\n\t" \
+ "movclr.l %%acc0, %[t]\n\t" \
+ : [t] "=r" (t) : [a] "r" (x), [b] "r" (y)); \
+ t; \
+})
+
+/* Multiply two S.31 fractional integers, and return the 32 most significant
+ * bits after a shift left by the constant z. NOTE: Only works for shifts of
+ * up to 8 on Coldfire!
+ */
+#define FRACMUL_SHL(x, y, z) \
+({ \
+ long t, t2; \
+ asm volatile ("mac.l %[a], %[b], %%acc0\n\t" \
+ "moveq.l %[d], %[t]\n\t" \
+ "move.l %%accext01, %[t2]\n\t" \
+ "and.l %[mask], %[t2]\n\t" \
+ "lsr.l %[t], %[t2]\n\t" \
+ "movclr.l %%acc0, %[t]\n\t" \
+ "asl.l %[c], %[t]\n\t" \
+ "or.l %[t2], %[t]\n\t" \
+ : [t] "=d" (t), [t2] "=d" (t2) \
+ : [a] "r" (x), [b] "r" (y), [mask] "d" (0xff), \
+ [c] "i" ((z)), [d] "i" (8 - (z))); \
+ t; \
+})
+
+/* Multiply one S.31-bit and one S8.23 fractional integer and return the
+ * sign bit and the 31 most significant bits of the result.
+ */
+#define FRACMUL_8(x, y) \
+({ \
+ long t; \
+ long u; \
+ asm volatile ("mac.l %[a], %[b], %%acc0\n\t" \
+ "move.l %%accext01, %[u]\n\t" \
+ "movclr.l %%acc0, %[t]\n\t" \
+ : [t] "=r" (t), [u] "=r" (u) : [a] "r" (x), [b] "r" (y)); \
+ (t << 8) | (u & 0xff); \
+})
+
+/* Multiply one S.31-bit and one S8.23 fractional integer and return the
+ * sign bit and the 31 most significant bits of the result. Load next value
+ * to multiply with into x from s (and increase s); x must contain the
+ * initial value.
+ */
+#define FRACMUL_8_LOOP_PART(x, s, d, y) \
+{ \
+ long u; \
+ asm volatile ("mac.l %[a], %[b], (%[c])+, %[a], %%acc0\n\t" \
+ "move.l %%accext01, %[u]\n\t" \
+ "movclr.l %%acc0, %[t]" \
+ : [a] "+r" (x), [c] "+a" (s), [t] "=r" (d), [u] "=r" (u) \
+ : [b] "r" (y)); \
+ d = (d << 8) | (u & 0xff); \
+}
+
+#define FRACMUL_8_LOOP(x, y, s, d) \
+{ \
+ long t; \
+ FRACMUL_8_LOOP_PART(x, s, t, y); \
+ asm volatile ("move.l %[t],(%[d])+" \
+ : [d] "+a" (d)\
+ : [t] "r" (t)); \
+}
+
+#define ACC(acc, x, y) \
+ (void)acc; \
+ asm volatile ("mac.l %[a], %[b], %%acc0" \
+ : : [a] "i,r" (x), [b] "i,r" (y));
+
+#define GET_ACC(acc) \
+({ \
+ long t; \
+ (void)acc; \
+ asm volatile ("movclr.l %%acc0, %[t]" \
+ : [t] "=r" (t)); \
+ t; \
+})
+
+#define ACC_INIT(acc, x, y) ACC(acc, x, y)
+
+#elif defined(CPU_ARM) && !defined(SIMULATOR)
+
+/* Multiply two S.31 fractional integers and return the sign bit and the
+ * 31 most significant bits of the result.
+ */
+#define FRACMUL(x, y) \
+({ \
+ long t; \
+ asm volatile ("smull r0, r1, %[a], %[b]\n\t" \
+ "mov %[t], r1, asl #1\n\t" \
+ "orr %[t], %[t], r0, lsr #31\n\t" \
+ : [t] "=r" (t) : [a] "r" (x), [b] "r" (y) : "r0", "r1"); \
+ t; \
+})
+
+/* Multiply two S.31 fractional integers, and return the 32 most significant
+ * bits after a shift left by the constant z.
+ */
+#define FRACMUL_SHL(x, y, z) \
+({ \
+ long t; \
+ asm volatile ("smull r0, r1, %[a], %[b]\n\t" \
+ "mov %[t], r1, asl %[c]\n\t" \
+ "orr %[t], %[t], r0, lsr %[d]\n\t" \
+ : [t] "=r" (t) \
+ : [a] "r" (x), [b] "r" (y), \
+ [c] "M" ((z) + 1), [d] "M" (31 - (z)) \
+ : "r0", "r1"); \
+ t; \
+})
+
+#define ACC_INIT(acc, x, y) acc = FRACMUL(x, y)
+#define ACC(acc, x, y) acc += FRACMUL(x, y)
+#define GET_ACC(acc) acc
+
+/* Multiply one S.31-bit and one S8.23 fractional integer and store the
+ * sign bit and the 31 most significant bits of the result to d (and
+ * increase d). Load next value to multiply with into x from s (and
+ * increase s); x must contain the initial value.
+ */
+#define FRACMUL_8_LOOP(x, y, s, d) \
+({ \
+ asm volatile ("smull r0, r1, %[a], %[b]\n\t" \
+ "mov %[t], r1, asl #9\n\t" \
+ "orr %[t], %[t], r0, lsr #23\n\t" \
+ : [t] "=r" (*(d)++) : [a] "r" (x), [b] "r" (y) : "r0", "r1"); \
+ x = *(s)++; \
+})
+
+#else
+
+#define ACC_INIT(acc, x, y) acc = FRACMUL(x, y)
+#define ACC(acc, x, y) acc += FRACMUL(x, y)
+#define GET_ACC(acc) acc
+#define FRACMUL(x, y) (long) (((((long long) (x)) * ((long long) (y))) >> 31))
+#define FRACMUL_SHL(x, y, z) ((long)(((((long long) (x)) * ((long long) (y))) >> (31 - (z)))))
+#define FRACMUL_8(x, y) (long) (((((long long) (x)) * ((long long) (y))) >> 23))
+#define FRACMUL_8_LOOP(x, y, s, d) \
+({ \
+ long t = x; \
+ x = *(s)++; \
+ *(d)++ = (long) (((((long long) (t)) * ((long long) (y))) >> 23)); \
+})
+
+#endif
+
+#define DIV64(x, y, z) (long)(((long long)(x) << (z))/(y))
+
long dsp_process(char *dest, const char *src[], long size);
long dsp_input_size(long size);
long dsp_output_size(long size);