From dab4d9068d9ad54cbc9d6ff8a51a39beec7d2ef9 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 5 Oct 2009 14:34:26 +0000 Subject: [PATCH] update to spandsp snapshot 20091005 git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@15084 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- libs/spandsp/.update | 2 +- libs/spandsp/configure.ac | 34 +- libs/spandsp/spandsp-sim/line_model.c | 22 +- libs/spandsp/spandsp-sim/make_line_models.c | 12 +- libs/spandsp/spandsp-sim/spandsp/line_model.h | 4 +- libs/spandsp/spandsp/fax-tests.dtd | 1 + libs/spandsp/src/Makefile.am | 7 +- libs/spandsp/src/at_interpreter.c | 4 +- libs/spandsp/src/echo.c | 4 +- libs/spandsp/src/fax.c | 92 +++-- libs/spandsp/src/fax_modems.c | 9 +- libs/spandsp/src/libspandsp.2005.vcproj | 5 + libs/spandsp/src/libspandsp.2008.vcproj | 5 + libs/spandsp/src/libspandsp.dsp | 20 + libs/spandsp/src/make_modem_filter.c | 4 +- libs/spandsp/src/modem_echo.c | 4 +- libs/spandsp/src/msvc/spandsp.h | 3 +- libs/spandsp/src/sig_tone.c | 138 ++++--- libs/spandsp/src/silence_gen.c | 8 +- libs/spandsp/src/spandsp.h.in | 3 +- libs/spandsp/src/spandsp/echo.h | 56 +-- libs/spandsp/src/spandsp/expose.h | 5 +- libs/spandsp/src/spandsp/fast_convert.h | 6 +- libs/spandsp/src/spandsp/modem_echo.h | 19 +- libs/spandsp/src/spandsp/private/echo.h | 94 +++++ libs/spandsp/src/spandsp/private/fax_modems.h | 6 +- libs/spandsp/src/spandsp/private/modem_echo.h | 58 +++ libs/spandsp/src/spandsp/private/sig_tone.h | 21 +- libs/spandsp/src/spandsp/private/swept_tone.h | 44 +++ libs/spandsp/src/spandsp/private/t30.h | 10 +- libs/spandsp/src/spandsp/sig_tone.h | 41 +- libs/spandsp/src/spandsp/silence_gen.h | 12 +- libs/spandsp/src/spandsp/swept_tone.h | 59 +++ libs/spandsp/src/spandsp/t30.h | 6 +- libs/spandsp/src/spandsp/timing.h | 6 +- libs/spandsp/src/spandsp/version.h | 6 +- libs/spandsp/src/swept_tone.c | 128 +++++++ libs/spandsp/src/t30.c | 360 ++++++++++++------ libs/spandsp/src/t31.c | 84 +++- libs/spandsp/src/t38_terminal.c | 8 +- libs/spandsp/tests/Makefile.am | 6 +- libs/spandsp/tests/fax_decode.c | 4 +- libs/spandsp/tests/line_model_tests.c | 124 ++++-- libs/spandsp/tests/regression_tests.sh | 12 +- libs/spandsp/tests/sig_tone_tests.c | 164 ++++---- libs/spandsp/tests/swept_tone_tests.c | 101 +++++ 46 files changed, 1316 insertions(+), 505 deletions(-) create mode 100644 libs/spandsp/src/spandsp/private/echo.h create mode 100644 libs/spandsp/src/spandsp/private/modem_echo.h create mode 100644 libs/spandsp/src/spandsp/private/swept_tone.h create mode 100644 libs/spandsp/src/spandsp/swept_tone.h create mode 100644 libs/spandsp/src/swept_tone.c create mode 100644 libs/spandsp/tests/swept_tone_tests.c diff --git a/libs/spandsp/.update b/libs/spandsp/.update index df0d5762bf..0c4f2f72a7 100644 --- a/libs/spandsp/.update +++ b/libs/spandsp/.update @@ -1 +1 @@ -Wed Oct 1 00:08:32 EDT 2008 +Mon Oct 5 09:33:55 CDT 2009 diff --git a/libs/spandsp/configure.ac b/libs/spandsp/configure.ac index d23c63016c..58b7af50d0 100644 --- a/libs/spandsp/configure.ac +++ b/libs/spandsp/configure.ac @@ -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: configure.ac,v 1.71 2009/07/12 09:29:18 steveu Exp $ +# $Id: configure.ac,v 1.73 2009/10/03 04:37:25 steveu Exp $ # @start 1 @@ -108,20 +108,20 @@ else CXXFLAGS=${CXXFLAGS-"-g -O2"} fi -AC_DEFUN([REMOVE_FROM_VAR],[ - new_val="" - removed=0 - for i in $$1; do - if test "x$i" != "x$2"; then - new_val="$new_val $i" - else - removed=1 - fi - done - if test $removed = "1"; then - echo " removed \"$2\" from $1" - $1=$new_val - fi +AC_DEFUN([REMOVE_FROM_VAR],[ + new_val="" + removed=0 + for i in $$1; do + if test "x$i" != "x$2"; then + new_val="$new_val $i" + else + removed=1 + fi + done + if test $removed = "1"; then + echo " removed \"$2\" from $1" + $1=$new_val + fi ]) AC_C_CONST @@ -146,9 +146,9 @@ AC_ARG_ENABLE(sse4_2, [ --enable-sse4-2 Enable SSE4.2 support]) AC_ARG_ENABLE(sse4a, [ --enable-sse4a Enable SSE4A support]) AC_ARG_ENABLE(sse5, [ --enable-sse5 Enable SSE5 support]) AC_ARG_ENABLE(fixed_point, [ --enable-fixed-point Enable fixed point support]) +# The following is for MSVC, where we may be using a local copy of libtiff, built alongside spandsp AC_ARG_ENABLE(builtin_tiff, -[AC_HELP_STRING([--enable-builtin-tiff],[build with builtin libtiff])],[enable_builtin_tiff="$enableval"],[enable_builtin_tiff="no"]) - + [AC_HELP_STRING([--enable-builtin-tiff],[build with builtin libtiff])],[enable_builtin_tiff="$enableval"],[enable_builtin_tiff="no"]) AC_FUNC_ERROR_AT_LINE AC_FUNC_VPRINTF diff --git a/libs/spandsp/spandsp-sim/line_model.c b/libs/spandsp/spandsp-sim/line_model.c index 0c1e2564e0..5e09b39fd1 100644 --- a/libs/spandsp/spandsp-sim/line_model.c +++ b/libs/spandsp/spandsp-sim/line_model.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: line_model.c,v 1.12 2009/06/01 16:27:12 steveu Exp $ + * $Id: line_model.c,v 1.14 2009/09/23 16:02:59 steveu Exp $ */ #if defined(HAVE_CONFIG_H) @@ -54,7 +54,7 @@ #define NULL (void *) 0 #endif -float null_line_model[] = +static const float null_line_model[] = { 0.0, 0.0, @@ -187,7 +187,7 @@ float null_line_model[] = 1.0 }; -static float *models[] = +SPAN_DECLARE_DATA const float *line_models[] = { null_line_model, /* 0 */ proakis_line_model, @@ -225,7 +225,7 @@ static float calc_near_line_filter(one_way_line_model_state_t *s, float v) s->near_buf_ptr = p; /* Apply the filter */ - sum = 0; + sum = 0.0f; for (j = 0; j < s->near_filter_len; j++) { sum += s->near_filter[j]*s->near_buf[p]; @@ -254,7 +254,7 @@ static float calc_far_line_filter(one_way_line_model_state_t *s, float v) s->far_buf_ptr = p; /* Apply the filter */ - sum = 0; + sum = 0.0f; for (j = 0; j < s->far_filter_len; j++) { sum += s->far_filter[j]*s->far_buf[p]; @@ -479,10 +479,10 @@ SPAN_DECLARE(one_way_line_model_state_t *) one_way_line_model_init(int model, fl s->munge = codec_munge_init(codec, rbs_pattern); - s->near_filter = models[model]; + s->near_filter = line_models[model]; s->near_filter_len = 129; - s->far_filter = models[model]; + s->far_filter = line_models[model]; s->far_filter_len = 129; /* Put half the noise in each analogue section */ @@ -526,14 +526,14 @@ SPAN_DECLARE(both_ways_line_model_state_t *) both_ways_line_model_init(int model s->line1.bulk_delay_ptr = 0; s->line2.bulk_delay_ptr = 0; - s->line1.near_filter = models[model1]; + s->line1.near_filter = line_models[model1]; s->line1.near_filter_len = 129; - s->line2.near_filter = models[model2]; + s->line2.near_filter = line_models[model2]; s->line2.near_filter_len = 129; - s->line1.far_filter = models[model1]; + s->line1.far_filter = line_models[model1]; s->line1.far_filter_len = 129; - s->line2.far_filter = models[model2]; + s->line2.far_filter = line_models[model2]; s->line2.far_filter_len = 129; /* Put half the noise in each analogue section */ diff --git a/libs/spandsp/spandsp-sim/make_line_models.c b/libs/spandsp/spandsp-sim/make_line_models.c index aabbfd2602..42fac11fa8 100644 --- a/libs/spandsp/spandsp-sim/make_line_models.c +++ b/libs/spandsp/spandsp-sim/make_line_models.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: make_line_models.c,v 1.9 2009/02/10 17:49:20 steveu Exp $ + * $Id: make_line_models.c,v 1.10 2009/09/23 16:02:59 steveu Exp $ */ /*! \page make_line_models_page Telephony line model construction @@ -849,7 +849,8 @@ static void generate_ad_edd(void) offset = (f - edd[l - 1].freq)/(edd[l].freq - edd[l - 1].freq); delay = (1.0f - offset)*edd[l - 1].edd[k] + offset*edd[l].edd[k]; } - phase = 2.0f*M_PI*f*delay*0.001f; + //phase = 2.0f*M_PI*f*delay*0.001f; + phase = 0.0f; #if defined(HAVE_FFTW3_H) in[i][0] = amp*cosf(phase); in[i][1] = amp*sinf(phase); @@ -874,7 +875,7 @@ static void generate_ad_edd(void) fprintf(outfile, "/* V.56bis AD-%d, EDD%d */\n", (j == 0) ? 1 : j + 4, k + 1); - fprintf(outfile, "float ad_%d_edd_%d_model[] =\n", (j == 0) ? 1 : j + 4, k + 1); + fprintf(outfile, "const float ad_%d_edd_%d_model[] =\n", (j == 0) ? 1 : j + 4, k + 1); fprintf(outfile, "{\n"); /* Normalise the filter's gain */ pw = 0.0f; @@ -955,7 +956,8 @@ static void generate_proakis(void) /* Linear interpolation */ amp = ((1.0f - offset)*proakis[index].amp + offset*proakis[index + 1].amp)/2.3f; delay = (1.0f - offset)*proakis[index].delay + offset*proakis[index + 1].delay; - phase = 2.0f*M_PI*f*delay*0.001f; + //phase = 2.0f*M_PI*f*delay*0.001f; + phase = 0.0f; #if defined(HAVE_FFTW3_H) in[i][0] = amp*cosf(phase); in[i][1] = amp*sinf(phase); @@ -978,7 +980,7 @@ static void generate_proakis(void) fprintf(outfile, "/* Medium range telephone line response\n"); fprintf(outfile, " (from p 537, Digital Communication, John G. Proakis */\n"); - fprintf(outfile, "float proakis_line_model[] =\n"); + fprintf(outfile, "const float proakis_line_model[] =\n"); fprintf(outfile, "{\n"); /* Normalise the filter's gain */ pw = 0.0f; diff --git a/libs/spandsp/spandsp-sim/spandsp/line_model.h b/libs/spandsp/spandsp-sim/spandsp/line_model.h index ebe1592bcc..a8131e2707 100644 --- a/libs/spandsp/spandsp-sim/spandsp/line_model.h +++ b/libs/spandsp/spandsp-sim/spandsp/line_model.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: line_model.h,v 1.6 2009/05/31 14:47:10 steveu Exp $ + * $Id: line_model.h,v 1.7 2009/09/23 16:02:59 steveu Exp $ */ /*! \file */ @@ -132,6 +132,8 @@ extern "C" { #endif +SPAN_DECLARE_DATA extern const float *line_models[]; + SPAN_DECLARE(void) both_ways_line_model(both_ways_line_model_state_t *s, int16_t output1[], const int16_t input1[], diff --git a/libs/spandsp/spandsp/fax-tests.dtd b/libs/spandsp/spandsp/fax-tests.dtd index 38dd7cd0d8..beb4eae3ef 100644 --- a/libs/spandsp/spandsp/fax-tests.dtd +++ b/libs/spandsp/spandsp/fax-tests.dtd @@ -1,6 +1,7 @@ + modems.rx_handler = handler; + s->modems.rx_handler = rx_handler; + s->modems.rx_fillin_handler = fillin_handler; s->modems.rx_user_data = user_data; } /*- End of function --------------------------------------------------------*/ @@ -162,7 +166,7 @@ static int v17_v21_rx(void *user_data, const int16_t amp[], int len) /* The fast modem has trained, so we no longer need to run the slow one in parallel. */ span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.17 + V.21 to V.17 (%.2fdBm0)\n", v17_rx_signal_power(&s->v17_rx)); - set_rx_handler(t, (span_rx_handler_t *) &v17_rx, &s->v17_rx); + set_rx_handler(t, (span_rx_handler_t *) &v17_rx, (span_rx_fillin_handler_t *) &v17_rx_fillin, &s->v17_rx); } else { @@ -172,13 +176,26 @@ static int v17_v21_rx(void *user_data, const int16_t amp[], int len) /* We have received something, and the fast modem has not trained. We must be receiving valid V.21 */ span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.17 + V.21 to V.21 (%.2fdBm0)\n", fsk_rx_signal_power(&s->v21_rx)); - set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, &s->v21_rx); + set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, (span_rx_fillin_handler_t *) &fsk_rx_fillin, &s->v21_rx); } } return 0; } /*- End of function --------------------------------------------------------*/ +static int v17_v21_rx_fillin(void *user_data, int len) +{ + fax_state_t *t; + fax_modems_state_t *s; + + t = (fax_state_t *) user_data; + s = &t->modems; + v17_rx_fillin(&s->v17_rx, len); + fsk_rx_fillin(&s->v21_rx, len); + return 0; +} +/*- End of function --------------------------------------------------------*/ + static int v27ter_v21_rx(void *user_data, const int16_t amp[], int len) { fax_state_t *t; @@ -192,7 +209,7 @@ static int v27ter_v21_rx(void *user_data, const int16_t amp[], int len) /* The fast modem has trained, so we no longer need to run the slow one in parallel. */ span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.27ter + V.21 to V.27ter (%.2fdBm0)\n", v27ter_rx_signal_power(&s->v27ter_rx)); - set_rx_handler(t, (span_rx_handler_t *) &v27ter_rx, &s->v27ter_rx); + set_rx_handler(t, (span_rx_handler_t *) &v27ter_rx, (span_rx_fillin_handler_t *) &v27ter_rx_fillin, &s->v27ter_rx); } else { @@ -202,13 +219,26 @@ static int v27ter_v21_rx(void *user_data, const int16_t amp[], int len) /* We have received something, and the fast modem has not trained. We must be receiving valid V.21 */ span_log(&s->logging, SPAN_LOG_FLOW, "Switching from V.27ter + V.21 to V.21 (%.2fdBm0)\n", fsk_rx_signal_power(&s->v21_rx)); - set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, &s->v21_rx); + set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, (span_rx_fillin_handler_t *) &fsk_rx_fillin, &s->v21_rx); } } return 0; } /*- End of function --------------------------------------------------------*/ +static int v27ter_v21_rx_fillin(void *user_data, int len) +{ + fax_state_t *t; + fax_modems_state_t *s; + + t = (fax_state_t *) user_data; + s = &t->modems; + v27ter_rx_fillin(&s->v27ter_rx, len); + fsk_rx_fillin(&s->v21_rx, len); + return 0; +} +/*- End of function --------------------------------------------------------*/ + static int v29_v21_rx(void *user_data, const int16_t amp[], int len) { fax_state_t *t; @@ -222,7 +252,7 @@ static int v29_v21_rx(void *user_data, const int16_t amp[], int len) /* The fast modem has trained, so we no longer need to run the slow one in parallel. */ span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.29 + V.21 to V.29 (%.2fdBm0)\n", v29_rx_signal_power(&s->v29_rx)); - set_rx_handler(t, (span_rx_handler_t *) &v29_rx, &s->v29_rx); + set_rx_handler(t, (span_rx_handler_t *) &v29_rx, (span_rx_fillin_handler_t *) &v29_rx_fillin, &s->v29_rx); } else { @@ -232,13 +262,26 @@ static int v29_v21_rx(void *user_data, const int16_t amp[], int len) /* We have received something, and the fast modem has not trained. We must be receiving valid V.21 */ span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.29 + V.21 to V.21 (%.2fdBm0)\n", fsk_rx_signal_power(&s->v21_rx)); - set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, &s->v21_rx); + set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, (span_rx_fillin_handler_t *) &fsk_rx_fillin, &s->v21_rx); } } return 0; } /*- End of function --------------------------------------------------------*/ +static int v29_v21_rx_fillin(void *user_data, int len) +{ + fax_state_t *t; + fax_modems_state_t *s; + + t = (fax_state_t *) user_data; + s = &t->modems; + v29_rx_fillin(&s->v29_rx, len); + fsk_rx_fillin(&s->v21_rx, len); + return 0; +} +/*- End of function --------------------------------------------------------*/ + SPAN_DECLARE(int) fax_rx(fax_state_t *s, int16_t *amp, int len) { int i; @@ -276,26 +319,9 @@ SPAN_DECLARE(int) fax_rx_fillin(fax_state_t *s, int len) write(s->modems.audio_rx_log, amp, len*sizeof(int16_t)); } #endif - t30_timer_update(&s->t30, len); /* Call the fillin function of the current modem (if there is one). */ - switch (s->modems.current_rx_type) - { - case T30_MODEM_V21: - len = fsk_rx_fillin(&s->modems.v21_rx, len); - break; - case T30_MODEM_V27TER: - /* TODO: what about FSK in the early stages */ - len = v27ter_rx_fillin(&s->modems.v27ter_rx, len); - break; - case T30_MODEM_V29: - /* TODO: what about FSK in the early stages */ - len = v29_rx_fillin(&s->modems.v29_rx, len); - break; - case T30_MODEM_V17: - /* TODO: what about FSK in the early stages */ - len = v17_rx_fillin(&s->modems.v17_rx, len); - break; - } + s->modems.rx_fillin_handler(s->modems.rx_user_data, len); + t30_timer_update(&s->t30, len); return len; } /*- End of function --------------------------------------------------------*/ @@ -399,27 +425,27 @@ static void fax_set_rx_type(void *user_data, int type, int bit_rate, int short_t case T30_MODEM_V21: fsk_rx_init(&t->v21_rx, &preset_fsk_specs[FSK_V21CH2], TRUE, (put_bit_func_t) hdlc_rx_put_bit, put_bit_user_data); fsk_rx_signal_cutoff(&t->v21_rx, -45.5f); - set_rx_handler(s, (span_rx_handler_t *) &fsk_rx, &t->v21_rx); + set_rx_handler(s, (span_rx_handler_t *) &fsk_rx, (span_rx_fillin_handler_t *) &fsk_rx_fillin, &t->v21_rx); break; case T30_MODEM_V27TER: v27ter_rx_restart(&t->v27ter_rx, bit_rate, FALSE); v27ter_rx_set_put_bit(&t->v27ter_rx, put_bit_func, put_bit_user_data); - set_rx_handler(s, &v27ter_v21_rx, s); + set_rx_handler(s, &v27ter_v21_rx, &v27ter_v21_rx_fillin, s); break; case T30_MODEM_V29: v29_rx_restart(&t->v29_rx, bit_rate, FALSE); v29_rx_set_put_bit(&t->v29_rx, put_bit_func, put_bit_user_data); - set_rx_handler(s, &v29_v21_rx, s); + set_rx_handler(s, &v29_v21_rx, &v29_v21_rx_fillin, s); break; case T30_MODEM_V17: v17_rx_restart(&t->v17_rx, bit_rate, short_train); v17_rx_set_put_bit(&t->v17_rx, put_bit_func, put_bit_user_data); - set_rx_handler(s, &v17_v21_rx, s); + set_rx_handler(s, &v17_v21_rx, &v17_v21_rx_fillin, s); break; case T30_MODEM_DONE: span_log(&s->logging, SPAN_LOG_FLOW, "FAX exchange complete\n"); default: - set_rx_handler(s, (span_rx_handler_t *) &span_dummy_rx, s); + set_rx_handler(s, (span_rx_handler_t *) &span_dummy_rx, (span_rx_fillin_handler_t *) &span_dummy_rx_fillin, s); break; } } diff --git a/libs/spandsp/src/fax_modems.c b/libs/spandsp/src/fax_modems.c index 3ab3e3b151..740569e4e0 100644 --- a/libs/spandsp/src/fax_modems.c +++ b/libs/spandsp/src/fax_modems.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: fax_modems.c,v 1.5 2009/04/12 03:29:58 steveu Exp $ + * $Id: fax_modems.c,v 1.6 2009/09/04 14:38:46 steveu Exp $ */ /*! \file */ @@ -101,6 +101,7 @@ SPAN_DECLARE(int) fax_modems_v17_v21_rx(void *user_data, const int16_t amp[], in be receiving valid V.21 */ span_log(&s->logging, SPAN_LOG_FLOW, "Switching from V.17 + V.21 to V.21 (%.2fdBm0)\n", fsk_rx_signal_power(&s->v21_rx)); s->rx_handler = (span_rx_handler_t *) &fsk_rx; + s->rx_fillin_handler = (span_rx_fillin_handler_t *) &fsk_rx_fillin; s->rx_user_data = &s->v21_rx; } return 0; @@ -131,6 +132,7 @@ SPAN_DECLARE(int) fax_modems_v27ter_v21_rx(void *user_data, const int16_t amp[], be receiving valid V.21 */ span_log(&s->logging, SPAN_LOG_FLOW, "Switching from V.27ter + V.21 to V.21 (%.2fdBm0)\n", fsk_rx_signal_power(&s->v21_rx)); s->rx_handler = (span_rx_handler_t *) &fsk_rx; + s->rx_fillin_handler = (span_rx_fillin_handler_t *) &fsk_rx_fillin; s->rx_user_data = &s->v21_rx; } return 0; @@ -161,6 +163,7 @@ SPAN_DECLARE(int) fax_modems_v29_v21_rx(void *user_data, const int16_t amp[], in be receiving valid V.21 */ span_log(&s->logging, SPAN_LOG_FLOW, "Switching from V.29 + V.21 to V.21 (%.2fdBm0)\n", fsk_rx_signal_power(&s->v21_rx)); s->rx_handler = (span_rx_handler_t *) &fsk_rx; + s->rx_fillin_handler = (span_rx_fillin_handler_t *) &fsk_rx_fillin; s->rx_user_data = &s->v21_rx; } return 0; @@ -196,6 +199,7 @@ static void v17_rx_status_handler(void *user_data, int status) case SIG_STATUS_TRAINING_SUCCEEDED: span_log(&s->logging, SPAN_LOG_FLOW, "Switching to V.17 (%.2fdBm0)\n", v17_rx_signal_power(&s->v17_rx)); s->rx_handler = (span_rx_handler_t *) &v17_rx; + s->rx_fillin_handler = (span_rx_fillin_handler_t *) &v17_rx_fillin; s->rx_user_data = &s->v17_rx; break; } @@ -212,6 +216,7 @@ static void v27ter_rx_status_handler(void *user_data, int status) case SIG_STATUS_TRAINING_SUCCEEDED: span_log(&s->logging, SPAN_LOG_FLOW, "Switching to V.27ter (%.2fdBm0)\n", v27ter_rx_signal_power(&s->v27ter_rx)); s->rx_handler = (span_rx_handler_t *) &v27ter_rx; + s->rx_fillin_handler = (span_rx_fillin_handler_t *) &v27ter_rx_fillin; s->rx_user_data = &s->v27ter_rx; break; } @@ -228,6 +233,7 @@ static void v29_rx_status_handler(void *user_data, int status) case SIG_STATUS_TRAINING_SUCCEEDED: span_log(&s->logging, SPAN_LOG_FLOW, "Switching to V.29 (%.2fdBm0)\n", v29_rx_signal_power(&s->v29_rx)); s->rx_handler = (span_rx_handler_t *) &v29_rx; + s->rx_fillin_handler = (span_rx_fillin_handler_t *) &v29_rx_fillin; s->rx_user_data = &s->v29_rx; break; } @@ -300,6 +306,7 @@ SPAN_DECLARE(fax_modems_state_t *) fax_modems_init(fax_modems_state_t *s, s->rx_signal_present = FALSE; s->rx_handler = (span_rx_handler_t *) &span_dummy_rx; + s->rx_fillin_handler = (span_rx_fillin_handler_t *) &span_dummy_rx; s->rx_user_data = NULL; s->tx_handler = (span_tx_handler_t *) &silence_gen; s->tx_user_data = &s->silence_gen; diff --git a/libs/spandsp/src/libspandsp.2005.vcproj b/libs/spandsp/src/libspandsp.2005.vcproj index 5479159aab..453f519b61 100644 --- a/libs/spandsp/src/libspandsp.2005.vcproj +++ b/libs/spandsp/src/libspandsp.2005.vcproj @@ -142,6 +142,7 @@ + @@ -219,6 +220,7 @@ + @@ -257,6 +259,7 @@ + @@ -269,6 +272,7 @@ + @@ -277,6 +281,7 @@ + diff --git a/libs/spandsp/src/libspandsp.2008.vcproj b/libs/spandsp/src/libspandsp.2008.vcproj index 8b18789579..c0bb6f77e9 100644 --- a/libs/spandsp/src/libspandsp.2008.vcproj +++ b/libs/spandsp/src/libspandsp.2008.vcproj @@ -212,6 +212,7 @@ + @@ -289,6 +290,7 @@ + @@ -327,6 +329,7 @@ + @@ -339,6 +342,7 @@ + @@ -347,6 +351,7 @@ + diff --git a/libs/spandsp/src/libspandsp.dsp b/libs/spandsp/src/libspandsp.dsp index 6c062168bb..96f955ebf4 100644 --- a/libs/spandsp/src/libspandsp.dsp +++ b/libs/spandsp/src/libspandsp.dsp @@ -293,6 +293,10 @@ SOURCE=.\super_tone_tx.c # End Source File # Begin Source File +SOURCE=.\swept_tone.c +# End Source File +# Begin Source File + SOURCE=.\t4.c # End Source File # Begin Source File @@ -599,6 +603,10 @@ SOURCE=.\spandsp/super_tone_tx.h # End Source File # Begin Source File +SOURCE=.\spandsp/swept_tone.h +# End Source File +# Begin Source File + SOURCE=.\spandsp/t4.h # End Source File # Begin Source File @@ -751,6 +759,10 @@ SOURCE=.\spandsp/private/dtmf.h # End Source File # Begin Source File +SOURCE=.\spandsp/private/echo.h +# End Source File +# Begin Source File + SOURCE=.\spandsp/private/fax.h # End Source File # Begin Source File @@ -799,6 +811,10 @@ SOURCE=.\spandsp/private/modem_connect_tones.h # End Source File # Begin Source File +SOURCE=.\spandsp/private/modem_echo.h +# End Source File +# Begin Source File + SOURCE=.\spandsp/private/noise.h # End Source File # Begin Source File @@ -831,6 +847,10 @@ SOURCE=.\spandsp/private/super_tone_tx.h # End Source File # Begin Source File +SOURCE=.\spandsp/private/swept_tone.h +# End Source File +# Begin Source File + SOURCE=.\spandsp/private/t30.h # 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 ce659b30c3..b158f413c8 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.16 2009/07/10 13:15:56 steveu Exp $ + * $Id: make_modem_filter.c,v 1.17 2009/10/03 04:37:25 steveu Exp $ */ #if defined(HAVE_CONFIG_H) @@ -44,7 +44,7 @@ #include #include #include -#if defined(__sunos) || defined(__solaris) || defined(__sun) +#if defined(__sunos) || defined(__solaris) || defined(__sun) #include #endif diff --git a/libs/spandsp/src/modem_echo.c b/libs/spandsp/src/modem_echo.c index 8ed03c983b..c31d4cba31 100644 --- a/libs/spandsp/src/modem_echo.c +++ b/libs/spandsp/src/modem_echo.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: modem_echo.c,v 1.25 2009/02/03 16:28:39 steveu Exp $ + * $Id: modem_echo.c,v 1.26 2009/09/22 13:11:04 steveu Exp $ */ /*! \file */ @@ -53,6 +53,8 @@ #include "spandsp/dc_restore.h" #include "spandsp/modem_echo.h" +#include "spandsp/private/modem_echo.h" + SPAN_DECLARE(modem_echo_can_state_t *) modem_echo_can_create(int len) { modem_echo_can_state_t *ec; diff --git a/libs/spandsp/src/msvc/spandsp.h b/libs/spandsp/src/msvc/spandsp.h index 81b74f172f..25f705f5ab 100644 --- a/libs/spandsp/src/msvc/spandsp.h +++ b/libs/spandsp/src/msvc/spandsp.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: spandsp.h.in,v 1.18 2009/04/02 13:43:49 steveu Exp $ + * $Id: spandsp.h.in,v 1.19 2009/09/22 13:11:04 steveu Exp $ */ /*! \file */ @@ -69,6 +69,7 @@ #include #include #include +#include #include #include #include diff --git a/libs/spandsp/src/sig_tone.c b/libs/spandsp/src/sig_tone.c index dea3ed79f3..0183dadedb 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.32 2009/04/12 14:18:02 steveu Exp $ + * $Id: sig_tone.c,v 1.33 2009/09/04 14:38:46 steveu Exp $ */ /*! \file */ @@ -44,14 +44,17 @@ #include "floating_fudge.h" #include #include +#include #undef SPANDSP_USE_FIXED_POINT #include "spandsp/telephony.h" #include "spandsp/fast_convert.h" #include "spandsp/dc_restore.h" #include "spandsp/saturated.h" +#include "spandsp/vector_int.h" #include "spandsp/complex.h" #include "spandsp/dds.h" +#include "spandsp/super_tone_rx.h" #include "spandsp/sig_tone.h" #include "spandsp/private/sig_tone.h" @@ -67,12 +70,12 @@ sig_tone_descriptor_t sig_tones[4] = { /* 2280Hz (e.g. AC15, and many other European protocols) */ {2280, 0}, - {-10, -20}, /* -10+-1 dBmO and -20+-1 dBm0 */ - 400*(SAMPLE_RATE/1000), /* 300ms to 550ms */ + {{-10, -20}, {0, 0}}, /* -10+-1 dBmO and -20+-1 dBm0 */ + ms_to_samples(400), /* 300ms to 550ms */ - 225*(SAMPLE_RATE/1000), + ms_to_samples(225), - 225*(SAMPLE_RATE/1000), + ms_to_samples(225), TRUE, 24, @@ -135,12 +138,12 @@ sig_tone_descriptor_t sig_tones[4] = { /* 2600Hz (e.g. many US protocols) */ {2600, 0}, - {-8, -8}, - 400*(SAMPLE_RATE/1000), + {{-8, -8}, {0, 0}}, + ms_to_samples(400), - 225*(SAMPLE_RATE/1000), + ms_to_samples(225), - 225*(SAMPLE_RATE/1000), + ms_to_samples(225), FALSE, 24, @@ -202,13 +205,13 @@ sig_tone_descriptor_t sig_tones[4] = }, { /* 2400Hz/2600Hz (e.g. SS5 and SS5bis) */ - {2400, 2600}, - {-8, -8}, - 400*(SAMPLE_RATE/1000), + {2600, 2400}, + {{-8, -8}, {-8, -8}}, + ms_to_samples(400), - 225*(SAMPLE_RATE/1000), + ms_to_samples(225), - 225*(SAMPLE_RATE/1000), + ms_to_samples(225), FALSE, 24, @@ -276,19 +279,40 @@ SPAN_DECLARE(int) sig_tone_tx(sig_tone_tx_state_t *s, int16_t amp[], int len) int j; int n; int16_t tone; - int update; + int need_update; int high_low; for (i = 0; i < len; i += n) { - if (s->current_tx_timeout < len - i) - n = s->current_tx_timeout; + if (s->current_tx_timeout) + { + if (s->current_tx_timeout <= len - i) + { + n = s->current_tx_timeout; + need_update = TRUE; + } + else + { + n = len - i; + need_update = FALSE; + } + s->current_tx_timeout -= n; + } else + { n = len - i; + need_update = FALSE; + } + if (!(s->current_tx_tone & SIG_TONE_TX_PASSTHROUGH)) + vec_zeroi16(&[i], n); + /*endif*/ if ((s->current_tx_tone & (SIG_TONE_1_PRESENT || SIG_TONE_2_PRESENT))) { /* Are we in the early phase (high tone energy level), or the sustaining phase (low tone energy level) of tone generation? */ + /* This doesn't try to get the high/low timing precise, as there is no + value in doing so. It works block by block, and the blocks are normally + quite short. */ if (s->high_low_timer > 0) { if (n > s->high_low_timer) @@ -301,47 +325,30 @@ SPAN_DECLARE(int) sig_tone_tx(sig_tone_tx_state_t *s, int16_t amp[], int len) high_low = 1; } /*endif*/ - if (s->current_tx_tone & SIG_TONE_TX_PASSTHROUGH) + if ((s->current_tx_tone & SIG_TONE_1_PRESENT) && s->phase_rate[0]) { for (j = i; j < i + n; j++) { - tone = dds_mod(&(s->phase_acc[0]), s->phase_rate[0], s->tone_scaling[high_low], 0); + tone = dds_mod(&(s->phase_acc[0]), s->phase_rate[0], s->tone_scaling[0][high_low], 0); amp[j] = saturate(amp[j] + tone); } /*endfor*/ } - else + /*endif*/ + if ((s->current_tx_tone & SIG_TONE_2_PRESENT) && s->phase_rate[1]) { for (j = i; j < i + n; j++) - amp[j] = dds_mod(&(s->phase_acc[0]), s->phase_rate[0], s->tone_scaling[high_low], 0); + { + tone = dds_mod(&(s->phase_acc[1]), s->phase_rate[1], s->tone_scaling[1][high_low], 0); + amp[j] = saturate(amp[j] + tone); + } /*endfor*/ } /*endif*/ } - else - { - /* There is no tone. We either leave the audio in the buffer, or silence it. */ - if (!(s->current_tx_tone & SIG_TONE_TX_PASSTHROUGH)) - { - /* Zap any audio in the buffer */ - memset(amp + i, 0, sizeof(int16_t)*n); - } - /*endif*/ - } /*endif*/ - if ((s->current_tx_timeout -= n) <= 0) - { - if (s->sig_update) - { - update = s->sig_update(s->user_data, SIG_TONE_UPDATE_REQUEST); - if ((update & 0x03) == 0x03) - s->high_low_timer = s->desc->high_low_timeout; - /*endif*/ - s->current_tx_tone = update & 0xFFFF; - s->current_tx_timeout = (update >> 16) & 0xFFFF; - } - /*endif*/ - } + if (need_update && s->sig_update) + s->sig_update(s->user_data, SIG_TONE_TX_UPDATE_REQUEST, 0, 0); /*endif*/ } /*endfor*/ @@ -349,17 +356,22 @@ SPAN_DECLARE(int) sig_tone_tx(sig_tone_tx_state_t *s, int16_t amp[], int len) } /*- End of function --------------------------------------------------------*/ -SPAN_DECLARE(void) sig_tone_tx_set_mode(sig_tone_tx_state_t *s, int mode) +SPAN_DECLARE(void) sig_tone_tx_set_mode(sig_tone_tx_state_t *s, int mode, int duration) { - if ((mode & 0x03) == 0x03 && !(s->current_tx_tone & SIG_TONE_1_PRESENT)) + int old_tones; + int new_tones; + + old_tones = s->current_tx_tone & (SIG_TONE_1_PRESENT | SIG_TONE_2_PRESENT); + new_tones = mode & (SIG_TONE_1_PRESENT | SIG_TONE_2_PRESENT); + if (new_tones && old_tones != new_tones) s->high_low_timer = s->desc->high_low_timeout; /*endif*/ - s->current_tx_tone = mode & 0xFFFF; - s->current_tx_timeout = (mode >> 16) & 0xFFFF; + s->current_tx_tone = mode; + s->current_tx_timeout = duration; } /*- End of function --------------------------------------------------------*/ -SPAN_DECLARE(sig_tone_tx_state_t *) sig_tone_tx_init(sig_tone_tx_state_t *s, int tone_type, sig_tone_func_t sig_update, void *user_data) +SPAN_DECLARE(sig_tone_tx_state_t *) sig_tone_tx_init(sig_tone_tx_state_t *s, int tone_type, tone_report_func_t sig_update, void *user_data) { int i; @@ -385,7 +397,8 @@ SPAN_DECLARE(sig_tone_tx_state_t *) sig_tone_tx_init(sig_tone_tx_state_t *s, int s->phase_rate[i] = dds_phase_rate((float) s->desc->tone_freq[i]); else s->phase_rate[i] = 0; - s->tone_scaling[i] = dds_scaling_dbm0((float) s->desc->tone_amp[i]); + s->tone_scaling[i][0] = dds_scaling_dbm0((float) s->desc->tone_amp[i][0]); + s->tone_scaling[i][1] = dds_scaling_dbm0((float) s->desc->tone_amp[i][1]); } return s; } @@ -404,6 +417,7 @@ SPAN_DECLARE(int) sig_tone_tx_free(sig_tone_tx_state_t *s) return 0; } /*- End of function --------------------------------------------------------*/ + SPAN_DECLARE(int) sig_tone_rx(sig_tone_rx_state_t *s, int16_t amp[], int len) { #if defined(SPANDSP_USE_FIXED_POINT) @@ -422,7 +436,7 @@ SPAN_DECLARE(int) sig_tone_rx(sig_tone_rx_state_t *s, int16_t amp[], int len) for (i = 0; i < len; i++) { - if (s->signaling_state_duration < 0xFFFF) + if (s->signaling_state_duration < INT_MAX) s->signaling_state_duration++; /*endif*/ notched_signal = 0; @@ -529,7 +543,7 @@ SPAN_DECLARE(int) sig_tone_rx(sig_tone_rx_state_t *s, int16_t amp[], int len) if (!s->tone_present) { if (s->sig_update) - s->sig_update(s->user_data, SIG_TONE_1_CHANGE | (s->signaling_state_duration << 16)); + s->sig_update(s->user_data, SIG_TONE_1_CHANGE, 0, s->signaling_state_duration); /*endif*/ s->signaling_state_duration = 0; } @@ -541,15 +555,15 @@ SPAN_DECLARE(int) sig_tone_rx(sig_tone_rx_state_t *s, int16_t amp[], int len) if (s->tone_present) { if (s->sig_update) - s->sig_update(s->user_data, SIG_TONE_1_CHANGE | SIG_TONE_1_PRESENT | (s->signaling_state_duration << 16)); + s->sig_update(s->user_data, SIG_TONE_1_CHANGE | SIG_TONE_1_PRESENT, 0, s->signaling_state_duration); /*endif*/ s->signaling_state_duration = 0; } /*endif*/ } /*endif*/ - /* Notch insertion logic */ - + + /* Notch insertion logic */ /* tone_present and tone_on are equivalent in flat mode */ if (s->tone_present) { @@ -590,7 +604,7 @@ SPAN_DECLARE(int) sig_tone_rx(sig_tone_rx_state_t *s, int16_t amp[], int len) s->tone_persistence_timeout = s->desc->tone_off_check_time; s->notch_insertion_timeout = s->desc->notch_lag_time; if (s->sig_update) - s->sig_update(s->user_data, SIG_TONE_1_CHANGE | SIG_TONE_1_PRESENT | (s->signaling_state_duration << 16)); + s->sig_update(s->user_data, SIG_TONE_1_CHANGE | SIG_TONE_1_PRESENT, 0, s->signaling_state_duration); /*endif*/ s->signaling_state_duration = 0; } @@ -626,7 +640,7 @@ SPAN_DECLARE(int) sig_tone_rx(sig_tone_rx_state_t *s, int16_t amp[], int len) s->tone_present = FALSE; s->tone_persistence_timeout = s->desc->tone_on_check_time; if (s->sig_update) - s->sig_update(s->user_data, SIG_TONE_1_CHANGE | (s->signaling_state_duration << 16)); + s->sig_update(s->user_data, SIG_TONE_1_CHANGE, 0, s->signaling_state_duration); /*endif*/ s->signaling_state_duration = 0; } @@ -648,7 +662,7 @@ SPAN_DECLARE(int) sig_tone_rx(sig_tone_rx_state_t *s, int16_t amp[], int len) if ((s->current_rx_tone & SIG_TONE_RX_PASSTHROUGH)) { - if (s->notch_enabled) + if ((s->current_rx_tone & SIG_TONE_RX_FILTER_TONE) || s->notch_enabled) amp[i] = (int16_t) notched_signal; /*endif*/ } @@ -663,7 +677,13 @@ SPAN_DECLARE(int) sig_tone_rx(sig_tone_rx_state_t *s, int16_t amp[], int len) } /*- End of function --------------------------------------------------------*/ -SPAN_DECLARE(sig_tone_rx_state_t *) sig_tone_rx_init(sig_tone_rx_state_t *s, int tone_type, sig_tone_func_t sig_update, void *user_data) +SPAN_DECLARE(void) sig_tone_rx_set_mode(sig_tone_rx_state_t *s, int mode, int duration) +{ + s->current_rx_tone = mode; +} +/*- End of function --------------------------------------------------------*/ + +SPAN_DECLARE(sig_tone_rx_state_t *) sig_tone_rx_init(sig_tone_rx_state_t *s, int tone_type, tone_report_func_t sig_update, void *user_data) { if (sig_update == NULL || tone_type < 1 || tone_type > 3) return NULL; diff --git a/libs/spandsp/src/silence_gen.c b/libs/spandsp/src/silence_gen.c index fa6529021a..4998f8bc0e 100644 --- a/libs/spandsp/src/silence_gen.c +++ b/libs/spandsp/src/silence_gen.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: silence_gen.c,v 1.22 2009/06/02 16:03:56 steveu Exp $ + * $Id: silence_gen.c,v 1.23 2009/09/04 14:38:46 steveu Exp $ */ /*! \file */ @@ -158,4 +158,10 @@ SPAN_DECLARE(int) span_dummy_mod(void *user_data, int16_t amp[], int len) return len; } /*- End of function --------------------------------------------------------*/ + +SPAN_DECLARE_NONSTD(int) span_dummy_rx_fillin(void *user_data, int len) +{ + return 0; +} +/*- End of function --------------------------------------------------------*/ /*- End of file ------------------------------------------------------------*/ diff --git a/libs/spandsp/src/spandsp.h.in b/libs/spandsp/src/spandsp.h.in index f5b7b0fe88..59122b654f 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.18 2009/04/02 13:43:49 steveu Exp $ + * $Id: spandsp.h.in,v 1.19 2009/09/22 13:11:04 steveu Exp $ */ /*! \file */ @@ -66,6 +66,7 @@ #include #include #include +#include #include #include #include diff --git a/libs/spandsp/src/spandsp/echo.h b/libs/spandsp/src/spandsp/echo.h index eb423dd0f7..b476909181 100644 --- a/libs/spandsp/src/spandsp/echo.h +++ b/libs/spandsp/src/spandsp/echo.h @@ -24,7 +24,7 @@ * License along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Id: echo.h,v 1.19 2009/02/10 13:06:47 steveu Exp $ + * $Id: echo.h,v 1.20 2009/09/22 13:11:04 steveu Exp $ */ /*! \file */ @@ -133,59 +133,7 @@ enum G.168 echo canceller descriptor. This defines the working state for a line echo canceller. */ -typedef struct -{ - int tx_power[4]; - int rx_power[3]; - int clean_rx_power; - - int rx_power_threshold; - int nonupdate_dwell; - - int curr_pos; - - int taps; - int tap_mask; - int adaption_mode; - - int32_t supp_test1; - int32_t supp_test2; - int32_t supp1; - int32_t supp2; - int vad; - int cng; - - int16_t geigel_max; - int geigel_lag; - int dtd_onset; - int tap_set; - int tap_rotate_counter; - - int32_t latest_correction; /* Indication of the magnitude of the latest - adaption, or a code to indicate why adaption - was skipped, for test purposes */ - int32_t last_acf[28]; - int narrowband_count; - int narrowband_score; - - fir16_state_t fir_state; - /*! Echo FIR taps (16 bit version) */ - int16_t *fir_taps16[4]; - /*! Echo FIR taps (32 bit version) */ - int32_t *fir_taps32; - - /* DC and near DC blocking filter states */ - int32_t tx_hpf[2]; - int32_t rx_hpf[2]; - - /* Parameters for the optional Hoth noise generator */ - int cng_level; - int cng_rndnum; - int cng_filter; - - /* Snapshot sample of coeffs used for development */ - int16_t *snapshot; -} echo_can_state_t; +typedef struct echo_can_state_s echo_can_state_t; #if defined(__cplusplus) extern "C" diff --git a/libs/spandsp/src/spandsp/expose.h b/libs/spandsp/src/spandsp/expose.h index 25b671827c..44a3c5c7b5 100644 --- a/libs/spandsp/src/spandsp/expose.h +++ b/libs/spandsp/src/spandsp/expose.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: expose.h,v 1.13 2009/05/16 03:34:45 steveu Exp $ + * $Id: expose.h,v 1.14 2009/09/22 13:11:04 steveu Exp $ */ /*! \file */ @@ -56,6 +56,9 @@ #include #include #include +#include +#include +#include #include #include #include diff --git a/libs/spandsp/src/spandsp/fast_convert.h b/libs/spandsp/src/spandsp/fast_convert.h index 1620042c2a..ccf275aaf3 100644 --- a/libs/spandsp/src/spandsp/fast_convert.h +++ b/libs/spandsp/src/spandsp/fast_convert.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: fast_convert.h,v 1.8 2009/07/10 13:15:56 steveu Exp $ + * $Id: fast_convert.h,v 1.9 2009/10/03 04:37:25 steveu Exp $ */ #if !defined(_SPANDSP_FAST_CONVERT_H_) @@ -150,7 +150,7 @@ extern "C" ); return retval; } -#elif defined(__GNUC__) || (__SUNPRO_C >= 0x0590) +#elif defined(__GNUC__) || (__SUNPRO_C >= 0x0590) #if defined(__i386__) /* These routines are guaranteed fast on an i386 machine. Using the built in @@ -403,7 +403,7 @@ extern "C" the accuracy issues related to changing the rounding scheme are of little concern to us. */ - #if !defined(__sgi) && !defined(__sunos) && !defined(__solaris) && !defined(__sun) + #if !defined(__sgi) && !defined(__sunos) && !defined(__solaris) && !defined(__sun) #warning "No usable lrint() and lrintf() functions available." #warning "Replacing these functions with a simple C cast." #endif diff --git a/libs/spandsp/src/spandsp/modem_echo.h b/libs/spandsp/src/spandsp/modem_echo.h index cc9f06e45e..77ffe6b535 100644 --- a/libs/spandsp/src/spandsp/modem_echo.h +++ b/libs/spandsp/src/spandsp/modem_echo.h @@ -25,7 +25,7 @@ * License along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Id: modem_echo.h,v 1.13 2009/02/03 16:28:41 steveu Exp $ + * $Id: modem_echo.h,v 1.14 2009/09/22 13:11:04 steveu Exp $ */ /*! \file */ @@ -84,22 +84,7 @@ minor burden. Modem line echo canceller descriptor. This defines the working state for a line echo canceller. */ -typedef struct -{ - int adapt; - int taps; - - fir16_state_t fir_state; - /*! Echo FIR taps (16 bit version) */ - int16_t *fir_taps16; - /*! Echo FIR taps (32 bit version) */ - int32_t *fir_taps32; - - int tx_power; - int rx_power; - - int curr_pos; -} modem_echo_can_state_t; +typedef struct modem_echo_can_state_s modem_echo_can_state_t; #if defined(__cplusplus) extern "C" diff --git a/libs/spandsp/src/spandsp/private/echo.h b/libs/spandsp/src/spandsp/private/echo.h new file mode 100644 index 0000000000..4a91798315 --- /dev/null +++ b/libs/spandsp/src/spandsp/private/echo.h @@ -0,0 +1,94 @@ +/* + * SpanDSP - a series of DSP components for telephony + * + * private/echo.h - An echo cancellor, suitable for electrical and acoustic + * cancellation. This code does not currently comply with + * any relevant standards (e.g. G.164/5/7/8). + * + * Written by Steve Underwood + * + * Copyright (C) 2001 Steve Underwood + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 2.1, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * $Id: echo.h,v 1.1 2009/09/22 13:11:04 steveu Exp $ + */ + +/*! \file */ + +#if !defined(_SPANDSP_PRIVATE_ECHO_H_) +#define _SPANDSP_PRIVATE_ECHO_H_ + +/*! + G.168 echo canceller descriptor. This defines the working state for a line + echo canceller. +*/ +struct echo_can_state_s +{ + int tx_power[4]; + int rx_power[3]; + int clean_rx_power; + + int rx_power_threshold; + int nonupdate_dwell; + + int curr_pos; + + int taps; + int tap_mask; + int adaption_mode; + + int32_t supp_test1; + int32_t supp_test2; + int32_t supp1; + int32_t supp2; + int vad; + int cng; + + int16_t geigel_max; + int geigel_lag; + int dtd_onset; + int tap_set; + int tap_rotate_counter; + + int32_t latest_correction; /* Indication of the magnitude of the latest + adaption, or a code to indicate why adaption + was skipped, for test purposes */ + int32_t last_acf[28]; + int narrowband_count; + int narrowband_score; + + fir16_state_t fir_state; + /*! Echo FIR taps (16 bit version) */ + int16_t *fir_taps16[4]; + /*! Echo FIR taps (32 bit version) */ + int32_t *fir_taps32; + + /* DC and near DC blocking filter states */ + int32_t tx_hpf[2]; + int32_t rx_hpf[2]; + + /* Parameters for the optional Hoth noise generator */ + int cng_level; + int cng_rndnum; + int cng_filter; + + /* Snapshot sample of coeffs used for development */ + int16_t *snapshot; +}; + +#endif +/*- End of file ------------------------------------------------------------*/ diff --git a/libs/spandsp/src/spandsp/private/fax_modems.h b/libs/spandsp/src/spandsp/private/fax_modems.h index 1eec1c9bbc..a46749c0cf 100644 --- a/libs/spandsp/src/spandsp/private/fax_modems.h +++ b/libs/spandsp/src/spandsp/private/fax_modems.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: fax_modems.h,v 1.3 2009/03/23 14:17:42 steveu Exp $ + * $Id: fax_modems.h,v 1.4 2009/09/04 14:38:47 steveu Exp $ */ /*! \file */ @@ -95,11 +95,9 @@ struct fax_modems_state_s /*! The current receive signal handler */ span_rx_handler_t *rx_handler; - void *rx_user_data; - /*! The current receive missing signal fill-in handler */ span_rx_fillin_handler_t *rx_fillin_handler; - void *rx_fillin_user_data; + void *rx_user_data; /*! The current transmit signal handler */ span_tx_handler_t *tx_handler; diff --git a/libs/spandsp/src/spandsp/private/modem_echo.h b/libs/spandsp/src/spandsp/private/modem_echo.h new file mode 100644 index 0000000000..082cb8d569 --- /dev/null +++ b/libs/spandsp/src/spandsp/private/modem_echo.h @@ -0,0 +1,58 @@ +/* + * SpanDSP - a series of DSP components for telephony + * + * private/modem_echo.h - An echo cancellor, suitable for electrical echos in GSTN modems + * + * Written by Steve Underwood + * + * Copyright (C) 2001, 2004 Steve Underwood + * + * Based on a bit from here, a bit from there, eye of toad, + * ear of bat, etc - plus, of course, my own 2 cents. + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 2.1, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * $Id: modem_echo.h,v 1.1 2009/09/22 13:11:04 steveu Exp $ + */ + +/*! \file */ + +#if !defined(_SPANDSP_PRIVATE_MODEM_ECHO_H_) +#define _SPANDSP_PRIVATE_MODEM_ECHO_H_ + +/*! + Modem line echo canceller descriptor. This defines the working state for a line + echo canceller. +*/ +struct modem_echo_can_state_s +{ + int adapt; + int taps; + + fir16_state_t fir_state; + /*! Echo FIR taps (16 bit version) */ + int16_t *fir_taps16; + /*! Echo FIR taps (32 bit version) */ + int32_t *fir_taps32; + + int tx_power; + int rx_power; + + int curr_pos; +}; + +#endif +/*- End of file ------------------------------------------------------------*/ diff --git a/libs/spandsp/src/spandsp/private/sig_tone.h b/libs/spandsp/src/spandsp/private/sig_tone.h index a98c8b16b4..edf7a68bb7 100644 --- a/libs/spandsp/src/spandsp/private/sig_tone.h +++ b/libs/spandsp/src/spandsp/private/sig_tone.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: sig_tone.h,v 1.3 2009/04/12 14:18:02 steveu Exp $ + * $Id: sig_tone.h,v 1.4 2009/09/04 14:38:47 steveu Exp $ */ #if !defined(_SPANDSP_PRIVATE_SIG_TONE_H_) @@ -38,8 +38,8 @@ struct sig_tone_descriptor_s { /*! \brief The tones used. */ int tone_freq[2]; - /*! \brief The high and low tone amplitudes. */ - int tone_amp[2]; + /*! \brief The high and low tone amplitudes for each of the tones. */ + int tone_amp[2][2]; /*! \brief The delay, in audio samples, before the high level tone drops to a low level tone. */ @@ -80,7 +80,6 @@ struct sig_tone_descriptor_s #endif } tone[2]; - #if defined(SPANDSP_USE_FIXED_POINT) /*! \brief Flat mode bandpass bi-quad parameters */ int32_t broad_a[3]; @@ -128,23 +127,23 @@ struct sig_tone_descriptor_s struct sig_tone_tx_state_s { /*! \brief The callback function used to handle signaling changes. */ - sig_tone_func_t sig_update; + tone_report_func_t sig_update; /*! \brief A user specified opaque pointer passed to the callback function. */ void *user_data; /*! \brief Tone descriptor */ sig_tone_descriptor_t *desc; - /*! The scaling values for the high and low level tones */ - int16_t tone_scaling[2]; - /*! The sample timer, used to switch between the high and low level tones. */ - int high_low_timer; - /*! The phase rates for the one or two tones */ int32_t phase_rate[2]; /*! The phase accumulators for the one or two tones */ uint32_t phase_acc[2]; + /*! The scaling values for the one or two tones, and the high and low level of each tone */ + int16_t tone_scaling[2][2]; + /*! The sample timer, used to switch between the high and low level tones. */ + int high_low_timer; + /*! \brief Current transmit tone */ int current_tx_tone; /*! \brief Current transmit timeout */ @@ -159,7 +158,7 @@ struct sig_tone_tx_state_s struct sig_tone_rx_state_s { /*! \brief The callback function used to handle signaling changes. */ - sig_tone_func_t sig_update; + tone_report_func_t sig_update; /*! \brief A user specified opaque pointer passed to the callback function. */ void *user_data; diff --git a/libs/spandsp/src/spandsp/private/swept_tone.h b/libs/spandsp/src/spandsp/private/swept_tone.h new file mode 100644 index 0000000000..ce8e5a634e --- /dev/null +++ b/libs/spandsp/src/spandsp/private/swept_tone.h @@ -0,0 +1,44 @@ +/* + * SpanDSP - a series of DSP components for telephony + * + * private/swept_tone.h - Swept tone generation + * + * Written by Steve Underwood + * + * Copyright (C) 2009 Steve Underwood + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * $Id: swept_tone.h,v 1.1 2009/09/22 12:54:33 steveu Exp $ + */ + +#if !defined(_SPANDSP_PRIVATE_SWEPT_TONE_H_) +#define _SPANDSP_PRIVATE_SWEPT_TONE_H_ + +struct swept_tone_state_s +{ + int32_t starting_phase_inc; + int32_t phase_inc_step; + int scale; + int duration; + int repeating; + int pos; + int32_t current_phase_inc; + uint32_t phase; +}; + +#endif +/*- End of file ------------------------------------------------------------*/ diff --git a/libs/spandsp/src/spandsp/private/t30.h b/libs/spandsp/src/spandsp/private/t30.h index 00dbeabff0..958a553c89 100644 --- a/libs/spandsp/src/spandsp/private/t30.h +++ b/libs/spandsp/src/spandsp/private/t30.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: t30.h,v 1.4 2009/04/12 14:18:02 steveu Exp $ + * $Id: t30.h,v 1.5 2009/09/20 13:42:29 steveu Exp $ */ /*! \file */ @@ -221,10 +221,10 @@ struct t30_state_s /*! \brief A bit map of the OK ECM frames, constructed as a PPR frame. */ uint8_t ecm_frame_map[3 + 32]; - /*! \brief The current page number for receiving, in ECM mode. This is reset at the start of a call. */ - int ecm_rx_page; - /*! \brief The current page number for sending, in ECM mode. This is reset at the start of a call. */ - int ecm_tx_page; + /*! \brief The current page number for receiving, in ECM or non-ECM mode. This is reset at the start of a call. */ + int rx_page_number; + /*! \brief The current page number for sending, in ECM or non-ECM mode. This is reset at the start of a call. */ + int tx_page_number; /*! \brief The current block number, in ECM mode */ int ecm_block; /*! \brief The number of frames in the current block number, in ECM mode */ diff --git a/libs/spandsp/src/spandsp/sig_tone.h b/libs/spandsp/src/spandsp/sig_tone.h index eecbfdd438..64bcd6f422 100644 --- a/libs/spandsp/src/spandsp/sig_tone.h +++ b/libs/spandsp/src/spandsp/sig_tone.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: sig_tone.h,v 1.19 2009/04/12 14:18:02 steveu Exp $ + * $Id: sig_tone.h,v 1.20 2009/09/04 14:38:46 steveu Exp $ */ /*! \file */ @@ -54,32 +54,39 @@ least supervisory information may be heard. #if !defined(_SPANDSP_SIG_TONE_H_) #define _SPANDSP_SIG_TONE_H_ -typedef int (*sig_tone_func_t)(void *user_data, int what); - /* The optional tone sets */ enum { - /*! European 2280Hz signaling tone */ + /*! European 2280Hz signaling tone. Tone 1 is 2280Hz. Tone 2 is not used. */ SIG_TONE_2280HZ = 1, - /*! US 2600Hz signaling tone */ + /*! US 2600Hz signaling tone. Tone 1 is 2600Hz. Tone 2 is not used. */ SIG_TONE_2600HZ, - /*! US 2400Hz + 2600Hz signaling tones */ + /*! US 2400Hz + 2600Hz signaling tones. Tone 1 is 2600Hz. Tone 2 is 2400Hz. */ SIG_TONE_2400HZ_2600HZ }; +/* Mode control and report bits for transmit and receive */ enum { /*! Signaling tone 1 is present */ SIG_TONE_1_PRESENT = 0x001, + /*! Signaling tone 1 has changed state (ignored when setting tx mode) */ SIG_TONE_1_CHANGE = 0x002, /*! Signaling tone 2 is present */ SIG_TONE_2_PRESENT = 0x004, + /*! Signaling tone 2 has changed state (ignored when setting tx mode) */ SIG_TONE_2_CHANGE = 0x008, /*! The media signal is passing through. Tones might be added to it. */ SIG_TONE_TX_PASSTHROUGH = 0x010, /*! The media signal is passing through. Tones might be extracted from it, if detected. */ - SIG_TONE_RX_PASSTHROUGH = 0x020, - SIG_TONE_UPDATE_REQUEST = 0x100 + SIG_TONE_RX_PASSTHROUGH = 0x040, + /*! Force filtering of the signaling tone, whether signaling is being detected or not. + This is mostly useful for test purposes. */ + SIG_TONE_RX_FILTER_TONE = 0x080, + /*! Request an update of the transmit status, upon timeout of the previous status. */ + SIG_TONE_TX_UPDATE_REQUEST = 0x100, + /*! Request an update of the receiver status, upon timeout of the previous status. */ + SIG_TONE_RX_UPDATE_REQUEST = 0x200 }; /*! @@ -106,6 +113,14 @@ extern "C" \return The number of samples unprocessed. */ SPAN_DECLARE(int) sig_tone_rx(sig_tone_rx_state_t *s, int16_t amp[], int len); +/*! Set the receive mode. + \brief Set the receive mode. + \param s The signaling tone context. + \param mode The new mode for the receiver. + \param duration The duration for this mode, before an update is requested. + A duration of zero means forever. */ +SPAN_DECLARE(void) sig_tone_rx_set_mode(sig_tone_rx_state_t *s, int mode, int duration); + /*! Initialise a signaling tone receiver context. \brief Initialise a signaling tone context. \param s The signaling tone context. @@ -113,7 +128,7 @@ SPAN_DECLARE(int) sig_tone_rx(sig_tone_rx_state_t *s, int16_t amp[], int len); \param sig_update Callback function to handle signaling updates. \param user_data An opaque pointer. \return A pointer to the signalling tone context, or NULL if there was a problem. */ -SPAN_DECLARE(sig_tone_rx_state_t *) sig_tone_rx_init(sig_tone_rx_state_t *s, int tone_type, sig_tone_func_t sig_update, void *user_data); +SPAN_DECLARE(sig_tone_rx_state_t *) sig_tone_rx_init(sig_tone_rx_state_t *s, int tone_type, tone_report_func_t sig_update, void *user_data); /*! Release a signaling tone receiver context. \brief Release a signaling tone receiver context. @@ -138,8 +153,10 @@ SPAN_DECLARE(int) sig_tone_tx(sig_tone_tx_state_t *s, int16_t amp[], int len); /*! Set the tone mode. \brief Set the tone mode. \param s The signaling tone context. - \param mode The new mode for the transmitted tones. */ -SPAN_DECLARE(void) sig_tone_tx_set_mode(sig_tone_tx_state_t *s, int mode); + \param mode The new mode for the transmitted tones. + \param duration The duration for this mode, before an update is requested. + A duration of zero means forever. */ +SPAN_DECLARE(void) sig_tone_tx_set_mode(sig_tone_tx_state_t *s, int mode, int duration); /*! Initialise a signaling tone transmitter context. \brief Initialise a signaling tone context. @@ -148,7 +165,7 @@ SPAN_DECLARE(void) sig_tone_tx_set_mode(sig_tone_tx_state_t *s, int mode); \param sig_update Callback function to handle signaling updates. \param user_data An opaque pointer. \return A pointer to the signalling tone context, or NULL if there was a problem. */ -SPAN_DECLARE(sig_tone_tx_state_t *) sig_tone_tx_init(sig_tone_tx_state_t *s, int tone_type, sig_tone_func_t sig_update, void *user_data); +SPAN_DECLARE(sig_tone_tx_state_t *) sig_tone_tx_init(sig_tone_tx_state_t *s, int tone_type, tone_report_func_t sig_update, void *user_data); /*! Release a signaling tone transmitter context. \brief Release a signaling tone transmitter context. diff --git a/libs/spandsp/src/spandsp/silence_gen.h b/libs/spandsp/src/spandsp/silence_gen.h index c7300ec4aa..467408d75b 100644 --- a/libs/spandsp/src/spandsp/silence_gen.h +++ b/libs/spandsp/src/spandsp/silence_gen.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: silence_gen.h,v 1.18 2009/06/02 16:03:56 steveu Exp $ + * $Id: silence_gen.h,v 1.19 2009/09/04 14:38:47 steveu Exp $ */ #if !defined(_SPANDSP_SILENCE_GEN_H_) @@ -125,6 +125,16 @@ SPAN_DECLARE_NONSTD(int) span_dummy_rx(void *user_data, const int16_t amp[], int */ SPAN_DECLARE(int) span_dummy_mod(void *user_data, int16_t amp[], int len); +/*! A dummy routine to use as a receive fillin callback, when we aren't really + trying to process what is received. It just absorbs and ignores the + request. + \brief Dummy receive fillin callback. + \param user_data The context. + \param len The length of the signal buffer + \return 0. +*/ +SPAN_DECLARE_NONSTD(int) span_dummy_rx_fillin(void *user_data, int len); + #if defined(__cplusplus) } #endif diff --git a/libs/spandsp/src/spandsp/swept_tone.h b/libs/spandsp/src/spandsp/swept_tone.h new file mode 100644 index 0000000000..414f951fb3 --- /dev/null +++ b/libs/spandsp/src/spandsp/swept_tone.h @@ -0,0 +1,59 @@ +/* + * SpanDSP - a series of DSP components for telephony + * + * swept_tone.h - Swept tone generation + * + * Written by Steve Underwood + * + * Copyright (C) 2009 Steve Underwood + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * $Id: swept_tone.h,v 1.1 2009/09/22 12:54:33 steveu Exp $ + */ + +/*! \file */ + +#if !defined(_SPANDSP_SWEPT_TONE_H_) +#define _SPANDSP_SWEPT_TONE_H_ + +/*! \page swept_tone_page The swept tone generator +\section swept_tone_page_sec_1 What does it do? +*/ + +typedef struct swept_tone_state_s swept_tone_state_t; + +#if defined(__cplusplus) +extern "C" +{ +#endif + +SPAN_DECLARE(swept_tone_state_t *) swept_tone_init(swept_tone_state_t *s, float start, float end, float level, int duration, int repeating); + +SPAN_DECLARE(int) swept_tone(swept_tone_state_t *s, int16_t amp[], int len); + +SPAN_DECLARE(float) swept_tone_current_frequency(swept_tone_state_t *s); + +SPAN_DECLARE(int) swept_tone_release(swept_tone_state_t *s); + +SPAN_DECLARE(int) swept_tone_free(swept_tone_state_t *s); + +#if defined(__cplusplus) +} +#endif + +#endif +/*- End of file ------------------------------------------------------------*/ diff --git a/libs/spandsp/src/spandsp/t30.h b/libs/spandsp/src/spandsp/t30.h index dbd3dec1e2..d0d71f674d 100644 --- a/libs/spandsp/src/spandsp/t30.h +++ b/libs/spandsp/src/spandsp/t30.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: t30.h,v 1.125 2009/04/12 09:12:10 steveu Exp $ + * $Id: t30.h,v 1.126 2009/09/21 15:52:39 steveu Exp $ */ /*! \file */ @@ -524,9 +524,9 @@ typedef struct int pages_rx; /*! \brief The number of pages in the file (<0 if not known). */ int pages_in_file; - /*! \brief The horizontal column-to-column resolution of the page, in pixels per metre */ + /*! \brief The horizontal column-to-column resolution of the most recent page, in pixels per metre */ int x_resolution; - /*! \brief The vertical row-to-row resolution of the page, in pixels per metre */ + /*! \brief The vertical row-to-row resolution of the most recent page, in pixels per metre */ int y_resolution; /*! \brief The number of horizontal pixels in the most recent page. */ int width; diff --git a/libs/spandsp/src/spandsp/timing.h b/libs/spandsp/src/spandsp/timing.h index 735471659f..85f3ce5f43 100644 --- a/libs/spandsp/src/spandsp/timing.h +++ b/libs/spandsp/src/spandsp/timing.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: timing.h,v 1.13 2008/04/17 14:27:01 steveu Exp $ + * $Id: timing.h,v 1.14 2009/09/04 14:38:47 steveu Exp $ */ #if !defined(_SPANDSP_TIMING_H_) @@ -56,8 +56,8 @@ static __inline__ uint64_t rdtscll(void) #elif defined(__x86_64__) static __inline__ uint64_t rdtscll(void) { - unsigned int a; - unsigned int d; + uint32_t a; + uint32_t d; /* For x86_64 we need to merge the result in 2 32 bit registers into one clean 64 bit result. */ diff --git a/libs/spandsp/src/spandsp/version.h b/libs/spandsp/src/spandsp/version.h index 88a8ab76df..fe4e70aa73 100644 --- a/libs/spandsp/src/spandsp/version.h +++ b/libs/spandsp/src/spandsp/version.h @@ -30,9 +30,9 @@ /* The date and time of the version are in UTC form. */ -#define SPANDSP_RELEASE_DATE 20090714 -#define SPANDSP_RELEASE_TIME 135534 -#define SPANDSP_RELEASE_DATETIME_STRING "20090714 135534" +#define SPANDSP_RELEASE_DATE 20091005 +#define SPANDSP_RELEASE_TIME 132812 +#define SPANDSP_RELEASE_DATETIME_STRING "20091005 132812" #endif /*- End of file ------------------------------------------------------------*/ diff --git a/libs/spandsp/src/swept_tone.c b/libs/spandsp/src/swept_tone.c new file mode 100644 index 0000000000..78555ab8fa --- /dev/null +++ b/libs/spandsp/src/swept_tone.c @@ -0,0 +1,128 @@ +/* + * SpanDSP - a series of DSP components for telephony + * + * swept_tone.c - Swept tone generation + * + * Written by Steve Underwood + * + * Copyright (C) 2009 Steve Underwood + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * $Id: swept_tone.c,v 1.2 2009/09/23 16:02:59 steveu Exp $ + */ + +/*! \file */ + +#if defined(HAVE_CONFIG_H) +#include "config.h" +#endif + +#include +#include +#include +#include +#if defined(HAVE_TGMATH_H) +#include +#endif +#if defined(HAVE_MATH_H) +#include +#endif +#include "floating_fudge.h" + +#include "spandsp/telephony.h" +#include "spandsp/logging.h" +#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/dds.h" + +#include "spandsp/swept_tone.h" + +#include "spandsp/private/logging.h" +#include "spandsp/private/swept_tone.h" + +SPAN_DECLARE(swept_tone_state_t *) swept_tone_init(swept_tone_state_t *s, float start, float end, float level, int duration, int repeating) +{ + if (s == NULL) + { + if ((s = (swept_tone_state_t *) malloc(sizeof(*s))) == NULL) + return NULL; + } + memset(s, 0, sizeof(*s)); + s->current_phase_inc = + s->starting_phase_inc = dds_phase_rate(start); + s->phase_inc_step = dds_phase_rate((end - start)/(float) duration); + s->scale = dds_scaling_dbm0(level); + s->duration = duration; + s->repeating = repeating; + s->pos = 0; + s->phase = 0; + return s; +} +/*- End of function --------------------------------------------------------*/ + +SPAN_DECLARE(int) swept_tone(swept_tone_state_t *s, int16_t amp[], int max_len) +{ + int i; + int len; + int chunk_len; + + for (len = 0; len < max_len; ) + { + chunk_len = max_len - len; + if (chunk_len > s->duration - s->pos) + chunk_len = s->duration - s->pos; + for (i = len; i < len + chunk_len; i++) + { + amp[i] = (dds(&s->phase, s->current_phase_inc)*s->scale) >> 15; + s->current_phase_inc += s->phase_inc_step; + } + len += chunk_len; + s->pos += chunk_len; + if (s->pos >= s->duration) + { + if (!s->repeating) + break; + s->pos = 0; + s->current_phase_inc = s->starting_phase_inc; + } + } + return len; +} +/*- End of function --------------------------------------------------------*/ + +SPAN_DECLARE(float) swept_tone_current_frequency(swept_tone_state_t *s) +{ + return dds_frequency(s->current_phase_inc); +} +/*- End of function --------------------------------------------------------*/ + +SPAN_DECLARE(int) swept_tone_release(swept_tone_state_t *s) +{ + return 0; +} +/*- End of function --------------------------------------------------------*/ + +SPAN_DECLARE(int) swept_tone_free(swept_tone_state_t *s) +{ + free(s); + return 0; +} +/*- End of function --------------------------------------------------------*/ +/*- End of file ------------------------------------------------------------*/ diff --git a/libs/spandsp/src/t30.c b/libs/spandsp/src/t30.c index 6640fd8294..a112dd9fac 100644 --- a/libs/spandsp/src/t30.c +++ b/libs/spandsp/src/t30.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: t30.c,v 1.301 2009/05/25 12:37:38 steveu Exp $ + * $Id: t30.c,v 1.303 2009/09/21 15:51:18 steveu Exp $ */ /*! \file */ @@ -421,7 +421,7 @@ static int tx_start_page(t30_state_t *s) } s->ecm_block = 0; s->error_correcting_mode_retries = 0; - span_log(&s->logging, SPAN_LOG_FLOW, "Starting page %d of transfer\n", s->ecm_tx_page + 1); + span_log(&s->logging, SPAN_LOG_FLOW, "Starting page %d of transfer\n", s->tx_page_number + 1); return 0; } /*- End of function --------------------------------------------------------*/ @@ -431,7 +431,7 @@ static int tx_end_page(t30_state_t *s) s->retries = 0; if (t4_tx_end_page(&(s->t4)) == 0) { - s->ecm_tx_page++; + s->tx_page_number++; s->ecm_block = 0; } return 0; @@ -470,7 +470,7 @@ static int rx_end_page(t30_state_t *s) { if (t4_rx_end_page(&(s->t4)) == 0) { - s->ecm_rx_page++; + s->rx_page_number++; s->ecm_block = 0; } return 0; @@ -1042,7 +1042,7 @@ static int send_pps_frame(t30_state_t *s) frame[1] = CONTROL_FIELD_FINAL_FRAME; frame[2] = (uint8_t) (T30_PPS | s->dis_received); frame[3] = (s->ecm_at_page_end) ? ((uint8_t) (s->next_tx_step | s->dis_received)) : T30_NULL; - frame[4] = (uint8_t) (s->ecm_tx_page & 0xFF); + frame[4] = (uint8_t) (s->tx_page_number & 0xFF); frame[5] = (uint8_t) (s->ecm_block & 0xFF); frame[6] = (uint8_t) ((s->ecm_frames_this_tx_burst == 0) ? 0 : (s->ecm_frames_this_tx_burst - 1)); span_log(&s->logging, SPAN_LOG_FLOW, "Sending PPS + %s\n", t30_frametype(frame[3])); @@ -1957,30 +1957,19 @@ static int start_receiving_document(t30_state_t *s) } /*- End of function --------------------------------------------------------*/ -static void unexpected_frame(t30_state_t *s, const uint8_t *msg, int len) -{ - span_log(&s->logging, SPAN_LOG_FLOW, "Unexpected %s received in state %d\n", t30_frametype(msg[2]), s->state); - switch (s->state) - { - case T30_STATE_F_DOC_ECM: - case T30_STATE_F_DOC_NON_ECM: - s->current_status = T30_ERR_RX_INVALCMD; - break; - } -} -/*- End of function --------------------------------------------------------*/ - static void unexpected_non_final_frame(t30_state_t *s, const uint8_t *msg, int len) { span_log(&s->logging, SPAN_LOG_FLOW, "Unexpected %s frame in state %d\n", t30_frametype(msg[2]), s->state); - s->current_status = T30_ERR_UNEXPECTED; + if (s->current_status == T30_ERR_OK) + s->current_status = T30_ERR_UNEXPECTED; } /*- End of function --------------------------------------------------------*/ static void unexpected_final_frame(t30_state_t *s, const uint8_t *msg, int len) { - span_log(&s->logging, SPAN_LOG_FLOW, "Unexpected %s received in state %d\n", t30_frametype(msg[2]), s->state); - s->current_status = T30_ERR_UNEXPECTED; + span_log(&s->logging, SPAN_LOG_FLOW, "Unexpected %s frame in state %d\n", t30_frametype(msg[2]), s->state); + if (s->current_status == T30_ERR_OK) + s->current_status = T30_ERR_UNEXPECTED; send_dcn(s); } /*- End of function --------------------------------------------------------*/ @@ -1988,7 +1977,8 @@ static void unexpected_final_frame(t30_state_t *s, const uint8_t *msg, int len) static void unexpected_frame_length(t30_state_t *s, const uint8_t *msg, int len) { span_log(&s->logging, SPAN_LOG_FLOW, "Unexpected %s frame length - %d\n", t30_frametype(msg[0]), len); - s->current_status = T30_ERR_UNEXPECTED; + if (s->current_status == T30_ERR_OK) + s->current_status = T30_ERR_UNEXPECTED; send_dcn(s); } /*- End of function --------------------------------------------------------*/ @@ -2372,9 +2362,9 @@ static int process_rx_pps(t30_state_t *s, const uint8_t *msg, int len) } } span_log(&s->logging, SPAN_LOG_FLOW, "Received PPS + %s - page %d, block %d, %d frames\n", t30_frametype(msg[3]), page, block, frames); - if (page != s->ecm_rx_page) + if (page != s->rx_page_number) { - span_log(&s->logging, SPAN_LOG_FLOW, "ECM rx page mismatch - expected %d, but received %d.\n", s->ecm_rx_page, page); + span_log(&s->logging, SPAN_LOG_FLOW, "ECM rx page mismatch - expected %d, but received %d.\n", s->rx_page_number, page); } if (block != s->ecm_block) { @@ -2645,7 +2635,11 @@ static void process_rx_fnv(t30_state_t *s, const uint8_t *msg, int len) static void process_state_answering(t30_state_t *s, const uint8_t *msg, int len) { - switch (msg[2] & 0xFE) + uint8_t fcf; + + /* We should be sending the TCF data right now */ + fcf = msg[2] & 0xFE; + switch (fcf) { case T30_DIS: /* TODO: This is a fudge to allow for starting up in T.38, where the other end has @@ -2675,7 +2669,11 @@ static void process_state_answering(t30_state_t *s, const uint8_t *msg, int len) static void process_state_b(t30_state_t *s, const uint8_t *msg, int len) { - switch (msg[2] & 0xFE) + uint8_t fcf; + + /* We should be sending the TCF data right now */ + fcf = msg[2] & 0xFE; + switch (fcf) { case T30_DCN: /* Just ignore any DCN's which appear at this stage. */ @@ -2696,7 +2694,10 @@ static void process_state_b(t30_state_t *s, const uint8_t *msg, int len) static void process_state_c(t30_state_t *s, const uint8_t *msg, int len) { - switch (msg[2] & 0xFE) + uint8_t fcf; + + fcf = msg[2] & 0xFE; + switch (fcf) { case T30_DCN: /* Just ignore any DCN's which appear at this stage. */ @@ -2717,8 +2718,11 @@ static void process_state_c(t30_state_t *s, const uint8_t *msg, int len) static void process_state_d(t30_state_t *s, const uint8_t *msg, int len) { + uint8_t fcf; + /* We should be sending the DCS sequence right now */ - switch (msg[2] & 0xFE) + fcf = msg[2] & 0xFE; + switch (fcf) { case T30_DCN: s->current_status = T30_ERR_TX_BADDCS; @@ -2740,8 +2744,11 @@ static void process_state_d(t30_state_t *s, const uint8_t *msg, int len) static void process_state_d_tcf(t30_state_t *s, const uint8_t *msg, int len) { + uint8_t fcf; + /* We should be sending the TCF data right now */ - switch (msg[2] & 0xFE) + fcf = msg[2] & 0xFE; + switch (fcf) { case T30_DCN: s->current_status = T30_ERR_TX_BADDCS; @@ -2763,7 +2770,10 @@ static void process_state_d_tcf(t30_state_t *s, const uint8_t *msg, int len) static void process_state_d_post_tcf(t30_state_t *s, const uint8_t *msg, int len) { - switch (msg[2] & 0xFE) + uint8_t fcf; + + fcf = msg[2] & 0xFE; + switch (fcf) { case T30_CFR: /* Trainability test succeeded. Send the document. */ @@ -2832,8 +2842,11 @@ static void process_state_d_post_tcf(t30_state_t *s, const uint8_t *msg, int len static void process_state_f_tcf(t30_state_t *s, const uint8_t *msg, int len) { + uint8_t fcf; + /* We should be receiving TCF right now, not HDLC messages */ - switch (msg[2] & 0xFE) + fcf = msg[2] & 0xFE; + switch (fcf) { case T30_CRP: repeat_last_command(s); @@ -2851,8 +2864,11 @@ static void process_state_f_tcf(t30_state_t *s, const uint8_t *msg, int len) static void process_state_f_cfr(t30_state_t *s, const uint8_t *msg, int len) { + uint8_t fcf; + /* We're waiting for a response to the CFR we sent */ - switch (msg[2] & 0xFE) + fcf = msg[2] & 0xFE; + switch (fcf) { case T30_DCS: /* If we received another DCS, they must have missed our CFR */ @@ -2874,8 +2890,11 @@ static void process_state_f_cfr(t30_state_t *s, const uint8_t *msg, int len) static void process_state_f_ftt(t30_state_t *s, const uint8_t *msg, int len) { + uint8_t fcf; + /* We're waiting for a response to the FTT we sent */ - switch (msg[2] & 0xFE) + fcf = msg[2] & 0xFE; + switch (fcf) { case T30_DCS: process_rx_dcs(s, msg, len); @@ -2896,12 +2915,15 @@ static void process_state_f_ftt(t30_state_t *s, const uint8_t *msg, int len) static void process_state_f_doc_non_ecm(t30_state_t *s, const uint8_t *msg, int len) { + uint8_t fcf; + /* If we are getting HDLC messages, and we have not moved to the _POST_DOC_NON_ECM state, it looks like either: - we didn't see the image data carrier properly, or - they didn't see our T30_CFR, and are repeating the DCS/TCF sequence. - they didn't see out T30_MCF, and are repeating the end of page message. */ - switch (msg[2] & 0xFE) + fcf = msg[2] & 0xFE; + switch (fcf) { case T30_DIS: process_rx_dis_dtc(s, msg, len); @@ -2912,7 +2934,7 @@ static void process_state_f_doc_non_ecm(t30_state_t *s, const uint8_t *msg, int case T30_MPS: /* Treat this as a bad quality page. */ if (s->phase_d_handler) - s->phase_d_handler(s, s->phase_d_user_data, msg[2] & 0xFE); + s->phase_d_handler(s, s->phase_d_user_data, fcf); s->next_rx_step = msg[2] & 0xFE; queue_phase(s, T30_PHASE_D_TX); set_state(s, T30_STATE_III_Q_RTN); @@ -2922,7 +2944,7 @@ static void process_state_f_doc_non_ecm(t30_state_t *s, const uint8_t *msg, int /* Treat this as a bad quality page. */ if (s->phase_d_handler) { - s->phase_d_handler(s, s->phase_d_user_data, msg[2] & 0xFE); + s->phase_d_handler(s, s->phase_d_user_data, fcf); s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3); } s->next_rx_step = msg[2] & 0xFE; @@ -2932,7 +2954,7 @@ static void process_state_f_doc_non_ecm(t30_state_t *s, const uint8_t *msg, int case T30_EOS: /* Treat this as a bad quality page. */ if (s->phase_d_handler) - s->phase_d_handler(s, s->phase_d_user_data, msg[2] & 0xFE); + s->phase_d_handler(s, s->phase_d_user_data, fcf); s->next_rx_step = msg[2] & 0xFE; /* Return to phase B */ queue_phase(s, T30_PHASE_B_TX); @@ -2943,7 +2965,7 @@ static void process_state_f_doc_non_ecm(t30_state_t *s, const uint8_t *msg, int /* Treat this as a bad quality page. */ if (s->phase_d_handler) { - s->phase_d_handler(s, s->phase_d_user_data, msg[2] & 0xFE); + s->phase_d_handler(s, s->phase_d_user_data, fcf); s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3); } s->next_rx_step = T30_PRI_EOM; @@ -2952,7 +2974,7 @@ static void process_state_f_doc_non_ecm(t30_state_t *s, const uint8_t *msg, int case T30_EOP: /* Treat this as a bad quality page. */ if (s->phase_d_handler) - s->phase_d_handler(s, s->phase_d_user_data, msg[2] & 0xFE); + s->phase_d_handler(s, s->phase_d_user_data, fcf); s->next_rx_step = msg[2] & 0xFE; queue_phase(s, T30_PHASE_D_TX); set_state(s, T30_STATE_III_Q_RTN); @@ -2962,7 +2984,7 @@ static void process_state_f_doc_non_ecm(t30_state_t *s, const uint8_t *msg, int /* Treat this as a bad quality page. */ if (s->phase_d_handler) { - s->phase_d_handler(s, s->phase_d_user_data, msg[2] & 0xFE); + s->phase_d_handler(s, s->phase_d_user_data, fcf); s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3); } s->next_rx_step = msg[2] & 0xFE; @@ -2980,6 +3002,7 @@ static void process_state_f_doc_non_ecm(t30_state_t *s, const uint8_t *msg, int break; default: /* We don't know what to do with this. */ + s->current_status = T30_ERR_RX_INVALCMD; unexpected_final_frame(s, msg, len); break; } @@ -2988,12 +3011,15 @@ static void process_state_f_doc_non_ecm(t30_state_t *s, const uint8_t *msg, int static void process_state_f_post_doc_non_ecm(t30_state_t *s, const uint8_t *msg, int len) { - switch (msg[2] & 0xFE) + uint8_t fcf; + + fcf = msg[2] & 0xFE; + switch (fcf) { case T30_MPS: if (s->phase_d_handler) - s->phase_d_handler(s, s->phase_d_user_data, msg[2] & 0xFE); - s->next_rx_step = msg[2] & 0xFE; + s->phase_d_handler(s, s->phase_d_user_data, fcf); + s->next_rx_step = fcf; queue_phase(s, T30_PHASE_D_TX); switch (copy_quality(s)) { @@ -3020,10 +3046,10 @@ static void process_state_f_post_doc_non_ecm(t30_state_t *s, const uint8_t *msg, case T30_PRI_MPS: if (s->phase_d_handler) { - s->phase_d_handler(s, s->phase_d_user_data, msg[2] & 0xFE); + s->phase_d_handler(s, s->phase_d_user_data, fcf); s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3); } - s->next_rx_step = msg[2] & 0xFE; + s->next_rx_step = fcf; switch (copy_quality(s)) { case T30_COPY_QUALITY_PERFECT: @@ -3049,8 +3075,8 @@ static void process_state_f_post_doc_non_ecm(t30_state_t *s, const uint8_t *msg, case T30_EOM: case T30_EOS: if (s->phase_d_handler) - s->phase_d_handler(s, s->phase_d_user_data, msg[2] & 0xFE); - s->next_rx_step = msg[2] & 0xFE; + s->phase_d_handler(s, s->phase_d_user_data, fcf); + s->next_rx_step = fcf; /* Return to phase B */ queue_phase(s, T30_PHASE_B_TX); switch (copy_quality(s)) @@ -3078,10 +3104,10 @@ static void process_state_f_post_doc_non_ecm(t30_state_t *s, const uint8_t *msg, case T30_PRI_EOM: if (s->phase_d_handler) { - s->phase_d_handler(s, s->phase_d_user_data, msg[2] & 0xFE); + s->phase_d_handler(s, s->phase_d_user_data, fcf); s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3); } - s->next_rx_step = msg[2] & 0xFE; + s->next_rx_step = fcf; switch (copy_quality(s)) { case T30_COPY_QUALITY_PERFECT: @@ -3106,8 +3132,8 @@ static void process_state_f_post_doc_non_ecm(t30_state_t *s, const uint8_t *msg, break; case T30_EOP: if (s->phase_d_handler) - s->phase_d_handler(s, s->phase_d_user_data, msg[2] & 0xFE); - s->next_rx_step = msg[2] & 0xFE; + s->phase_d_handler(s, s->phase_d_user_data, fcf); + s->next_rx_step = fcf; queue_phase(s, T30_PHASE_D_TX); switch (copy_quality(s)) { @@ -3137,10 +3163,10 @@ static void process_state_f_post_doc_non_ecm(t30_state_t *s, const uint8_t *msg, case T30_PRI_EOP: if (s->phase_d_handler) { - s->phase_d_handler(s, s->phase_d_user_data, msg[2] & 0xFE); + s->phase_d_handler(s, s->phase_d_user_data, fcf); s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3); } - s->next_rx_step = msg[2] & 0xFE; + s->next_rx_step = fcf; switch (copy_quality(s)) { case T30_COPY_QUALITY_PERFECT: @@ -3175,6 +3201,7 @@ static void process_state_f_post_doc_non_ecm(t30_state_t *s, const uint8_t *msg, break; default: /* We don't know what to do with this. */ + s->current_status = T30_ERR_RX_INVALCMD; unexpected_final_frame(s, msg, len); break; } @@ -3183,10 +3210,12 @@ static void process_state_f_post_doc_non_ecm(t30_state_t *s, const uint8_t *msg, static void process_state_f_doc_and_post_doc_ecm(t30_state_t *s, const uint8_t *msg, int len) { + uint8_t fcf; uint8_t fcf2; /* This actually handles 2 states - _DOC_ECM and _POST_DOC_ECM - as they are very similar */ - switch (msg[2] & 0xFE) + fcf = msg[2] & 0xFE; + switch (fcf) { case T30_DIS: process_rx_dis_dtc(s, msg, len); @@ -3267,6 +3296,7 @@ static void process_state_f_doc_and_post_doc_ecm(t30_state_t *s, const uint8_t * break; default: /* We don't know what to do with this. */ + s->current_status = T30_ERR_RX_INVALCMD; unexpected_final_frame(s, msg, len); break; } @@ -3275,7 +3305,10 @@ static void process_state_f_doc_and_post_doc_ecm(t30_state_t *s, const uint8_t * static void process_state_f_post_rcp_mcf(t30_state_t *s, const uint8_t *msg, int len) { - switch (msg[2] & 0xFE) + uint8_t fcf; + + fcf = msg[2] & 0xFE; + switch (fcf) { case T30_CRP: repeat_last_command(s); @@ -3296,7 +3329,10 @@ static void process_state_f_post_rcp_mcf(t30_state_t *s, const uint8_t *msg, int static void process_state_f_post_rcp_ppr(t30_state_t *s, const uint8_t *msg, int len) { - switch (msg[2] & 0xFE) + uint8_t fcf; + + fcf = msg[2] & 0xFE; + switch (fcf) { case T30_CRP: repeat_last_command(s); @@ -3314,7 +3350,10 @@ static void process_state_f_post_rcp_ppr(t30_state_t *s, const uint8_t *msg, int static void process_state_f_post_rcp_rnr(t30_state_t *s, const uint8_t *msg, int len) { - switch (msg[2] & 0xFE) + uint8_t fcf; + + fcf = msg[2] & 0xFE; + switch (fcf) { case T30_RR: if (s->receiver_not_ready_count > 0) @@ -3345,7 +3384,10 @@ static void process_state_f_post_rcp_rnr(t30_state_t *s, const uint8_t *msg, int static void process_state_r(t30_state_t *s, const uint8_t *msg, int len) { - switch (msg[2] & 0xFE) + uint8_t fcf; + + fcf = msg[2] & 0xFE; + switch (fcf) { case T30_DIS: process_rx_dis_dtc(s, msg, len); @@ -3374,7 +3416,10 @@ static void process_state_r(t30_state_t *s, const uint8_t *msg, int len) static void process_state_t(t30_state_t *s, const uint8_t *msg, int len) { - switch (msg[2] & 0xFE) + uint8_t fcf; + + fcf = msg[2] & 0xFE; + switch (fcf) { case T30_DIS: process_rx_dis_dtc(s, msg, len); @@ -3400,7 +3445,10 @@ static void process_state_t(t30_state_t *s, const uint8_t *msg, int len) static void process_state_i(t30_state_t *s, const uint8_t *msg, int len) { - switch (msg[2] & 0xFE) + uint8_t fcf; + + fcf = msg[2] & 0xFE; + switch (fcf) { case T30_CRP: repeat_last_command(s); @@ -3418,7 +3466,10 @@ static void process_state_i(t30_state_t *s, const uint8_t *msg, int len) static void process_state_ii(t30_state_t *s, const uint8_t *msg, int len) { - switch (msg[2] & 0xFE) + uint8_t fcf; + + fcf = msg[2] & 0xFE; + switch (fcf) { case T30_CRP: repeat_last_command(s); @@ -3437,8 +3488,10 @@ static void process_state_ii(t30_state_t *s, const uint8_t *msg, int len) static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len) { t4_stats_t stats; + uint8_t fcf; - switch (msg[2] & 0xFE) + fcf = msg[2] & 0xFE; + switch (fcf) { case T30_MCF: switch (s->next_tx_step) @@ -3447,7 +3500,8 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len) case T30_PRI_MPS: tx_end_page(s); if (s->phase_d_handler) - s->phase_d_handler(s, s->phase_d_user_data, T30_MCF); + s->phase_d_handler(s, s->phase_d_user_data, fcf); + /* Transmit the next page */ if (tx_start_page(s)) { /* TODO: recover */ @@ -3461,7 +3515,7 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len) case T30_EOS: tx_end_page(s); if (s->phase_d_handler) - s->phase_d_handler(s, s->phase_d_user_data, T30_MCF); + s->phase_d_handler(s, s->phase_d_user_data, fcf); t4_tx_release(&(s->t4)); s->operation_in_progress = OPERATION_IN_PROGRESS_NONE; if (span_log_test(&s->logging, SPAN_LOG_FLOW)) @@ -3475,7 +3529,7 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len) case T30_PRI_EOP: tx_end_page(s); if (s->phase_d_handler) - s->phase_d_handler(s, s->phase_d_user_data, T30_MCF); + s->phase_d_handler(s, s->phase_d_user_data, fcf); t4_tx_release(&(s->t4)); s->operation_in_progress = OPERATION_IN_PROGRESS_NONE; send_dcn(s); @@ -3488,13 +3542,16 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len) } break; case T30_RTP: +#if 0 + s->rtp_events++; +#endif switch (s->next_tx_step) { case T30_MPS: case T30_PRI_MPS: tx_end_page(s); if (s->phase_d_handler) - s->phase_d_handler(s, s->phase_d_user_data, T30_RTP); + s->phase_d_handler(s, s->phase_d_user_data, fcf); if (tx_start_page(s)) { /* TODO: recover */ @@ -3517,7 +3574,7 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len) case T30_EOS: tx_end_page(s); if (s->phase_d_handler) - s->phase_d_handler(s, s->phase_d_user_data, T30_RTP); + s->phase_d_handler(s, s->phase_d_user_data, fcf); t4_tx_release(&(s->t4)); /* TODO: should go back to T, and resend */ return_to_phase_b(s, TRUE); @@ -3526,22 +3583,35 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len) case T30_PRI_EOP: tx_end_page(s); if (s->phase_d_handler) - s->phase_d_handler(s, s->phase_d_user_data, T30_RTP); + s->phase_d_handler(s, s->phase_d_user_data, fcf); t4_tx_release(&(s->t4)); - s->current_status = T30_ERR_TX_INVALRSP; send_dcn(s); break; } break; case T30_RTN: +#if 0 + s->rtn_events++; +#endif switch (s->next_tx_step) { case T30_MPS: case T30_PRI_MPS: s->retries = 0; if (s->phase_d_handler) - s->phase_d_handler(s, s->phase_d_user_data, T30_RTN); - /* Send fresh training, and then repeat the last page */ + s->phase_d_handler(s, s->phase_d_user_data, fcf); +#if 0 + if (!s->retransmit_capable) +#endif + { + /* Send the next page, regardless of the problem with the current one. */ + if (tx_start_page(s)) + { + /* TODO: recover */ + break; + } + } + /* Send fresh training */ if (step_fallback_entry(s) < 0) { /* We have fallen back as far as we can go. Give up. */ @@ -3558,17 +3628,43 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len) case T30_EOS: s->retries = 0; if (s->phase_d_handler) - s->phase_d_handler(s, s->phase_d_user_data, T30_RTN); - s->current_status = T30_ERR_TX_INVALRSP; - return_to_phase_b(s, TRUE); + s->phase_d_handler(s, s->phase_d_user_data, fcf); +#if 0 + if (s->retransmit_capable) + { + /* Wait for DIS */ + } + else +#endif + { + return_to_phase_b(s, TRUE); + } break; case T30_EOP: case T30_PRI_EOP: s->retries = 0; if (s->phase_d_handler) - s->phase_d_handler(s, s->phase_d_user_data, T30_RTN); - s->current_status = T30_ERR_TX_INVALRSP; - send_dcn(s); + s->phase_d_handler(s, s->phase_d_user_data, fcf); +#if 0 + if (s->retransmit_capable) + { + /* Send fresh training, and then repeat the last page */ + if (step_fallback_entry(s) < 0) + { + /* We have fallen back as far as we can go. Give up. */ + s->current_fallback = 0; + s->current_status = T30_ERR_CANNOT_TRAIN; + send_dcn(s); + break; + } + queue_phase(s, T30_PHASE_B_TX); + restart_sending_document(s); + } + else +#endif + { + send_dcn(s); + } break; } break; @@ -3576,7 +3672,7 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len) s->retries = 0; if (s->phase_d_handler) { - s->phase_d_handler(s, s->phase_d_user_data, T30_PIP); + s->phase_d_handler(s, s->phase_d_user_data, fcf); s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3); } break; @@ -3584,7 +3680,7 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len) s->retries = 0; if (s->phase_d_handler) { - s->phase_d_handler(s, s->phase_d_user_data, T30_PIN); + s->phase_d_handler(s, s->phase_d_user_data, fcf); s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3); } break; @@ -3613,6 +3709,7 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len) break; default: /* We don't know what to do with this. */ + s->current_status = T30_ERR_TX_INVALRSP; unexpected_final_frame(s, msg, len); break; } @@ -3621,7 +3718,10 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len) static void process_state_iii_q_mcf(t30_state_t *s, const uint8_t *msg, int len) { - switch (msg[2] & 0xFE) + uint8_t fcf; + + fcf = msg[2] & 0xFE; + switch (fcf) { case T30_EOP: case T30_EOM: @@ -3655,7 +3755,10 @@ static void process_state_iii_q_mcf(t30_state_t *s, const uint8_t *msg, int len) static void process_state_iii_q_rtp(t30_state_t *s, const uint8_t *msg, int len) { - switch (msg[2] & 0xFE) + uint8_t fcf; + + fcf = msg[2] & 0xFE; + switch (fcf) { case T30_EOP: case T30_EOM: @@ -3686,7 +3789,10 @@ static void process_state_iii_q_rtp(t30_state_t *s, const uint8_t *msg, int len) static void process_state_iii_q_rtn(t30_state_t *s, const uint8_t *msg, int len) { - switch (msg[2] & 0xFE) + uint8_t fcf; + + fcf = msg[2] & 0xFE; + switch (fcf) { case T30_EOP: case T30_EOM: @@ -3721,7 +3827,10 @@ static void process_state_iii_q_rtn(t30_state_t *s, const uint8_t *msg, int len) static void process_state_iv(t30_state_t *s, const uint8_t *msg, int len) { - switch (msg[2] & 0xFE) + uint8_t fcf; + + fcf = msg[2] & 0xFE; + switch (fcf) { case T30_CRP: repeat_last_command(s); @@ -3740,8 +3849,10 @@ static void process_state_iv(t30_state_t *s, const uint8_t *msg, int len) static void process_state_iv_pps_null(t30_state_t *s, const uint8_t *msg, int len) { t4_stats_t stats; + uint8_t fcf; - switch (msg[2] & 0xFE) + fcf = msg[2] & 0xFE; + switch (fcf) { case T30_MCF: s->retries = 0; @@ -3765,7 +3876,7 @@ static void process_state_iv_pps_null(t30_state_t *s, const uint8_t *msg, int le case T30_PRI_MPS: tx_end_page(s); if (s->phase_d_handler) - s->phase_d_handler(s, s->phase_d_user_data, T30_MCF); + s->phase_d_handler(s, s->phase_d_user_data, fcf); if (tx_start_page(s)) { /* TODO: recover */ @@ -3783,7 +3894,7 @@ static void process_state_iv_pps_null(t30_state_t *s, const uint8_t *msg, int le case T30_EOS: tx_end_page(s); if (s->phase_d_handler) - s->phase_d_handler(s, s->phase_d_user_data, T30_MCF); + s->phase_d_handler(s, s->phase_d_user_data, fcf); t4_tx_release(&(s->t4)); s->operation_in_progress = OPERATION_IN_PROGRESS_NONE; if (span_log_test(&s->logging, SPAN_LOG_FLOW)) @@ -3797,7 +3908,7 @@ static void process_state_iv_pps_null(t30_state_t *s, const uint8_t *msg, int le case T30_PRI_EOP: tx_end_page(s); if (s->phase_d_handler) - s->phase_d_handler(s, s->phase_d_user_data, T30_MCF); + s->phase_d_handler(s, s->phase_d_user_data, fcf); t4_tx_release(&(s->t4)); s->operation_in_progress = OPERATION_IN_PROGRESS_NONE; send_dcn(s); @@ -3842,8 +3953,10 @@ static void process_state_iv_pps_null(t30_state_t *s, const uint8_t *msg, int le static void process_state_iv_pps_q(t30_state_t *s, const uint8_t *msg, int len) { t4_stats_t stats; + uint8_t fcf; - switch (msg[2] & 0xFE) + fcf = msg[2] & 0xFE; + switch (fcf) { case T30_MCF: s->retries = 0; @@ -3867,7 +3980,7 @@ static void process_state_iv_pps_q(t30_state_t *s, const uint8_t *msg, int len) case T30_PRI_MPS: tx_end_page(s); if (s->phase_d_handler) - s->phase_d_handler(s, s->phase_d_user_data, T30_MCF); + s->phase_d_handler(s, s->phase_d_user_data, fcf); if (tx_start_page(s)) { /* TODO: recover */ @@ -3885,7 +3998,7 @@ static void process_state_iv_pps_q(t30_state_t *s, const uint8_t *msg, int len) case T30_EOS: tx_end_page(s); if (s->phase_d_handler) - s->phase_d_handler(s, s->phase_d_user_data, T30_MCF); + s->phase_d_handler(s, s->phase_d_user_data, fcf); t4_tx_release(&(s->t4)); s->operation_in_progress = OPERATION_IN_PROGRESS_NONE; if (span_log_test(&s->logging, SPAN_LOG_FLOW)) @@ -3899,7 +4012,7 @@ static void process_state_iv_pps_q(t30_state_t *s, const uint8_t *msg, int len) case T30_PRI_EOP: tx_end_page(s); if (s->phase_d_handler) - s->phase_d_handler(s, s->phase_d_user_data, T30_MCF); + s->phase_d_handler(s, s->phase_d_user_data, fcf); t4_tx_release(&(s->t4)); s->operation_in_progress = OPERATION_IN_PROGRESS_NONE; send_dcn(s); @@ -3923,7 +4036,7 @@ static void process_state_iv_pps_q(t30_state_t *s, const uint8_t *msg, int len) s->retries = 0; if (s->phase_d_handler) { - s->phase_d_handler(s, s->phase_d_user_data, T30_PIP); + s->phase_d_handler(s, s->phase_d_user_data, fcf); s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3); } break; @@ -3931,7 +4044,7 @@ static void process_state_iv_pps_q(t30_state_t *s, const uint8_t *msg, int len) s->retries = 0; if (s->phase_d_handler) { - s->phase_d_handler(s, s->phase_d_user_data, T30_PIN); + s->phase_d_handler(s, s->phase_d_user_data, fcf); s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3); } break; @@ -3960,8 +4073,10 @@ static void process_state_iv_pps_q(t30_state_t *s, const uint8_t *msg, int len) static void process_state_iv_pps_rnr(t30_state_t *s, const uint8_t *msg, int len) { t4_stats_t stats; + uint8_t fcf; - switch (msg[2] & 0xFE) + fcf = msg[2] & 0xFE; + switch (fcf) { case T30_MCF: s->retries = 0; @@ -3985,7 +4100,7 @@ static void process_state_iv_pps_rnr(t30_state_t *s, const uint8_t *msg, int len case T30_PRI_MPS: tx_end_page(s); if (s->phase_d_handler) - s->phase_d_handler(s, s->phase_d_user_data, T30_MCF); + s->phase_d_handler(s, s->phase_d_user_data, fcf); if (tx_start_page(s)) { /* TODO: recover */ @@ -4003,7 +4118,7 @@ static void process_state_iv_pps_rnr(t30_state_t *s, const uint8_t *msg, int len case T30_EOS: tx_end_page(s); if (s->phase_d_handler) - s->phase_d_handler(s, s->phase_d_user_data, T30_MCF); + s->phase_d_handler(s, s->phase_d_user_data, fcf); t4_tx_release(&(s->t4)); s->operation_in_progress = OPERATION_IN_PROGRESS_NONE; if (span_log_test(&s->logging, SPAN_LOG_FLOW)) @@ -4017,7 +4132,7 @@ static void process_state_iv_pps_rnr(t30_state_t *s, const uint8_t *msg, int len case T30_PRI_EOP: tx_end_page(s); if (s->phase_d_handler) - s->phase_d_handler(s, s->phase_d_user_data, T30_MCF); + s->phase_d_handler(s, s->phase_d_user_data, fcf); t4_tx_release(&(s->t4)); s->operation_in_progress = OPERATION_IN_PROGRESS_NONE; send_dcn(s); @@ -4041,7 +4156,7 @@ static void process_state_iv_pps_rnr(t30_state_t *s, const uint8_t *msg, int len s->retries = 0; if (s->phase_d_handler) { - s->phase_d_handler(s, s->phase_d_user_data, T30_PIP); + s->phase_d_handler(s, s->phase_d_user_data, fcf); s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3); } break; @@ -4049,7 +4164,7 @@ static void process_state_iv_pps_rnr(t30_state_t *s, const uint8_t *msg, int len s->retries = 0; if (s->phase_d_handler) { - s->phase_d_handler(s, s->phase_d_user_data, T30_PIN); + s->phase_d_handler(s, s->phase_d_user_data, fcf); s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3); } break; @@ -4073,7 +4188,10 @@ static void process_state_iv_pps_rnr(t30_state_t *s, const uint8_t *msg, int len static void process_state_iv_ctc(t30_state_t *s, const uint8_t *msg, int len) { - switch (msg[2] & 0xFE) + uint8_t fcf; + + fcf = msg[2] & 0xFE; + switch (fcf) { case T30_CTR: /* Valid response to a CTC received */ @@ -4100,7 +4218,10 @@ static void process_state_iv_ctc(t30_state_t *s, const uint8_t *msg, int len) static void process_state_iv_eor(t30_state_t *s, const uint8_t *msg, int len) { - switch (msg[2] & 0xFE) + uint8_t fcf; + + fcf = msg[2] & 0xFE; + switch (fcf) { case T30_RNR: if (s->timer_t5 == 0) @@ -4113,7 +4234,7 @@ static void process_state_iv_eor(t30_state_t *s, const uint8_t *msg, int len) s->retries = 0; if (s->phase_d_handler) { - s->phase_d_handler(s, s->phase_d_user_data, T30_PIN); + s->phase_d_handler(s, s->phase_d_user_data, fcf); s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3); } break; @@ -4138,7 +4259,10 @@ static void process_state_iv_eor(t30_state_t *s, const uint8_t *msg, int len) static void process_state_iv_eor_rnr(t30_state_t *s, const uint8_t *msg, int len) { - switch (msg[2] & 0xFE) + uint8_t fcf; + + fcf = msg[2] & 0xFE; + switch (fcf) { case T30_RNR: if (s->timer_t5 == 0) @@ -4151,7 +4275,7 @@ static void process_state_iv_eor_rnr(t30_state_t *s, const uint8_t *msg, int len s->retries = 0; if (s->phase_d_handler) { - s->phase_d_handler(s, s->phase_d_user_data, T30_PIN); + s->phase_d_handler(s, s->phase_d_user_data, fcf); s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3); } break; @@ -4257,7 +4381,7 @@ static void process_rx_control_msg(t30_state_t *s, const uint8_t *msg, int len) } else { - unexpected_frame(s, msg, len); + unexpected_non_final_frame(s, msg, len); } break; case (T30_SEP & 0xFE): @@ -4269,7 +4393,7 @@ static void process_rx_control_msg(t30_state_t *s, const uint8_t *msg, int len) } else { - unexpected_frame(s, msg, len); + unexpected_non_final_frame(s, msg, len); } break; case (T30_PSA & 0xFE): @@ -4280,7 +4404,7 @@ static void process_rx_control_msg(t30_state_t *s, const uint8_t *msg, int len) } else { - unexpected_frame(s, msg, len); + unexpected_non_final_frame(s, msg, len); } break; case (T30_CIA & 0xFE): @@ -4291,7 +4415,7 @@ static void process_rx_control_msg(t30_state_t *s, const uint8_t *msg, int len) } else { - unexpected_frame(s, msg, len); + unexpected_non_final_frame(s, msg, len); } break; case (T30_ISP & 0xFE): @@ -4302,7 +4426,7 @@ static void process_rx_control_msg(t30_state_t *s, const uint8_t *msg, int len) } else { - unexpected_frame(s, msg, len); + unexpected_non_final_frame(s, msg, len); } break; case (T30_TSI & 0xFE): @@ -5956,8 +6080,8 @@ SPAN_DECLARE(void) t30_get_transfer_statistics(t30_state_t *s, t30_stats_t *t) t->error_correcting_mode = s->error_correcting_mode; t->error_correcting_mode_retries = s->error_correcting_mode_retries; t4_get_transfer_statistics(&s->t4, &stats); - t->pages_tx = s->ecm_tx_page; - t->pages_rx = s->ecm_rx_page; + t->pages_tx = s->tx_page_number; + t->pages_rx = s->rx_page_number; t->pages_in_file = stats.pages_in_file; t->width = stats.width; t->length = stats.length; @@ -5968,6 +6092,10 @@ SPAN_DECLARE(void) t30_get_transfer_statistics(t30_state_t *s, t30_stats_t *t) t->encoding = stats.encoding; t->image_size = stats.line_image_size; t->current_status = s->current_status; +#if 0 + t->rtn_events = s->rtn_events; + t->rtp_events = s->rtp_events; +#endif } /*- End of function --------------------------------------------------------*/ @@ -6000,9 +6128,13 @@ SPAN_DECLARE(int) t30_restart(t30_state_t *s) t30_build_dis_or_dtc(s); memset(&s->rx_info, 0, sizeof(s->rx_info)); release_resources(s); - /* The ECM page number is only reset at call establishment */ - s->ecm_rx_page = 0; - s->ecm_tx_page = 0; + /* The page number is only reset at call establishment */ + s->rx_page_number = 0; + s->tx_page_number = 0; +#if 0 + s->rtn_events = 0; + s->rtp_events = 0; +#endif s->far_end_detected = FALSE; s->timer_t0_t1 = ms_to_samples(DEFAULT_TIMER_T0); if (s->calling_party) diff --git a/libs/spandsp/src/t31.c b/libs/spandsp/src/t31.c index c9871a19b2..307a2c38da 100644 --- a/libs/spandsp/src/t31.c +++ b/libs/spandsp/src/t31.c @@ -25,7 +25,7 @@ * License along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Id: t31.c,v 1.151 2009/07/14 13:54:22 steveu Exp $ + * $Id: t31.c,v 1.152 2009/09/04 14:38:46 steveu Exp $ */ /*! \file */ @@ -176,12 +176,15 @@ enum static int restart_modem(t31_state_t *s, int new_modem); static void hdlc_accept_frame(void *user_data, const uint8_t *msg, int len, int ok); -static void set_rx_handler(t31_state_t *s, span_rx_handler_t *handler, void *user_data); +static void set_rx_handler(t31_state_t *s, span_rx_handler_t *rx_handler, span_rx_fillin_handler_t *fillin_handler, void *user_data); static void set_tx_handler(t31_state_t *s, span_tx_handler_t *handler, void *user_data); static void set_next_tx_handler(t31_state_t *s, span_tx_handler_t *handler, void *user_data); static int v17_v21_rx(void *user_data, const int16_t amp[], int len); +static int v17_v21_rx_fillin(void *user_data, int len); static int v27ter_v21_rx(void *user_data, const int16_t amp[], int len); +static int v27ter_v21_rx_fillin(void *user_data, int len); static int v29_v21_rx(void *user_data, const int16_t amp[], int len); +static int v29_v21_rx_fillin(void *user_data, int len); static int silence_rx(void *user_data, const int16_t amp[], int len); static int cng_rx(void *user_data, const int16_t amp[], int len); static void non_ecm_put_bit(void *user_data, int bit); @@ -1527,7 +1530,7 @@ static int restart_modem(t31_state_t *s, int new_modem) s->at_state.rx_signal_present = FALSE; s->at_state.rx_trained = FALSE; s->rx_frame_received = FALSE; - set_rx_handler(s, (span_rx_handler_t *) &span_dummy_rx, NULL); + set_rx_handler(s, (span_rx_handler_t *) &span_dummy_rx, (span_rx_fillin_handler_t *) &span_dummy_rx_fillin, NULL); use_hdlc = FALSE; switch (s->modem) { @@ -1546,7 +1549,7 @@ static int restart_modem(t31_state_t *s, int new_modem) /* Do V.21/HDLC receive in parallel. The other end may send its first message at any time. The CNG tone will continue until we get a valid preamble. */ - set_rx_handler(s, (span_rx_handler_t *) &cng_rx, s); + set_rx_handler(s, (span_rx_handler_t *) &cng_rx, (span_rx_fillin_handler_t *) &span_dummy_rx_fillin, s); t31_v21_rx(s); set_tx_handler(s, (span_tx_handler_t *) &modem_connect_tones_tx, &t->connect_tx); set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL); @@ -1559,7 +1562,7 @@ static int restart_modem(t31_state_t *s, int new_modem) } else { - set_rx_handler(s, (span_rx_handler_t *) &cng_rx, s); + set_rx_handler(s, (span_rx_handler_t *) &cng_rx, (span_rx_fillin_handler_t *) &span_dummy_rx_fillin, s); t31_v21_rx(s); silence_gen_set(&t->silence_gen, 0); set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen); @@ -1610,7 +1613,7 @@ static int restart_modem(t31_state_t *s, int new_modem) } else { - set_rx_handler(s, (span_rx_handler_t *) &fsk_rx, &t->v21_rx); + set_rx_handler(s, (span_rx_handler_t *) &fsk_rx, (span_rx_fillin_handler_t *) &fsk_rx_fillin, &t->v21_rx); t31_v21_rx(s); } break; @@ -1652,7 +1655,7 @@ static int restart_modem(t31_state_t *s, int new_modem) case FAX_MODEM_V17_RX: if (!s->t38_mode) { - set_rx_handler(s, (span_rx_handler_t *) &v17_v21_rx, s); + set_rx_handler(s, (span_rx_handler_t *) &v17_v21_rx, (span_rx_fillin_handler_t *) &v17_v21_rx_fillin, s); v17_rx_restart(&t->v17_rx, s->bit_rate, s->short_train); /* Allow for +FCERROR/+FRH:3 */ t31_v21_rx(s); @@ -1689,7 +1692,7 @@ static int restart_modem(t31_state_t *s, int new_modem) case FAX_MODEM_V27TER_RX: if (!s->t38_mode) { - set_rx_handler(s, (span_rx_handler_t *) &v27ter_v21_rx, s); + set_rx_handler(s, (span_rx_handler_t *) &v27ter_v21_rx, (span_rx_fillin_handler_t *) &v27ter_v21_rx_fillin, s); v27ter_rx_restart(&t->v27ter_rx, s->bit_rate, FALSE); /* Allow for +FCERROR/+FRH:3 */ t31_v21_rx(s); @@ -1726,7 +1729,7 @@ static int restart_modem(t31_state_t *s, int new_modem) case FAX_MODEM_V29_RX: if (!s->t38_mode) { - set_rx_handler(s, (span_rx_handler_t *) &v29_v21_rx, s); + set_rx_handler(s, (span_rx_handler_t *) &v29_v21_rx, (span_rx_fillin_handler_t *) &v29_v21_rx_fillin, s); v29_rx_restart(&t->v29_rx, s->bit_rate, FALSE); /* Allow for +FCERROR/+FRH:3 */ t31_v21_rx(s); @@ -1752,7 +1755,7 @@ static int restart_modem(t31_state_t *s, int new_modem) case FAX_MODEM_SILENCE_RX: if (!s->t38_mode) { - set_rx_handler(s, (span_rx_handler_t *) &silence_rx, s); + set_rx_handler(s, (span_rx_handler_t *) &silence_rx, (span_rx_fillin_handler_t *) &span_dummy_rx_fillin, s); silence_gen_set(&t->silence_gen, 0); set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen); set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL); @@ -2113,7 +2116,7 @@ SPAN_DECLARE(int) t31_at_rx(t31_state_t *s, const char *t, int len) s->at_state.rx_data_bytes = 0; s->at_state.transmit = FALSE; s->modem = FAX_MODEM_SILENCE_TX; - set_rx_handler(s, (span_rx_handler_t *) &span_dummy_rx, NULL); + set_rx_handler(s, (span_rx_handler_t *) &span_dummy_rx, (span_rx_fillin_handler_t *) &span_dummy_rx_fillin, NULL); t31_set_at_rx_mode(s, AT_MODE_OFFHOOK_COMMAND); at_put_response_code(&s->at_state, AT_RESPONSE_CODE_OK); } @@ -2136,9 +2139,13 @@ SPAN_DECLARE(int) t31_at_rx(t31_state_t *s, const char *t, int len) } /*- End of function --------------------------------------------------------*/ -static void set_rx_handler(t31_state_t *s, span_rx_handler_t *handler, void *user_data) +static void set_rx_handler(t31_state_t *s, + span_rx_handler_t *rx_handler, + span_rx_fillin_handler_t *fillin_handler, + void *user_data) { - s->audio.modems.rx_handler = handler; + s->audio.modems.rx_handler = rx_handler; + s->audio.modems.rx_fillin_handler = fillin_handler; s->audio.modems.rx_user_data = user_data; } /*- End of function --------------------------------------------------------*/ @@ -2208,7 +2215,7 @@ static int v17_v21_rx(void *user_data, const int16_t amp[], int len) /* The fast modem has trained, so we no longer need to run the slow one in parallel. */ span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.17 + V.21 to V.17 (%.2fdBm0)\n", v17_rx_signal_power(&s->v17_rx)); - set_rx_handler(t, (span_rx_handler_t *) &v17_rx, &s->v17_rx); + set_rx_handler(t, (span_rx_handler_t *) &v17_rx, (span_rx_fillin_handler_t *) &v17_rx_fillin, &s->v17_rx); } else { @@ -2218,13 +2225,26 @@ static int v17_v21_rx(void *user_data, const int16_t amp[], int len) /* We have received something, and the fast modem has not trained. We must be receiving valid V.21 */ span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.17 + V.21 to V.21 (%.2fdBm0)\n", fsk_rx_signal_power(&s->v21_rx)); - set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, &s->v21_rx); + set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, (span_rx_fillin_handler_t *) &fsk_rx_fillin, &s->v21_rx); } } return len; } /*- End of function --------------------------------------------------------*/ +static int v17_v21_rx_fillin(void *user_data, int len) +{ + t31_state_t *t; + fax_modems_state_t *s; + + t = (t31_state_t *) user_data; + s = &t->audio.modems; + v17_rx_fillin(&s->v17_rx, len); + fsk_rx_fillin(&s->v21_rx, len); + return 0; +} +/*- End of function --------------------------------------------------------*/ + static int v27ter_v21_rx(void *user_data, const int16_t amp[], int len) { t31_state_t *t; @@ -2238,7 +2258,7 @@ static int v27ter_v21_rx(void *user_data, const int16_t amp[], int len) /* The fast modem has trained, so we no longer need to run the slow one in parallel. */ span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.27ter + V.21 to V.27ter (%.2fdBm0)\n", v27ter_rx_signal_power(&s->v27ter_rx)); - set_rx_handler(t, (span_rx_handler_t *) &v27ter_rx, &s->v27ter_rx); + set_rx_handler(t, (span_rx_handler_t *) &v27ter_rx, (span_rx_fillin_handler_t *) &v27ter_rx_fillin, &s->v27ter_rx); } else { @@ -2248,13 +2268,26 @@ static int v27ter_v21_rx(void *user_data, const int16_t amp[], int len) /* We have received something, and the fast modem has not trained. We must be receiving valid V.21 */ span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.27ter + V.21 to V.21 (%.2fdBm0)\n", fsk_rx_signal_power(&s->v21_rx)); - set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, &s->v21_rx); + set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, (span_rx_fillin_handler_t *) &fsk_rx_fillin, &s->v21_rx); } } return len; } /*- End of function --------------------------------------------------------*/ +static int v27ter_v21_rx_fillin(void *user_data, int len) +{ + t31_state_t *t; + fax_modems_state_t *s; + + t = (t31_state_t *) user_data; + s = &t->audio.modems; + v17_rx_fillin(&s->v27ter_rx, len); + fsk_rx_fillin(&s->v21_rx, len); + return 0; +} +/*- End of function --------------------------------------------------------*/ + static int v29_v21_rx(void *user_data, const int16_t amp[], int len) { t31_state_t *t; @@ -2268,7 +2301,7 @@ static int v29_v21_rx(void *user_data, const int16_t amp[], int len) /* The fast modem has trained, so we no longer need to run the slow one in parallel. */ span_log(&s->logging, SPAN_LOG_FLOW, "Switching from V.29 + V.21 to V.29 (%.2fdBm0)\n", v29_rx_signal_power(&s->v29_rx)); - set_rx_handler(t, (span_rx_handler_t *) &v29_rx, &s->v29_rx); + set_rx_handler(t, (span_rx_handler_t *) &v29_rx, (span_rx_fillin_handler_t *) &v29_rx_fillin, &s->v29_rx); } else { @@ -2278,13 +2311,26 @@ static int v29_v21_rx(void *user_data, const int16_t amp[], int len) /* We have received something, and the fast modem has not trained. We must be receiving valid V.21 */ span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.29 + V.21 to V.21 (%.2fdBm0)\n", fsk_rx_signal_power(&s->v21_rx)); - set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, &s->v21_rx); + set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, (span_rx_fillin_handler_t *) &fsk_rx_fillin, &s->v21_rx); } } return len; } /*- End of function --------------------------------------------------------*/ +static int v29_v21_rx_fillin(void *user_data, int len) +{ + t31_state_t *t; + fax_modems_state_t *s; + + t = (t31_state_t *) user_data; + s = &t->audio.modems; + v29_rx_fillin(&s->v29_rx, len); + fsk_rx_fillin(&s->v21_rx, len); + return 0; +} +/*- End of function --------------------------------------------------------*/ + SPAN_DECLARE(int) t31_rx(t31_state_t *s, int16_t amp[], int len) { int i; diff --git a/libs/spandsp/src/t38_terminal.c b/libs/spandsp/src/t38_terminal.c index 4ea4dd4579..1e9c70926f 100644 --- a/libs/spandsp/src/t38_terminal.c +++ b/libs/spandsp/src/t38_terminal.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: t38_terminal.c,v 1.127 2009/07/14 13:54:22 steveu Exp $ + * $Id: t38_terminal.c,v 1.128 2009/09/04 14:38:46 steveu Exp $ */ /*! \file */ @@ -93,9 +93,9 @@ enum { - T38_CHUNKING_MERGE_FCS_WITH_DATA = 0x0001, - T38_CHUNKING_WHOLE_FRAMES = 0x0002, - T38_CHUNKING_ALLOW_TEP_TIME = 0x0004 + T38_CHUNKING_MERGE_FCS_WITH_DATA = 0x0001, + T38_CHUNKING_WHOLE_FRAMES = 0x0002, + T38_CHUNKING_ALLOW_TEP_TIME = 0x0004 }; enum diff --git a/libs/spandsp/tests/Makefile.am b/libs/spandsp/tests/Makefile.am index 07083318f4..253d398d31 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.116 2009/05/30 15:23:13 steveu Exp $ +## $Id: Makefile.am,v 1.117 2009/09/22 13:11:04 steveu Exp $ AM_CFLAGS = $(COMP_VENDOR_CFLAGS) AM_LDFLAGS = $(COMP_VENDOR_LDFLAGS) @@ -99,6 +99,7 @@ noinst_PROGRAMS = adsi_tests \ sig_tone_tests \ super_tone_rx_tests \ super_tone_tx_tests \ + swept_tone_tests \ t4_tests \ t31_tests \ t38_core_tests \ @@ -273,6 +274,9 @@ super_tone_rx_tests_LDADD = -L$(top_builddir)/spandsp-sim -lspandsp-sim $(LIBDIR super_tone_tx_tests_SOURCES = super_tone_tx_tests.c super_tone_tx_tests_LDADD = -L$(top_builddir)/spandsp-sim -lspandsp-sim $(LIBDIR) -lspandsp +swept_tone_tests_SOURCES = swept_tone_tests.c +swept_tone_tests_LDADD = -L$(top_builddir)/spandsp-sim -lspandsp-sim $(LIBDIR) -lspandsp + t4_tests_SOURCES = t4_tests.c t4_tests_LDADD = $(LIBDIR) -lspandsp diff --git a/libs/spandsp/tests/fax_decode.c b/libs/spandsp/tests/fax_decode.c index 131244db23..ec5a493f4c 100644 --- a/libs/spandsp/tests/fax_decode.c +++ b/libs/spandsp/tests/fax_decode.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: fax_decode.c,v 1.56 2009/05/30 15:23:13 steveu Exp $ + * $Id: fax_decode.c,v 1.57 2009/09/15 14:01:53 steveu Exp $ */ /*! \page fax_decode_page FAX decoder @@ -124,7 +124,7 @@ static void print_frame(const char *io, const uint8_t *fr, int frlen) type = fr[2] & 0xFE; if (type == T30_DIS || type == T30_DTC || type == T30_DCS) t30_decode_dis_dtc_dcs(&t30_dummy, fr, frlen); - if (type == T30_NSF) + if (type == T30_NSF || type == T30_NSS || type == T30_NSC) { if (t35_decode(&fr[3], frlen - 3, &country, &vendor, &model)) { diff --git a/libs/spandsp/tests/line_model_tests.c b/libs/spandsp/tests/line_model_tests.c index b769e717e6..309e2e7890 100644 --- a/libs/spandsp/tests/line_model_tests.c +++ b/libs/spandsp/tests/line_model_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: line_model_tests.c,v 1.27 2009/05/30 15:23:14 steveu Exp $ + * $Id: line_model_tests.c,v 1.28 2009/09/23 16:02:59 steveu Exp $ */ /*! \page line_model_tests_page Telephony line model tests @@ -62,7 +62,7 @@ #define IN_FILE_NAME1 "line_model_test_in1.wav" #define IN_FILE_NAME2 "line_model_test_in2.wav" #define OUT_FILE_NAME1 "line_model_one_way_test_out.wav" -#define OUT_FILE_NAME "line_model_test_out.wav" +#define OUT_FILE_NAME2 "line_model_two_way_test_out.wav" int channel_codec; int rbs_pattern; @@ -128,10 +128,17 @@ static void test_one_way_model(int line_model_no, int speech_test) awgn_init_dbm0(&noise1, 1234567, -10.0f); - if ((inhandle1 = sf_open_telephony_read(IN_FILE_NAME1, 1)) == NULL) + if (speech_test) { - fprintf(stderr, " Cannot open audio file '%s'\n", IN_FILE_NAME1); - exit(2); + if ((inhandle1 = sf_open_telephony_read(IN_FILE_NAME1, 1)) == NULL) + { + fprintf(stderr, " Cannot open audio file '%s'\n", IN_FILE_NAME1); + exit(2); + } + } + else + { + inhandle1 = NULL; } if ((outhandle = sf_open_telephony_write(OUT_FILE_NAME1, 1)) == NULL) { @@ -167,10 +174,13 @@ static void test_one_way_model(int line_model_no, int speech_test) exit(2); } } - if (sf_close(inhandle1)) + if (speech_test) { - fprintf(stderr, " Cannot close audio file '%s'\n", IN_FILE_NAME1); - exit(2); + if (sf_close(inhandle1)) + { + fprintf(stderr, " Cannot close audio file '%s'\n", IN_FILE_NAME1); + exit(2); + } } if (sf_close(outhandle)) { @@ -208,19 +218,27 @@ static void test_both_ways_model(int line_model_no, int speech_test) awgn_init_dbm0(&noise1, 1234567, -10.0f); awgn_init_dbm0(&noise2, 1234567, -10.0f); - if ((inhandle1 = sf_open_telephony_read(IN_FILE_NAME1, 1)) == NULL) + if (speech_test) { - fprintf(stderr, " Cannot open audio file '%s'\n", IN_FILE_NAME1); - exit(2); + if ((inhandle1 = sf_open_telephony_read(IN_FILE_NAME1, 1)) == NULL) + { + fprintf(stderr, " Cannot open audio file '%s'\n", IN_FILE_NAME1); + exit(2); + } + if ((inhandle2 = sf_open_telephony_read(IN_FILE_NAME2, 1)) == NULL) + { + fprintf(stderr, " Cannot open audio file '%s'\n", IN_FILE_NAME2); + exit(2); + } } - if ((inhandle2 = sf_open_telephony_read(IN_FILE_NAME2, 1)) == NULL) + else { - fprintf(stderr, " Cannot open audio file '%s'\n", IN_FILE_NAME2); - exit(2); + inhandle1 = + inhandle2 = NULL; } - if ((outhandle = sf_open_telephony_write(OUT_FILE_NAME, 2)) == NULL) + if ((outhandle = sf_open_telephony_write(OUT_FILE_NAME2, 2)) == NULL) { - fprintf(stderr, " Cannot create audio file '%s'\n", OUT_FILE_NAME); + fprintf(stderr, " Cannot create audio file '%s'\n", OUT_FILE_NAME2); exit(2); } for (i = 0; i < 10000; i++) @@ -261,25 +279,80 @@ static void test_both_ways_model(int line_model_no, int speech_test) exit(2); } } - if (sf_close(inhandle1)) + if (speech_test) { - fprintf(stderr, " Cannot close audio file '%s'\n", IN_FILE_NAME1); - exit(2); - } - if (sf_close(inhandle2)) - { - fprintf(stderr, " Cannot close audio file '%s'\n", IN_FILE_NAME2); - exit(2); + if (sf_close(inhandle1)) + { + fprintf(stderr, " Cannot close audio file '%s'\n", IN_FILE_NAME1); + exit(2); + } + if (sf_close(inhandle2)) + { + fprintf(stderr, " Cannot close audio file '%s'\n", IN_FILE_NAME2); + exit(2); + } } if (sf_close(outhandle)) { - fprintf(stderr, " Cannot close audio file '%s'\n", OUT_FILE_NAME); + fprintf(stderr, " Cannot close audio file '%s'\n", OUT_FILE_NAME2); exit(2); } both_ways_line_model_release(model); } /*- End of function --------------------------------------------------------*/ +static void test_line_filter(int line_model_no) +{ + float out; + double sumin; + double sumout; + int i; + int j; + int p; + int ptr; + int len; + swept_tone_state_t *s; + float filter[129]; + int16_t buf[BLOCK_LEN]; + + s = swept_tone_init(NULL, 200.0f, 3900.0f, -10.0f, 120*SAMPLE_RATE, 0); + for (j = 0; j < 129; j++) + filter[j] = 0.0f; + ptr = 0; + for (;;) + { + if ((len = swept_tone(s, buf, BLOCK_LEN)) <= 0) + break; + sumin = 0.0; + sumout = 0.0; + for (i = 0; i < len; i++) + { + /* Add the sample in the filter buffer */ + p = ptr; + filter[p] = buf[i]; + if (++p == 129) + p = 0; + ptr = p; + + /* Apply the filter */ + out = 0.0f; + for (j = 0; j < 129; j++) + { + out += line_models[line_model_no][128 - j]*filter[p]; + if (++p >= 129) + p = 0; + } + sumin += buf[i]*buf[i]; + sumout += out*out; + } + /*endfor*/ + printf("%7.1f %f\n", swept_tone_current_frequency(s), 10.0*log10(sumout/sumin)); + } + /*endfor*/ + swept_tone_free(s); +} +/*- End of function --------------------------------------------------------*/ + int main(int argc, char *argv[]) { int line_model_no; @@ -319,6 +392,7 @@ int main(int argc, char *argv[]) complexify_tests(); test_one_way_model(line_model_no, speech_test); test_both_ways_model(line_model_no, speech_test); + test_line_filter(line_model_no); } /*- End of function --------------------------------------------------------*/ /*- End of file ------------------------------------------------------------*/ diff --git a/libs/spandsp/tests/regression_tests.sh b/libs/spandsp/tests/regression_tests.sh index 4f77c9c54a..efd02619fb 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.58 2009/05/19 14:47:02 steveu Exp $ +# $Id: regression_tests.sh,v 1.59 2009/09/22 13:28:18 steveu Exp $ # ITUTESTS_TIF=../test-data/itu/fax/itutests.tif @@ -468,6 +468,16 @@ echo super_tone_rx_tests not enabled #echo super_tone_tx_tests completed OK echo super_tone_tx_tests not enabled +#./swept_tone_tests >$STDOUT_DEST 2>$STDERR_DEST +#RETVAL=$? +#if [ $RETVAL != 0 ] +#then +# echo swept_tone_tests failed! +# exit $RETVAL +#fi +#echo swept_tone_tests completed OK +echo swept_tone_tests not enabled + ./t31_tests -r >$STDOUT_DEST 2>$STDERR_DEST RETVAL=$? if [ $RETVAL != 0 ] diff --git a/libs/spandsp/tests/sig_tone_tests.c b/libs/spandsp/tests/sig_tone_tests.c index e795fc87f9..e2afea4a3d 100644 --- a/libs/spandsp/tests/sig_tone_tests.c +++ b/libs/spandsp/tests/sig_tone_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: sig_tone_tests.c,v 1.25 2009/05/30 15:23:14 steveu Exp $ + * $Id: sig_tone_tests.c,v 1.27 2009/09/23 16:02:59 steveu Exp $ */ /*! \file */ @@ -58,112 +58,97 @@ static int sampleno = 0; static int tone_1_present = 0; static int tone_2_present = 0; -static int ping = 0; +static int tx_section = 0; +static int dial_pulses = 0; -void map_frequency_response(sig_tone_rx_state_t *s); - -static int tx_handler(void *user_data, int what) +static void tx_handler(void *user_data, int what, int level, int duration) { - //printf("What - %d\n", what); - if ((what & SIG_TONE_UPDATE_REQUEST)) + sig_tone_tx_state_t *s; + + s = (sig_tone_tx_state_t *) user_data; + //printf("What - %d, duration - %d\n", what, duration); + if ((what & SIG_TONE_TX_UPDATE_REQUEST)) { printf("Tx: update request\n"); - /* The signaling processor wants to know what to do next */ - if (sampleno < ms_to_samples(100)) + /* The sig tone transmit side wants to know what to do next */ + switch (tx_section) { - /* 100ms off-hook */ - printf("100ms off-hook - %d samples\n", 800 - sampleno); - return 0x02 | ((ms_to_samples(100) - sampleno) << 16); - } - else if (sampleno < ms_to_samples(600)) - { - /* 500ms idle */ - printf("500ms idle - %d samples\n", ms_to_samples(600) - sampleno); - return 0x02 | SIG_TONE_1_PRESENT | ((ms_to_samples(600) - sampleno) << 16); - } - else if (sampleno < ms_to_samples(700)) - { - /* 100ms seize */ - printf("100ms seize - %d samples\n", ms_to_samples(700) - sampleno); - return 0x02 | ((ms_to_samples(700) - sampleno) << 16); - } - else if (sampleno < ms_to_samples(1700)) - { - if (ping) - { - printf("33ms break - %d samples\n", ms_to_samples(33)); - ping = !ping; - return 0x02 | (ms_to_samples(33) << 16); - } + case 0: + printf("33ms break - %d samples\n", ms_to_samples(33)); + tx_section++; + sig_tone_tx_set_mode(s, SIG_TONE_1_PRESENT, ms_to_samples(33)); + break; + case 1: + printf("67ms make - %d samples\n", ms_to_samples(67)); + if (++dial_pulses == 9) + tx_section++; else - { - printf("67ms make - %d samples\n", ms_to_samples(67)); - ping = !ping; - return 0x02 | SIG_TONE_1_PRESENT | (ms_to_samples(67) << 16); - } - /*endif*/ + tx_section--; + sig_tone_tx_set_mode(s, 0, ms_to_samples(67)); + break; + case 2: + tx_section++; + sig_tone_tx_set_mode(s, SIG_TONE_1_PRESENT, ms_to_samples(600)); + break; + case 3: + sig_tone_tx_set_mode(s, SIG_TONE_1_PRESENT | SIG_TONE_TX_PASSTHROUGH, 0); + break; } - else - { - return 0x02 | SIG_TONE_1_PRESENT | ((ms_to_samples(700) - sampleno) << 16) | SIG_TONE_TX_PASSTHROUGH; - } - /*endif*/ + /*endswitch*/ } /*endif*/ - return 0; } /*- End of function --------------------------------------------------------*/ -static int rx_handler(void *user_data, int what) +static void rx_handler(void *user_data, int what, int level, int duration) { - //printf("What - %d\n", what); + float ms; + + ms = 1000.0f*(float) duration/(float) SAMPLE_RATE; + printf("What - %d, duration - %d\n", what, duration); if ((what & SIG_TONE_1_CHANGE)) { tone_1_present = what & SIG_TONE_1_PRESENT; - printf("Rx: tone 1 is %s after %d samples\n", (tone_1_present) ? "on" : "off", (what >> 16) & 0xFFFF); + printf("Rx: tone 1 is %s after %d samples (%fms)\n", (tone_1_present) ? "on" : "off", duration, ms); } /*endif*/ if ((what & SIG_TONE_2_CHANGE)) { tone_2_present = what & SIG_TONE_2_PRESENT; - printf("Rx: tone 2 is %s after %d samples\n", (tone_2_present) ? "on" : "off", (what >> 16) & 0xFFFF); + printf("Rx: tone 2 is %s after %d samples (%fms)\n", (tone_2_present) ? "on" : "off", duration, ms); } /*endif*/ - return 0; } /*- End of function --------------------------------------------------------*/ -void map_frequency_response(sig_tone_rx_state_t *s) +static void map_frequency_response(sig_tone_rx_state_t *s) { int16_t buf[8192]; - awgn_state_t noise_source; int i; - int f; - uint32_t phase_acc; - int32_t phase_rate; - int32_t scaling; - double sum; + int len; + double sumin; + double sumout; + swept_tone_state_t *swept; /* Things like noise don't highlight the frequency response of the high Q notch very well. We use a slowly swept frequency to check it. */ - awgn_init_dbm0(&noise_source, 1234567, -10.0f); - for (f = 1; f < 4000; f++) + swept = swept_tone_init(NULL, 200.0f, 3900.0f, -10.0f, 120*SAMPLE_RATE, 0); + for (;;) { - phase_rate = dds_phase_rate(f); - scaling = dds_scaling_dbm0(-10); - phase_acc = 0; - for (i = 0; i < 8192; i++) - buf[i] = dds_mod(&phase_acc, phase_rate, scaling, 0); + if ((len = swept_tone(swept, buf, SAMPLES_PER_CHUNK)) <= 0) + break; + sumin = 0.0; + for (i = 0; i < len; i++) + sumin += (double) buf[i]*(double) buf[i]; + sig_tone_rx(s, buf, len); + sumout = 0.0; + for (i = 0; i < len; i++) + sumout += (double) buf[i]*(double) buf[i]; /*endfor*/ - sig_tone_rx(s, buf, 8192); - sum = 0.0; - for (i = 1000; i < 8192; i++) - sum += (double) buf[i]*(double) buf[i]; - /*endfor*/ - sum = sqrt(sum); - printf("%7d %f\n", f, sum); + printf("%7.1f %f\n", swept_tone_current_frequency(swept), 10.0*log10(sumout/sumin)); } /*endfor*/ + swept_tone_free(swept); } /*- End of function --------------------------------------------------------*/ @@ -189,45 +174,56 @@ int main(int argc, char *argv[]) } /*endif*/ - awgn_init_dbm0(&noise_source, 1234567, -10.0f); + awgn_init_dbm0(&noise_source, 1234567, -20.0f); for (type = 1; type <= 3; type++) { sampleno = 0; tone_1_present = 0; tone_2_present = 0; - ping = 0; + tx_section = 0; munge = NULL; switch (type) { case 1: printf("2280Hz tests.\n"); munge = codec_munge_init(MUNGE_CODEC_ALAW, 0); - sig_tone_tx_init(&tx_state, SIG_TONE_2280HZ, tx_handler, NULL); - sig_tone_rx_init(&rx_state, SIG_TONE_2280HZ, rx_handler, NULL); + sig_tone_tx_init(&tx_state, SIG_TONE_2280HZ, tx_handler, &tx_state); + sig_tone_rx_init(&rx_state, SIG_TONE_2280HZ, rx_handler, &rx_state); rx_state.current_rx_tone |= SIG_TONE_RX_PASSTHROUGH; break; case 2: - printf("26000Hz tests.\n"); + printf("2600Hz tests.\n"); munge = codec_munge_init(MUNGE_CODEC_ULAW, 0); - sig_tone_tx_init(&tx_state, SIG_TONE_2600HZ, tx_handler, NULL); - sig_tone_rx_init(&rx_state, SIG_TONE_2600HZ, rx_handler, NULL); + sig_tone_tx_init(&tx_state, SIG_TONE_2600HZ, tx_handler, &tx_state); + sig_tone_rx_init(&rx_state, SIG_TONE_2600HZ, rx_handler, &rx_state); rx_state.current_rx_tone |= SIG_TONE_RX_PASSTHROUGH; break; case 3: - printf("2400Hz/26000Hz tests.\n"); + printf("2400Hz/2600Hz tests.\n"); munge = codec_munge_init(MUNGE_CODEC_ULAW, 0); - sig_tone_tx_init(&tx_state, SIG_TONE_2400HZ_2600HZ, tx_handler, NULL); - sig_tone_rx_init(&rx_state, SIG_TONE_2400HZ_2600HZ, rx_handler, NULL); + sig_tone_tx_init(&tx_state, SIG_TONE_2400HZ_2600HZ, tx_handler, &tx_state); + sig_tone_rx_init(&rx_state, SIG_TONE_2400HZ_2600HZ, rx_handler, &rx_state); rx_state.current_rx_tone |= SIG_TONE_RX_PASSTHROUGH; break; } /*endswitch*/ - - //map_frequency_response(&rx_state); + /* Set to the default of hook condition */ + sig_tone_rx_set_mode(&rx_state, SIG_TONE_RX_PASSTHROUGH | SIG_TONE_RX_FILTER_TONE, 0); + sig_tone_tx_set_mode(&tx_state, SIG_TONE_1_PRESENT | SIG_TONE_2_PRESENT | SIG_TONE_TX_PASSTHROUGH, 0); - for (sampleno = 0; sampleno < 20000; sampleno += SAMPLES_PER_CHUNK) + map_frequency_response(&rx_state); + + sig_tone_rx_set_mode(&rx_state, SIG_TONE_RX_PASSTHROUGH, 0); + for (sampleno = 0; sampleno < 30000; sampleno += SAMPLES_PER_CHUNK) { + if (sampleno == 8000) + { + /* 100ms seize */ + printf("100ms seize - %d samples\n", ms_to_samples(100)); + dial_pulses = 0; + sig_tone_tx_set_mode(&tx_state, 0, ms_to_samples(100)); + } for (i = 0; i < SAMPLES_PER_CHUNK; i++) amp[i] = awgn(&noise_source); /*endfor*/ diff --git a/libs/spandsp/tests/swept_tone_tests.c b/libs/spandsp/tests/swept_tone_tests.c new file mode 100644 index 0000000000..010fbcd3d5 --- /dev/null +++ b/libs/spandsp/tests/swept_tone_tests.c @@ -0,0 +1,101 @@ +/* + * SpanDSP - a series of DSP components for telephony + * + * swept_tone_tests.c + * + * Written by Steve Underwood + * + * Copyright (C) 2009 Steve Underwood + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * $Id: swept_tone_tests.c,v 1.2 2009/09/22 13:28:18 steveu Exp $ + */ + +/*! \file */ + +#if defined(HAVE_CONFIG_H) +#include "config.h" +#endif + +#include +#include +#include +#include +#include + +#include "spandsp.h" +#include "spandsp-sim.h" + +#define OUTPUT_FILE_NAME "swept_tone.wav" + +#define BLOCK_LEN 160 + +int main(int argc, char *argv[]) +{ + int i; + int j; + int outframes; + int len; + SNDFILE *outhandle; + power_meter_t meter; + swept_tone_state_t *s; + int16_t buf[BLOCK_LEN]; + + power_meter_init(&meter, 10); + + if ((outhandle = sf_open_telephony_write(OUTPUT_FILE_NAME, 1)) == NULL) + { + fprintf(stderr, " Cannot create audio file '%s'\n", OUTPUT_FILE_NAME); + exit(2); + } + + printf("Test with swept tone.\n"); + s = swept_tone_init(NULL, 200.0f, 3900.0f, -10.0f, 60*SAMPLE_RATE, 1); + for (j = 0; j < 60*SAMPLE_RATE; j += BLOCK_LEN) + { + len = swept_tone(s, buf, BLOCK_LEN); + for (i = 0; i < len; i++) + power_meter_update(&meter, buf[i]); + outframes = sf_writef_short(outhandle, buf, len); + if (outframes != len) + { + fprintf(stderr, " Error writing audio file\n"); + exit(2); + } +#if 0 + printf("Current freq %.1fHz, Level is %fdBOv/%fdBm0\n", + swept_tone_current_frequency(s), + power_meter_current_dbov(&meter), + power_meter_current_dbm0(&meter)); +#else + printf("%.1f %f\n", + swept_tone_current_frequency(s), + power_meter_current_dbm0(&meter)); +#endif + } + + if (sf_close(outhandle) != 0) + { + fprintf(stderr, " Cannot close audio file '%s'\n", OUTPUT_FILE_NAME); + exit(2); + } + + printf("Tests passed.\n"); + return 0; +} +/*- End of function --------------------------------------------------------*/ +/*- End of file ------------------------------------------------------------*/