]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
update to snapshot spandsp-20080919.tar.gz
authorAnthony Minessale <anthony.minessale@gmail.com>
Wed, 1 Oct 2008 03:59:45 +0000 (03:59 +0000)
committerAnthony Minessale <anthony.minessale@gmail.com>
Wed, 1 Oct 2008 03:59:45 +0000 (03:59 +0000)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@9770 d0543943-73ff-0310-b7d9-9358b9ac24b2

40 files changed:
libs/spandsp/.update
libs/spandsp/src/Makefile.am
libs/spandsp/src/awgn.c
libs/spandsp/src/complex_vector_float.c
libs/spandsp/src/echo.c
libs/spandsp/src/gsm0610_decode.c
libs/spandsp/src/gsm0610_encode.c
libs/spandsp/src/gsm0610_long_term.c
libs/spandsp/src/gsm0610_lpc.c
libs/spandsp/src/gsm0610_preprocess.c
libs/spandsp/src/gsm0610_rpe.c
libs/spandsp/src/gsm0610_short_term.c
libs/spandsp/src/ima_adpcm.c
libs/spandsp/src/libspandsp.dsp
libs/spandsp/src/make_modem_filter.c
libs/spandsp/src/noise.c
libs/spandsp/src/plc.c
libs/spandsp/src/sig_tone.c
libs/spandsp/src/spandsp.h.in
libs/spandsp/src/spandsp/complex_vector_float.h
libs/spandsp/src/spandsp/complex_vector_int.h
libs/spandsp/src/spandsp/dc_restore.h
libs/spandsp/src/spandsp/g722.h
libs/spandsp/src/spandsp/v17rx.h
libs/spandsp/src/spandsp/v27ter_rx.h
libs/spandsp/src/spandsp/v29rx.h
libs/spandsp/src/spandsp/vector_float.h
libs/spandsp/src/spandsp/vector_int.h
libs/spandsp/src/spandsp/version.h
libs/spandsp/src/time_scale.c
libs/spandsp/src/v17rx.c
libs/spandsp/src/v22bis_rx.c
libs/spandsp/src/v27ter_rx.c
libs/spandsp/src/v29rx.c
libs/spandsp/src/vector_float.c
libs/spandsp/src/vector_int.c
libs/spandsp/tests/Makefile.am
libs/spandsp/tests/g722_tests.c
libs/spandsp/tests/regression_tests.sh
libs/spandsp/tests/vector_int_tests.c

index 1e1ab309d60e1ba7972b7a512ebf7acda9b09e77..786c42ad089f739dce5c3c4f77142a893149f353 100644 (file)
@@ -1 +1 @@
-Tue Sep 30 23:55:26 EDT 2008
+Tue Sep 30 23:59:24 EDT 2008
index 82704812e627bda7430677e99a63ba970085e133..8ec021bd60433d68ab2d08290455c78e50b73a3f 100644 (file)
@@ -16,7 +16,7 @@
 ## License along with this program; if not, write to the Free Software
 ## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 ##
-## $Id: Makefile.am,v 1.101 2008/09/08 12:45:02 steveu Exp $
+## $Id: Makefile.am,v 1.103 2008/09/19 14:02:05 steveu Exp $
 
 AM_CFLAGS = $(COMP_VENDOR_CFLAGS)
 AM_LDFLAGS = $(COMP_VENDOR_LDFLAGS)
@@ -37,6 +37,7 @@ libspandsp_la_SOURCES = adsi.c \
                         bitstream.c \
                         complex_filters.c \
                         complex_vector_float.c \
+                        complex_vector_int.c \
                         crc.c \
                         dds_float.c \
                         dds_int.c \
@@ -45,8 +46,7 @@ libspandsp_la_SOURCES = adsi.c \
                         fax.c \
                         fsk.c \
                         g711.c \
-                        g722_encode.c \
-                        g722_decode.c \
+                        g722.c \
                         g726.c \
                         gsm0610_decode.c \
                         gsm0610_encode.c \
index 6c8103295fae3520c80a8b6ea8885af1276451f1..9d17487824081bc2abb90b6f009ae9e7200d507e 100644 (file)
@@ -22,7 +22,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: awgn.c,v 1.16 2008/07/02 14:48:25 steveu Exp $
+ * $Id: awgn.c,v 1.17 2008/09/19 14:02:05 steveu Exp $
  */
 
 /*! \file */
@@ -57,7 +57,7 @@
 #endif
 
 #include "spandsp/telephony.h"
-#include "spandsp/dc_restore.h"
+#include "spandsp/saturated.h"
 #include "spandsp/awgn.h"
 
 /* Gaussian noise generator constants */
index 88ee2a4536a0922f19e3b369b066cedfdca4adf9..974ce289ce3a293b7b087b310732ffe9f77c4718 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * SpanDSP - a series of DSP components for telephony
  *
- * vector_float.c - Floating vector arithmetic routines.
+ * complex_vector_float.c - Floating complex vector arithmetic routines.
  *
  * Written by Steve Underwood <steveu@coppice.org>
  *
@@ -22,7 +22,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: complex_vector_float.c,v 1.8 2008/07/02 14:48:25 steveu Exp $
+ * $Id: complex_vector_float.c,v 1.10 2008/09/18 13:16:49 steveu Exp $
  */
 
 /*! \file */
 #include "spandsp/vector_float.h"
 #include "spandsp/complex_vector_float.h"
 
+complexf_t cvec_dot_prodf(const complexf_t x[], const complexf_t y[], int n)
+{
+    int i;
+    complexf_t z;
+
+    z = complex_setf(0.0f, 0.0f);
+    for (i = 0;  i < n;  i++)
+    {
+        z.re += (x[i].re*y[i].re - x[i].im*y[i].im);
+        z.im += (x[i].re*y[i].im + x[i].im*y[i].re);
+    }
+    return z;
+}
+/*- End of function --------------------------------------------------------*/
+
+complex_t cvec_dot_prod(const complex_t x[], const complex_t y[], int n)
+{
+    int i;
+    complex_t z;
+
+    z = complex_set(0.0, 0.0);
+    for (i = 0;  i < n;  i++)
+    {
+        z.re += (x[i].re*y[i].re - x[i].im*y[i].im);
+        z.im += (x[i].re*y[i].im + x[i].im*y[i].re);
+    }
+    return z;
+}
+/*- End of function --------------------------------------------------------*/
+
+#if defined(HAVE_LONG_DOUBLE)
+complexl_t cvec_dot_prodl(const complexl_t x[], const complexl_t y[], int n)
+{
+    int i;
+    complexl_t z;
+
+    z = complex_setl(0.0L, 0.0L);
+    for (i = 0;  i < n;  i++)
+    {
+        z.re += (x[i].re*y[i].re - x[i].im*y[i].im);
+        z.im += (x[i].re*y[i].im + x[i].im*y[i].re);
+    }
+    return z;
+}
+/*- End of function --------------------------------------------------------*/
+#endif
+
+complexf_t cvec_circular_dot_prodf(const complexf_t x[], const complexf_t y[], int n, int pos)
+{
+    complexf_t z;
+    complexf_t z1;
+
+    z = cvec_dot_prodf(&x[pos], &y[0], n - pos);
+    z1 = cvec_dot_prodf(&x[0], &y[n - pos], pos);
+    z = complex_addf(&z, &z1);
+    return z;
+}
+/*- End of function --------------------------------------------------------*/
+
+void cvec_lmsf(const complexf_t x[], complexf_t y[], int n, const complexf_t *error)
+{
+    int i;
+
+    for (i = 0;  i < n;  i++)
+    {
+        y[i].re += (x[i].im*error->im + x[i].re*error->re);
+        y[i].im += (x[i].re*error->im - x[i].im*error->re);
+        /* Leak a little to tame uncontrolled wandering */
+        y[i].re *= 0.9999f;
+        y[i].im *= 0.9999f;
+    }
+}
+/*- End of function --------------------------------------------------------*/
+
+void cvec_circular_lmsf(const complexf_t x[], complexf_t y[], int n, int pos, const complexf_t *error)
+{
+    cvec_lmsf(&x[pos], &y[0], n - pos, error);
+    cvec_lmsf(&x[0], &y[n - pos], pos, error);
+}
+/*- End of function --------------------------------------------------------*/
 /*- End of file ------------------------------------------------------------*/
index 6a4699cc1bb14fd22b48a795b790d6b5d33a74ad..d106a92803d6d13752cd42954e4c33a44a286aaa 100644 (file)
@@ -27,7 +27,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: echo.c,v 1.27 2008/08/29 09:28:13 steveu Exp $
+ * $Id: echo.c,v 1.28 2008/09/19 14:02:05 steveu Exp $
  */
 
 /*! \file */
@@ -96,6 +96,7 @@
 
 #include "spandsp/telephony.h"
 #include "spandsp/logging.h"
+#include "spandsp/saturated.h"
 #include "spandsp/dc_restore.h"
 #include "spandsp/bit_operations.h"
 #include "spandsp/echo.h"
index 49b8fcb8691857aff5ad69a6c05fca7985232d26..84c28cf3d33864f3f728a55fc46f0f9486480d10 100644 (file)
@@ -25,7 +25,7 @@
  * This code is based on the widely used GSM 06.10 code available from
  * http://kbs.cs.tu-berlin.de/~jutta/toast.html
  *
- * $Id: gsm0610_decode.c,v 1.21 2008/07/02 14:48:25 steveu Exp $
+ * $Id: gsm0610_decode.c,v 1.22 2008/09/19 14:02:05 steveu Exp $
  */
 
 /*! \file */
@@ -48,7 +48,7 @@
 
 #include "spandsp/telephony.h"
 #include "spandsp/bitstream.h"
-#include "spandsp/dc_restore.h"
+#include "spandsp/saturated.h"
 #include "spandsp/gsm0610.h"
 
 #include "gsm0610_local.h"
@@ -66,9 +66,9 @@ static void postprocessing(gsm0610_state_t *s, int16_t amp[])
     {
         tmp = gsm_mult_r(msr, 28180);
         /* De-emphasis */
-        msr = gsm_add(amp[k], tmp);
+        msr = saturated_add16(amp[k], tmp);
         /* Truncation & upscaling */
-        amp[k] = (int16_t) (gsm_add(msr, msr) & 0xFFF8);
+        amp[k] = (int16_t) (saturated_add16(msr, msr) & 0xFFF8);
     }
     /*endfor*/
     s->msr = msr;
index 94f14b05141b48f3639eab10184c671701af4a62..f6844577a1bd0fa47d4e515800fff3481ca8500a 100644 (file)
@@ -25,7 +25,7 @@
  * This code is based on the widely used GSM 06.10 code available from
  * http://kbs.cs.tu-berlin.de/~jutta/toast.html
  *
- * $Id: gsm0610_encode.c,v 1.25 2008/07/02 14:48:25 steveu Exp $
+ * $Id: gsm0610_encode.c,v 1.26 2008/09/19 14:02:05 steveu Exp $
  */
 
 /*! \file */
@@ -48,7 +48,7 @@
 
 #include "spandsp/telephony.h"
 #include "spandsp/bitstream.h"
-#include "spandsp/dc_restore.h"
+#include "spandsp/saturated.h"
 #include "spandsp/gsm0610.h"
 
 #include "gsm0610_local.h"
