shithub: opus

Download patch

ref: 4e018b22bb1594daccb29cd6e92cca11809111d2
parent: 39cbc45828cdbb2a74e4bea44a399e3a5b0a4530
author: Jean-Marc Valin <[email protected]>
date: Thu Jun 13 19:51:58 EDT 2013

SSE optimization of remove_doubling()

Should be trivial to adapt for Neon.

--- a/celt/pitch.c
+++ b/celt/pitch.c
@@ -394,6 +394,20 @@
    RESTORE_STACK;
 }
 
+#ifndef OVERRIDE_DUAL_INNER_PROD
+static opus_val32 dual_inner_prod(opus_val16 *x, opus_val16 *y1, opus_val16 *y2, int N)
+{
+   int i;
+   opus_val32 xy=0;
+   for (i=0;i<N;i++)
+   {
+      xy = MAC16_16(xy, x[i], y1[i]);
+      xy = MAC16_16(xy, x[i], y2[i]);
+   }
+   return xy;
+}
+#endif
+
 static const int second_check[16] = {0, 0, 3, 2, 3, 2, 5, 2, 3, 2, 3, 2, 5, 2, 3, 2};
 opus_val16 remove_doubling(opus_val16 *x, int maxperiod, int minperiod,
       int N, int *T0_, int prev_period, opus_val16 prev_gain)
@@ -470,12 +484,7 @@
       {
          T1b = (2*second_check[k]*T0+k)/(2*k);
       }
-      xy=0;
-      for (i=0;i<N;i++)
-      {
-         xy = MAC16_16(xy, x[i], x[i-T1]);
-         xy = MAC16_16(xy, x[i], x[i-T1b]);
-      }
+      xy = dual_inner_prod(x, &x[-T1], &x[-T1b], N);
       yy = yy_lookup[T1] + yy_lookup[T1b];
 #ifdef FIXED_POINT
       {
--- a/celt/x86/pitch_sse.h
+++ b/celt/x86/pitch_sse.h
@@ -71,4 +71,34 @@
    _mm_storeu_ps(sum,_mm_add_ps(xsum1,xsum2));
 }
 
+#define OVERRIDE_DUAL_INNER_PROD
+static inline opus_val32 dual_inner_prod(const opus_val16 *x, const opus_val16 *y1, const opus_val16 *y2, int N)
+{
+   int i;
+   __m128 xsum1, xsum2;
+   opus_val32 xy=0;
+   xsum1 = _mm_setzero_ps();
+   xsum2 = _mm_setzero_ps();
+   for (i=0;i<N-3;i+=4)
+   {
+      __m128 xi = _mm_loadu_ps(x+i);
+      __m128 y1i = _mm_loadu_ps(y1+i);
+      __m128 y2i = _mm_loadu_ps(y2+i);
+      xsum1 = _mm_add_ps(xsum1,_mm_mul_ps(xi, y1i));
+      xsum2 = _mm_add_ps(xsum2,_mm_mul_ps(xi, y2i));
+   }
+   xsum1 = _mm_add_ps(xsum1,xsum2);
+   /* Horizontal sum */
+   xsum1 = _mm_add_ps(xsum1, _mm_movehl_ps(xsum1, xsum1));
+   xsum1 = _mm_add_ss(xsum1, _mm_shuffle_ps(xsum1, xsum1, 0x55));
+   _mm_store_ss(&xy, xsum1);
+   for (;i<N;i++)
+   {
+      xy = MAC16_16(xy, x[i], y1[i]);
+      xy = MAC16_16(xy, x[i], y2[i]);
+   }
+   return xy;
+}
+
+
 #endif