shithub: opus

Download patch

ref: 387a20d740caa9cbe9893d468bcd679e0219ff7b
parent: e40a19cbe9c121444c28905b217275b21dee1c05
author: Jean-Marc Valin <[email protected]>
date: Wed Feb 27 08:49:54 EST 2008

fixed-point: exp_rotation() mostly converted (still need to convert the cos/sin)

--- a/libcelt/bands.c
+++ b/libcelt/bands.c
@@ -39,32 +39,32 @@
 #include "vq.h"
 #include "cwrs.h"
 
-/** Applies a series of rotations so that pulses are spread like a two-sided
-exponential. The effect of this is to reduce the tonal noise created by the
-sparse spectrum resulting from the pulse codebook */
-static void exp_rotation(celt_norm_t *X, int len, float theta, int dir, int stride, int iter)
+
+void exp_rotation(celt_norm_t *X, int len, float theta, int dir, int stride, int iter)
 {
    int i, k;
-   float c, s;
-   c = cos(theta);
-   s = dir*sin(theta);
+   celt_word16_t c, s;
+   c = Q15ONE*cos(theta);
+   s = dir*Q15ONE*sin(theta);
    for (k=0;k<iter;k++)
    {
+      /* We could use MULT16_16_P15 instead of MULT16_16_Q15 for more accuracy, 
+         but at this point, I really don't think it's necessary */
       for (i=0;i<len-stride;i++)
       {
-         float x1, x2;
+         celt_norm_t x1, x2;
          x1 = X[i];
          x2 = X[i+stride];
-         X[i] = c*x1 - s*x2;
-         X[i+stride] = c*x2 + s*x1;
+         X[i] = MULT16_16_Q15(c,x1) - MULT16_16_Q15(s,x2);
+         X[i+stride] = MULT16_16_Q15(c,x2) + MULT16_16_Q15(s,x1);
       }
       for (i=len-2*stride-1;i>=0;i--)
       {
-         float x1, x2;
+         celt_norm_t x1, x2;
          x1 = X[i];
          x2 = X[i+stride];
-         X[i] = c*x1 - s*x2;
-         X[i+stride] = c*x2 + s*x1;
+         X[i] = MULT16_16_Q15(c,x1) - MULT16_16_Q15(s,x2);
+         X[i+stride] = MULT16_16_Q15(c,x2) + MULT16_16_Q15(s,x1);
       }
    }
 }
--- a/libcelt/bands.h
+++ b/libcelt/bands.h
@@ -38,6 +38,11 @@
 #include "entdec.h"
 #include "rate.h"
 
+/** Applies a series of rotations so that pulses are spread like a two-sided
+exponential. The effect of this is to reduce the tonal noise created by the
+sparse spectrum resulting from the pulse codebook */
+void exp_rotation(celt_norm_t *X, int len, float theta, int dir, int stride, int iter);
+
 /** Compute the amplitude (sqrt energy) in each of the bands 
  * @param m Mode data 
  * @param X Spectrum
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1,9 +1,9 @@
 INCLUDES = -I$(top_srcdir)/libcelt
 METASOURCES = AUTO
 
-TESTS = type-test ectest cwrs32-test cwrs64-test real-fft-test dft-test laplace-test mdct-test
+TESTS = type-test ectest cwrs32-test cwrs64-test real-fft-test dft-test laplace-test mdct-test rotation-test
 
-noinst_PROGRAMS = type-test ectest cwrs32-test cwrs64-test real-fft-test dft-test laplace-test mdct-test
+noinst_PROGRAMS = type-test ectest cwrs32-test cwrs64-test real-fft-test dft-test laplace-test mdct-test rotation-test
 
 type_test_SOURCES = type-test.c
 ectest_SOURCES = ectest.c
@@ -13,5 +13,6 @@
 dft_test_SOURCES = dft-test.c
 laplace_test_SOURCES = laplace-test.c
 mdct_test_SOURCES = mdct-test.c
+rotation_test_SOURCES = rotation-test.c
 
 LDADD = $(top_builddir)/libcelt/libcelt.la
--- /dev/null
+++ b/tests/rotation-test.c
@@ -1,0 +1,43 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "celt_types.h"
+#include "bands.h"
+#include <math.h>
+#define MAX_SIZE 100
+
+int ret=0;
+void test_rotation(int N, int K)
+{
+   int i;
+   double err = 0, ener = 0, snr;
+   float theta = .007*N/K;
+   celt_word16_t x0[MAX_SIZE];
+   celt_word16_t x1[MAX_SIZE];
+   for (i=0;i<N;i++)
+      x1[i] = x0[i] = rand()%32767-16384;
+   exp_rotation(x1, N, theta, 1, 1, 8);
+   exp_rotation(x1, N, theta, -1, 1, 8);
+   for (i=0;i<N;i++)
+   {
+      err += (x0[i]-(double)x1[i])*(x0[i]-(double)x1[i]);
+      ener += x0[i]*(double)x0[i];
+   }
+   snr = 20*log10(ener/err);
+   printf ("SNR for size %d (%d pulses) is %f\n", N, K, snr);
+   if (snr < 60)
+      ret = 1;
+}
+
+int main()
+{
+   test_rotation(4, 40);
+   test_rotation(7, 20);
+   test_rotation(10, 10);
+   test_rotation(23, 5);
+   test_rotation(50, 3);
+   return ret;
+}