@@ -93,7 +93,7 @@ static void encode_a_frame(gsm0610_state_t *s, gsm0610_frame_t *f, const int16_t
         gsm0610_rpe_encoding(s, s->e + 5, &f->xmaxc[k], &f->Mc[k], f->xMc[k]);
 
         for (i = 0;  i < 40;  i++)
-            dp[i] = gsm_add(s->e[5 + i], dpp[i]);
+            dp[i] = saturated_add16(s->e[5 + i], dpp[i]);
         /*endfor*/
         dp += 40;
         dpp += 40;
index 80bad2ccd5fa3ea38ed1828c65a4e1c10557b514..a17b5d54134ab4cc13913dbb3117b59fc10ec3d4 100644 (file)
@@ -25,7 +25,7 @@
  * This code is based on the widely used GSM 06.10 code available from
  * http://kbs.cs.tu-berlin.de/~jutta/toast.html
  *
- * $Id: gsm0610_long_term.c,v 1.16 2008/07/02 14:48:25 steveu Exp $
+ * $Id: gsm0610_long_term.c,v 1.17 2008/09/19 14:02:05 steveu Exp $
  */
 
 /*! \file */
@@ -47,7 +47,7 @@
 
 #include "spandsp/telephony.h"
 #include "spandsp/bitstream.h"
-#include "spandsp/dc_restore.h"
+#include "spandsp/saturated.h"
 #include "spandsp/gsm0610.h"
 
 #include "gsm0610_local.h"
@@ -185,7 +185,7 @@ static int16_t evaluate_ltp_parameters(int16_t d[40],
     for (k = 0;  k < 40;  k++)
     {
         temp = d[k];
-        temp = gsm_abs(temp);
+        temp = saturated_abs16(temp);
         if (temp > dmax)
             dmax = temp;
         /*endif*/
@@ -314,12 +314,12 @@ static int16_t evaluate_ltp_parameters(int16_t d[40],
        quantization of the LTP gain b to get the coded version bc. */
     for (bc = 0;  bc <= 2;  bc++)
     {
-        if (R <= gsm_mult(S, gsm_DLB[bc]))
+        if (R <= saturated_mul16(S, gsm_DLB[bc]))
             break;
         /*endif*/
     }
     /*endfor*/
-    return  bc;
+    return bc;
 }
 /*- End of function --------------------------------------------------------*/
 
@@ -340,7 +340,7 @@ static void long_term_analysis_filtering(int16_t bc,
     for (k = 0;  k < 40;  k++)
     {
         dpp[k] = gsm_mult_r(gsm_QLB[bc], dp[k - Nc]);
-        e[k] = gsm_sub(d[k], dpp[k]);
+        e[k] = saturated_sub16(d[k], dpp[k]);
     }
     /*endfor*/
 }
@@ -398,7 +398,7 @@ void gsm0610_long_term_synthesis_filtering(gsm0610_state_t *s,
     for (k = 0;  k < 40;  k++)
     {
         drpp = gsm_mult_r(brp, drp[k - Nr]);
-        drp[k] = gsm_add(erp[k], drpp);
+        drp[k] = saturated_add16(erp[k], drpp);
     }
     /*endfor*/
 
index 05e65a393a7b9e7a99370d5c098b1962f8e0daa8..e64d5b6d1872cc45af98912107b9457eff53c32e 100644 (file)
@@ -25,7 +25,7 @@
  * This code is based on the widely used GSM 06.10 code available from
  * http://kbs.cs.tu-berlin.de/~jutta/toast.html
  *
- * $Id: gsm0610_lpc.c,v 1.21 2008/09/04 14:40:05 steveu Exp $
+ * $Id: gsm0610_lpc.c,v 1.22 2008/09/19 14:02:05 steveu Exp $
  */
 
 /*! \file */
@@ -49,7 +49,7 @@
 #include "spandsp/telephony.h"
 #include "spandsp/bitstream.h"
 #include "spandsp/bit_operations.h"
-#include "spandsp/dc_restore.h"
+#include "spandsp/saturated.h"
 #include "spandsp/vector_int.h"
 #include "spandsp/gsm0610.h"
 
@@ -230,7 +230,7 @@ static void autocorrelation(int16_t amp[GSM0610_FRAME_LEN], int32_t L_ACF[9])
 #else
     for (smax = 0, k = 0;  k < GSM0610_FRAME_LEN;  k++)
     {
-        temp = gsm_abs(amp[k]);
+        temp = saturated_abs16(amp[k]);
         if (temp > smax)
             smax = (int16_t) temp;
         /*endif*/
@@ -398,7 +398,7 @@ static void reflection_coefficients(int32_t L_ACF[9], int16_t r[8])
     for (n = 1;  n <= 8;  n++, r++)
     {
         temp = P[1];
-        temp = gsm_abs (temp);
+        temp = saturated_abs16(temp);
         if (P[0] < temp)
         {
             for (i = n;  i <= 8;  i++)
@@ -421,15 +421,15 @@ static void reflection_coefficients(int32_t L_ACF[9], int16_t r[8])
 
         /* Schur recursion */
         temp = gsm_mult_r(P[1], *r);
-        P[0] = gsm_add(P[0], temp);
+        P[0] = saturated_add16(P[0], temp);
 
         for (m = 1;  m <= 8 - n;  m++)
         {
             temp = gsm_mult_r(K[m], *r);
-            P[m] = gsm_add(P[m + 1], temp);
+            P[m] = saturated_add16(P[m + 1], temp);
 
             temp = gsm_mult_r(P[m + 1], *r);
-            K[m] = gsm_add(K[m], temp);
+            K[m] = saturated_add16(K[m], temp);
         }
         /*endfor*/
     }
@@ -453,8 +453,7 @@ static void transform_to_log_area_ratios(int16_t r[8])
     /* Computation of the LAR[0..7] from the r[0..7] */
     for (i = 1;  i <= 8;  i++, r++)
     {
-        temp = *r;
-        temp = gsm_abs(temp);
+        temp = saturated_abs16(*r);
         assert(temp >= 0);
 
         if (temp < 22118)
@@ -496,9 +495,9 @@ static void quantization_and_coding(int16_t LAR[8])
 
 #undef STEP
 #define STEP(A,B,MAC,MIC)                                       \
-        temp = gsm_mult(A, *LAR);                               \
-        temp = gsm_add(temp, B);                                \
-        temp = gsm_add(temp, 256);                              \
+        temp = saturated_mul16(A, *LAR);                        \
+        temp = saturated_add16(temp, B);                        \
+        temp = saturated_add16(temp, 256);                      \
         temp >>= 9;                                             \
         *LAR  = (int16_t) ((temp > MAC)                         \
                          ?                                      \
index 81fff74093fc6fcf397be2ad0b8f1c6e2550e847..edbe7c58795890de327dbd0d856ca183b083dd9d 100644 (file)
@@ -25,7 +25,7 @@
  * This code is based on the widely used GSM 06.10 code available from
  * http://kbs.cs.tu-berlin.de/~jutta/toast.html
  *
- * $Id: gsm0610_preprocess.c,v 1.13 2008/07/02 14:48:25 steveu Exp $
+ * $Id: gsm0610_preprocess.c,v 1.14 2008/09/19 14:02:05 steveu Exp $
  */
 
 /*! \file */
@@ -47,7 +47,7 @@
 
 #include "spandsp/telephony.h"
 #include "spandsp/bitstream.h"
-#include "spandsp/dc_restore.h"
+#include "spandsp/saturated.h"
 #include "spandsp/gsm0610.h"
 
 #include "gsm0610_local.h"
@@ -121,7 +121,7 @@ void gsm0610_preprocess(gsm0610_state_t *s, const int16_t amp[GSM0610_FRAME_LEN]
          * L_temp = (++L_temp) >> 1;
          * L_z2 = L_z2 - L_temp;
          */
-        L_z2 = gsm_l_add(L_z2, L_s2);
+        L_z2 = saturated_add32(L_z2, L_s2);
 #else
         /* This does L_z2  = L_z2 * 0x7FD5/0x8000 + L_s2 */
         msp = (int16_t) (L_z2 >> 15);
@@ -129,16 +129,16 @@ void gsm0610_preprocess(gsm0610_state_t *s, const int16_t amp[GSM0610_FRAME_LEN]
 
         L_s2 += gsm_mult_r(lsp, 32735);
         L_temp = (int32_t) msp*32735;
-        L_z2 = gsm_l_add(L_temp, L_s2);
+        L_z2 = saturated_add32(L_temp, L_s2);
 #endif
 
         /* Compute sof[k] with rounding */
-        L_temp = gsm_l_add(L_z2, 16384);
+        L_temp = saturated_add32(L_z2, 16384);
 
         /* 4.2.3  Preemphasis */
         msp = gsm_mult_r(mp, -28180);
         mp = (int16_t) (L_temp >> 15);
-        so[k] = gsm_add(mp, msp);
+        so[k] = saturated_add16(mp, msp);
     }
     /*endfor*/
 
index 567d3c57c2a67efdef11be09561a795bb2de23e7..cf4113b3ce9d330219fc9224fc27309c722cd51c 100644 (file)
@@ -25,7 +25,7 @@
  * This code is based on the widely used GSM 06.10 code available from
  * http://kbs.cs.tu-berlin.de/~jutta/toast.html
  *
- * $Id: gsm0610_rpe.c,v 1.21 2008/07/02 14:48:25 steveu Exp $
+ * $Id: gsm0610_rpe.c,v 1.22 2008/09/19 14:02:05 steveu Exp $
  */
 
 /*! \file */
@@ -47,7 +47,7 @@
 
 #include "spandsp/telephony.h"
 #include "spandsp/bitstream.h"
-#include "spandsp/dc_restore.h"
+#include "spandsp/saturated.h"
 #include "spandsp/gsm0610.h"
 
 #include "gsm0610_local.h"
@@ -139,8 +139,8 @@ static void weighting_filter(const int16_t *e,     // signal [-5..0.39.44] IN
 
         /* for (i = 0; i <= 10; i++)
          * {
-         *      L_temp   = gsm_l_mult(wt[k + i], gsm_H[i]);
-         *      L_result = gsm_l_add(L_result, L_temp);
+         *      L_temp   = saturated_mul_16_32(wt[k + i], gsm_H[i]);
+         *      L_result = saturated_add32(L_result, L_temp);
          * }
          */
 
@@ -351,7 +351,7 @@ static void apcm_quantization(int16_t xM[13],
     for (i = 0;  i < 13;  i++)
     {
         temp = xM[i];
-        temp = gsm_abs(temp);
+        temp = saturated_abs16(temp);
         if (temp > xmax)
             xmax = temp;
         /*endif*/
@@ -379,7 +379,7 @@ static void apcm_quantization(int16_t xM[13],
     temp = (int16_t) (exp + 5);
 
     assert(temp <= 11  &&  temp >= 0);
-    xmaxc = gsm_add((xmax >> temp), exp << 3);
+    xmaxc = saturated_add16((xmax >> temp), exp << 3);
 
     /* Quantizing and coding of the xM[0..12] RPE sequence
        to get the xMc[0..12] */
@@ -406,7 +406,7 @@ static void apcm_quantization(int16_t xM[13],
         assert(temp1 >= 0  &&  temp1 < 16);
 
         temp = xM[i] << temp1;
-        temp = gsm_mult(temp, temp2);
+        temp = saturated_mul16(temp, temp2);
         temp >>= 12;
         xMc[i] = (int16_t) (temp + 4);      /* See note below */
     }
@@ -444,9 +444,9 @@ static void apcm_inverse_quantization(int16_t xMc[13],
     assert(mant >= 0  &&  mant <= 7);
 #endif
 
-    temp1 = gsm_FAC[mant];          /* See 4.2-15 for mant */
-    temp2 = gsm_sub(6, exp);        /* See 4.2-15 for exp */
-    temp3 = gsm_asl(1, gsm_sub (temp2, 1));
+    temp1 = gsm_FAC[mant];                  /* See 4.2-15 for mant */
+    temp2 = saturated_sub16(6, exp);        /* See 4.2-15 for exp */
+    temp3 = gsm_asl(1, saturated_sub16(temp2, 1));
 
     for (i = 0;  i < 13;  i++)
     {
@@ -457,7 +457,7 @@ static void apcm_inverse_quantization(int16_t xMc[13],
 
         temp <<= 12;                            /* 16 bit signed */
         temp = gsm_mult_r(temp1, temp);
-        temp = gsm_add(temp, temp3);
+        temp = saturated_add16(temp, temp3);
         xMp[i] = gsm_asr(temp, temp2);
     }
     /*endfor*/
index e68623265438a03ad07fe4710baee2a63cc6f958..4eaace5a5d98be362f6d321da713234af6615078 100644 (file)
@@ -25,7 +25,7 @@
  * This code is based on the widely used GSM 06.10 code available from
  * http://kbs.cs.tu-berlin.de/~jutta/toast.html
  *
- * $Id: gsm0610_short_term.c,v 1.15 2008/07/02 14:48:25 steveu Exp $
+ * $Id: gsm0610_short_term.c,v 1.16 2008/09/19 14:02:05 steveu Exp $
  */
 
 /*! \file */
@@ -47,7 +47,7 @@
 
 #include "spandsp/telephony.h"
 #include "spandsp/bitstream.h"
-#include "spandsp/dc_restore.h"
+#include "spandsp/saturated.h"
 #include "spandsp/gsm0610.h"
 
 #include "gsm0610_local.h"
@@ -68,11 +68,11 @@ static void decode_log_area_ratios(int16_t LARc[8], int16_t *LARpp)
     /* Compute the LARpp[1..8] */
 
 #undef STEP
-#define STEP(B,MIC,INVA)                        \
-    temp1 = gsm_add(*LARc++, MIC) << 10;       \
-    temp1 = gsm_sub(temp1, B << 1);            \
-    temp1 = gsm_mult_r (INVA, temp1);           \
-    *LARpp++ = gsm_add(temp1, temp1);
+#define STEP(B,MIC,INVA)                            \
+    temp1 = saturated_add16(*LARc++, MIC) << 10;    \
+    temp1 = saturated_sub16(temp1, B << 1);         \
+    temp1 = gsm_mult_r(INVA, temp1);                \
+    *LARpp++ = saturated_add16(temp1, temp1);
 
     STEP(    0,  -32,  13107);
     STEP(    0,  -32,  13107);
@@ -110,8 +110,8 @@ static void coefficients_0_12(int16_t *LARpp_j_1,
 
     for (i = 1;  i <= 8;  i++, LARp++, LARpp_j_1++, LARpp_j++)
     {
-        *LARp = gsm_add(*LARpp_j_1 >> 2, *LARpp_j >> 2);
-        *LARp = gsm_add(*LARp, *LARpp_j_1 >> 1);
+        *LARp = saturated_add16(*LARpp_j_1 >> 2, *LARpp_j >> 2);
+        *LARp = saturated_add16(*LARp, *LARpp_j_1 >> 1);
     }
     /*endfor*/
 }
@@ -124,7 +124,7 @@ static void coefficients_13_26(int16_t *LARpp_j_1,
     int i;
 
     for (i = 1;  i <= 8;  i++, LARpp_j_1++, LARpp_j++, LARp++)
-        *LARp = gsm_add(*LARpp_j_1 >> 1, *LARpp_j >> 1);
+        *LARp = saturated_add16(*LARpp_j_1 >> 1, *LARpp_j >> 1);
     /*endfor*/
 }
 /*- End of function --------------------------------------------------------*/
@@ -137,8 +137,8 @@ static void coefficients_27_39(int16_t *LARpp_j_1,
 
     for (i = 1;  i <= 8;  i++, LARpp_j_1++, LARpp_j++, LARp++)
     {
-        *LARp = gsm_add(*LARpp_j_1 >> 2, *LARpp_j >> 2);
-        *LARp = gsm_add(*LARp, *LARpp_j >> 1);
+        *LARp = saturated_add16(*LARpp_j_1 >> 2, *LARpp_j >> 2);
+        *LARp = saturated_add16(*LARp, *LARpp_j >> 1);
     }
     /*endfor*/
 }
@@ -182,7 +182,7 @@ static void larp_to_rp(int16_t LARp[8])
             else if (temp < 20070)
                 temp += 11059;
             else
-                temp = gsm_add(temp >> 2, 26112);
+                temp = saturated_add16(temp >> 2, 26112);
             /*endif*/
             *LARpx = -temp;
         }
@@ -193,7 +193,7 @@ static void larp_to_rp(int16_t LARp[8])
             else if (temp < 20070)
                 temp += 11059;
             else
-                temp = gsm_add(temp >> 2, 26112);
+                temp = saturated_add16(temp >> 2, 26112);
             /*endif*/
             *LARpx = temp;
         }
@@ -279,7 +279,7 @@ static void short_term_synthesis_filtering(gsm0610_state_t *s,
                    :
                    (int16_t) (((int32_t) tmp1*(int32_t) tmp2 + 16384) >> 15) & 0xFFFF);
 
-            sri = gsm_sub(sri, tmp2);
+            sri = saturated_sub16(sri, tmp2);
 
             tmp1 = ((tmp1 == INT16_MIN  &&  sri == INT16_MIN)
                     ?
@@ -287,7 +287,7 @@ static void short_term_synthesis_filtering(gsm0610_state_t *s,
                     :
                     (int16_t) (((int32_t) tmp1*(int32_t) sri + 16384) >> 15) & 0xFFFF);
 
-            v[i + 1] = gsm_add(v[i], tmp1);
+            v[i + 1] = saturated_add16(v[i], tmp1);
         }
         /*endfor*/
         *sr++ =
index 6be16b57347eb537b0c65540a78cee1801aaf6a4..d92f28b9eed278fd504dbc1e912de31d13aff875 100644 (file)
@@ -23,7 +23,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: ima_adpcm.c,v 1.28 2008/07/02 14:48:25 steveu Exp $
+ * $Id: ima_adpcm.c,v 1.29 2008/09/19 14:02:05 steveu Exp $
  */
 
 /*! \file */
@@ -44,7 +44,7 @@
 #endif
 
 #include "spandsp/telephony.h"
-#include "spandsp/dc_restore.h"
+#include "spandsp/saturated.h"
 #include "spandsp/ima_adpcm.h"
 
 /*
index cc031e142bb98cde98d31db65f0629928f105365..fc6cda3186750223ce66f44de33c0957a96a188b 100644 (file)
@@ -133,6 +133,10 @@ SOURCE=.\complex_vector_float.c
 # End Source File\r
 # Begin Source File\r
 \r
+SOURCE=.\complex_vector_int.c\r
+# End Source File\r
+# Begin Source File\r
+\r
 SOURCE=.\crc.c\r
 # End Source File\r
 # Begin Source File\r
@@ -165,11 +169,7 @@ SOURCE=.\g711.c
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\g722_encode.c\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\g722_decode.c\r
+SOURCE=.\g722.c\r
 # End Source File\r
 # Begin Source File\r
 \r
index b8599bdce82d97b1a7efe639a0c6aaed9c66dea7..ddfdb6e41d42a136c4c59f1cfb988a5c50e23f36 100644 (file)
@@ -23,7 +23,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: make_modem_filter.c,v 1.11 2008/07/02 14:48:25 steveu Exp $
+ * $Id: make_modem_filter.c,v 1.12 2008/09/18 14:59:30 steveu Exp $
  */
 
 #if defined(HAVE_CONFIG_H)
@@ -158,6 +158,7 @@ static void make_rx_filter(int coeff_sets,
 {
     int i;
     int j;
+    int k;
     int m;
     int x;
     int total_coeffs;
@@ -166,7 +167,11 @@ static void make_rx_filter(int coeff_sets,
     double gain;
     double peak;
     double coeffs[MAX_COEFF_SETS*MAX_COEFFS_PER_FILTER + 1];
+#if 0
     complex_t co[MAX_COEFFS_PER_FILTER];
+#else
+    double cox[MAX_COEFFS_PER_FILTER];
+#endif
 
     total_coeffs = coeff_sets*coeffs_per_filter + 1;
     alpha = baud_rate/(2.0*(double) (coeff_sets*SAMPLE_RATE));
@@ -203,6 +208,7 @@ static void make_rx_filter(int coeff_sets,
        modem code. */
     printf("#define RX_PULSESHAPER%s_GAIN        %ff\n", tag, gain);
     printf("#define RX_PULSESHAPER%s_COEFF_SETS  %d\n", tag, coeff_sets);
+#if 0
     printf("static const %s rx_pulseshaper%s[RX_PULSESHAPER%s_COEFF_SETS][%d] =\n",
            (fixed_point)  ?  "complexi16_t"  :  "complexf_t",
            tag,
@@ -244,6 +250,55 @@ static void make_rx_filter(int coeff_sets,
             printf("    }\n");
     }
     printf("};\n");
+#else
+    for (k = 0;  k < 2;  k++)
+    {
+        printf("static const %s rx_pulseshaper%s_%s[RX_PULSESHAPER%s_COEFF_SETS][%d] =\n",
+               (fixed_point)  ?  "int16_t"  :  "float",
+               tag,
+               (k == 0)  ?  "re"  :  "im",
+               tag,
+               coeffs_per_filter);
+        printf("{\n");
+        for (j = 0;  j < coeff_sets;  j++)
+        {
+            /* Complex modulate the filter, to make it a complex pulse shaping bandpass filter
+               centred at the nominal carrier frequency. Use the same phase for all the coefficient
+               sets. This means the modem can step the carrier in whole samples, and not worry about
+               the fractional sample shift caused by selecting amongst the various coefficient sets. */
+            for (i = 0;  i < coeffs_per_filter;  i++)
+            {
+                m = i - (coeffs_per_filter >> 1);
+                x = i*coeff_sets + j;
+                if (k == 0)
+                    cox[i] = coeffs[x]*cos(carrier*m);
+                else
+                    cox[i] = coeffs[x]*sin(carrier*m);
+            }
+            printf("    {\n");
+            if (fixed_point)
+                printf("        %8d,     /* Filter %d */\n", (int) cox[0], j);
+            else
+                printf("        %15.10ff,     /* Filter %d */\n", cox[0], j);
+            for (i = 1;  i < coeffs_per_filter - 1;  i++)
+            {
+                if (fixed_point)
+                    printf("        %8d,\n", (int) cox[i]);
+                else
+                    printf("        %15.10ff,\n", cox[i]);
+            }
+            if (fixed_point)
+                printf("        %8d\n", (int) cox[i]);
+            else
+                printf("        %15.10ff\n", cox[i]);
+            if (j < coeff_sets - 1)
+                printf("    },\n");
+            else
+                printf("    }\n");
+        }
+        printf("};\n");
+    }
+#endif
 }
 /*- End of function --------------------------------------------------------*/
 
index 559741dd081b7e97c71413fb30212e236a1b6d89..baee0d1edd2d420bb010f27997c2abe08cee4d6e 100644 (file)
@@ -23,7 +23,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: noise.c,v 1.24 2008/08/17 14:18:11 steveu Exp $
+ * $Id: noise.c,v 1.25 2008/09/19 14:02:05 steveu Exp $
  */
 
 /*! \file */
@@ -45,7 +45,7 @@
 #endif
 
 #include "spandsp/telephony.h"
-#include "spandsp/dc_restore.h"
+#include "spandsp/saturated.h"
 #include "spandsp/noise.h"
 
 int16_t noise(noise_state_t *s)
index 1b01e220cdbfc252fd02a1ced47bf034e5f1f22f..ce6a096796eb36b27e53160c5019e2a46480073f 100644 (file)
@@ -22,7 +22,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: plc.c,v 1.22 2008/07/02 14:48:25 steveu Exp $
+ * $Id: plc.c,v 1.23 2008/09/19 14:02:05 steveu Exp $
  */
 
 /*! \file */
@@ -45,7 +45,7 @@
 #include <limits.h>
 
 #include "spandsp/telephony.h"
-#include "spandsp/dc_restore.h"
+#include "spandsp/saturated.h"
 #include "spandsp/plc.h"
 
 /* We do a straight line fade to zero volume in 50ms when we are filling in for missing data. */
index 19c73e26949247970bffc36741fdf8315d908686..6c498d108511d2429055f5762ddd7210bf6d9964 100644 (file)
@@ -23,7 +23,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: sig_tone.c,v 1.24 2008/08/17 16:25:52 steveu Exp $
+ * $Id: sig_tone.c,v 1.25 2008/09/19 14:02:05 steveu Exp $
  */
 
 /*! \file */
@@ -48,6 +48,7 @@
 #undef SPANDSP_USE_FIXED_POINT
 #include "spandsp/telephony.h"
 #include "spandsp/dc_restore.h"
+#include "spandsp/saturated.h"
 #include "spandsp/complex.h"
 #include "spandsp/dds.h"
 #include "spandsp/sig_tone.h"
index c59f68382c59d57e4ff84a0139ab582a6d35957e..1611b871606c9fc6c648dc15e8be06d05782deaf 100644 (file)
@@ -22,7 +22,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: spandsp.h.in,v 1.10 2008/09/01 16:07:34 steveu Exp $
+ * $Id: spandsp.h.in,v 1.11 2008/09/19 14:02:05 steveu Exp $
  */
 
 /*! \file */
@@ -69,6 +69,7 @@
 #include <spandsp/hdlc.h>
 #include <spandsp/async.h>
 #include <spandsp/noise.h>
+#include <spandsp/saturated.h>
 #include <spandsp/time_scale.h>
 #include <spandsp/tone_detect.h>
 #include <spandsp/tone_generate.h>
index c8931e4560ff9fccb50819be602c2e7e1f55ef24..5f144458e199e1f26b332bdb247bd4b75e593bd7 100644 (file)
@@ -22,7 +22,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: complex_vector_float.h,v 1.8 2008/04/17 14:27:00 steveu Exp $
+ * $Id: complex_vector_float.h,v 1.10 2008/09/18 13:16:49 steveu Exp $
  */
 
 #if !defined(_SPANDSP_COMPLEX_VECTOR_FLOAT_H_)
@@ -120,6 +120,42 @@ static __inline__ void cvec_setl(complexl_t z[], complexl_t *x, int n)
 /*- End of function --------------------------------------------------------*/
 #endif
 
+/*! \brief Find the dot product of two complex float vectors.
+    \param x The first vector.
+    \param y The first vector.
+    \param n The number of elements in the vectors.
+    \return The dot product of the two vectors. */
+complexf_t cvec_dot_prodf(const complexf_t x[], const complexf_t y[], int n);
+
+/*! \brief Find the dot product of two complex double vectors.
+    \param x The first vector.
+    \param y The first vector.
+    \param n The number of elements in the vectors.
+    \return The dot product of the two vectors. */
+complex_t cvec_dot_prod(const complex_t x[], const complex_t y[], int n);
+
+#if defined(HAVE_LONG_DOUBLE)
+/*! \brief Find the dot product of two complex long double vectors.
+    \param x The first vector.
+    \param y The first vector.
+    \param n The number of elements in the vectors.
+    \return The dot product of the two vectors. */
+complexl_t cvec_dot_prodl(const complexl_t x[], const complexl_t y[], int n);
+#endif
+
+/*! \brief Find the dot product of two complex float vectors, where the first is a circular buffer
+           with an offset for the starting position.
+    \param x The first vector.
+    \param y The first vector.
+    \param n The number of elements in the vectors.
+    \param pos The starting position in the x vector.
+    \return The dot product of the two vectors. */
+complexf_t cvec_circular_dot_prodf(const complexf_t x[], const complexf_t y[], int n, int pos);
+
+void cvec_lmsf(const complexf_t x[], complexf_t y[], int n, const complexf_t *error);
+
+void cvec_circular_lmsf(const complexf_t x[], complexf_t y[], int n, int pos, const complexf_t *error);
+
 #if defined(__cplusplus)
 }
 #endif
index 278b9296ae2f725a60ab908ff964a2f3dd888e8f..5eb4515a2920cf9cca60990d73cf1f668c8ef69a 100644 (file)
@@ -22,7 +22,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: complex_vector_int.h,v 1.1 2008/09/01 16:07:34 steveu Exp $
+ * $Id: complex_vector_int.h,v 1.3 2008/09/18 13:16:49 steveu Exp $
  */
 
 #if !defined(_SPANDSP_COMPLEX_VECTOR_INT_H_)
@@ -96,6 +96,33 @@ static __inline__ void cvec_seti32(complexi32_t z[], complexi32_t *x, int n)
 }
 /*- End of function --------------------------------------------------------*/
 
+/*! \brief Find the dot product of two complex int16_t vectors.
+    \param x The first vector.
+    \param y The first vector.
+    \param n The number of elements in the vectors.
+    \return The dot product of the two vectors. */
+complexi32_t cvec_dot_prodi16(const complexi16_t x[], const complexi16_t y[], int n);
+
+/*! \brief Find the dot product of two complex int32_t vectors.
+    \param x The first vector.
+    \param y The first vector.
+    \param n The number of elements in the vectors.
+    \return The dot product of the two vectors. */
+complexi32_t cvec_dot_prodi32(const complexi32_t x[], const complexi32_t y[], int n);
+
+/*! \brief Find the dot product of two complex int16_t vectors, where the first is a circular buffer
+           with an offset for the starting position.
+    \param x The first vector.
+    \param y The first vector.
+    \param n The number of elements in the vectors.
+    \param pos The starting position in the x vector.
+    \return The dot product of the two vectors. */
+complexi32_t cvec_circular_dot_prodi16(const complexi16_t x[], const complexi16_t y[], int n, int pos);
+
+void cvec_lmsi16(const complexi16_t x[], complexi16_t y[], int n, const complexi16_t *error);
+
+void cvec_circular_lmsi16(const complexi16_t x[], complexi16_t y[], int n, int pos, const complexi16_t *error);
+
 #if defined(__cplusplus)
 }
 #endif
index 33393a92a2b31be74648a6dd83fa91b48b37452a..4061f41137d33fc2431f1b422b2edce35652764e 100644 (file)
@@ -23,7 +23,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: dc_restore.h,v 1.23 2008/08/16 14:59:50 steveu Exp $
+ * $Id: dc_restore.h,v 1.24 2008/09/19 14:02:05 steveu Exp $
  */
 
 /*! \file */
@@ -85,60 +85,6 @@ static __inline__ int16_t dc_restore_estimate(dc_restore_state_t *dc)
 }
 /*- End of function --------------------------------------------------------*/
 
-static __inline__ int16_t saturate(int32_t amp)
-{
-    int16_t amp16;
-
-    /* Hopefully this is optimised for the common case - not clipping */
-    amp16 = (int16_t) amp;
-    if (amp == amp16)
-        return amp16;
-    if (amp > INT16_MAX)
-        return  INT16_MAX;
-    return  INT16_MIN;
-}
-/*- End of function --------------------------------------------------------*/
-
-static __inline__ int16_t fsaturatef(float famp)
-{
-    if (famp > 32767.0f)
-        return  INT16_MAX;
-    if (famp < -32768.0f)
-        return  INT16_MIN;
-    return (int16_t) rintf(famp);
-}
-/*- End of function --------------------------------------------------------*/
-
-static __inline__ int16_t fsaturate(double damp)
-{
-    if (damp > 32767.0)
-        return  INT16_MAX;
-    if (damp < -32768.0)
-        return  INT16_MIN;
-    return (int16_t) rint(damp);
-}
-/*- End of function --------------------------------------------------------*/
-
-static __inline__ float ffsaturatef(float famp)
-{
-    if (famp > 32767.0f)
-        return  (float) INT16_MAX;
-    if (famp < -32768.0f)
-        return  (float) INT16_MIN;
-    return famp;
-}
-/*- End of function --------------------------------------------------------*/
-
-static __inline__ double ffsaturate(double famp)
-{
-    if (famp > 32767.0)
-        return  (double) INT16_MAX;
-    if (famp < -32768.0)
-        return  (double) INT16_MIN;
-    return famp;
-}
-/*- End of function --------------------------------------------------------*/
-
 #if defined(__cplusplus)
 }
 #endif
index 11a901d00f7bc5159666690c9a364c05109a5325..7d2936bdb9f58361a6fde564e70e92d9af9834eb 100644 (file)
@@ -28,7 +28,7 @@
  * Computer Science, Speech Group
  * Chengxiang Lu and Alex Hauptmann
  *
- * $Id: g722.h,v 1.19 2008/04/17 14:27:00 steveu Exp $
+ * $Id: g722.h,v 1.20 2008/09/19 14:02:05 steveu Exp $
  */
 
 
@@ -56,6 +56,20 @@ enum
     G722_PACKED = 0x0002
 };
 
+/*! The per band parameters for both encoding and decoding G.722 */
+typedef struct
+{
+    int16_t s;
+    int16_t sz;
+    int16_t r[3];
+    int16_t a[3];
+    int16_t p[3];
+    int16_t d[7];
+    int16_t b[7];
+    int16_t nb;
+    int16_t det;
+} g722_band_t;
+
 typedef struct
 {
     /*! TRUE if the operating in the special ITU test mode, with the band split filters
@@ -69,28 +83,15 @@ typedef struct
     int bits_per_sample;
 
     /*! Signal history for the QMF */
-    int x[24];
-
-    struct
-    {
-        int s;
-        int sp;
-        int sz;
-        int r[3];
-        int a[3];
-        int ap[3];
-        int p[3];
-        int d[7];
-        int b[7];
-        int bp[7];
-        int sg[7];
-        int nb;
-        int det;
-    } band[2];
-
-    unsigned int in_buffer;
+    int16_t x[12];
+    int16_t y[12];
+    int ptr;
+
+    g722_band_t band[2];
+
+    uint32_t in_buffer;
     int in_bits;
-    unsigned int out_buffer;
+    uint32_t out_buffer;
     int out_bits;
 } g722_encode_state_t;
 
@@ -107,28 +108,15 @@ typedef struct
     int bits_per_sample;
 
     /*! Signal history for the QMF */
-    int x[24];
-
-    struct
-    {
-        int s;
-        int sp;
-        int sz;
-        int r[3];
-        int a[3];
-        int ap[3];
-        int p[3];
-        int d[7];
-        int b[7];
-        int bp[7];
-        int sg[7];
-        int nb;
-        int det;
-    } band[2];
+    int16_t x[12];
+    int16_t y[12];
+    int ptr;
+
+    g722_band_t band[2];
     
-    unsigned int in_buffer;
+    uint32_t in_buffer;
     int in_bits;
-    unsigned int out_buffer;
+    uint32_t out_buffer;
     int out_bits;
 } g722_decode_state_t;
 
index d7fb9cc5f5f34e0bc6f039e52292d610fd7f5d87..347170743a2d5e290961e3eb3c71dcde3aa79f58 100644 (file)
@@ -22,7 +22,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: v17rx.h,v 1.54 2008/09/16 13:02:05 steveu Exp $
+ * $Id: v17rx.h,v 1.57 2008/09/18 14:59:30 steveu Exp $
  */
 
 /*! \file */
@@ -213,9 +213,8 @@ TCM absolutely transformed the phone line modem business.
 
 /* Target length for the equalizer is about 63 taps, to deal with the worst stuff
    in V.56bis. */
-#define V17_EQUALIZER_PRE_LEN       7  /* this much before the real event */
-#define V17_EQUALIZER_POST_LEN      7  /* this much after the real event */
-#define V17_EQUALIZER_MASK          63 /* one less than a power of 2 >= (V17_EQUALIZER_PRE_LEN + 1 + V17_EQUALIZER_POST_LEN) */
+#define V17_EQUALIZER_PRE_LEN       8  /* This much before the real event */
+#define V17_EQUALIZER_POST_LEN      8  /* This much after the real event (must be even) */
 
 #define V17_RX_FILTER_STEPS         27
 
@@ -253,9 +252,9 @@ typedef struct
 
     /*! \brief The route raised cosine (RRC) pulse shaping filter buffer. */
 #if defined(SPANDSP_USE_FIXED_POINT)
-    int16_t rrc_filter[2*V17_RX_FILTER_STEPS];
+    int16_t rrc_filter[V17_RX_FILTER_STEPS];
 #else
-    float rrc_filter[2*V17_RX_FILTER_STEPS];
+    float rrc_filter[V17_RX_FILTER_STEPS];
 #endif
     /*! \brief Current offset into the RRC pulse shaping filter buffer. */
     int rrc_filter_step;
@@ -332,7 +331,7 @@ typedef struct
     /*! \brief A saved set of adaptive equalizer coefficients for use after restarts. */
     complexi16_t eq_coeff_save[V17_EQUALIZER_PRE_LEN + 1 + V17_EQUALIZER_POST_LEN];
     /*! \brief The equalizer signal buffer. */
-    complexi16_t eq_buf[V17_EQUALIZER_MASK + 1];
+    complexi16_t eq_buf[V17_EQUALIZER_PRE_LEN + 1 + V17_EQUALIZER_POST_LEN];
 
     /*! Low band edge filter for symbol sync. */
     int32_t symbol_sync_low[2];
@@ -355,7 +354,7 @@ typedef struct
     /*! \brief A saved set of adaptive equalizer coefficients for use after restarts. */
     complexf_t eq_coeff_save[V17_EQUALIZER_PRE_LEN + 1 + V17_EQUALIZER_POST_LEN];
     /*! \brief The equalizer signal buffer. */
-    complexf_t eq_buf[V17_EQUALIZER_MASK + 1];
+    complexf_t eq_buf[V17_EQUALIZER_PRE_LEN + 1 + V17_EQUALIZER_POST_LEN];
 
     /*! Low band edge filter for symbol sync. */
     float symbol_sync_low[2];
index cc6be878b135ce3295333c0f76dfb6ee96323d46..a70465423c647496e9ff5562cb187440923f4e5f 100644 (file)
@@ -22,7 +22,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: v27ter_rx.h,v 1.51 2008/09/16 14:12:23 steveu Exp $
+ * $Id: v27ter_rx.h,v 1.53 2008/09/18 14:59:30 steveu Exp $
  */
 
 /*! \file */
@@ -48,9 +48,8 @@ straightforward.
 
 /* Target length for the equalizer is about 43 taps for 4800bps and 32 taps for 2400bps
    to deal with the worst stuff in V.56bis. */
-#define V27TER_EQUALIZER_PRE_LEN        15  /* this much before the real event */
-#define V27TER_EQUALIZER_POST_LEN       15  /* this much after the real event */
-#define V27TER_EQUALIZER_MASK           63  /* one less than a power of 2 >= (V27TER_EQUALIZER_PRE_LEN + 1 + V27TER_EQUALIZER_POST_LEN) */
+#define V27TER_EQUALIZER_PRE_LEN        16  /* This much before the real event */
+#define V27TER_EQUALIZER_POST_LEN       14  /* This much after the real event (must be even) */
 
 #define V27TER_RX_4800_FILTER_STEPS     27
 #define V27TER_RX_2400_FILTER_STEPS     27
@@ -88,9 +87,9 @@ typedef struct
 
     /*! \brief The route raised cosine (RRC) pulse shaping filter buffer. */
 #if defined(SPANDSP_USE_FIXED_POINT)
-    int16_t rrc_filter[2*V27TER_RX_FILTER_STEPS];
+    int16_t rrc_filter[V27TER_RX_FILTER_STEPS];
 #else
-    float rrc_filter[2*V27TER_RX_FILTER_STEPS];
+    float rrc_filter[V27TER_RX_FILTER_STEPS];
 #endif
     /*! \brief Current offset into the RRC pulse shaping filter buffer. */
     int rrc_filter_step;
@@ -174,7 +173,7 @@ typedef struct
     /*! \brief A saved set of adaptive equalizer coefficients for use after restarts. */
     /*complexi16_t*/ complexf_t  eq_coeff_save[V27TER_EQUALIZER_PRE_LEN + 1 + V27TER_EQUALIZER_POST_LEN];
     /*! \brief The equalizer signal buffer. */
-    /*complexi16_t*/ complexf_t eq_buf[V27TER_EQUALIZER_MASK + 1];
+    /*complexi16_t*/ complexf_t eq_buf[V27TER_EQUALIZER_PRE_LEN + 1 + V27TER_EQUALIZER_POST_LEN];
 #else
     /*! \brief The scaling factor accessed by the AGC algorithm. */
     float agc_scaling;
@@ -188,7 +187,7 @@ typedef struct
     /*! \brief A saved set of adaptive equalizer coefficients for use after restarts. */
     complexf_t eq_coeff_save[V27TER_EQUALIZER_PRE_LEN + 1 + V27TER_EQUALIZER_POST_LEN];
     /*! \brief The equalizer signal buffer. */
-    complexf_t eq_buf[V27TER_EQUALIZER_MASK + 1];
+    complexf_t eq_buf[V27TER_EQUALIZER_PRE_LEN + 1 + V27TER_EQUALIZER_POST_LEN];
 #endif
 
     /*! \brief Integration variable for damping the Gardner algorithm tests. */
index 20671542b6a1d0a45340c6e5c33d97cc1f03ba19..cac4a9d47de11e13c2509bca7afbe83e4b748f9a 100644 (file)
@@ -22,7 +22,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: v29rx.h,v 1.62 2008/09/16 14:12:23 steveu Exp $
+ * $Id: v29rx.h,v 1.64 2008/09/18 14:59:30 steveu Exp $
  */
 
 /*! \file */
@@ -122,9 +122,8 @@ therefore, only tests that bits starting at bit 24 are really ones.
 
 /* Target length for the equalizer is about 63 taps, to deal with the worst stuff
    in V.56bis. */
-#define V29_EQUALIZER_PRE_LEN   15  /* this much before the real event */
-#define V29_EQUALIZER_POST_LEN  15  /* this much after the real event */
-#define V29_EQUALIZER_MASK      63  /* one less than a power of 2 >= (2*V29_EQUALIZER_LEN + 1) */
+#define V29_EQUALIZER_PRE_LEN   16  /* This much before the real event */
+#define V29_EQUALIZER_POST_LEN  14  /* This much after the real event (must be even) */
 
 #define V29_RX_FILTER_STEPS     27
 
@@ -157,9 +156,9 @@ typedef struct
 
     /*! \brief The route raised cosine (RRC) pulse shaping filter buffer. */
 #if defined(SPANDSP_USE_FIXED_POINT)
-    int16_t rrc_filter[2*V29_RX_FILTER_STEPS];
+    int16_t rrc_filter[V29_RX_FILTER_STEPS];
 #else
-    float rrc_filter[2*V29_RX_FILTER_STEPS];
+    float rrc_filter[V29_RX_FILTER_STEPS];
 #endif
     /*! \brief Current offset into the RRC pulse shaping filter buffer. */
     int rrc_filter_step;
@@ -242,7 +241,7 @@ typedef struct
     /*! \brief A saved set of adaptive equalizer coefficients for use after restarts. */
     complexi16_t eq_coeff_save[V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN];
     /*! \brief The equalizer signal buffer. */
-    complexi16_t eq_buf[V29_EQUALIZER_MASK + 1];
+    complexi16_t eq_buf[V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN];
 
     /*! Low band edge filter for symbol sync. */
     int32_t symbol_sync_low[2];
@@ -265,7 +264,7 @@ typedef struct
     /*! \brief A saved set of adaptive equalizer coefficients for use after restarts. */
     complexf_t eq_coeff_save[V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN];
     /*! \brief The equalizer signal buffer. */
-    complexf_t eq_buf[V29_EQUALIZER_MASK + 1];
+    complexf_t eq_buf[V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN];
 
     /*! Low band edge filter for symbol sync. */
     float symbol_sync_low[2];
index 94c67cf33ecc8c674e0f1fd8b8efeb9eedf43c08..946d84741a8a3101d9436596fcd7e97d9f8807f5 100644 (file)
@@ -22,7 +22,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: vector_float.h,v 1.11 2008/09/01 16:07:34 steveu Exp $
+ * $Id: vector_float.h,v 1.13 2008/09/18 13:54:32 steveu Exp $
  */
 
 #if !defined(_SPANDSP_VECTOR_FLOAT_H_)
@@ -128,6 +128,19 @@ double vec_dot_prod(const double x[], const double y[], int n);
 long double vec_dot_prodl(const long double x[], const long double y[], int n);
 #endif
 
+/*! \brief Find the dot product of two float vectors, where the first is a circular buffer
+           with an offset for the starting position.
+    \param x The first vector.
+    \param y The first vector.
+    \param n The number of elements in the vectors.
+    \param pos The starting position in the x vector.
+    \return The dot product of the two vectors. */
+float vec_circular_dot_prodf(const float x[], const float y[], int n, int pos);
+
+void vec_lmsf(const float x[], float y[], int n, float error);
+
+void vec_circular_lmsf(const float x[], float y[], int n, int pos, float error);
+
 #if defined(__cplusplus)
 }
 #endif
index f603bd21432b0e7b5ddfab9a839976bcb96070ca..7f9b011049e5081b79c712bee2abaacd8c3359f4 100644 (file)
@@ -22,7 +22,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: vector_int.h,v 1.11 2008/09/01 16:07:34 steveu Exp $
+ * $Id: vector_int.h,v 1.13 2008/09/18 13:54:32 steveu Exp $
  */
 
 #if !defined(_SPANDSP_VECTOR_INT_H_)
@@ -103,6 +103,19 @@ static __inline__ void vec_seti32(int32_t z[], int32_t x, int n)
     \return The dot product of the two vectors. */
 int32_t vec_dot_prodi16(const int16_t x[], const int16_t y[], int n);
 
+/*! \brief Find the dot product of two int16_t vectors, where the first is a circular buffer
+           with an offset for the starting position.
+    \param x The first vector.
+    \param y The first vector.
+    \param n The number of elements in the vectors.
+    \param pos The starting position in the x vector.
+    \return The dot product of the two vectors. */
+int32_t vec_circular_dot_prodi16(const int16_t x[], const int16_t y[], int n, int pos);
+
+void vec_lmsi16(const int16_t x[], int16_t y[], int n, int16_t error);
+
+void vec_circular_lmsi16(const int16_t x[], int16_t y[], int n, int pos, int16_t error);
+
 /*! \brief Find the minimum and maximum values in an int16_t vector.
     \param x The vector to be searched.
     \param n The number of elements in the vector.
index eef22ad70e4f97d8802e181647d47f37a2336750..537acce6fb8b9b3c5c2ab61314e942d8f90ba7a9 100644 (file)
@@ -30,8 +30,8 @@
 
 /* The date and time of the version are in UTC form. */
 
-#define SPANDSP_RELEASE_DATE    20080916
-#define SPANDSP_RELEASE_TIME    152844
+#define SPANDSP_RELEASE_DATE    20080919
+#define SPANDSP_RELEASE_TIME    142905
 
 #endif
 /*- End of file ------------------------------------------------------------*/
index 27e02bd899188003de42828255270503976efa4d..0b913ad7ffdf5a2c066fb3d45378ed5b81bafda2 100644 (file)
@@ -22,7 +22,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: time_scale.c,v 1.23 2008/07/28 15:14:30 steveu Exp $
+ * $Id: time_scale.c,v 1.24 2008/09/19 14:02:05 steveu Exp $
  */
 
 /*! \file */
@@ -48,6 +48,7 @@
 
 #include "spandsp/telephony.h"
 #include "spandsp/time_scale.h"
+#include "spandsp/saturated.h"
 
 /*
     Time scaling for speech, based on the Pointer Interval Controlled
index 82a3f54a5857a2d0e6d6e730f5034d0b1b5c4e70..edccf3143e0414b7e4344041057bcc0bd168bc5e 100644 (file)
@@ -22,7 +22,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: v17rx.c,v 1.118 2008/09/16 14:12:23 steveu Exp $
+ * $Id: v17rx.c,v 1.123 2008/09/18 15:59:55 steveu Exp $
  */
 
 /*! \file */
@@ -48,6 +48,8 @@
 #include "spandsp/complex.h"
 #include "spandsp/vector_float.h"
 #include "spandsp/complex_vector_float.h"
+#include "spandsp/vector_int.h"
+#include "spandsp/complex_vector_int.h"
 #include "spandsp/async.h"
 #include "spandsp/power_meter.h"
 #include "spandsp/arctan2.h"
@@ -81,6 +83,8 @@
 
 #define V17_BRIDGE_WORD                 0x8880
 
+#define V17_EQUALIZER_LEN    (V17_EQUALIZER_PRE_LEN + 1 + V17_EQUALIZER_POST_LEN)
+
 enum
 {
     TRAINING_STAGE_NORMAL_OPERATION = 0,
@@ -149,16 +153,16 @@ int v17_rx_equalizer_state(v17_rx_state_t *s, complexf_t **coeffs)
 #endif
 {
     *coeffs = s->eq_coeff;
-    return V17_EQUALIZER_PRE_LEN + 1 + V17_EQUALIZER_POST_LEN;
+    return V17_EQUALIZER_LEN;
 }
 /*- End of function --------------------------------------------------------*/
 
 static void equalizer_save(v17_rx_state_t *s)
 {
 #if defined(SPANDSP_USE_FIXED_POINTx)
-    cvec_copyi16(s->eq_coeff_save, s->eq_coeff, V17_EQUALIZER_PRE_LEN + 1 + V17_EQUALIZER_POST_LEN);
+    cvec_copyi16(s->eq_coeff_save, s->eq_coeff, V17_EQUALIZER_LEN);
 #else
-    cvec_copyf(s->eq_coeff_save, s->eq_coeff, V17_EQUALIZER_PRE_LEN + 1 + V17_EQUALIZER_POST_LEN);
+    cvec_copyf(s->eq_coeff_save, s->eq_coeff, V17_EQUALIZER_LEN);
 #endif
 }
 /*- End of function --------------------------------------------------------*/
@@ -166,13 +170,13 @@ static void equalizer_save(v17_rx_state_t *s)
 static void equalizer_restore(v17_rx_state_t *s)
 {
 #if defined(SPANDSP_USE_FIXED_POINTx)
-    cvec_copyi16(s->eq_coeff, s->eq_coeff_save, V17_EQUALIZER_PRE_LEN + 1 + V17_EQUALIZER_POST_LEN);
-    cvec_zeroi16(s->eq_buf, V17_EQUALIZER_MASK);
-    s->eq_delta = 32768.0f*EQUALIZER_SLOW_ADAPT_RATIO*EQUALIZER_DELTA/(V17_EQUALIZER_PRE_LEN + 1 + V17_EQUALIZER_POST_LEN);
+    cvec_copyi16(s->eq_coeff, s->eq_coeff_save, V17_EQUALIZER_LEN);
+    cvec_zeroi16(s->eq_buf, V17_EQUALIZER_LEN);
+    s->eq_delta = 32768.0f*EQUALIZER_SLOW_ADAPT_RATIO*EQUALIZER_DELTA/V17_EQUALIZER_LEN;
 #else
-    cvec_copyf(s->eq_coeff, s->eq_coeff_save, V17_EQUALIZER_PRE_LEN + 1 + V17_EQUALIZER_POST_LEN);
-    cvec_zerof(s->eq_buf, V17_EQUALIZER_MASK);
-    s->eq_delta = EQUALIZER_SLOW_ADAPT_RATIO*EQUALIZER_DELTA/(V17_EQUALIZER_PRE_LEN + 1 + V17_EQUALIZER_POST_LEN);
+    cvec_copyf(s->eq_coeff, s->eq_coeff_save, V17_EQUALIZER_LEN);
+    cvec_zerof(s->eq_buf, V17_EQUALIZER_LEN);
+    s->eq_delta = EQUALIZER_SLOW_ADAPT_RATIO*EQUALIZER_DELTA/V17_EQUALIZER_LEN;
 #endif
 
     s->eq_put_step = RX_PULSESHAPER_COEFF_SETS*10/(3*2) - 1;
@@ -184,15 +188,15 @@ static void equalizer_reset(v17_rx_state_t *s)
 {
     /* Start with an equalizer based on everything being perfect */
 #if defined(SPANDSP_USE_FIXED_POINTx)
-    cvec_zeroi16(s->eq_coeff, V17_EQUALIZER_PRE_LEN + 1 + V17_EQUALIZER_POST_LEN);
+    cvec_zeroi16(s->eq_coeff, V17_EQUALIZER_LEN);
     s->eq_coeff[V17_EQUALIZER_PRE_LEN] = complex_seti16(3*FP_FACTOR, 0);
-    cvec_zeroi16(s->eq_buf, V17_EQUALIZER_MASK);
-    s->eq_delta = 32768.0f*EQUALIZER_DELTA/(V17_EQUALIZER_PRE_LEN + 1 + V17_EQUALIZER_POST_LEN);
+    cvec_zeroi16(s->eq_buf, V17_EQUALIZER_LEN);
+    s->eq_delta = 32768.0f*EQUALIZER_DELTA/V17_EQUALIZER_LEN;
 #else
-    cvec_zerof(s->eq_coeff, V17_EQUALIZER_PRE_LEN + 1 + V17_EQUALIZER_POST_LEN);
+    cvec_zerof(s->eq_coeff, V17_EQUALIZER_LEN);
     s->eq_coeff[V17_EQUALIZER_PRE_LEN] = complex_setf(3.0f, 0.0f);
-    cvec_zerof(s->eq_buf, V17_EQUALIZER_MASK);
-    s->eq_delta = EQUALIZER_DELTA/(V17_EQUALIZER_PRE_LEN + 1 + V17_EQUALIZER_POST_LEN);
+    cvec_zerof(s->eq_buf, V17_EQUALIZER_LEN);
+    s->eq_delta = EQUALIZER_DELTA/V17_EQUALIZER_LEN;
 #endif
 
     s->eq_put_step = RX_PULSESHAPER_COEFF_SETS*10/(3*2) - 1;
@@ -206,21 +210,7 @@ static __inline__ complexi16_t equalizer_get(v17_rx_state_t *s)
 static __inline__ complexf_t equalizer_get(v17_rx_state_t *s)
 #endif
 {
-    int i;
-    int p;
-    complexf_t z;
-    complexf_t z1;
-
-    /* Get the next equalized value. */
-    z = complex_setf(0.0f, 0.0f);
-    p = s->eq_step - 1;
-    for (i = 0;  i < V17_EQUALIZER_PRE_LEN + 1 + V17_EQUALIZER_POST_LEN;  i++)
-    {
-        p = (p - 1) & V17_EQUALIZER_MASK;
-        z1 = complex_mulf(&s->eq_coeff[i], &s->eq_buf[p]);
-        z = complex_addf(&z, &z1);
-    }
-    return z;
+    return cvec_circular_dot_prodf(s->eq_buf, s->eq_coeff, V17_EQUALIZER_LEN, s->eq_step);
 }
 /*- End of function --------------------------------------------------------*/
 
@@ -230,28 +220,18 @@ static void tune_equalizer(v17_rx_state_t *s, const complexi16_t *z, const compl
 static void tune_equalizer(v17_rx_state_t *s, const complexf_t *z, const complexf_t *target)
 #endif
 {
-    int i;
-    int p;
-    complexf_t ez;
-    complexf_t z1;
+    complexf_t err;
 
     /* Find the x and y mismatch from the exact constellation position. */
-    ez = complex_subf(target, z);
+    err = complex_subf(target, z);
     //span_log(&s->logging, SPAN_LOG_FLOW, "Equalizer error %f\n", sqrt(ez.re*ez.re + ez.im*ez.im));
-    ez.re *= s->eq_delta;
-    ez.im *= s->eq_delta;
+    err.re *= s->eq_delta;
+    err.im *= s->eq_delta;
 
-    p = s->eq_step - 1;
-    for (i = 0;  i < V17_EQUALIZER_PRE_LEN + 1 + V17_EQUALIZER_POST_LEN;  i++)
-    {
-        p = (p - 1) & V17_EQUALIZER_MASK;
-        z1 = complex_conjf(&s->eq_buf[p]);
-        z1 = complex_mulf(&ez, &z1);
-        s->eq_coeff[i] = complex_addf(&s->eq_coeff[i], &z1);
-        /* Leak a little to tame uncontrolled wandering */
-        s->eq_coeff[i].re *= 0.9999f;
-        s->eq_coeff[i].im *= 0.9999f;
-    }
+    err = complex_subf(target, z);
+    err.re *= s->eq_delta;
+    err.im *= s->eq_delta;
+    cvec_circular_lmsf(s->eq_buf, s->eq_coeff, V17_EQUALIZER_LEN, s->eq_step, &err);
 }
 /*- End of function --------------------------------------------------------*/
 
@@ -565,7 +545,8 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
     /* Add a sample to the equalizer's circular buffer, but don't calculate anything
        at this time. */
     s->eq_buf[s->eq_step] = *sample;
-    s->eq_step = (s->eq_step + 1) & V17_EQUALIZER_MASK;
+    if (++s->eq_step >= V17_EQUALIZER_LEN)
+        s->eq_step = 0;
 
     /* On alternate insertions we have a whole baud and must process it. */
     if ((s->baud_half ^= 1))
@@ -628,7 +609,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
             p = 3.14159f + angle*2.0f*3.14159f/(65536.0f*65536.0f) - 0.321751f;
             span_log(&s->logging, SPAN_LOG_FLOW, "Spin (short) by %.5f rads\n", p);
             zz = complex_setf(cosf(p), -sinf(p));
-            for (i = 0;  i <= V17_EQUALIZER_MASK;  i++)
+            for (i = 0;  i < V17_EQUALIZER_LEN;  i++)
                 s->eq_buf[i] = complex_mulf(&s->eq_buf[i], &zz);
             s->carrier_phase += (0x80000000 + angle - 219937506);
 
@@ -716,7 +697,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
             p = angle*2.0f*3.14159f/(65536.0f*65536.0f) - 0.321751f;
             span_log(&s->logging, SPAN_LOG_FLOW, "Spin (long) by %.5f rads\n", p);
             zz = complex_setf(cosf(p), -sinf(p));
-            for (i = 0;  i <= V17_EQUALIZER_MASK;  i++)
+            for (i = 0;  i < V17_EQUALIZER_LEN;  i++)
                 s->eq_buf[i] = complex_mulf(&s->eq_buf[i], &zz);
             s->carrier_phase += (angle - 219937506);
 
@@ -960,7 +941,6 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
 int v17_rx(v17_rx_state_t *s, const int16_t amp[], int len)
 {
     int i;
-    int j;
     int step;
     int16_t x;
     int32_t diff;
@@ -968,15 +948,18 @@ int v17_rx(v17_rx_state_t *s, const int16_t amp[], int len)
     complexf_t zz;
     complexf_t sample;
 #if defined(SPANDSP_USE_FIXED_POINT)
-    complexi_t zi;
+    int32_t vi;
 #endif
-    int32_t power;
+#if defined(SPANDSP_USE_FIXED_POINTx)
+    int32_t v;
+#else
     float v;
+#endif
+    int32_t power;
 
     for (i = 0;  i < len;  i++)
     {
-        s->rrc_filter[s->rrc_filter_step] =
-        s->rrc_filter[s->rrc_filter_step + V17_RX_FILTER_STEPS] = amp[i];
+        s->rrc_filter[s->rrc_filter_step] = amp[i];
         if (++s->rrc_filter_step >= V17_RX_FILTER_STEPS)
             s->rrc_filter_step = 0;
 
@@ -1052,17 +1035,13 @@ int v17_rx(v17_rx_state_t *s, const int16_t amp[], int len)
         if (step < 0)
             step += RX_PULSESHAPER_COEFF_SETS;
 #if defined(SPANDSP_USE_FIXED_POINT)
-        zi.re = (int32_t) rx_pulseshaper[step][0].re*(int32_t) s->rrc_filter[s->rrc_filter_step];
-        for (j = 1;  j < V17_RX_FILTER_STEPS;  j++)
-            zi.re += (int32_t) rx_pulseshaper[step][j].re*(int32_t) s->rrc_filter[j + s->rrc_filter_step];
-        sample.re = zi.re*s->agc_scaling;
+        vi = vec_circular_dot_prodi16(s->rrc_filter, rx_pulseshaper_re[step], V17_RX_FILTER_STEPS, s->rrc_filter_step);
+        //sample.re = (vi*(int32_t) s->agc_scaling) >> 15;
+        sample.re = vi*s->agc_scaling;
 #else
-        zz.re = rx_pulseshaper[step][0].re*s->rrc_filter[s->rrc_filter_step];
-        for (j = 1;  j < V17_RX_FILTER_STEPS;  j++)
-            zz.re += rx_pulseshaper[step][j].re*s->rrc_filter[j + s->rrc_filter_step];
-        sample.re = zz.re*s->agc_scaling;
+        v = vec_circular_dot_prodf(s->rrc_filter, rx_pulseshaper_re[step], V17_RX_FILTER_STEPS, s->rrc_filter_step);
+        sample.re = v*s->agc_scaling;
 #endif
-
         /* Symbol timing synchronisation band edge filters */
         /* Low Nyquist band edge filter */
         v = s->symbol_sync_low[0]*SYNC_LOW_BAND_EDGE_COEFF_0 + s->symbol_sync_low[1]*SYNC_LOW_BAND_EDGE_COEFF_1 + sample.re;
@@ -1087,27 +1066,22 @@ int v17_rx(v17_rx_state_t *s, const int16_t amp[], int len)
             step = -s->eq_put_step;
             if (step > RX_PULSESHAPER_COEFF_SETS - 1)
                 step = RX_PULSESHAPER_COEFF_SETS - 1;
-#if defined(SPANDSP_USE_FIXED_POINT)
-            zi.im = (int32_t) rx_pulseshaper[step][0].im*(int32_t) s->rrc_filter[s->rrc_filter_step];
-            for (j = 1;  j < V17_RX_FILTER_STEPS;  j++)
-                zi.im += (int32_t) rx_pulseshaper[step][j].im*(int32_t) s->rrc_filter[j + s->rrc_filter_step];
-            sample.im = zi.im*s->agc_scaling;
             s->eq_put_step += RX_PULSESHAPER_COEFF_SETS*10/(3*2);
+#if defined(SPANDSP_USE_FIXED_POINT)
+            vi = vec_circular_dot_prodi16(s->rrc_filter, rx_pulseshaper_im[step], V17_RX_FILTER_STEPS, s->rrc_filter_step);
+            //sample.im = (vi*(int32_t) s->agc_scaling) >> 15;
+            sample.im = vi*s->agc_scaling;
             z = dds_lookup_complexf(s->carrier_phase);
             zz.re = sample.re*z.re - sample.im*z.im;
             zz.im = -sample.re*z.im - sample.im*z.re;
-            process_half_baud(s, &zz);
 #else
-            zz.im = rx_pulseshaper[step][0].im*s->rrc_filter[s->rrc_filter_step];
-            for (j = 1;  j < V17_RX_FILTER_STEPS;  j++)
-                zz.im += rx_pulseshaper[step][j].im*s->rrc_filter[j + s->rrc_filter_step];
-            sample.im = zz.im*s->agc_scaling;
-            s->eq_put_step += RX_PULSESHAPER_COEFF_SETS*10/(3*2);
+            v = vec_circular_dot_prodf(s->rrc_filter, rx_pulseshaper_im[step], V17_RX_FILTER_STEPS, s->rrc_filter_step);
+            sample.im = v*s->agc_scaling;
             z = dds_lookup_complexf(s->carrier_phase);
             zz.re = sample.re*z.re - sample.im*z.im;
             zz.im = -sample.re*z.im - sample.im*z.re;
-            process_half_baud(s, &zz);
 #endif
+            process_half_baud(s, &zz);
         }
 #if defined(SPANDSP_USE_FIXED_POINT)
         dds_advance(&s->carrier_phase, s->carrier_phase_rate);
@@ -1165,7 +1139,7 @@ int v17_rx_restart(v17_rx_state_t *s, int bit_rate, int short_train)
     }
     s->bit_rate = bit_rate;
 #if defined(SPANDSP_USE_FIXED_POINT)
-    memset(s->rrc_filter, 0, sizeof(s->rrc_filter));
+    vec_zeroi16(s->rrc_filter, sizeof(s->rrc_filter)/sizeof(s->rrc_filter[0]));
 #else
     vec_zerof(s->rrc_filter, sizeof(s->rrc_filter)/sizeof(s->rrc_filter[0]));
 #endif
index be9ac1efe283eb8559f3e8133b6976f9d57219e1..9a5d7e848bbdfc6d4312205526d1a31df2fbd94e 100644 (file)
@@ -22,7 +22,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: v22bis_rx.c,v 1.41 2008/09/07 12:45:17 steveu Exp $
+ * $Id: v22bis_rx.c,v 1.42 2008/09/18 14:59:30 steveu Exp $
  */
 
 /*! \file */
@@ -590,15 +590,15 @@ int v22bis_rx(v22bis_state_t *s, const int16_t amp[], int len)
         /* TODO: get rid of this */
         if (s->caller)
         {
-            ii = rx_pulseshaper_2400[6][0].re*s->rx.rrc_filter[s->rx.rrc_filter_step];
+            ii = rx_pulseshaper_2400_re[6][0]*s->rx.rrc_filter[s->rx.rrc_filter_step];
             for (j = 1;  j < V22BIS_RX_FILTER_STEPS;  j++)
-                ii += rx_pulseshaper_2400[6][j].re*s->rx.rrc_filter[j + s->rx.rrc_filter_step];
+                ii += rx_pulseshaper_2400_re[6][j]*s->rx.rrc_filter[j + s->rx.rrc_filter_step];
         }
         else
         {
-            ii = rx_pulseshaper_1200[6][0].re*s->rx.rrc_filter[s->rx.rrc_filter_step];
+            ii = rx_pulseshaper_1200_re[6][0]*s->rx.rrc_filter[s->rx.rrc_filter_step];
             for (j = 1;  j < V22BIS_RX_FILTER_STEPS;  j++)
-                ii += rx_pulseshaper_1200[6][j].re*s->rx.rrc_filter[j + s->rx.rrc_filter_step];
+                ii += rx_pulseshaper_1200_re[6][j]*s->rx.rrc_filter[j + s->rx.rrc_filter_step];
         }
         power = power_meter_update(&(s->rx.rx_power), (int16_t) (ii/10.0f));
         if (s->rx.signal_present)
@@ -643,22 +643,22 @@ int v22bis_rx(v22bis_state_t *s, const int16_t amp[], int len)
                 s->rx.eq_put_step += PULSESHAPER_COEFF_SETS*40/(3*2);
                 if (s->caller)
                 {
-                    ii = rx_pulseshaper_2400[step][0].re*s->rx.rrc_filter[s->rx.rrc_filter_step];
-                    qq = rx_pulseshaper_2400[step][0].im*s->rx.rrc_filter[s->rx.rrc_filter_step];
+                    ii = rx_pulseshaper_2400_re[step][0]*s->rx.rrc_filter[s->rx.rrc_filter_step];
+                    qq = rx_pulseshaper_2400_im[step][0]*s->rx.rrc_filter[s->rx.rrc_filter_step];
                     for (j = 1;  j < V22BIS_RX_FILTER_STEPS;  j++)
                     {
-                        ii += rx_pulseshaper_2400[step][j].re*s->rx.rrc_filter[j + s->rx.rrc_filter_step];
-                        qq += rx_pulseshaper_2400[step][j].im*s->rx.rrc_filter[j + s->rx.rrc_filter_step];
+                        ii += rx_pulseshaper_2400_re[step][j]*s->rx.rrc_filter[j + s->rx.rrc_filter_step];
+                        qq += rx_pulseshaper_2400_im[step][j]*s->rx.rrc_filter[j + s->rx.rrc_filter_step];
                     }
                 }
                 else
                 {
-                    ii = rx_pulseshaper_1200[step][0].re*s->rx.rrc_filter[s->rx.rrc_filter_step];
-                    qq = rx_pulseshaper_1200[step][0].im*s->rx.rrc_filter[s->rx.rrc_filter_step];
+                    ii = rx_pulseshaper_1200_re[step][0]*s->rx.rrc_filter[s->rx.rrc_filter_step];
+                    qq = rx_pulseshaper_1200_im[step][0]*s->rx.rrc_filter[s->rx.rrc_filter_step];
                     for (j = 1;  j < V22BIS_RX_FILTER_STEPS;  j++)
                     {
-                        ii += rx_pulseshaper_1200[step][j].re*s->rx.rrc_filter[j + s->rx.rrc_filter_step];
-                        qq += rx_pulseshaper_1200[step][j].im*s->rx.rrc_filter[j + s->rx.rrc_filter_step];
+                        ii += rx_pulseshaper_1200_re[step][j]*s->rx.rrc_filter[j + s->rx.rrc_filter_step];
+                        qq += rx_pulseshaper_1200_im[step][j]*s->rx.rrc_filter[j + s->rx.rrc_filter_step];
                     }
                 }
                 sample.re = ii*s->rx.agc_scaling;
index 8f9ca872e4eb54a0911e467a9f4e2175cd0984e4..605a6997329feafa889912b140e287d6e15db67a 100644 (file)
@@ -22,7 +22,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: v27ter_rx.c,v 1.104 2008/09/16 14:12:23 steveu Exp $
+ * $Id: v27ter_rx.c,v 1.107 2008/09/18 14:59:30 steveu Exp $
  */
 
 /*! \file */
@@ -86,6 +86,8 @@
 #define V27TER_TRAINING_SEG_5_LEN       1074
 #define V27TER_TRAINING_SEG_6_LEN       8
 
+#define V27TER_EQUALIZER_LEN    (V27TER_EQUALIZER_PRE_LEN + 1 + V27TER_EQUALIZER_POST_LEN)
+
 enum
 {
     TRAINING_STAGE_NORMAL_OPERATION = 0,
@@ -168,16 +170,16 @@ int v27ter_rx_equalizer_state(v27ter_rx_state_t *s, complexf_t **coeffs)
 #endif
 {
     *coeffs = s->eq_coeff;
-    return V27TER_EQUALIZER_PRE_LEN + 1 + V27TER_EQUALIZER_POST_LEN;
+    return V27TER_EQUALIZER_LEN;
 }
 /*- End of function --------------------------------------------------------*/
 
 static void equalizer_save(v27ter_rx_state_t *s)
 {
 #if defined(SPANDSP_USE_FIXED_POINTx)
-    cvec_copyi16(s->eq_coeff_save, s->eq_coeff, V27TER_EQUALIZER_PRE_LEN + 1 + V27TER_EQUALIZER_POST_LEN);
+    cvec_copyi16(s->eq_coeff_save, s->eq_coeff, V27TER_EQUALIZER_LEN);
 #else
-    cvec_copyf(s->eq_coeff_save, s->eq_coeff, V27TER_EQUALIZER_PRE_LEN + 1 + V27TER_EQUALIZER_POST_LEN);
+    cvec_copyf(s->eq_coeff_save, s->eq_coeff, V27TER_EQUALIZER_LEN);
 #endif
 }
 /*- End of function --------------------------------------------------------*/
@@ -185,13 +187,13 @@ static void equalizer_save(v27ter_rx_state_t *s)
 static void equalizer_restore(v27ter_rx_state_t *s)
 {
 #if defined(SPANDSP_USE_FIXED_POINTx)
-    cvec_copyi16(s->eq_coeff, s->eq_coeff_save, V27TER_EQUALIZER_PRE_LEN + 1 + V27TER_EQUALIZER_POST_LEN);
-    cvec_zeroi16(s->eq_buf, V27TER_EQUALIZER_MASK);
-    s->eq_delta = 32768.0f*EQUALIZER_DELTA/(V27TER_EQUALIZER_PRE_LEN + 1 + V27TER_EQUALIZER_POST_LEN);
+    cvec_copyi16(s->eq_coeff, s->eq_coeff_save, V27TER_EQUALIZER_LEN);
+    cvec_zeroi16(s->eq_buf, V27TER_EQUALIZER_LEN);
+    s->eq_delta = 32768.0f*EQUALIZER_DELTA/V27TER_EQUALIZER_LEN);
 #else
-    cvec_copyf(s->eq_coeff, s->eq_coeff_save, V27TER_EQUALIZER_PRE_LEN + 1 + V27TER_EQUALIZER_POST_LEN);
-    cvec_zerof(s->eq_buf, V27TER_EQUALIZER_MASK);
-    s->eq_delta = EQUALIZER_DELTA/(V27TER_EQUALIZER_PRE_LEN + 1 + V27TER_EQUALIZER_POST_LEN);
+    cvec_copyf(s->eq_coeff, s->eq_coeff_save, V27TER_EQUALIZER_LEN);
+    cvec_zerof(s->eq_buf, V27TER_EQUALIZER_LEN);
+    s->eq_delta = EQUALIZER_DELTA/V27TER_EQUALIZER_LEN;
 #endif
 
     s->eq_put_step = (s->bit_rate == 4800)  ?  RX_PULSESHAPER_4800_COEFF_SETS*5/2  :  RX_PULSESHAPER_2400_COEFF_SETS*20/(3*2);
@@ -203,15 +205,15 @@ static void equalizer_reset(v27ter_rx_state_t *s)
 {
     /* Start with an equalizer based on everything being perfect. */
 #if defined(SPANDSP_USE_FIXED_POINTx)
-    cvec_zeroi16(s->eq_coeff, V27TER_EQUALIZER_PRE_LEN + 1 + V27TER_EQUALIZER_POST_LEN);
+    cvec_zeroi16(s->eq_coeff, V27TER_EQUALIZER_LEN);
     s->eq_coeff[V27TER_EQUALIZER_PRE_LEN] = complex_seti16(1.414f*FP_FACTOR, 0);
-    cvec_zeroi16(s->eq_buf, V27TER_EQUALIZER_MASK);
-    s->eq_delta = 32768.0f*EQUALIZER_DELTA/(V27TER_EQUALIZER_PRE_LEN + 1 + V27TER_EQUALIZER_POST_LEN);
+    cvec_zeroi16(s->eq_buf, V27TER_EQUALIZER_LEN);
+    s->eq_delta = 32768.0f*EQUALIZER_DELTA/V27TER_EQUALIZER_LEN);
 #else
-    cvec_zerof(s->eq_coeff, V27TER_EQUALIZER_PRE_LEN + 1 + V27TER_EQUALIZER_POST_LEN);
+    cvec_zerof(s->eq_coeff, V27TER_EQUALIZER_LEN);
     s->eq_coeff[V27TER_EQUALIZER_PRE_LEN] = complex_setf(1.414f, 0.0f);
-    cvec_zerof(s->eq_buf, V27TER_EQUALIZER_MASK);
-    s->eq_delta = EQUALIZER_DELTA/(V27TER_EQUALIZER_PRE_LEN + 1 + V27TER_EQUALIZER_POST_LEN);
+    cvec_zerof(s->eq_buf, V27TER_EQUALIZER_LEN);
+    s->eq_delta = EQUALIZER_DELTA/V27TER_EQUALIZER_LEN;
 #endif
 
     s->eq_put_step = (s->bit_rate == 4800)  ?  RX_PULSESHAPER_4800_COEFF_SETS*5/2  :  RX_PULSESHAPER_2400_COEFF_SETS*20/(3*2);
@@ -237,36 +239,19 @@ static __inline__ complexi16_t equalizer_get(v27ter_rx_state_t *s)
 static __inline__ complexf_t equalizer_get(v27ter_rx_state_t *s)
 #endif
 {
-    int i;
-    int p;
 #if defined(SPANDSP_USE_FIXED_POINTx)
+    complexi32_t zz;
     complexi16_t z;
-    complexi16_t z1;
-#else
-    complexf_t z;
-    complexf_t z1;
-#endif
 
     /* Get the next equalized value. */
-    p = s->eq_step - 1;
-#if defined(SPANDSP_USE_FIXED_POINTx)
-    z = complex_seti16(0, 0);
-    for (i = 0;  i < V27TER_EQUALIZER_PRE_LEN + 1 + V27TER_EQUALIZER_POST_LEN;  i++)
-    {
-        p = (p - 1) & V27TER_EQUALIZER_MASK;
-        z1 = complex_mul_q4_12(&s->eq_coeff[i], &s->eq_buf[p]);
-        z = complex_addi16(&z, &z1);
-    }
+    zz = cvec_circular_dot_prodi16(s->eq_buf, s->eq_coeff, V27TER_EQUALIZER_LEN, s->eq_step);
+    z.re = zz.re >> FP_SHIFT_FACTOR;
+    z.im = zz.im >> FP_SHIFT_FACTOR;
+    return z;
 #else
-    z = complex_setf(0.0f, 0.0f);
-    for (i = 0;  i < V27TER_EQUALIZER_PRE_LEN + 1 + V27TER_EQUALIZER_POST_LEN;  i++)
-    {
-        p = (p - 1) & V27TER_EQUALIZER_MASK;
-        z1 = complex_mulf(&s->eq_coeff[i], &s->eq_buf[p]);
-        z = complex_addf(&z, &z1);
-    }
+    /* Get the next equalized value. */
+    return cvec_circular_dot_prodf(s->eq_buf, s->eq_coeff, V27TER_EQUALIZER_LEN, s->eq_step);
 #endif
-    return z;
 }
 /*- End of function --------------------------------------------------------*/
 
@@ -276,45 +261,24 @@ static void tune_equalizer(v27ter_rx_state_t *s, const complexi16_t *z, const co
 static void tune_equalizer(v27ter_rx_state_t *s, const complexf_t *z, const complexf_t *target)
 #endif
 {
-    int i;
-    int p;
 #if defined(SPANDSP_USE_FIXED_POINTx)
-    complexi16_t ez;
-    complexi16_t z1;
-#else
-    complexf_t ez;
-    complexf_t z1;
-#endif
+    complexi16_t err;
 
     /* Find the x and y mismatch from the exact constellation position. */
-#if defined(SPANDSP_USE_FIXED_POINTx)
-    ez.re = target->re*FP_FACTOR - z->re;
-    ez.im = target->im*FP_FACTOR - z->im;
-    ez.re = ((int32_t) ez.re*(int32_t) s->eq_delta) >> 15;
-    ez.im = ((int32_t) ez.im*(int32_t) s->eq_delta) >> 15;
+    err.re = target->re*FP_FACTOR - z->re;
+    err.im = target->im*FP_FACTOR - z->im;
+    err.re = ((int32_t) err.re*(int32_t) s->eq_delta) >> 15;
+    err.im = ((int32_t) err.im*(int32_t) s->eq_delta) >> 15;
+    cvec_circular_lmsi16(s->eq_buf, s->eq_coeff, V27TER_EQUALIZER_LEN, s->eq_step, &err);
 #else
-    ez = complex_subf(target, z);
-    ez.re *= s->eq_delta;
-    ez.im *= s->eq_delta;
-#endif
+    complexf_t err;
 
-    p = s->eq_step - 1;
-    for (i = 0;  i < V27TER_EQUALIZER_PRE_LEN + 1 + V27TER_EQUALIZER_POST_LEN;  i++)
-    {
-        p = (p - 1) & V27TER_EQUALIZER_MASK;
-#if defined(SPANDSP_USE_FIXED_POINTx)
-        z1 = complex_conji16(&s->eq_buf[p]);
-        z1 = complex_mul_q4_12(&ez, &z1);
-        s->eq_coeff[i] = complex_addi16(&s->eq_coeff[i], &z1);
-#else
-        z1 = complex_conjf(&s->eq_buf[p]);
-        z1 = complex_mulf(&ez, &z1);
-        s->eq_coeff[i] = complex_addf(&s->eq_coeff[i], &z1);
-        /* Leak a little to tame uncontrolled wandering */
-        s->eq_coeff[i].re *= 0.9999f;
-        s->eq_coeff[i].im *= 0.9999f;
+    /* Find the x and y mismatch from the exact constellation position. */
+    err = complex_subf(target, z);
+    err.re *= s->eq_delta;
+    err.im *= s->eq_delta;
+    cvec_circular_lmsf(s->eq_buf, s->eq_coeff, V27TER_EQUALIZER_LEN, s->eq_step, &err);
 #endif
-    }
 }
 /*- End of function --------------------------------------------------------*/
 
@@ -508,13 +472,13 @@ static __inline__ void symbol_sync(v27ter_rx_state_t *s)
     /* This routine adapts the position of the half baud samples entering the equalizer. */
 
     /* Perform a Gardner test for baud alignment */
-    p = s->eq_buf[(s->eq_step - 3) & V27TER_EQUALIZER_MASK].re
-      - s->eq_buf[(s->eq_step - 1) & V27TER_EQUALIZER_MASK].re;
-    p *= s->eq_buf[(s->eq_step - 2) & V27TER_EQUALIZER_MASK].re;
+    p = s->eq_buf[(s->eq_step - 3) & V27TER_EQUALIZER_LEN].re
+      - s->eq_buf[(s->eq_step - 1) & V27TER_EQUALIZER_LEN].re;
+    p *= s->eq_buf[(s->eq_step - 2) & V27TER_EQUALIZER_LEN].re;
 
-    q = s->eq_buf[(s->eq_step - 3) & V27TER_EQUALIZER_MASK].im
-      - s->eq_buf[(s->eq_step - 1) & V27TER_EQUALIZER_MASK].im;
-    q *= s->eq_buf[(s->eq_step - 2) & V27TER_EQUALIZER_MASK].im;
+    q = s->eq_buf[(s->eq_step - 3) & V27TER_EQUALIZER_LEN].im
+      - s->eq_buf[(s->eq_step - 1) & V27TER_EQUALIZER_LEN].im;
+    q *= s->eq_buf[(s->eq_step - 2) & V27TER_EQUALIZER_LEN].im;
 
     s->gardner_integrate += (p + q > 0.0f)  ?  s->gardner_step  :  -s->gardner_step;
 
@@ -560,7 +524,8 @@ static __inline__ void process_half_baud(v27ter_rx_state_t *s, const complexf_t
 #else
     s->eq_buf[s->eq_step] = *sample;
 #endif
-    s->eq_step = (s->eq_step + 1) & V27TER_EQUALIZER_MASK;
+    if (++s->eq_step >= V27TER_EQUALIZER_LEN)
+        s->eq_step = 0;
         
     /* On alternate insertions we have a whole baud, and must process it. */
     if ((s->baud_half ^= 1))
@@ -642,7 +607,7 @@ static __inline__ void process_half_baud(v27ter_rx_state_t *s, const complexf_t
             p = angle*2.0f*3.14159f/(65536.0f*65536.0f);
 #if defined(SPANDSP_USE_FIXED_POINTx)
             zz = complex_setf(cosf(p), -sinf(p));
-            for (i = 0;  i <= V27TER_EQUALIZER_MASK;  i++)
+            for (i = 0;  i < V27TER_EQUALIZER_LEN;  i++)
             {
                 z1 = complex_setf(s->eq_buf[i].re, s->eq_buf[i].im);
                 z1 = complex_mulf(&z1, &zz);
@@ -651,7 +616,7 @@ static __inline__ void process_half_baud(v27ter_rx_state_t *s, const complexf_t
             }
 #else
             zz = complex_setf(cosf(p), -sinf(p));
-            for (i = 0;  i <= V27TER_EQUALIZER_MASK;  i++)
+            for (i = 0;  i < V27TER_EQUALIZER_LEN;  i++)
                 s->eq_buf[i] = complex_mulf(&s->eq_buf[i], &zz);
 #endif
             s->carrier_phase += angle;
@@ -774,7 +739,6 @@ static __inline__ void process_half_baud(v27ter_rx_state_t *s, const complexf_t
 int v27ter_rx(v27ter_rx_state_t *s, const int16_t amp[], int len)
 {
     int i;
-    int j;
     int step;
     int16_t x;
     int32_t diff;
@@ -782,11 +746,12 @@ int v27ter_rx(v27ter_rx_state_t *s, const int16_t amp[], int len)
     complexi16_t z;
     complexi16_t zz;
     complexi16_t sample;
-    complexi32_t zi;
+    int32_t v;
 #else
     complexf_t z;
     complexf_t zz;
     complexf_t sample;
+    float v;
 #endif
     int32_t power;
 
@@ -794,8 +759,7 @@ int v27ter_rx(v27ter_rx_state_t *s, const int16_t amp[], int len)
     {
         for (i = 0;  i < len;  i++)
         {
-            s->rrc_filter[s->rrc_filter_step] =
-            s->rrc_filter[s->rrc_filter_step + V27TER_RX_4800_FILTER_STEPS] = amp[i];
+            s->rrc_filter[s->rrc_filter_step] = amp[i];
             if (++s->rrc_filter_step >= V27TER_RX_4800_FILTER_STEPS)
                 s->rrc_filter_step = 0;
 
@@ -887,28 +851,18 @@ int v27ter_rx(v27ter_rx_state_t *s, const int16_t amp[], int len)
                     step = RX_PULSESHAPER_4800_COEFF_SETS - 1;
                 s->eq_put_step += RX_PULSESHAPER_4800_COEFF_SETS*5/2;
 #if defined(SPANDSP_USE_FIXED_POINT)
-                zi.re = (int32_t) rx_pulseshaper_4800[step][0].re*(int32_t) s->rrc_filter[s->rrc_filter_step];
-                zi.im = (int32_t) rx_pulseshaper_4800[step][0].im*(int32_t) s->rrc_filter[s->rrc_filter_step];
-                for (j = 1;  j < V27TER_RX_4800_FILTER_STEPS;  j++)
-                {
-                    zi.re += (int32_t) rx_pulseshaper_4800[step][j].re*(int32_t) s->rrc_filter[j + s->rrc_filter_step];
-                    zi.im += (int32_t) rx_pulseshaper_4800[step][j].im*(int32_t) s->rrc_filter[j + s->rrc_filter_step];
-                }
-                sample.re = ((int32_t) zi.re*(int32_t) s->agc_scaling) >> 15;
-                sample.im = ((int32_t) zi.im*(int32_t) s->agc_scaling) >> 15;
+                v = vec_circular_dot_prodi16(s->rrc_filter, rx_pulseshaper_4800_re[step], V27TER_RX_FILTER_STEPS, s->rrc_filter_step);
+                sample.re = (v*(int32_t) s->agc_scaling) >> 15;
+                v = vec_circular_dot_prodi16(s->rrc_filter, rx_pulseshaper_4800_im[step], V27TER_RX_FILTER_STEPS, s->rrc_filter_step);
+                sample.im = (v*(int32_t) s->agc_scaling) >> 15;
                 z = dds_lookup_complexi16(s->carrier_phase);
                 zz.re = ((int32_t) sample.re*(int32_t) z.re - (int32_t) sample.im*(int32_t) z.im) >> 15;
                 zz.im = ((int32_t) -sample.re*(int32_t) z.im - (int32_t) sample.im*(int32_t) z.re) >> 15;
 #else
-                zz.re = rx_pulseshaper_4800[step][0].re*s->rrc_filter[s->rrc_filter_step];
-                zz.im = rx_pulseshaper_4800[step][0].im*s->rrc_filter[s->rrc_filter_step];
-                for (j = 1;  j < V27TER_RX_4800_FILTER_STEPS;  j++)
-                {
-                    zz.re += rx_pulseshaper_4800[step][j].re*s->rrc_filter[j + s->rrc_filter_step];
-                    zz.im += rx_pulseshaper_4800[step][j].im*s->rrc_filter[j + s->rrc_filter_step];
-                }
-                sample.re = zz.re*s->agc_scaling;
-                sample.im = zz.im*s->agc_scaling;
+                v = vec_circular_dot_prodf(s->rrc_filter, rx_pulseshaper_4800_re[step], V27TER_RX_FILTER_STEPS, s->rrc_filter_step);
+                sample.re = v*s->agc_scaling;
+                v = vec_circular_dot_prodf(s->rrc_filter, rx_pulseshaper_4800_im[step], V27TER_RX_FILTER_STEPS, s->rrc_filter_step);
+                sample.im = v*s->agc_scaling;
                 z = dds_lookup_complexf(s->carrier_phase);
                 zz.re = sample.re*z.re - sample.im*z.im;
                 zz.im = -sample.re*z.im - sample.im*z.re;
@@ -926,8 +880,7 @@ int v27ter_rx(v27ter_rx_state_t *s, const int16_t amp[], int len)
     {
         for (i = 0;  i < len;  i++)
         {
-            s->rrc_filter[s->rrc_filter_step] =
-            s->rrc_filter[s->rrc_filter_step + V27TER_RX_2400_FILTER_STEPS] = amp[i];
+            s->rrc_filter[s->rrc_filter_step] = amp[i];
             if (++s->rrc_filter_step >= V27TER_RX_2400_FILTER_STEPS)
                 s->rrc_filter_step = 0;
 
@@ -1020,28 +973,18 @@ int v27ter_rx(v27ter_rx_state_t *s, const int16_t amp[], int len)
                     step = RX_PULSESHAPER_2400_COEFF_SETS - 1;
                 s->eq_put_step += RX_PULSESHAPER_2400_COEFF_SETS*20/(3*2);
 #if defined(SPANDSP_USE_FIXED_POINT)
-                zi.re = (int32_t) rx_pulseshaper_2400[step][0].re*(int32_t) s->rrc_filter[s->rrc_filter_step];
-                zi.im = (int32_t) rx_pulseshaper_2400[step][0].im*(int32_t) s->rrc_filter[s->rrc_filter_step];
-                for (j = 1;  j < V27TER_RX_2400_FILTER_STEPS;  j++)
-                {
-                    zi.re += (int32_t) rx_pulseshaper_2400[step][j].re*(int32_t) s->rrc_filter[j + s->rrc_filter_step];
-                    zi.im += (int32_t) rx_pulseshaper_2400[step][j].im*(int32_t) s->rrc_filter[j + s->rrc_filter_step];
-                }
-                sample.re = ((int32_t) zi.re*(int32_t) s->agc_scaling) >> 15;
-                sample.im = ((int32_t) zi.im*(int32_t) s->agc_scaling) >> 15;
+                v = vec_circular_dot_prodi16(s->rrc_filter, rx_pulseshaper_2400_re[step], V27TER_RX_FILTER_STEPS, s->rrc_filter_step);
+                sample.re = (v*(int32_t) s->agc_scaling) >> 15;
+                v = vec_circular_dot_prodi16(s->rrc_filter, rx_pulseshaper_2400_im[step], V27TER_RX_FILTER_STEPS, s->rrc_filter_step);
+                sample.im = (v*(int32_t) s->agc_scaling) >> 15;
                 z = dds_lookup_complexi16(s->carrier_phase);
                 zz.re = ((int32_t) sample.re*(int32_t) z.re - (int32_t) sample.im*(int32_t) z.im) >> 15;
                 zz.im = ((int32_t) -sample.re*(int32_t) z.im - (int32_t) sample.im*(int32_t) z.re) >> 15;
 #else
-                zz.re = rx_pulseshaper_2400[step][0].re*s->rrc_filter[s->rrc_filter_step];
-                zz.im = rx_pulseshaper_2400[step][0].im*s->rrc_filter[s->rrc_filter_step];
-                for (j = 1;  j < V27TER_RX_2400_FILTER_STEPS;  j++)
-                {
-                    zz.re += rx_pulseshaper_2400[step][j].re*s->rrc_filter[j + s->rrc_filter_step];
-                    zz.im += rx_pulseshaper_2400[step][j].im*s->rrc_filter[j + s->rrc_filter_step];
-                }
-                sample.re = zz.re*s->agc_scaling;
-                sample.im = zz.im*s->agc_scaling;
+                v = vec_circular_dot_prodf(s->rrc_filter, rx_pulseshaper_2400_re[step], V27TER_RX_FILTER_STEPS, s->rrc_filter_step);
+                sample.re = v*s->agc_scaling;
+                v = vec_circular_dot_prodf(s->rrc_filter, rx_pulseshaper_2400_im[step], V27TER_RX_FILTER_STEPS, s->rrc_filter_step);
+                sample.im = v*s->agc_scaling;
                 z = dds_lookup_complexf(s->carrier_phase);
                 zz.re = sample.re*z.re - sample.im*z.im;
                 zz.im = -sample.re*z.im - sample.im*z.re;
index 50dba0120f4e2b2e424e8d00a3d1faa206f712ed..ec36b637cfa59de098d0ce4f53139bcec60f524d 100644 (file)
@@ -22,7 +22,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: v29rx.c,v 1.140 2008/09/16 14:12:23 steveu Exp $
+ * $Id: v29rx.c,v 1.144 2008/09/18 14:59:30 steveu Exp $
  */
 
 /*! \file */
@@ -79,6 +79,8 @@
 #define V29_TRAINING_SEG_3_LEN          384
 #define V29_TRAINING_SEG_4_LEN          48
 
+#define V29_EQUALIZER_LEN    (V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN)
+
 enum
 {
     TRAINING_STAGE_NORMAL_OPERATION = 0,
@@ -176,16 +178,16 @@ int v29_rx_equalizer_state(v29_rx_state_t *s, complexf_t **coeffs)
 #endif
 {
     *coeffs = s->eq_coeff;
-    return V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN;
+    return V29_EQUALIZER_LEN;
 }
 /*- End of function --------------------------------------------------------*/
 
 static void equalizer_save(v29_rx_state_t *s)
 {
 #if defined(SPANDSP_USE_FIXED_POINT)
-    cvec_copyi16(s->eq_coeff_save, s->eq_coeff, V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN);
+    cvec_copyi16(s->eq_coeff_save, s->eq_coeff, V29_EQUALIZER_LEN);
 #else
-    cvec_copyf(s->eq_coeff_save, s->eq_coeff, V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN);
+    cvec_copyf(s->eq_coeff_save, s->eq_coeff, V29_EQUALIZER_LEN);
 #endif
 }
 /*- End of function --------------------------------------------------------*/
@@ -193,13 +195,13 @@ static void equalizer_save(v29_rx_state_t *s)
 static void equalizer_restore(v29_rx_state_t *s)
 {
 #if defined(SPANDSP_USE_FIXED_POINT)
-    cvec_copyi16(s->eq_coeff, s->eq_coeff_save, V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN);
-    cvec_zeroi16(s->eq_buf, V29_EQUALIZER_MASK);
-    s->eq_delta = 32768.0f*EQUALIZER_DELTA/(V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN);
+    cvec_copyi16(s->eq_coeff, s->eq_coeff_save, V29_EQUALIZER_LEN);
+    cvec_zeroi16(s->eq_buf, V29_EQUALIZER_LEN);
+    s->eq_delta = 32768.0f*EQUALIZER_DELTA/V29_EQUALIZER_LEN;
 #else
-    cvec_copyf(s->eq_coeff, s->eq_coeff_save, V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN);
-    cvec_zerof(s->eq_buf, V29_EQUALIZER_MASK);
-    s->eq_delta = EQUALIZER_DELTA/(V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN);
+    cvec_copyf(s->eq_coeff, s->eq_coeff_save, V29_EQUALIZER_LEN);
+    cvec_zerof(s->eq_buf, V29_EQUALIZER_LEN);
+    s->eq_delta = EQUALIZER_DELTA/V29_EQUALIZER_LEN;
 #endif
 
     s->eq_put_step = RX_PULSESHAPER_COEFF_SETS*10/(3*2) - 1;
@@ -211,15 +213,15 @@ static void equalizer_reset(v29_rx_state_t *s)
 {
     /* Start with an equalizer based on everything being perfect */
 #if defined(SPANDSP_USE_FIXED_POINT)
-    cvec_zeroi16(s->eq_coeff, V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN);
-    s->eq_coeff[V29_EQUALIZER_PRE_LEN] = complex_seti16(3*FP_FACTOR, 0*FP_FACTOR);
-    cvec_zeroi16(s->eq_buf, V29_EQUALIZER_MASK);
-    s->eq_delta = 32768.0f*EQUALIZER_DELTA/(V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN);
+    cvec_zeroi16(s->eq_coeff, V29_EQUALIZER_LEN);
+    s->eq_coeff[V29_EQUALIZER_POST_LEN] = complex_seti16(3*FP_FACTOR, 0*FP_FACTOR);
+    cvec_zeroi16(s->eq_buf, V29_EQUALIZER_LEN);
+    s->eq_delta = 32768.0f*EQUALIZER_DELTA/V29_EQUALIZER_LEN;
 #else
-    cvec_zerof(s->eq_coeff, V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN);
-    s->eq_coeff[V29_EQUALIZER_PRE_LEN] = complex_setf(3.0f, 0.0f);
-    cvec_zerof(s->eq_buf, V29_EQUALIZER_MASK);
-    s->eq_delta = EQUALIZER_DELTA/(V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN);
+    cvec_zerof(s->eq_coeff, V29_EQUALIZER_LEN);
+    s->eq_coeff[V29_EQUALIZER_POST_LEN] = complex_setf(3.0f, 0.0f);
+    cvec_zerof(s->eq_buf, V29_EQUALIZER_LEN);
+    s->eq_delta = EQUALIZER_DELTA/V29_EQUALIZER_LEN;
 #endif
 
     s->eq_put_step = RX_PULSESHAPER_COEFF_SETS*10/(3*2) - 1;
@@ -232,8 +234,8 @@ static __inline__ complexi16_t complex_mul_q4_12(const complexi16_t *x, const co
 {
     complexi16_t z;
 
-    z.re = ((int32_t) x->re*(int32_t) y->re - (int32_t) x->im*(int32_t) y->im) >> 12;
-    z.im = ((int32_t) x->re*(int32_t) y->im + (int32_t) x->im*(int32_t) y->re) >> 12;
+    z.re = ((int32_t) x->re*(int32_t) y->re - (int32_t) x->im*(int32_t) y->im) >> FP_SHIFT_FACTOR;
+    z.im = ((int32_t) x->re*(int32_t) y->im + (int32_t) x->im*(int32_t) y->re) >> FP_SHIFT_FACTOR;
     return z;
 }
 /*- End of function --------------------------------------------------------*/
@@ -245,36 +247,19 @@ static __inline__ complexi16_t equalizer_get(v29_rx_state_t *s)
 static __inline__ complexf_t equalizer_get(v29_rx_state_t *s)
 #endif
 {
-    int i;
-    int p;
 #if defined(SPANDSP_USE_FIXED_POINT)
+    complexi32_t zz;
     complexi16_t z;
-    complexi16_t z1;
-#else
-    complexf_t z;
-    complexf_t z1;
-#endif
 
     /* Get the next equalized value. */
-    p = s->eq_step - 1;
-#if defined(SPANDSP_USE_FIXED_POINT)
-    z = complex_seti16(0, 0);
-    for (i = 0;  i < V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN;  i++)
-    {
-        p = (p - 1) & V29_EQUALIZER_MASK;
-        z1 = complex_mul_q4_12(&s->eq_coeff[i], &s->eq_buf[p]);
-        z = complex_addi16(&z, &z1);
-    }
+    zz = cvec_circular_dot_prodi16(s->eq_buf, s->eq_coeff, V29_EQUALIZER_LEN, s->eq_step);
+    z.re = zz.re >> FP_SHIFT_FACTOR;
+    z.im = zz.im >> FP_SHIFT_FACTOR;
+    return z;
 #else
-    z = complex_setf(0.0f, 0.0f);
-    for (i = 0;  i < V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN;  i++)
-    {
-        p = (p - 1) & V29_EQUALIZER_MASK;
-        z1 = complex_mulf(&s->eq_coeff[i], &s->eq_buf[p]);
-        z = complex_addf(&z, &z1);
-    }
+    /* Get the next equalized value. */
+    return cvec_circular_dot_prodf(s->eq_buf, s->eq_coeff, V29_EQUALIZER_LEN, s->eq_step);
 #endif
-    return z;
 }
 /*- End of function --------------------------------------------------------*/
 
@@ -284,45 +269,24 @@ static void tune_equalizer(v29_rx_state_t *s, const complexi16_t *z, const compl
 static void tune_equalizer(v29_rx_state_t *s, const complexf_t *z, const complexf_t *target)
 #endif
 {
-    int i;
-    int p;
 #if defined(SPANDSP_USE_FIXED_POINT)
-    complexi16_t ez;
-    complexi16_t z1;
-#else
-    complexf_t ez;
-    complexf_t z1;
-#endif
+    complexi16_t err;
 
     /* Find the x and y mismatch from the exact constellation position. */
-#if defined(SPANDSP_USE_FIXED_POINT)
-    ez.re = target->re*FP_FACTOR - z->re;
-    ez.im = target->im*FP_FACTOR - z->im;
-    ez.re = ((int32_t) ez.re*(int32_t) s->eq_delta) >> 15;
-    ez.im = ((int32_t) ez.im*(int32_t) s->eq_delta) >> 15;
+    err.re = target->re*FP_FACTOR - z->re;
+    err.im = target->im*FP_FACTOR - z->im;
+    err.re = ((int32_t) err.re*(int32_t) s->eq_delta) >> 15;
+    err.im = ((int32_t) err.im*(int32_t) s->eq_delta) >> 15;
+    cvec_circular_lmsi16(s->eq_buf, s->eq_coeff, V29_EQUALIZER_LEN, s->eq_step, &err);
 #else
-    ez = complex_subf(target, z);
-    ez.re *= s->eq_delta;
-    ez.im *= s->eq_delta;
-#endif
+    complexf_t err;
 
-    p = s->eq_step - 1;
-    for (i = 0;  i < V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN;  i++)
-    {
-        p = (p - 1) & V29_EQUALIZER_MASK;
-#if defined(SPANDSP_USE_FIXED_POINT)
-        z1 = complex_conji16(&s->eq_buf[p]);
-        z1 = complex_mul_q4_12(&ez, &z1);
-        s->eq_coeff[i] = complex_addi16(&s->eq_coeff[i], &z1);
-#else
-        z1 = complex_conjf(&s->eq_buf[p]);
-        z1 = complex_mulf(&ez, &z1);
-        s->eq_coeff[i] = complex_addf(&s->eq_coeff[i], &z1);
-        /* Leak a little to tame uncontrolled wandering */
-        s->eq_coeff[i].re *= 0.9999f;
-        s->eq_coeff[i].im *= 0.9999f;
+    /* Find the x and y mismatch from the exact constellation position. */
+    err = complex_subf(target, z);
+    err.re *= s->eq_delta;
+    err.im *= s->eq_delta;
+    cvec_circular_lmsf(s->eq_buf, s->eq_coeff, V29_EQUALIZER_LEN, s->eq_step, &err);
 #endif
-    }
 }
 /*- End of function --------------------------------------------------------*/
 
@@ -597,7 +561,8 @@ static void process_half_baud(v29_rx_state_t *s, complexf_t *sample)
     /* Add a sample to the equalizer's circular buffer, but don't calculate anything
        at this time. */
     s->eq_buf[s->eq_step] = *sample;
-    s->eq_step = (s->eq_step + 1) & V29_EQUALIZER_MASK;
+    if (++s->eq_step >= V29_EQUALIZER_LEN)
+        s->eq_step = 0;
 
     /* On alternate insertions we have a whole baud, and must process it. */
     if ((s->baud_half ^= 1))
@@ -687,7 +652,7 @@ static void process_half_baud(v29_rx_state_t *s, complexf_t *sample)
             p = angle*2.0f*3.14159f/(65536.0f*65536.0f);
 #if defined(SPANDSP_USE_FIXED_POINT)
             zz = complex_setf(cosf(p), -sinf(p));
-            for (i = 0;  i <= V29_EQUALIZER_MASK;  i++)
+            for (i = 0;  i < V29_EQUALIZER_LEN;  i++)
             {
                 z1 = complex_setf(s->eq_buf[i].re, s->eq_buf[i].im);
                 z1 = complex_mulf(&z1, &zz);
@@ -696,7 +661,7 @@ static void process_half_baud(v29_rx_state_t *s, complexf_t *sample)
             }
 #else
             zz = complex_setf(cosf(p), -sinf(p));
-            for (i = 0;  i <= V29_EQUALIZER_MASK;  i++)
+            for (i = 0;  i < V29_EQUALIZER_LEN;  i++)
                 s->eq_buf[i] = complex_mulf(&s->eq_buf[i], &zz);
 #endif
             s->carrier_phase += angle;
@@ -860,7 +825,6 @@ static void process_half_baud(v29_rx_state_t *s, complexf_t *sample)
 int v29_rx(v29_rx_state_t *s, const int16_t amp[], int len)
 {
     int i;
-    int j;
     int step;
     int16_t x;
     int32_t diff;
@@ -879,8 +843,7 @@ int v29_rx(v29_rx_state_t *s, const int16_t amp[], int len)
 
     for (i = 0;  i < len;  i++)
     {
-        s->rrc_filter[s->rrc_filter_step] =
-        s->rrc_filter[s->rrc_filter_step + V29_RX_FILTER_STEPS] = amp[i];
+        s->rrc_filter[s->rrc_filter_step] = amp[i];
         if (++s->rrc_filter_step >= V29_RX_FILTER_STEPS)
             s->rrc_filter_step = 0;
 
@@ -956,25 +919,21 @@ int v29_rx(v29_rx_state_t *s, const int16_t amp[], int len)
         if (step < 0)
             step += RX_PULSESHAPER_COEFF_SETS;
 #if defined(SPANDSP_USE_FIXED_POINT)
-        v = (int32_t) rx_pulseshaper[step][0].re*(int32_t) s->rrc_filter[s->rrc_filter_step];
-        for (j = 1;  j < V29_RX_FILTER_STEPS;  j++)
-            v += (int32_t) rx_pulseshaper[step][j].re*(int32_t) s->rrc_filter[j + s->rrc_filter_step];
+        v = vec_circular_dot_prodi16(s->rrc_filter, rx_pulseshaper_re[step], V29_RX_FILTER_STEPS, s->rrc_filter_step);
         sample.re = (v*s->agc_scaling) >> 15;
 #else
-        v = rx_pulseshaper[step][0].re*s->rrc_filter[s->rrc_filter_step];
-        for (j = 1;  j < V29_RX_FILTER_STEPS;  j++)
-            v += rx_pulseshaper[step][j].re*s->rrc_filter[j + s->rrc_filter_step];
+        v = vec_circular_dot_prodf(s->rrc_filter, rx_pulseshaper_re[step], V29_RX_FILTER_STEPS, s->rrc_filter_step);
         sample.re = v*s->agc_scaling;
 #endif
 
         /* Symbol timing synchronisation band edge filters */
 #if defined(SPANDSP_USE_FIXED_POINT)
         /* Low Nyquist band edge filter */
-        v = ((s->symbol_sync_low[0]*SYNC_LOW_BAND_EDGE_COEFF_0) >> 12) + ((s->symbol_sync_low[1]*SYNC_LOW_BAND_EDGE_COEFF_1) >> 12) + sample.re;
+        v = ((s->symbol_sync_low[0]*SYNC_LOW_BAND_EDGE_COEFF_0) >> FP_SHIFT_FACTOR) + ((s->symbol_sync_low[1]*SYNC_LOW_BAND_EDGE_COEFF_1) >> FP_SHIFT_FACTOR) + sample.re;
         s->symbol_sync_low[1] = s->symbol_sync_low[0];
         s->symbol_sync_low[0] = v;
         /* High Nyquist band edge filter */
-        v = ((s->symbol_sync_high[0]*SYNC_HIGH_BAND_EDGE_COEFF_0) >> 12) + ((s->symbol_sync_high[1]*SYNC_HIGH_BAND_EDGE_COEFF_1) >> 12) + sample.re;
+        v = ((s->symbol_sync_high[0]*SYNC_HIGH_BAND_EDGE_COEFF_0) >> FP_SHIFT_FACTOR) + ((s->symbol_sync_high[1]*SYNC_HIGH_BAND_EDGE_COEFF_1) >> FP_SHIFT_FACTOR) + sample.re;
         s->symbol_sync_high[1] = s->symbol_sync_high[0];
         s->symbol_sync_high[0] = v;
 #else
@@ -1008,17 +967,13 @@ int v29_rx(v29_rx_state_t *s, const int16_t amp[], int len)
                 step = RX_PULSESHAPER_COEFF_SETS - 1;
             s->eq_put_step += RX_PULSESHAPER_COEFF_SETS*10/(3*2);
 #if defined(SPANDSP_USE_FIXED_POINT)
-            v = (int32_t) rx_pulseshaper[step][0].im*(int32_t) s->rrc_filter[s->rrc_filter_step];
-            for (j = 1;  j < V29_RX_FILTER_STEPS;  j++)
-                v += (int32_t) rx_pulseshaper[step][j].im*(int32_t) s->rrc_filter[j + s->rrc_filter_step];
+            v = vec_circular_dot_prodi16(s->rrc_filter, rx_pulseshaper_im[step], V29_RX_FILTER_STEPS, s->rrc_filter_step);
             sample.im = (v*s->agc_scaling) >> 15;
             z = dds_lookup_complexi16(s->carrier_phase);
             zz.re = ((int32_t) sample.re*(int32_t) z.re - (int32_t) sample.im*(int32_t) z.im) >> 15;
             zz.im = ((int32_t) -sample.re*(int32_t) z.im - (int32_t) sample.im*(int32_t) z.re) >> 15;
 #else
-            v = rx_pulseshaper[step][0].im*s->rrc_filter[s->rrc_filter_step];
-            for (j = 1;  j < V29_RX_FILTER_STEPS;  j++)
-                v += rx_pulseshaper[step][j].im*s->rrc_filter[j + s->rrc_filter_step];
+            v = vec_circular_dot_prodf(s->rrc_filter, rx_pulseshaper_im[step], V29_RX_FILTER_STEPS, s->rrc_filter_step);
             sample.im = v*s->agc_scaling;
             z = dds_lookup_complexf(s->carrier_phase);
             zz.re = sample.re*z.re - sample.im*z.im;
index 0598ebe7dc632ed29c340ebb9db08f5e116583ff..1241b9e24862eb49eab43cdf96f7c9b5b7ef2bdb 100644 (file)
@@ -22,7 +22,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: vector_float.c,v 1.12 2008/09/16 15:21:52 steveu Exp $
+ * $Id: vector_float.c,v 1.14 2008/09/18 13:54:32 steveu Exp $
  */
 
 /*! \file */
@@ -337,22 +337,25 @@ float vec_dot_prodf(const float x[], const float y[], int n)
 {
     int i;
     float z;
-    __m128 num1, num2, num3, num4;
+    __m128 n1;
+    __m128 n2;
+    __m128 n3;
+    __m128 n4;
  
     z = 0.0f;
     if ((i = n & ~3))
     {    
-        num4 = _mm_setzero_ps();  //sets sum to zero
+        n4 = _mm_setzero_ps();  //sets sum to zero
         for (i -= 4;  i >= 0;  i -= 4)
         {
-            num1 = _mm_loadu_ps(x + i);
-            num2 = _mm_loadu_ps(y + i);
-            num3 = _mm_mul_ps(num1, num2);
-            num4 = _mm_add_ps(num4, num3);
+            n1 = _mm_loadu_ps(x + i);
+            n2 = _mm_loadu_ps(y + i);
+            n3 = _mm_mul_ps(n1, n2);
+            n4 = _mm_add_ps(n4, n3);
         }
-        num4 = _mm_add_ps(_mm_movehl_ps(num4, num4), num4);
-        num4 = _mm_add_ss(_mm_shuffle_ps(num4, num4, 1), num4);
-        _mm_store_ss(&z, num4);
+        n4 = _mm_add_ps(_mm_movehl_ps(n4, n4), n4);
+        n4 = _mm_add_ss(_mm_shuffle_ps(n4, n4, 1), n4);
+        _mm_store_ss(&z, n4);
     }
     /* Now deal with the last 1 to 3 elements, which don't fill in an SSE2 register */
     switch (n & 3)
@@ -405,4 +408,34 @@ long double vec_dot_prodl(const long double x[], const long double y[], int n)
 }
 /*- End of function --------------------------------------------------------*/
 #endif
+
+float vec_circular_dot_prodf(const float x[], const float y[], int n, int pos)
+{
+    float z;
+
+    z = vec_dot_prodf(&x[pos], &y[0], n - pos);
+    z += vec_dot_prodf(&x[0], &y[n - pos], pos);
+    return z;
+}
+/*- End of function --------------------------------------------------------*/
+
+void vec_lmsf(const float x[], float y[], int n, float error)
+{
+    int i;
+
+    for (i = 0;  i < n;  i++)
+    {
+        y[i] += x[i]*error;
+        /* Leak a little to tame uncontrolled wandering */
+        y[i] *= 0.9999f;
+    }
+}
+/*- End of function --------------------------------------------------------*/
+
+void vec_circular_lmsf(const float x[], float y[], int n, int pos, float error)
+{
+    vec_lmsf(&x[pos], &y[0], n - pos, error);
+    vec_lmsf(&x[0], &y[n - pos], pos, error);
+}
+/*- End of function --------------------------------------------------------*/
 /*- End of file ------------------------------------------------------------*/
index 5ba6f22d151ab8779bf24324e76b1096ee42d482..ac2ddae1b708ef1f31e191dd13cd2b2a153016fd 100644 (file)
@@ -22,7 +22,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: vector_int.c,v 1.13 2008/09/16 15:21:52 steveu Exp $
+ * $Id: vector_int.c,v 1.15 2008/09/18 13:54:32 steveu Exp $
  */
 
 /*! \file */
@@ -156,7 +156,33 @@ int32_t vec_dot_prodi16(const int16_t x[], const int16_t y[], int n)
     for (i = 0;  i < n;  i++)
         z += (int32_t) x[i]*(int32_t) y[i];
 #endif
-    return  z;
+    return z;
+}
+/*- End of function --------------------------------------------------------*/
+
+int32_t vec_circular_dot_prodi16(const int16_t x[], const int16_t y[], int n, int pos)
+{
+    int32_t z;
+
+    z = vec_dot_prodi16(&x[pos], &y[0], n - pos);
+    z += vec_dot_prodi16(&x[0], &y[n - pos], pos);
+    return z;
+}
+/*- End of function --------------------------------------------------------*/
+
+void vec_lmsi16(const int16_t x[], int16_t y[], int n, int16_t error)
+{
+    int i;
+
+    for (i = 0;  i < n;  i++)
+        y[i] += ((int32_t) x[i]*(int32_t) error) >> 15;
+}
+/*- End of function --------------------------------------------------------*/
+
+void vec_circular_lmsi16(const int16_t x[], int16_t y[], int n, int pos, int16_t error)
+{
+    vec_lmsi16(&x[pos], &y[0], n - pos, error);
+    vec_lmsi16(&x[0], &y[n - pos], pos, error);
 }
 /*- End of function --------------------------------------------------------*/
 
@@ -315,7 +341,7 @@ int32_t vec_min_maxi16(const int16_t x[], int n, int16_t out[])
         : "S" (x), "a" (n), "d" (out), [lower] "m" (lower_bound), [upper] "m" (upper_bound)
         : "ecx"
     );
-    return  max;
+    return max;
 #else
     int i;
     int16_t min;
index 4d965f3dec9e7aebd4f76035c3be7b0980ff69e8..3dee262fca933d4f26456e9847387cf0653f184d 100644 (file)
@@ -16,7 +16,7 @@
 ## along with this program; if not, write to the Free Software
 ## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 ##
-## $Id: Makefile.am,v 1.106 2008/09/09 14:05:55 steveu Exp $
+## $Id: Makefile.am,v 1.107 2008/09/18 12:05:35 steveu Exp $
 
 AM_CFLAGS = $(COMP_VENDOR_CFLAGS)
 AM_LDFLAGS = $(COMP_VENDOR_LDFLAGS)
@@ -41,6 +41,9 @@ noinst_PROGRAMS =   adsi_tests \
                     bell_mf_tx_tests \
                     bert_tests \
                     bit_operations_tests \
+                    complex_tests \
+                    complex_vector_float_tests \
+                    complex_vector_int_tests \
                     crc_tests \
                     dc_restore_tests \
                     dds_tests \
@@ -132,6 +135,15 @@ bert_tests_LDADD = $(LIBDIR) -lspandsp
 bit_operations_tests_SOURCES = bit_operations_tests.c
 bit_operations_tests_LDADD = $(LIBDIR) -lspandsp
 
+complex_tests_SOURCES = complex_tests.c
+complex_tests_LDADD = $(LIBDIR) -lspandsp
+
+complex_vector_float_tests_SOURCES = complex_vector_float_tests.c
+complex_vector_float_tests_LDADD = $(LIBDIR) -lspandsp
+
+complex_vector_int_tests_SOURCES = complex_vector_int_tests.c
+complex_vector_int_tests_LDADD = $(LIBDIR) -lspandsp
+
 crc_tests_SOURCES = crc_tests.c
 crc_tests_LDADD = $(LIBDIR) -lspandsp
 
index 062b53188a8649924a2c772b2ea06966397e5e42..14e50ab176de75d3b3aab445cbcf059c45c4552d 100644 (file)
@@ -22,7 +22,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: g722_tests.c,v 1.26 2008/05/13 13:17:25 steveu Exp $
+ * $Id: g722_tests.c,v 1.27 2008/09/19 14:02:05 steveu Exp $
  */
 
 /*! \file */
@@ -109,8 +109,10 @@ static const char *itu_test_files[] =
 
 static const char *encode_test_files[] =
 {
-    TESTDATA_DIR "T1C1.XMT",    TESTDATA_DIR "T2R1.COD",
-    TESTDATA_DIR "T1C2.XMT",    TESTDATA_DIR "T2R2.COD",
+    TESTDATA_DIR "T1C1.XMT",
+    TESTDATA_DIR "T2R1.COD",
+    TESTDATA_DIR "T1C2.XMT",
+    TESTDATA_DIR "T2R2.COD",
     NULL
 };
 
@@ -295,6 +297,7 @@ int main(int argc, char *argv[])
 
     if (itutests)
     {
+#if 1
         /* ITU G.722 encode tests, using configuration 1. The QMF is bypassed */
         for (file = 0;  encode_test_files[file];  file += 2)
         {
@@ -341,7 +344,8 @@ int main(int argc, char *argv[])
             }
             printf("Test passed\n");
         }
-
+#endif
+#if 1
         /* ITU G.722 decode tests, using configuration 2. The QMF is bypassed */
         /* Run each of the tests for each of the modes - 48kbps, 56kbps and 64kbps. */
         for (mode = 1;  mode <= 3;  mode++)
@@ -404,7 +408,7 @@ int main(int argc, char *argv[])
                 printf("Test passed\n");
             }
         }
-
+#endif
         printf("Tests passed.\n");
     }
     else
index 20848d6b0070fdad85b91e19dca2fe1b44eb14af..6f36b32af0dbe8c44ecc33abaa8f56c54e89b86f 100755 (executable)
@@ -17,7 +17,7 @@
 # License along with this program; if not, write to the Free Software
 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 #
-# $Id: regression_tests.sh,v 1.52 2008/09/02 13:56:10 steveu Exp $
+# $Id: regression_tests.sh,v 1.53 2008/09/18 12:09:51 steveu Exp $
 #
 
 ITUTESTS_TIF=../test-data/itu/fax/itutests.tif
@@ -99,6 +99,33 @@ then
 fi
 echo bit_operations_tests completed OK
 
+./complex_tests >$STDOUT_DEST 2>$STDERR_DEST
+RETVAL=$?
+if [ $RETVAL != 0 ]
+then
+    echo complex_tests failed!
+    exit $RETVAL
+fi
+echo complex_tests completed OK
+
+./complex_vector_float_tests >$STDOUT_DEST 2>$STDERR_DEST
+RETVAL=$?
+if [ $RETVAL != 0 ]
+then
+    echo complex_vector_float_tests failed!
+    exit $RETVAL
+fi
+echo complex_vector_float_tests completed OK
+
+./complex_vector_int_tests >$STDOUT_DEST 2>$STDERR_DEST
+RETVAL=$?
+if [ $RETVAL != 0 ]
+then
+    echo complex_vector_int_tests failed!
+    exit $RETVAL
+fi
+echo complex_vector_int_tests completed OK
+
 ./crc_tests >$STDOUT_DEST 2>$STDERR_DEST
 RETVAL=$?
 if [ $RETVAL != 0 ]
index 0c914cdb300be1b06f158eda370418fc14758ff4..67ad5e06284193456310b4f4da0a97962d81b843 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * SpanDSP - a series of DSP components for telephony
  *
- * vector_int_tests.c
+ * complex_vector_int_tests.c
  *
  * Written by Steve Underwood <steveu@coppice.org>
  *
@@ -22,7 +22,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: vector_int_tests.c,v 1.9 2008/09/16 15:21:52 steveu Exp $
+ * $Id: vector_int_tests.c,v 1.10 2008/09/18 12:05:35 steveu Exp $
  */
 
 #if defined(HAVE_CONFIG_H)
@@ -139,10 +139,51 @@ static int test_vec_min_maxi16(void)
 }
 /*- End of function --------------------------------------------------------*/
 
+static int test_vec_circular_dot_prodi16(void)
+{
+    int i;
+    int j;
+    int pos;
+    int len;
+    int32_t za;
+    int32_t zb;
+    int16_t x[99];
+    int16_t y[99];
+
+    /* Verify that we can do circular sample buffer "dot" linear coefficient buffer
+       operations properly, by doing two sub-dot products. */
+    for (i = 0;  i < 99;  i++)
+    {
+        x[i] = rand();
+        y[i] = rand();
+    }
+
+    len = 95;
+    for (pos = 0;  pos < len;  pos++)
+    {
+        za = vec_circular_dot_prodi16(x, y, len, pos);
+        zb = 0;
+        for (i = 0;  i < len;  i++)
+        {
+            j = (pos + i) % len;
+            zb += (int32_t) x[j]*(int32_t) y[i];
+        }
+
+        if (za != zb)
+        {
+            printf("Tests failed\n");
+            exit(2);
+        }
+    }
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
 int main(int argc, char *argv[])
 {
     test_vec_dot_prodi16();
     test_vec_min_maxi16();
+    test_vec_circular_dot_prodi16();
 
     printf("Tests passed.\n");
     return 0;