fixed-point: Defined fused multiply-add operators and some ARM assembly to
authorjm <jm@0101bb08-14d6-0310-b084-bc0e0c8e3800>
Tue, 11 Nov 2003 00:19:46 +0000 (00:19 +0000)
committerjm <jm@0101bb08-14d6-0310-b084-bc0e0c8e3800>
Tue, 11 Nov 2003 00:19:46 +0000 (00:19 +0000)
use it.

git-svn-id: http://svn.xiph.org/trunk/speex@5557 0101bb08-14d6-0310-b084-bc0e0c8e3800

configure.in
libspeex/filters.c
libspeex/ltp.c
libspeex/misc.h
libspeex/vq.c

index bbd8894..5938a67 100644 (file)
@@ -55,6 +55,7 @@ AC_DEFINE_UNQUOTED(VERSION, "${VERSION}")
 
 AC_ARG_ENABLE(sse, [  --enable-sse             enable SSE support], [if test "$enableval" = yes; then AC_DEFINE(_USE_SSE) fi])
 AC_ARG_ENABLE(fixed-point, [  --enable-fixed-point             compile as fixed-point], [if test "$enableval" = yes; then AC_DEFINE(FIXED_POINT) fi])
+AC_ARG_ENABLE(arm-asm, [  --enable-arm-asm             make use of ARM assembly instructions], [if test "$enableval" = yes; then AC_DEFINE(ARM_ASM) fi])
 
 AC_ARG_ENABLE(epic-48k, [  --enable-epic-48k             enable support for epic 4.8 kbps mode], [if test "$enableval" = yes; then AC_DEFINE(EPIC_48K) fi])
 
