From 2825fb6e5bcc6b7f64e129829817264deb7bb23f Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 1 Oct 2008 03:59:45 +0000 Subject: [PATCH] update to snapshot spandsp-20080919.tar.gz git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@9770 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- libs/spandsp/.update | 2 +- libs/spandsp/src/Makefile.am | 6 +- libs/spandsp/src/awgn.c | 4 +- libs/spandsp/src/complex_vector_float.c | 84 +++++++- libs/spandsp/src/echo.c | 3 +- libs/spandsp/src/gsm0610_decode.c | 8 +- libs/spandsp/src/gsm0610_encode.c | 6 +- libs/spandsp/src/gsm0610_long_term.c | 14 +- libs/spandsp/src/gsm0610_lpc.c | 23 +-- libs/spandsp/src/gsm0610_preprocess.c | 12 +- libs/spandsp/src/gsm0610_rpe.c | 22 +- libs/spandsp/src/gsm0610_short_term.c | 32 +-- libs/spandsp/src/ima_adpcm.c | 4 +- libs/spandsp/src/libspandsp.dsp | 10 +- libs/spandsp/src/make_modem_filter.c | 57 +++++- libs/spandsp/src/noise.c | 4 +- libs/spandsp/src/plc.c | 4 +- libs/spandsp/src/sig_tone.c | 3 +- libs/spandsp/src/spandsp.h.in | 3 +- .../src/spandsp/complex_vector_float.h | 38 +++- libs/spandsp/src/spandsp/complex_vector_int.h | 29 ++- libs/spandsp/src/spandsp/dc_restore.h | 56 +---- libs/spandsp/src/spandsp/g722.h | 66 +++--- libs/spandsp/src/spandsp/v17rx.h | 15 +- libs/spandsp/src/spandsp/v27ter_rx.h | 15 +- libs/spandsp/src/spandsp/v29rx.h | 15 +- libs/spandsp/src/spandsp/vector_float.h | 15 +- libs/spandsp/src/spandsp/vector_int.h | 15 +- libs/spandsp/src/spandsp/version.h | 4 +- libs/spandsp/src/time_scale.c | 3 +- libs/spandsp/src/v17rx.c | 132 +++++------- libs/spandsp/src/v22bis_rx.c | 26 +-- libs/spandsp/src/v27ter_rx.c | 193 ++++++------------ libs/spandsp/src/v29rx.c | 151 +++++--------- libs/spandsp/src/vector_float.c | 53 ++++- libs/spandsp/src/vector_int.c | 32 ++- libs/spandsp/tests/Makefile.am | 14 +- libs/spandsp/tests/g722_tests.c | 14 +- libs/spandsp/tests/regression_tests.sh | 29 ++- libs/spandsp/tests/vector_int_tests.c | 45 +++- 40 files changed, 717 insertions(+), 544 deletions(-) diff --git a/libs/spandsp/.update b/libs/spandsp/.update index 1e1ab309d6..786c42ad08 100644 --- a/libs/spandsp/.update +++ b/libs/spandsp/.update @@ -1 +1 @@ -Tue Sep 30 23:55:26 EDT 2008 +Tue Sep 30 23:59:24 EDT 2008 diff --git a/libs/spandsp/src/Makefile.am b/libs/spandsp/src/Makefile.am index 82704812e6..8ec021bd60 100644 --- a/libs/spandsp/src/Makefile.am +++ b/libs/spandsp/src/Makefile.am @@ -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 \ diff --git a/libs/spandsp/src/awgn.c b/libs/spandsp/src/awgn.c index 6c8103295f..9d17487824 100644 --- a/libs/spandsp/src/awgn.c +++ b/libs/spandsp/src/awgn.c @@ -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 */ diff --git a/libs/spandsp/src/complex_vector_float.c b/libs/spandsp/src/complex_vector_float.c index 88ee2a4536..974ce289ce 100644 --- a/libs/spandsp/src/complex_vector_float.c +++ b/libs/spandsp/src/complex_vector_float.c @@ -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 * @@ -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 */ @@ -50,4 +50,84 @@ #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 ------------------------------------------------------------*/ diff --git a/libs/spandsp/src/echo.c b/libs/spandsp/src/echo.c index 6a4699cc1b..d106a92803 100644 --- a/libs/spandsp/src/echo.c +++ b/libs/spandsp/src/echo.c @@ -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" diff --git a/libs/spandsp/src/gsm0610_decode.c b/libs/spandsp/src/gsm0610_decode.c index 49b8fcb869..84c28cf3d3 100644 --- a/libs/spandsp/src/gsm0610_decode.c +++ b/libs/spandsp/src/gsm0610_decode.c @@ -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; diff --git a/libs/spandsp/src/gsm0610_encode.c b/libs/spandsp/src/gsm0610_encode.c index 94f14b0514..f6844577a1 100644 --- a/libs/spandsp/src/gsm0610_encode.c +++ b/libs/spandsp/src/gsm0610_encode.c @@ -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; diff --git a/libs/spandsp/src/gsm0610_long_term.c b/libs/spandsp/src/gsm0610_long_term.c index 80bad2ccd5..a17b5d5413 100644 --- a/libs/spandsp/src/gsm0610_long_term.c +++ b/libs/spandsp/src/gsm0610_long_term.c @@ -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*/ diff --git a/libs/spandsp/src/gsm0610_lpc.c b/libs/spandsp/src/gsm0610_lpc.c index 05e65a393a..e64d5b6d18 100644 --- a/libs/spandsp/src/gsm0610_lpc.c +++ b/libs/spandsp/src/gsm0610_lpc.c @@ -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) \ ? \ diff --git a/libs/spandsp/src/gsm0610_preprocess.c b/libs/spandsp/src/gsm0610_preprocess.c index 81fff74093..edbe7c5879 100644 --- a/libs/spandsp/src/gsm0610_preprocess.c +++ b/libs/spandsp/src/gsm0610_preprocess.c @@ -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*/ diff --git a/libs/spandsp/src/gsm0610_rpe.c b/libs/spandsp/src/gsm0610_rpe.c index 567d3c57c2..cf4113b3ce 100644 --- a/libs/spandsp/src/gsm0610_rpe.c +++ b/libs/spandsp/src/gsm0610_rpe.c @@ -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*/ diff --git a/libs/spandsp/src/gsm0610_short_term.c b/libs/spandsp/src/gsm0610_short_term.c index e686232654..4eaace5a5d 100644 --- a/libs/spandsp/src/gsm0610_short_term.c +++ b/libs/spandsp/src/gsm0610_short_term.c @@ -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++ = diff --git a/libs/spandsp/src/ima_adpcm.c b/libs/spandsp/src/ima_adpcm.c index 6be16b5734..d92f28b9ee 100644 --- a/libs/spandsp/src/ima_adpcm.c +++ b/libs/spandsp/src/ima_adpcm.c @@ -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" /* diff --git a/libs/spandsp/src/libspandsp.dsp b/libs/spandsp/src/libspandsp.dsp index cc031e142b..fc6cda3186 100644 --- a/libs/spandsp/src/libspandsp.dsp +++ b/libs/spandsp/src/libspandsp.dsp @@ -133,6 +133,10 @@ SOURCE=.\complex_vector_float.c # End Source File # Begin Source File +SOURCE=.\complex_vector_int.c +# End Source File +# Begin Source File + SOURCE=.\crc.c # End Source File # Begin Source File @@ -165,11 +169,7 @@ SOURCE=.\g711.c # End Source File # Begin Source File -SOURCE=.\g722_encode.c -# End Source File -# Begin Source File - -SOURCE=.\g722_decode.c +SOURCE=.\g722.c # End Source File # Begin Source File diff --git a/libs/spandsp/src/make_modem_filter.c b/libs/spandsp/src/make_modem_filter.c index b8599bdce8..ddfdb6e41d 100644 --- a/libs/spandsp/src/make_modem_filter.c +++ b/libs/spandsp/src/make_modem_filter.c @@ -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 --------------------------------------------------------*/ diff --git a/libs/spandsp/src/noise.c b/libs/spandsp/src/noise.c index 559741dd08..baee0d1edd 100644 --- a/libs/spandsp/src/noise.c +++ b/libs/spandsp/src/noise.c @@ -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) diff --git a/libs/spandsp/src/plc.c b/libs/spandsp/src/plc.c index 1b01e220cd..ce6a096796 100644 --- a/libs/spandsp/src/plc.c +++ b/libs/spandsp/src/plc.c @@ -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 #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. */ diff --git a/libs/spandsp/src/sig_tone.c b/libs/spandsp/src/sig_tone.c index 19c73e2694..6c498d1085 100644 --- a/libs/spandsp/src/sig_tone.c +++ b/libs/spandsp/src/sig_tone.c @@ -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" diff --git a/libs/spandsp/src/spandsp.h.in b/libs/spandsp/src/spandsp.h.in index c59f68382c..1611b87160 100644 --- a/libs/spandsp/src/spandsp.h.in +++ b/libs/spandsp/src/spandsp.h.in @@ -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 #include #include +#include #include #include #include diff --git a/libs/spandsp/src/spandsp/complex_vector_float.h b/libs/spandsp/src/spandsp/complex_vector_float.h index c8931e4560..5f144458e1 100644 --- a/libs/spandsp/src/spandsp/complex_vector_float.h +++ b/libs/spandsp/src/spandsp/complex_vector_float.h @@ -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 diff --git a/libs/spandsp/src/spandsp/complex_vector_int.h b/libs/spandsp/src/spandsp/complex_vector_int.h index 278b9296ae..5eb4515a29 100644 --- a/libs/spandsp/src/spandsp/complex_vector_int.h +++ b/libs/spandsp/src/spandsp/complex_vector_int.h @@ -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 diff --git a/libs/spandsp/src/spandsp/dc_restore.h b/libs/spandsp/src/spandsp/dc_restore.h index 33393a92a2..4061f41137 100644 --- a/libs/spandsp/src/spandsp/dc_restore.h +++ b/libs/spandsp/src/spandsp/dc_restore.h @@ -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 diff --git a/libs/spandsp/src/spandsp/g722.h b/libs/spandsp/src/spandsp/g722.h index 11a901d00f..7d2936bdb9 100644 --- a/libs/spandsp/src/spandsp/g722.h +++ b/libs/spandsp/src/spandsp/g722.h @@ -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]; + int16_t x[12]; + int16_t y[12]; + int ptr; - 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]; + 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_encode_state_t; @@ -107,28 +108,15 @@ typedef struct int bits_per_sample; /*! Signal history for the QMF */ - int x[24]; + int16_t x[12]; + int16_t y[12]; + int ptr; - 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]; + 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; diff --git a/libs/spandsp/src/spandsp/v17rx.h b/libs/spandsp/src/spandsp/v17rx.h index d7fb9cc5f5..347170743a 100644 --- a/libs/spandsp/src/spandsp/v17rx.h +++ b/libs/spandsp/src/spandsp/v17rx.h @@ -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]; diff --git a/libs/spandsp/src/spandsp/v27ter_rx.h b/libs/spandsp/src/spandsp/v27ter_rx.h index cc6be878b1..a70465423c 100644 --- a/libs/spandsp/src/spandsp/v27ter_rx.h +++ b/libs/spandsp/src/spandsp/v27ter_rx.h @@ -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. */ diff --git a/libs/spandsp/src/spandsp/v29rx.h b/libs/spandsp/src/spandsp/v29rx.h index 20671542b6..cac4a9d47d 100644 --- a/libs/spandsp/src/spandsp/v29rx.h +++ b/libs/spandsp/src/spandsp/v29rx.h @@ -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]; diff --git a/libs/spandsp/src/spandsp/vector_float.h b/libs/spandsp/src/spandsp/vector_float.h index 94c67cf33e..946d84741a 100644 --- a/libs/spandsp/src/spandsp/vector_float.h +++ b/libs/spandsp/src/spandsp/vector_float.h @@ -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 diff --git a/libs/spandsp/src/spandsp/vector_int.h b/libs/spandsp/src/spandsp/vector_int.h index f603bd2143..7f9b011049 100644 --- a/libs/spandsp/src/spandsp/vector_int.h +++ b/libs/spandsp/src/spandsp/vector_int.h @@ -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. diff --git a/libs/spandsp/src/spandsp/version.h b/libs/spandsp/src/spandsp/version.h index eef22ad70e..537acce6fb 100644 --- a/libs/spandsp/src/spandsp/version.h +++ b/libs/spandsp/src/spandsp/version.h @@ -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 ------------------------------------------------------------*/ diff --git a/libs/spandsp/src/time_scale.c b/libs/spandsp/src/time_scale.c index 27e02bd899..0b913ad7ff 100644 --- a/libs/spandsp/src/time_scale.c +++ b/libs/spandsp/src/time_scale.c @@ -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 diff --git a/libs/spandsp/src/v17rx.c b/libs/spandsp/src/v17rx.c index 82a3f54a58..edccf3143e 100644 --- a/libs/spandsp/src/v17rx.c +++ b/libs/spandsp/src/v17rx.c @@ -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 +#if defined(SPANDSP_USE_FIXED_POINTx) + int32_t v; +#else + float v; #endif int32_t power; - float v; 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; + s->eq_put_step += RX_PULSESHAPER_COEFF_SETS*10/(3*2); #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); + 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 diff --git a/libs/spandsp/src/v22bis_rx.c b/libs/spandsp/src/v22bis_rx.c index be9ac1efe2..9a5d7e848b 100644 --- a/libs/spandsp/src/v22bis_rx.c +++ b/libs/spandsp/src/v22bis_rx.c @@ -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; diff --git a/libs/spandsp/src/v27ter_rx.c b/libs/spandsp/src/v27ter_rx.c index 8f9ca872e4..605a699732 100644 --- a/libs/spandsp/src/v27ter_rx.c +++ b/libs/spandsp/src/v27ter_rx.c @@ -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); - } -#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); - } -#endif + 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 + /* Get the next equalized value. */ + return cvec_circular_dot_prodf(s->eq_buf, s->eq_coeff, V27TER_EQUALIZER_LEN, s->eq_step); +#endif } /*- 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; diff --git a/libs/spandsp/src/v29rx.c b/libs/spandsp/src/v29rx.c index 50dba0120f..ec36b637cf 100644 --- a/libs/spandsp/src/v29rx.c +++ b/libs/spandsp/src/v29rx.c @@ -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); - } -#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); - } -#endif + 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 + /* Get the next equalized value. */ + return cvec_circular_dot_prodf(s->eq_buf, s->eq_coeff, V29_EQUALIZER_LEN, s->eq_step); +#endif } /*- 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; diff --git a/libs/spandsp/src/vector_float.c b/libs/spandsp/src/vector_float.c index 0598ebe7dc..1241b9e248 100644 --- a/libs/spandsp/src/vector_float.c +++ b/libs/spandsp/src/vector_float.c @@ -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 ------------------------------------------------------------*/ diff --git a/libs/spandsp/src/vector_int.c b/libs/spandsp/src/vector_int.c index 5ba6f22d15..ac2ddae1b7 100644 --- a/libs/spandsp/src/vector_int.c +++ b/libs/spandsp/src/vector_int.c @@ -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; diff --git a/libs/spandsp/tests/Makefile.am b/libs/spandsp/tests/Makefile.am index 4d965f3dec..3dee262fca 100644 --- a/libs/spandsp/tests/Makefile.am +++ b/libs/spandsp/tests/Makefile.am @@ -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 diff --git a/libs/spandsp/tests/g722_tests.c b/libs/spandsp/tests/g722_tests.c index 062b53188a..14e50ab176 100644 --- a/libs/spandsp/tests/g722_tests.c +++ b/libs/spandsp/tests/g722_tests.c @@ -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 diff --git a/libs/spandsp/tests/regression_tests.sh b/libs/spandsp/tests/regression_tests.sh index 20848d6b00..6f36b32af0 100755 --- a/libs/spandsp/tests/regression_tests.sh +++ b/libs/spandsp/tests/regression_tests.sh @@ -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 ] diff --git a/libs/spandsp/tests/vector_int_tests.c b/libs/spandsp/tests/vector_int_tests.c index 0c914cdb30..67ad5e0628 100644 --- a/libs/spandsp/tests/vector_int_tests.c +++ b/libs/spandsp/tests/vector_int_tests.c @@ -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 * @@ -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;