index 1849b45..35524c5 100644 (file)
@@ -189,17 +189,18 @@ spx_word16_t compute_rms(spx_sig_t *x, int len)
 void filter_mem2(spx_sig_t *x, spx_coef_t *num, spx_coef_t *den, spx_sig_t *y, int N, int ord, spx_mem_t *mem)
 {
    int i,j;
-   int xi,yi;
+   spx_sig_t xi,yi,nyi;
 
    for (i=0;i<N;i++)
    {
       int xh,xl,yh,yl;
       xi=x[i];
       yi = xi + (mem[0]<<2);
+      nyi = -yi;
       xh = xi>>15; xl=xi&0x00007fff; yh = yi>>15; yl=yi&0x00007fff; 
       for (j=0;j<ord-1;j++)
       {
-         mem[j] = SUB32(ADD32(mem[j+1],  MULT16_32_Q15(num[j+1],xi)), MULT16_32_Q15(den[j+1],yi));
+         mem[j] = MAC16_32_Q15(MAC16_32_Q15(mem[j+1], num[j+1],xi), den[j+1],nyi);
       }
       mem[ord-1] = SUB32(MULT16_32_Q15(num[ord],xi), MULT16_32_Q15(den[ord],yi));
       y[i] = yi;
@@ -209,17 +210,18 @@ void filter_mem2(spx_sig_t *x, spx_coef_t *num, spx_coef_t *den, spx_sig_t *y, i
 void iir_mem2(spx_sig_t *x, spx_coef_t *den, spx_sig_t *y, int N, int ord, spx_mem_t *mem)
 {
    int i,j;
-   int xi,yi;
+   spx_word32_t xi,yi,nyi;
 
    for (i=0;i<N;i++)
    {
       int yh,yl;
       xi=x[i];
       yi = xi + (mem[0]<<2);
+      nyi = -yi;
       yh = yi>>15; yl=yi&0x00007fff; 
       for (j=0;j<ord-1;j++)
       {
-         mem[j] = SUB32(mem[j+1], MULT16_32_Q15(den[j+1],yi));
+         mem[j] = MAC16_32_Q15(mem[j+1],den[j+1],nyi);
       }
       mem[ord-1] = - MULT16_32_Q15(den[ord],yi);
       y[i] = yi;
@@ -230,7 +232,7 @@ void iir_mem2(spx_sig_t *x, spx_coef_t *den, spx_sig_t *y, int N, int ord, spx_m
 void fir_mem2(spx_sig_t *x, spx_coef_t *num, spx_sig_t *y, int N, int ord, spx_mem_t *mem)
 {
    int i,j;
-   int xi,yi;
+   spx_word32_t xi,yi;
 
    for (i=0;i<N;i++)
    {
@@ -240,7 +242,7 @@ void fir_mem2(spx_sig_t *x, spx_coef_t *num, spx_sig_t *y, int N, int ord, spx_m
       xh = xi>>15; xl=xi&0x00007fff;
       for (j=0;j<ord-1;j++)
       {
-         mem[j] = ADD32(mem[j+1], MULT16_32_Q15(num[j+1],xi));
+         mem[j] = MAC16_32_Q15(mem[j+1], num[j+1],xi);
       }
       mem[ord-1] = MULT16_32_Q15(num[ord],xi);
       y[i] = yi;
index b6a2496..28ebebf 100644 (file)
@@ -48,10 +48,10 @@ static spx_word32_t inner_prod(spx_word16_t *x, spx_word16_t *y, int len)
    for (i=0;i<len;i+=4)
    {
       spx_word32_t part=0;
-      part = ADD32(part,MULT16_16(x[i],y[i]));
-      part = ADD32(part,MULT16_16(x[i+1],y[i+1]));
-      part = ADD32(part,MULT16_16(x[i+2],y[i+2]));
-      part = ADD32(part,MULT16_16(x[i+3],y[i+3]));
+      part = MAC16_16(part,x[i],y[i]);
+      part = MAC16_16(part,x[i+1],y[i+1]);
+      part = MAC16_16(part,x[i+2],y[i+2]);
+      part = MAC16_16(part,x[i+3],y[i+3]);
       sum = ADD32(sum,SHR(part,6));
    }
    return sum;
index be653ec..d15ef22 100644 (file)
@@ -111,6 +111,22 @@ static inline spx_word32_t MULT16_16(spx_word16_t x, spx_word16_t y) {
 
 #endif
 
+#ifdef ARM_ASM
+
+static inline spx_word32_t MAC16_16(spx_word32_t a, spx_word16_t x, spx_word32_t y) {
+  int res;
+  asm volatile("smlabb  %0,%1,%2,%3;\n"
+              : "=&r"(res)
+               : "%r"(x),"r"(y),"r"(a));
+  return(res);
+}
+
+#else
+
+#define MAC16_16(c,a,b)     (ADD32((c),MULT16_16((a),(b))))
+
+#endif
+
 #define MULT16_32_Q11(a,b) ADD32(MULT16_16((a),SHR((b),11)), SHR(MULT16_16((a),((b)&0x000007ff)),11))
 #define MULT16_32_Q12(a,b) ADD32(MULT16_16((a),SHR((b),12)), SHR(MULT16_16((a),((b)&0x00000fff)),11))
 #define MULT16_32_Q13(a,b) ADD32(MULT16_16((a),SHR((b),13)), SHR(MULT16_16((a),((b)&0x00001fff)),13))
@@ -124,9 +140,17 @@ static inline spx_word32_t MULT16_32_Q15(spx_word16_t x, spx_word32_t y) {
                : "%r"(y<<1),"r"(x));
   return(res);
 }
+static inline spx_word32_t MAC16_32_Q15(spx_word32_t a, spx_word16_t x, spx_word32_t y) {
+  int res;
+  asm volatile("smlawb  %0,%1,%2,%3;\n"
+              : "=&r"(res)
+               : "%r"(y<<1),"r"(x),"r"(a));
+  return(res);
+}
 
 #else
 #define MULT16_32_Q15(a,b) ADD32(MULT16_16((a),SHR((b),15)), SHR(MULT16_16((a),((b)&0x00007fff)),15))
+#define MAC16_32_Q15(c,a,b) ADD32(c,ADD32(MULT16_16((a),SHR((b),15)), SHR(MULT16_16((a),((b)&0x00007fff)),15)))
 #endif
 
 
@@ -171,12 +195,15 @@ typedef float spx_word64_t;
 #define ADD64(a,b) ((a)+(b))
 #define MULT16_16_16(a,b)     ((a)*(b))
 #define MULT16_16(a,b)     ((a)*(b))
+#define MAC16_16(c,a,b)     ((c)+(a)*(b))
 
 #define MULT16_32_Q11(a,b)     ((a)*(b))
 #define MULT16_32_Q13(a,b)     ((a)*(b))
 #define MULT16_32_Q14(a,b)     ((a)*(b))
 #define MULT16_32_Q15(a,b)     ((a)*(b))
 
+#define MAC16_32_Q15(c,a,b)     ((c)+(a)*(b))
+
 #define MULT16_16_Q13(a,b)     ((a)*(b))
 #define MULT16_16_Q14(a,b)     ((a)*(b))
 #define MULT16_16_Q15(a,b)     ((a)*(b))
index a7b2268..412507e 100644 (file)
@@ -63,13 +63,14 @@ void vq_nbest(spx_word16_t *in, spx_word16_t *codebook, int len, int entries, sp
    used = 0;
    for (i=0;i<entries;i++)
    {
+      spx_word32_t dist=0;
+      for (j=0;j<len;j++)
+         dist = MAC16_16(dist,in[j],*codebook++);
 #ifdef FIXED_POINT
-      spx_word32_t dist=SHR(E[i],1);
+      dist=SUB32(SHR(E[i],1),dist);
 #else
-      spx_word32_t dist=.5*E[i];
+      dist=.5*E[i]-dist;
 #endif
-      for (j=0;j<len;j++)
-         dist = SUB32(dist,MULT16_16(in[j],*codebook++));
       if (i<N || dist<best_dist[N-1])
       {
          for (k=N-1; (k >= 1) && (k > used || dist < best_dist[k-1]); k--)
@@ -93,14 +94,14 @@ void vq_nbest_sign(spx_word16_t *in, spx_word16_t *codebook, int len, int entrie
    {
       spx_word32_t dist=0;
       for (j=0;j<len;j++)
-         dist = SUB32(dist,MULT16_16(in[j],*codebook++));
+         dist = MAC16_16(dist,in[j],*codebook++);
       if (dist>0)
       {
-         sign=1;
+         sign=0;
          dist=-dist;
       } else
       {
-         sign=0;
+         sign=1;
       }
 #ifdef FIXED_POINT
       dist = ADD32(dist,SHR(E[i],1));