update to spandsp snapshot 20091005

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@15084 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
Anthony Minessale 2009-10-05 14:34:26 +00:00
parent 4e440b6e4c
commit dab4d9068d
46 changed files with 1316 additions and 505 deletions

View File

@ -1 +1 @@
Wed Oct 1 00:08:32 EDT 2008 Mon Oct 5 09:33:55 CDT 2009

View File

@ -16,7 +16,7 @@
# License along with this program; if not, write to the Free Software # License along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # 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 # @start 1
@ -108,20 +108,20 @@ else
CXXFLAGS=${CXXFLAGS-"-g -O2"} CXXFLAGS=${CXXFLAGS-"-g -O2"}
fi fi
AC_DEFUN([REMOVE_FROM_VAR],[ AC_DEFUN([REMOVE_FROM_VAR],[
new_val="" new_val=""
removed=0 removed=0
for i in $$1; do for i in $$1; do
if test "x$i" != "x$2"; then if test "x$i" != "x$2"; then
new_val="$new_val $i" new_val="$new_val $i"
else else
removed=1 removed=1
fi fi
done done
if test $removed = "1"; then if test $removed = "1"; then
echo " removed \"$2\" from $1" echo " removed \"$2\" from $1"
$1=$new_val $1=$new_val
fi fi
]) ])
AC_C_CONST 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(sse4a, [ --enable-sse4a Enable SSE4A support])
AC_ARG_ENABLE(sse5, [ --enable-sse5 Enable SSE5 support]) AC_ARG_ENABLE(sse5, [ --enable-sse5 Enable SSE5 support])
AC_ARG_ENABLE(fixed_point, [ --enable-fixed-point Enable fixed point 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_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_ERROR_AT_LINE
AC_FUNC_VPRINTF AC_FUNC_VPRINTF

View File

@ -22,7 +22,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 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) #if defined(HAVE_CONFIG_H)
@ -54,7 +54,7 @@
#define NULL (void *) 0 #define NULL (void *) 0
#endif #endif
float null_line_model[] = static const float null_line_model[] =
{ {
0.0, 0.0,
0.0, 0.0,
@ -187,7 +187,7 @@ float null_line_model[] =
1.0 1.0
}; };
static float *models[] = SPAN_DECLARE_DATA const float *line_models[] =
{ {
null_line_model, /* 0 */ null_line_model, /* 0 */
proakis_line_model, 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; s->near_buf_ptr = p;
/* Apply the filter */ /* Apply the filter */
sum = 0; sum = 0.0f;
for (j = 0; j < s->near_filter_len; j++) for (j = 0; j < s->near_filter_len; j++)
{ {
sum += s->near_filter[j]*s->near_buf[p]; 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; s->far_buf_ptr = p;
/* Apply the filter */ /* Apply the filter */
sum = 0; sum = 0.0f;
for (j = 0; j < s->far_filter_len; j++) for (j = 0; j < s->far_filter_len; j++)
{ {
sum += s->far_filter[j]*s->far_buf[p]; 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->munge = codec_munge_init(codec, rbs_pattern);
s->near_filter = models[model]; s->near_filter = line_models[model];
s->near_filter_len = 129; s->near_filter_len = 129;
s->far_filter = models[model]; s->far_filter = line_models[model];
s->far_filter_len = 129; s->far_filter_len = 129;
/* Put half the noise in each analogue section */ /* 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->line1.bulk_delay_ptr = 0;
s->line2.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->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->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->line1.far_filter_len = 129;
s->line2.far_filter = models[model2]; s->line2.far_filter = line_models[model2];
s->line2.far_filter_len = 129; s->line2.far_filter_len = 129;
/* Put half the noise in each analogue section */ /* Put half the noise in each analogue section */

View File

@ -22,7 +22,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 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 /*! \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); 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]; 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) #if defined(HAVE_FFTW3_H)
in[i][0] = amp*cosf(phase); in[i][0] = amp*cosf(phase);
in[i][1] = amp*sinf(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, "/* 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"); fprintf(outfile, "{\n");
/* Normalise the filter's gain */ /* Normalise the filter's gain */
pw = 0.0f; pw = 0.0f;
@ -955,7 +956,8 @@ static void generate_proakis(void)
/* Linear interpolation */ /* Linear interpolation */
amp = ((1.0f - offset)*proakis[index].amp + offset*proakis[index + 1].amp)/2.3f; 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; 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) #if defined(HAVE_FFTW3_H)
in[i][0] = amp*cosf(phase); in[i][0] = amp*cosf(phase);
in[i][1] = amp*sinf(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, "/* Medium range telephone line response\n");
fprintf(outfile, " (from p 537, Digital Communication, John G. Proakis */\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"); fprintf(outfile, "{\n");
/* Normalise the filter's gain */ /* Normalise the filter's gain */
pw = 0.0f; pw = 0.0f;

View File

@ -22,7 +22,7 @@
* License along with this program; if not, write to the Free Software * License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 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 */ /*! \file */
@ -132,6 +132,8 @@ extern "C"
{ {
#endif #endif
SPAN_DECLARE_DATA extern const float *line_models[];
SPAN_DECLARE(void) both_ways_line_model(both_ways_line_model_state_t *s, SPAN_DECLARE(void) both_ways_line_model(both_ways_line_model_state_t *s,
int16_t output1[], int16_t output1[],
const int16_t input1[], const int16_t input1[],

View File

@ -1,6 +1,7 @@
<!-- FAX test scripts --> <!-- FAX test scripts -->
<!ELEMENT fax-tests (config|messages|test-group)* > <!ELEMENT fax-tests (config|messages|test-group)* >
<!ELEMENT config (path)* > <!ELEMENT config (path)* >
<!ELEMENT path (EMPTY)* >
<!ATTLIST path <!ATTLIST path
type CDATA #REQUIRED type CDATA #REQUIRED
value CDATA #REQUIRED value CDATA #REQUIRED

View File

@ -16,7 +16,7 @@
## License along with this program; if not, write to the Free Software ## License along with this program; if not, write to the Free Software
## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
## ##
## $Id: Makefile.am,v 1.135 2009/07/12 09:23:09 steveu Exp $ ## $Id: Makefile.am,v 1.137 2009/09/22 14:52:31 steveu Exp $
AM_CFLAGS = $(COMP_VENDOR_CFLAGS) AM_CFLAGS = $(COMP_VENDOR_CFLAGS)
AM_LDFLAGS = $(COMP_VENDOR_LDFLAGS) AM_LDFLAGS = $(COMP_VENDOR_LDFLAGS)
@ -110,6 +110,7 @@ libspandsp_la_SOURCES = adsi.c \
silence_gen.c \ silence_gen.c \
super_tone_rx.c \ super_tone_rx.c \
super_tone_tx.c \ super_tone_tx.c \
swept_tone.c \
t4.c \ t4.c \
t30.c \ t30.c \
t30_api.c \ t30_api.c \
@ -188,6 +189,7 @@ nobase_include_HEADERS = spandsp/adsi.h \
spandsp/silence_gen.h \ spandsp/silence_gen.h \
spandsp/super_tone_rx.h \ spandsp/super_tone_rx.h \
spandsp/super_tone_tx.h \ spandsp/super_tone_tx.h \
spandsp/swept_tone.h \
spandsp/t4.h \ spandsp/t4.h \
spandsp/t30.h \ spandsp/t30.h \
spandsp/t30_api.h \ spandsp/t30_api.h \
@ -226,6 +228,7 @@ nobase_include_HEADERS = spandsp/adsi.h \
spandsp/private/bert.h \ spandsp/private/bert.h \
spandsp/private/bitstream.h \ spandsp/private/bitstream.h \
spandsp/private/dtmf.h \ spandsp/private/dtmf.h \
spandsp/private/echo.h \
spandsp/private/fax.h \ spandsp/private/fax.h \
spandsp/private/fax_modems.h \ spandsp/private/fax_modems.h \
spandsp/private/fsk.h \ spandsp/private/fsk.h \
@ -238,6 +241,7 @@ nobase_include_HEADERS = spandsp/adsi.h \
spandsp/private/logging.h \ spandsp/private/logging.h \
spandsp/private/lpc10.h \ spandsp/private/lpc10.h \
spandsp/private/modem_connect_tones.h \ spandsp/private/modem_connect_tones.h \
spandsp/private/modem_echo.h \
spandsp/private/noise.h \ spandsp/private/noise.h \
spandsp/private/oki_adpcm.h \ spandsp/private/oki_adpcm.h \
spandsp/private/queue.h \ spandsp/private/queue.h \
@ -246,6 +250,7 @@ nobase_include_HEADERS = spandsp/adsi.h \
spandsp/private/silence_gen.h \ spandsp/private/silence_gen.h \
spandsp/private/super_tone_rx.h \ spandsp/private/super_tone_rx.h \
spandsp/private/super_tone_tx.h \ spandsp/private/super_tone_tx.h \
spandsp/private/swept_tone.h \
spandsp/private/t30.h \ spandsp/private/t30.h \
spandsp/private/t31.h \ spandsp/private/t31.h \
spandsp/private/t38_core.h \ spandsp/private/t38_core.h \

View File

@ -25,7 +25,7 @@
* License along with this program; if not, write to the Free Software * License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *
* $Id: at_interpreter.c,v 1.40 2009/07/10 13:15:56 steveu Exp $ * $Id: at_interpreter.c,v 1.41 2009/10/03 04:37:25 steveu Exp $
*/ */
/*! \file */ /*! \file */
@ -80,7 +80,7 @@ enum
static at_profile_t profiles[3] = static at_profile_t profiles[3] =
{ {
{ {
#if defined(_MSC_VER) || defined(__sunos) || defined(__solaris) || defined(__sun) #if defined(_MSC_VER) || defined(__sunos) || defined(__solaris) || defined(__sun)
/*.echo =*/ TRUE, /*.echo =*/ TRUE,
/*.verbose =*/ TRUE, /*.verbose =*/ TRUE,
/*.result_code_format =*/ ASCII_RESULT_CODES, /*.result_code_format =*/ ASCII_RESULT_CODES,

View File

@ -27,7 +27,7 @@
* License along with this program; if not, write to the Free Software * License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *
* $Id: echo.c,v 1.32 2009/02/10 13:06:46 steveu Exp $ * $Id: echo.c,v 1.33 2009/09/22 13:11:04 steveu Exp $
*/ */
/*! \file */ /*! \file */
@ -102,6 +102,8 @@
#include "spandsp/bit_operations.h" #include "spandsp/bit_operations.h"
#include "spandsp/echo.h" #include "spandsp/echo.h"
#include "spandsp/private/echo.h"
#if !defined(NULL) #if !defined(NULL)
#define NULL (void *) 0 #define NULL (void *) 0
#endif #endif

View File

@ -23,7 +23,7 @@
* License along with this program; if not, write to the Free Software * License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *
* $Id: fax.c,v 1.93 2009/05/24 07:18:36 steveu Exp $ * $Id: fax.c,v 1.94 2009/09/04 14:38:46 steveu Exp $
*/ */
/*! \file */ /*! \file */
@ -128,9 +128,13 @@ static void hdlc_underflow_handler(void *user_data)
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
static void set_rx_handler(fax_state_t *s, span_rx_handler_t *handler, void *user_data) static void set_rx_handler(fax_state_t *s,
span_rx_handler_t *rx_handler,
span_rx_fillin_handler_t *fillin_handler,
void *user_data)
{ {
s->modems.rx_handler = handler; s->modems.rx_handler = rx_handler;
s->modems.rx_fillin_handler = fillin_handler;
s->modems.rx_user_data = user_data; s->modems.rx_user_data = user_data;
} }
/*- End of function --------------------------------------------------------*/ /*- 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 /* The fast modem has trained, so we no longer need to run the slow
one in parallel. */ 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)); 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 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 /* We have received something, and the fast modem has not trained. We must
be receiving valid V.21 */ 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)); 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; return 0;
} }
/*- End of function --------------------------------------------------------*/ /*- 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) static int v27ter_v21_rx(void *user_data, const int16_t amp[], int len)
{ {
fax_state_t *t; 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 /* The fast modem has trained, so we no longer need to run the slow
one in parallel. */ 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)); 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 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 /* We have received something, and the fast modem has not trained. We must
be receiving valid V.21 */ 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)); 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; return 0;
} }
/*- End of function --------------------------------------------------------*/ /*- 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) static int v29_v21_rx(void *user_data, const int16_t amp[], int len)
{ {
fax_state_t *t; 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 /* The fast modem has trained, so we no longer need to run the slow
one in parallel. */ 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)); 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 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 /* We have received something, and the fast modem has not trained. We must
be receiving valid V.21 */ 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)); 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; return 0;
} }
/*- End of function --------------------------------------------------------*/ /*- 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) SPAN_DECLARE(int) fax_rx(fax_state_t *s, int16_t *amp, int len)
{ {
int i; 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)); write(s->modems.audio_rx_log, amp, len*sizeof(int16_t));
} }
#endif #endif
t30_timer_update(&s->t30, len);
/* Call the fillin function of the current modem (if there is one). */ /* Call the fillin function of the current modem (if there is one). */
switch (s->modems.current_rx_type) s->modems.rx_fillin_handler(s->modems.rx_user_data, len);
{ t30_timer_update(&s->t30, len);
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;
}
return len; return len;
} }
/*- End of function --------------------------------------------------------*/ /*- 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: 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_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); 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; break;
case T30_MODEM_V27TER: case T30_MODEM_V27TER:
v27ter_rx_restart(&t->v27ter_rx, bit_rate, FALSE); v27ter_rx_restart(&t->v27ter_rx, bit_rate, FALSE);
v27ter_rx_set_put_bit(&t->v27ter_rx, put_bit_func, put_bit_user_data); 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; break;
case T30_MODEM_V29: case T30_MODEM_V29:
v29_rx_restart(&t->v29_rx, bit_rate, FALSE); v29_rx_restart(&t->v29_rx, bit_rate, FALSE);
v29_rx_set_put_bit(&t->v29_rx, put_bit_func, put_bit_user_data); 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; break;
case T30_MODEM_V17: case T30_MODEM_V17:
v17_rx_restart(&t->v17_rx, bit_rate, short_train); 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); 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; break;
case T30_MODEM_DONE: case T30_MODEM_DONE:
span_log(&s->logging, SPAN_LOG_FLOW, "FAX exchange complete\n"); span_log(&s->logging, SPAN_LOG_FLOW, "FAX exchange complete\n");
default: 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; break;
} }
} }

View File

@ -22,7 +22,7 @@
* License along with this program; if not, write to the Free Software * License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 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 */ /*! \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 */ 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)); 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_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; s->rx_user_data = &s->v21_rx;
} }
return 0; 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 */ 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)); 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_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; s->rx_user_data = &s->v21_rx;
} }
return 0; 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 */ 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)); 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_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; s->rx_user_data = &s->v21_rx;
} }
return 0; return 0;
@ -196,6 +199,7 @@ static void v17_rx_status_handler(void *user_data, int status)
case SIG_STATUS_TRAINING_SUCCEEDED: 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)); 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_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; s->rx_user_data = &s->v17_rx;
break; break;
} }
@ -212,6 +216,7 @@ static void v27ter_rx_status_handler(void *user_data, int status)
case SIG_STATUS_TRAINING_SUCCEEDED: 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)); 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_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; s->rx_user_data = &s->v27ter_rx;
break; break;
} }
@ -228,6 +233,7 @@ static void v29_rx_status_handler(void *user_data, int status)
case SIG_STATUS_TRAINING_SUCCEEDED: 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)); 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_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; s->rx_user_data = &s->v29_rx;
break; 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_signal_present = FALSE;
s->rx_handler = (span_rx_handler_t *) &span_dummy_rx; 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->rx_user_data = NULL;
s->tx_handler = (span_tx_handler_t *) &silence_gen; s->tx_handler = (span_tx_handler_t *) &silence_gen;
s->tx_user_data = &s->silence_gen; s->tx_user_data = &s->silence_gen;

View File

@ -142,6 +142,7 @@
<File RelativePath="silence_gen.c"></File> <File RelativePath="silence_gen.c"></File>
<File RelativePath="super_tone_rx.c"></File> <File RelativePath="super_tone_rx.c"></File>
<File RelativePath="super_tone_tx.c"></File> <File RelativePath="super_tone_tx.c"></File>
<File RelativePath="swept_tone.c"></File>
<File RelativePath="t4.c"></File> <File RelativePath="t4.c"></File>
<File RelativePath="t30.c"></File> <File RelativePath="t30.c"></File>
<File RelativePath="t30_api.c"></File> <File RelativePath="t30_api.c"></File>
@ -219,6 +220,7 @@
<File RelativePath="spandsp/silence_gen.h"></File> <File RelativePath="spandsp/silence_gen.h"></File>
<File RelativePath="spandsp/super_tone_rx.h"></File> <File RelativePath="spandsp/super_tone_rx.h"></File>
<File RelativePath="spandsp/super_tone_tx.h"></File> <File RelativePath="spandsp/super_tone_tx.h"></File>
<File RelativePath="spandsp/swept_tone.h"></File>
<File RelativePath="spandsp/t4.h"></File> <File RelativePath="spandsp/t4.h"></File>
<File RelativePath="spandsp/t30.h"></File> <File RelativePath="spandsp/t30.h"></File>
<File RelativePath="spandsp/t30_api.h"></File> <File RelativePath="spandsp/t30_api.h"></File>
@ -257,6 +259,7 @@
<File RelativePath="spandsp/private/bert.h"></File> <File RelativePath="spandsp/private/bert.h"></File>
<File RelativePath="spandsp/private/bitstream.h"></File> <File RelativePath="spandsp/private/bitstream.h"></File>
<File RelativePath="spandsp/private/dtmf.h"></File> <File RelativePath="spandsp/private/dtmf.h"></File>
<File RelativePath="spandsp/private/echo.h"></File>
<File RelativePath="spandsp/private/fax.h"></File> <File RelativePath="spandsp/private/fax.h"></File>
<File RelativePath="spandsp/private/fax_modems.h"></File> <File RelativePath="spandsp/private/fax_modems.h"></File>
<File RelativePath="spandsp/private/fsk.h"></File> <File RelativePath="spandsp/private/fsk.h"></File>
@ -269,6 +272,7 @@
<File RelativePath="spandsp/private/logging.h"></File> <File RelativePath="spandsp/private/logging.h"></File>
<File RelativePath="spandsp/private/lpc10.h"></File> <File RelativePath="spandsp/private/lpc10.h"></File>
<File RelativePath="spandsp/private/modem_connect_tones.h"></File> <File RelativePath="spandsp/private/modem_connect_tones.h"></File>
<File RelativePath="spandsp/private/modem_echo.h"></File>
<File RelativePath="spandsp/private/noise.h"></File> <File RelativePath="spandsp/private/noise.h"></File>
<File RelativePath="spandsp/private/oki_adpcm.h"></File> <File RelativePath="spandsp/private/oki_adpcm.h"></File>
<File RelativePath="spandsp/private/queue.h"></File> <File RelativePath="spandsp/private/queue.h"></File>
@ -277,6 +281,7 @@
<File RelativePath="spandsp/private/silence_gen.h"></File> <File RelativePath="spandsp/private/silence_gen.h"></File>
<File RelativePath="spandsp/private/super_tone_rx.h"></File> <File RelativePath="spandsp/private/super_tone_rx.h"></File>
<File RelativePath="spandsp/private/super_tone_tx.h"></File> <File RelativePath="spandsp/private/super_tone_tx.h"></File>
<File RelativePath="spandsp/private/swept_tone.h"></File>
<File RelativePath="spandsp/private/t30.h"></File> <File RelativePath="spandsp/private/t30.h"></File>
<File RelativePath="spandsp/private/t31.h"></File> <File RelativePath="spandsp/private/t31.h"></File>
<File RelativePath="spandsp/private/t38_core.h"></File> <File RelativePath="spandsp/private/t38_core.h"></File>

View File

@ -212,6 +212,7 @@
<File RelativePath="silence_gen.c"></File> <File RelativePath="silence_gen.c"></File>
<File RelativePath="super_tone_rx.c"></File> <File RelativePath="super_tone_rx.c"></File>
<File RelativePath="super_tone_tx.c"></File> <File RelativePath="super_tone_tx.c"></File>
<File RelativePath="swept_tone.c"></File>
<File RelativePath="t4.c"></File> <File RelativePath="t4.c"></File>
<File RelativePath="t30.c"></File> <File RelativePath="t30.c"></File>
<File RelativePath="t30_api.c"></File> <File RelativePath="t30_api.c"></File>
@ -289,6 +290,7 @@
<File RelativePath="spandsp/silence_gen.h"></File> <File RelativePath="spandsp/silence_gen.h"></File>
<File RelativePath="spandsp/super_tone_rx.h"></File> <File RelativePath="spandsp/super_tone_rx.h"></File>
<File RelativePath="spandsp/super_tone_tx.h"></File> <File RelativePath="spandsp/super_tone_tx.h"></File>
<File RelativePath="spandsp/swept_tone.h"></File>
<File RelativePath="spandsp/t4.h"></File> <File RelativePath="spandsp/t4.h"></File>
<File RelativePath="spandsp/t30.h"></File> <File RelativePath="spandsp/t30.h"></File>
<File RelativePath="spandsp/t30_api.h"></File> <File RelativePath="spandsp/t30_api.h"></File>
@ -327,6 +329,7 @@
<File RelativePath="spandsp/private/bert.h"></File> <File RelativePath="spandsp/private/bert.h"></File>
<File RelativePath="spandsp/private/bitstream.h"></File> <File RelativePath="spandsp/private/bitstream.h"></File>
<File RelativePath="spandsp/private/dtmf.h"></File> <File RelativePath="spandsp/private/dtmf.h"></File>
<File RelativePath="spandsp/private/echo.h"></File>
<File RelativePath="spandsp/private/fax.h"></File> <File RelativePath="spandsp/private/fax.h"></File>
<File RelativePath="spandsp/private/fax_modems.h"></File> <File RelativePath="spandsp/private/fax_modems.h"></File>
<File RelativePath="spandsp/private/fsk.h"></File> <File RelativePath="spandsp/private/fsk.h"></File>
@ -339,6 +342,7 @@
<File RelativePath="spandsp/private/logging.h"></File> <File RelativePath="spandsp/private/logging.h"></File>
<File RelativePath="spandsp/private/lpc10.h"></File> <File RelativePath="spandsp/private/lpc10.h"></File>
<File RelativePath="spandsp/private/modem_connect_tones.h"></File> <File RelativePath="spandsp/private/modem_connect_tones.h"></File>
<File RelativePath="spandsp/private/modem_echo.h"></File>
<File RelativePath="spandsp/private/noise.h"></File> <File RelativePath="spandsp/private/noise.h"></File>
<File RelativePath="spandsp/private/oki_adpcm.h"></File> <File RelativePath="spandsp/private/oki_adpcm.h"></File>
<File RelativePath="spandsp/private/queue.h"></File> <File RelativePath="spandsp/private/queue.h"></File>
@ -347,6 +351,7 @@
<File RelativePath="spandsp/private/silence_gen.h"></File> <File RelativePath="spandsp/private/silence_gen.h"></File>
<File RelativePath="spandsp/private/super_tone_rx.h"></File> <File RelativePath="spandsp/private/super_tone_rx.h"></File>
<File RelativePath="spandsp/private/super_tone_tx.h"></File> <File RelativePath="spandsp/private/super_tone_tx.h"></File>
<File RelativePath="spandsp/private/swept_tone.h"></File>
<File RelativePath="spandsp/private/t30.h"></File> <File RelativePath="spandsp/private/t30.h"></File>
<File RelativePath="spandsp/private/t31.h"></File> <File RelativePath="spandsp/private/t31.h"></File>
<File RelativePath="spandsp/private/t38_core.h"></File> <File RelativePath="spandsp/private/t38_core.h"></File>

View File

@ -293,6 +293,10 @@ SOURCE=.\super_tone_tx.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=.\swept_tone.c
# End Source File
# Begin Source File
SOURCE=.\t4.c SOURCE=.\t4.c
# End Source File # End Source File
# Begin Source File # Begin Source File
@ -599,6 +603,10 @@ SOURCE=.\spandsp/super_tone_tx.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=.\spandsp/swept_tone.h
# End Source File
# Begin Source File
SOURCE=.\spandsp/t4.h SOURCE=.\spandsp/t4.h
# End Source File # End Source File
# Begin Source File # Begin Source File
@ -751,6 +759,10 @@ SOURCE=.\spandsp/private/dtmf.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=.\spandsp/private/echo.h
# End Source File
# Begin Source File
SOURCE=.\spandsp/private/fax.h SOURCE=.\spandsp/private/fax.h
# End Source File # End Source File
# Begin Source File # Begin Source File
@ -799,6 +811,10 @@ SOURCE=.\spandsp/private/modem_connect_tones.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=.\spandsp/private/modem_echo.h
# End Source File
# Begin Source File
SOURCE=.\spandsp/private/noise.h SOURCE=.\spandsp/private/noise.h
# End Source File # End Source File
# Begin Source File # Begin Source File
@ -831,6 +847,10 @@ SOURCE=.\spandsp/private/super_tone_tx.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=.\spandsp/private/swept_tone.h
# End Source File
# Begin Source File
SOURCE=.\spandsp/private/t30.h SOURCE=.\spandsp/private/t30.h
# End Source File # End Source File
# Begin Source File # Begin Source File

View File

@ -23,7 +23,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 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) #if defined(HAVE_CONFIG_H)
@ -44,7 +44,7 @@
#include <stdio.h> #include <stdio.h>
#include <time.h> #include <time.h>
#include <fcntl.h> #include <fcntl.h>
#if defined(__sunos) || defined(__solaris) || defined(__sun) #if defined(__sunos) || defined(__solaris) || defined(__sun)
#include <getopt.h> #include <getopt.h>
#endif #endif

View File

@ -22,7 +22,7 @@
* License along with this program; if not, write to the Free Software * License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 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 */ /*! \file */
@ -53,6 +53,8 @@
#include "spandsp/dc_restore.h" #include "spandsp/dc_restore.h"
#include "spandsp/modem_echo.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) SPAN_DECLARE(modem_echo_can_state_t *) modem_echo_can_create(int len)
{ {
modem_echo_can_state_t *ec; modem_echo_can_state_t *ec;

View File

@ -22,7 +22,7 @@
* License along with this program; if not, write to the Free Software * License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 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 */ /*! \file */
@ -69,6 +69,7 @@
#include <spandsp/complex_filters.h> #include <spandsp/complex_filters.h>
#include <spandsp/dc_restore.h> #include <spandsp/dc_restore.h>
#include <spandsp/dds.h> #include <spandsp/dds.h>
#include <spandsp/swept_tone.h>
#include <spandsp/echo.h> #include <spandsp/echo.h>
#include <spandsp/modem_echo.h> #include <spandsp/modem_echo.h>
#include <spandsp/crc.h> #include <spandsp/crc.h>

View File

@ -23,7 +23,7 @@
* License along with this program; if not, write to the Free Software * License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 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 */ /*! \file */
@ -44,14 +44,17 @@
#include "floating_fudge.h" #include "floating_fudge.h"
#include <memory.h> #include <memory.h>
#include <string.h> #include <string.h>
#include <limits.h>
#undef SPANDSP_USE_FIXED_POINT #undef SPANDSP_USE_FIXED_POINT
#include "spandsp/telephony.h" #include "spandsp/telephony.h"
#include "spandsp/fast_convert.h" #include "spandsp/fast_convert.h"
#include "spandsp/dc_restore.h" #include "spandsp/dc_restore.h"
#include "spandsp/saturated.h" #include "spandsp/saturated.h"
#include "spandsp/vector_int.h"
#include "spandsp/complex.h" #include "spandsp/complex.h"
#include "spandsp/dds.h" #include "spandsp/dds.h"
#include "spandsp/super_tone_rx.h"
#include "spandsp/sig_tone.h" #include "spandsp/sig_tone.h"
#include "spandsp/private/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) */ /* 2280Hz (e.g. AC15, and many other European protocols) */
{2280, 0}, {2280, 0},
{-10, -20}, /* -10+-1 dBmO and -20+-1 dBm0 */ {{-10, -20}, {0, 0}}, /* -10+-1 dBmO and -20+-1 dBm0 */
400*(SAMPLE_RATE/1000), /* 300ms to 550ms */ ms_to_samples(400), /* 300ms to 550ms */
225*(SAMPLE_RATE/1000), ms_to_samples(225),
225*(SAMPLE_RATE/1000), ms_to_samples(225),
TRUE, TRUE,
24, 24,
@ -135,12 +138,12 @@ sig_tone_descriptor_t sig_tones[4] =
{ {
/* 2600Hz (e.g. many US protocols) */ /* 2600Hz (e.g. many US protocols) */
{2600, 0}, {2600, 0},
{-8, -8}, {{-8, -8}, {0, 0}},
400*(SAMPLE_RATE/1000), ms_to_samples(400),
225*(SAMPLE_RATE/1000), ms_to_samples(225),
225*(SAMPLE_RATE/1000), ms_to_samples(225),
FALSE, FALSE,
24, 24,
@ -202,13 +205,13 @@ sig_tone_descriptor_t sig_tones[4] =
}, },
{ {
/* 2400Hz/2600Hz (e.g. SS5 and SS5bis) */ /* 2400Hz/2600Hz (e.g. SS5 and SS5bis) */
{2400, 2600}, {2600, 2400},
{-8, -8}, {{-8, -8}, {-8, -8}},
400*(SAMPLE_RATE/1000), ms_to_samples(400),
225*(SAMPLE_RATE/1000), ms_to_samples(225),
225*(SAMPLE_RATE/1000), ms_to_samples(225),
FALSE, FALSE,
24, 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 j;
int n; int n;
int16_t tone; int16_t tone;
int update; int need_update;
int high_low; int high_low;
for (i = 0; i < len; i += n) for (i = 0; i < len; i += n)
{ {
if (s->current_tx_timeout < len - i) if (s->current_tx_timeout)
n = 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 else
{
n = len - i; n = len - i;
need_update = FALSE;
}
if (!(s->current_tx_tone & SIG_TONE_TX_PASSTHROUGH))
vec_zeroi16(&amp[i], n);
/*endif*/
if ((s->current_tx_tone & (SIG_TONE_1_PRESENT || SIG_TONE_2_PRESENT))) 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 /* Are we in the early phase (high tone energy level), or the sustaining
phase (low tone energy level) of tone generation? */ 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 (s->high_low_timer > 0)
{ {
if (n > s->high_low_timer) 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; high_low = 1;
} }
/*endif*/ /*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++) 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); amp[j] = saturate(amp[j] + tone);
} }
/*endfor*/ /*endfor*/
} }
else /*endif*/
if ((s->current_tx_tone & SIG_TONE_2_PRESENT) && s->phase_rate[1])
{ {
for (j = i; j < i + n; j++) 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*/ /*endfor*/
} }
/*endif*/ /*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*/ /*endif*/
if ((s->current_tx_timeout -= n) <= 0) if (need_update && s->sig_update)
{ s->sig_update(s->user_data, SIG_TONE_TX_UPDATE_REQUEST, 0, 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*/
}
/*endif*/ /*endif*/
} }
/*endfor*/ /*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 --------------------------------------------------------*/ /*- 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; s->high_low_timer = s->desc->high_low_timeout;
/*endif*/ /*endif*/
s->current_tx_tone = mode & 0xFFFF; s->current_tx_tone = mode;
s->current_tx_timeout = (mode >> 16) & 0xFFFF; s->current_tx_timeout = duration;
} }
/*- End of function --------------------------------------------------------*/ /*- 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; 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]); s->phase_rate[i] = dds_phase_rate((float) s->desc->tone_freq[i]);
else else
s->phase_rate[i] = 0; 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; return s;
} }
@ -404,6 +417,7 @@ SPAN_DECLARE(int) sig_tone_tx_free(sig_tone_tx_state_t *s)
return 0; return 0;
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) sig_tone_rx(sig_tone_rx_state_t *s, int16_t amp[], int len) SPAN_DECLARE(int) sig_tone_rx(sig_tone_rx_state_t *s, int16_t amp[], int len)
{ {
#if defined(SPANDSP_USE_FIXED_POINT) #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++) for (i = 0; i < len; i++)
{ {
if (s->signaling_state_duration < 0xFFFF) if (s->signaling_state_duration < INT_MAX)
s->signaling_state_duration++; s->signaling_state_duration++;
/*endif*/ /*endif*/
notched_signal = 0; 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->tone_present)
{ {
if (s->sig_update) 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*/ /*endif*/
s->signaling_state_duration = 0; 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->tone_present)
{ {
if (s->sig_update) 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*/ /*endif*/
s->signaling_state_duration = 0; s->signaling_state_duration = 0;
} }
/*endif*/ /*endif*/
} }
/*endif*/ /*endif*/
/* Notch insertion logic */
/* Notch insertion logic */
/* tone_present and tone_on are equivalent in flat mode */ /* tone_present and tone_on are equivalent in flat mode */
if (s->tone_present) 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->tone_persistence_timeout = s->desc->tone_off_check_time;
s->notch_insertion_timeout = s->desc->notch_lag_time; s->notch_insertion_timeout = s->desc->notch_lag_time;
if (s->sig_update) 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*/ /*endif*/
s->signaling_state_duration = 0; 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_present = FALSE;
s->tone_persistence_timeout = s->desc->tone_on_check_time; s->tone_persistence_timeout = s->desc->tone_on_check_time;
if (s->sig_update) 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*/ /*endif*/
s->signaling_state_duration = 0; 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->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; amp[i] = (int16_t) notched_signal;
/*endif*/ /*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 --------------------------------------------------------*/ /*- 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) if (sig_update == NULL || tone_type < 1 || tone_type > 3)
return NULL; return NULL;

View File

@ -22,7 +22,7 @@
* License along with this program; if not, write to the Free Software * License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 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 */ /*! \file */
@ -158,4 +158,10 @@ SPAN_DECLARE(int) span_dummy_mod(void *user_data, int16_t amp[], int len)
return len; return len;
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
SPAN_DECLARE_NONSTD(int) span_dummy_rx_fillin(void *user_data, int len)
{
return 0;
}
/*- End of function --------------------------------------------------------*/
/*- End of file ------------------------------------------------------------*/ /*- End of file ------------------------------------------------------------*/

View File

@ -22,7 +22,7 @@
* License along with this program; if not, write to the Free Software * License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 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 */ /*! \file */
@ -66,6 +66,7 @@
#include <spandsp/complex_filters.h> #include <spandsp/complex_filters.h>
#include <spandsp/dc_restore.h> #include <spandsp/dc_restore.h>
#include <spandsp/dds.h> #include <spandsp/dds.h>
#include <spandsp/swept_tone.h>
#include <spandsp/echo.h> #include <spandsp/echo.h>
#include <spandsp/modem_echo.h> #include <spandsp/modem_echo.h>
#include <spandsp/crc.h> #include <spandsp/crc.h>

View File

@ -24,7 +24,7 @@
* License along with this program; if not, write to the Free Software * License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 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 */ /*! \file */
@ -133,59 +133,7 @@ enum
G.168 echo canceller descriptor. This defines the working state for a line G.168 echo canceller descriptor. This defines the working state for a line
echo canceller. echo canceller.
*/ */
typedef struct typedef struct echo_can_state_s echo_can_state_t;
{
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;
#if defined(__cplusplus) #if defined(__cplusplus)
extern "C" extern "C"

View File

@ -23,7 +23,7 @@
* License along with this program; if not, write to the Free Software * License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 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 */ /*! \file */
@ -56,6 +56,9 @@
#include <spandsp/private/super_tone_tx.h> #include <spandsp/private/super_tone_tx.h>
#include <spandsp/private/super_tone_rx.h> #include <spandsp/private/super_tone_rx.h>
#include <spandsp/private/silence_gen.h> #include <spandsp/private/silence_gen.h>
#include <spandsp/private/swept_tone.h>
#include <spandsp/private/echo.h>
#include <spandsp/private/modem_echo.h>
#include <spandsp/private/async.h> #include <spandsp/private/async.h>
#include <spandsp/private/fsk.h> #include <spandsp/private/fsk.h>
#include <spandsp/private/v29rx.h> #include <spandsp/private/v29rx.h>

View File

@ -22,7 +22,7 @@
* License along with this program; if not, write to the Free Software * License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 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_) #if !defined(_SPANDSP_FAST_CONVERT_H_)
@ -150,7 +150,7 @@ extern "C"
); );
return retval; return retval;
} }
#elif defined(__GNUC__) || (__SUNPRO_C >= 0x0590) #elif defined(__GNUC__) || (__SUNPRO_C >= 0x0590)
#if defined(__i386__) #if defined(__i386__)
/* These routines are guaranteed fast on an i386 machine. Using the built in /* 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 the accuracy issues related to changing the rounding scheme are of little concern
to us. */ 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 "No usable lrint() and lrintf() functions available."
#warning "Replacing these functions with a simple C cast." #warning "Replacing these functions with a simple C cast."
#endif #endif

View File

@ -25,7 +25,7 @@
* License along with this program; if not, write to the Free Software * License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 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 */ /*! \file */
@ -84,22 +84,7 @@ minor burden.
Modem line echo canceller descriptor. This defines the working state for a line Modem line echo canceller descriptor. This defines the working state for a line
echo canceller. echo canceller.
*/ */
typedef struct typedef struct modem_echo_can_state_s modem_echo_can_state_t;
{
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;
#if defined(__cplusplus) #if defined(__cplusplus)
extern "C" extern "C"

View File

@ -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 <steveu@coppice.org>
*
* 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 ------------------------------------------------------------*/

View File

@ -22,7 +22,7 @@
* License along with this program; if not, write to the Free Software * License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 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 */ /*! \file */
@ -95,11 +95,9 @@ struct fax_modems_state_s
/*! The current receive signal handler */ /*! The current receive signal handler */
span_rx_handler_t *rx_handler; span_rx_handler_t *rx_handler;
void *rx_user_data;
/*! The current receive missing signal fill-in handler */ /*! The current receive missing signal fill-in handler */
span_rx_fillin_handler_t *rx_fillin_handler; span_rx_fillin_handler_t *rx_fillin_handler;
void *rx_fillin_user_data; void *rx_user_data;
/*! The current transmit signal handler */ /*! The current transmit signal handler */
span_tx_handler_t *tx_handler; span_tx_handler_t *tx_handler;

View File

@ -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 <steveu@coppice.org>
*
* 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 ------------------------------------------------------------*/

View File

@ -23,7 +23,7 @@
* License along with this program; if not, write to the Free Software * License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 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_) #if !defined(_SPANDSP_PRIVATE_SIG_TONE_H_)
@ -38,8 +38,8 @@ struct sig_tone_descriptor_s
{ {
/*! \brief The tones used. */ /*! \brief The tones used. */
int tone_freq[2]; int tone_freq[2];
/*! \brief The high and low tone amplitudes. */ /*! \brief The high and low tone amplitudes for each of the tones. */
int tone_amp[2]; int tone_amp[2][2];
/*! \brief The delay, in audio samples, before the high level tone drops /*! \brief The delay, in audio samples, before the high level tone drops
to a low level tone. */ to a low level tone. */
@ -80,7 +80,6 @@ struct sig_tone_descriptor_s
#endif #endif
} tone[2]; } tone[2];
#if defined(SPANDSP_USE_FIXED_POINT) #if defined(SPANDSP_USE_FIXED_POINT)
/*! \brief Flat mode bandpass bi-quad parameters */ /*! \brief Flat mode bandpass bi-quad parameters */
int32_t broad_a[3]; int32_t broad_a[3];
@ -128,23 +127,23 @@ struct sig_tone_descriptor_s
struct sig_tone_tx_state_s struct sig_tone_tx_state_s
{ {
/*! \brief The callback function used to handle signaling changes. */ /*! \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. */ /*! \brief A user specified opaque pointer passed to the callback function. */
void *user_data; void *user_data;
/*! \brief Tone descriptor */ /*! \brief Tone descriptor */
sig_tone_descriptor_t *desc; 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 */ /*! The phase rates for the one or two tones */
int32_t phase_rate[2]; int32_t phase_rate[2];
/*! The phase accumulators for the one or two tones */ /*! The phase accumulators for the one or two tones */
uint32_t phase_acc[2]; 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 */ /*! \brief Current transmit tone */
int current_tx_tone; int current_tx_tone;
/*! \brief Current transmit timeout */ /*! \brief Current transmit timeout */
@ -159,7 +158,7 @@ struct sig_tone_tx_state_s
struct sig_tone_rx_state_s struct sig_tone_rx_state_s
{ {
/*! \brief The callback function used to handle signaling changes. */ /*! \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. */ /*! \brief A user specified opaque pointer passed to the callback function. */
void *user_data; void *user_data;

View File

@ -0,0 +1,44 @@
/*
* SpanDSP - a series of DSP components for telephony
*
* private/swept_tone.h - Swept tone generation
*
* Written by Steve Underwood <steveu@coppice.org>
*
* 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 ------------------------------------------------------------*/

View File

@ -22,7 +22,7 @@
* License along with this program; if not, write to the Free Software * License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 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 */ /*! \file */
@ -221,10 +221,10 @@ struct t30_state_s
/*! \brief A bit map of the OK ECM frames, constructed as a PPR frame. */ /*! \brief A bit map of the OK ECM frames, constructed as a PPR frame. */
uint8_t ecm_frame_map[3 + 32]; 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. */ /*! \brief The current page number for receiving, in ECM or non-ECM mode. This is reset at the start of a call. */
int ecm_rx_page; int rx_page_number;
/*! \brief The current page number for sending, in ECM mode. This is reset at the start of a call. */ /*! \brief The current page number for sending, in ECM or non-ECM mode. This is reset at the start of a call. */
int ecm_tx_page; int tx_page_number;
/*! \brief The current block number, in ECM mode */ /*! \brief The current block number, in ECM mode */
int ecm_block; int ecm_block;
/*! \brief The number of frames in the current block number, in ECM mode */ /*! \brief The number of frames in the current block number, in ECM mode */

View File

@ -23,7 +23,7 @@
* License along with this program; if not, write to the Free Software * License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 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 */ /*! \file */
@ -54,32 +54,39 @@ least supervisory information may be heard.
#if !defined(_SPANDSP_SIG_TONE_H_) #if !defined(_SPANDSP_SIG_TONE_H_)
#define _SPANDSP_SIG_TONE_H_ #define _SPANDSP_SIG_TONE_H_
typedef int (*sig_tone_func_t)(void *user_data, int what);
/* The optional tone sets */ /* The optional tone sets */
enum enum
{ {
/*! European 2280Hz signaling tone */ /*! European 2280Hz signaling tone. Tone 1 is 2280Hz. Tone 2 is not used. */
SIG_TONE_2280HZ = 1, SIG_TONE_2280HZ = 1,
/*! US 2600Hz signaling tone */ /*! US 2600Hz signaling tone. Tone 1 is 2600Hz. Tone 2 is not used. */
SIG_TONE_2600HZ, 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 SIG_TONE_2400HZ_2600HZ
}; };
/* Mode control and report bits for transmit and receive */
enum enum
{ {
/*! Signaling tone 1 is present */ /*! Signaling tone 1 is present */
SIG_TONE_1_PRESENT = 0x001, SIG_TONE_1_PRESENT = 0x001,
/*! Signaling tone 1 has changed state (ignored when setting tx mode) */
SIG_TONE_1_CHANGE = 0x002, SIG_TONE_1_CHANGE = 0x002,
/*! Signaling tone 2 is present */ /*! Signaling tone 2 is present */
SIG_TONE_2_PRESENT = 0x004, SIG_TONE_2_PRESENT = 0x004,
/*! Signaling tone 2 has changed state (ignored when setting tx mode) */
SIG_TONE_2_CHANGE = 0x008, SIG_TONE_2_CHANGE = 0x008,
/*! The media signal is passing through. Tones might be added to it. */ /*! The media signal is passing through. Tones might be added to it. */
SIG_TONE_TX_PASSTHROUGH = 0x010, SIG_TONE_TX_PASSTHROUGH = 0x010,
/*! The media signal is passing through. Tones might be extracted from it, if detected. */ /*! The media signal is passing through. Tones might be extracted from it, if detected. */
SIG_TONE_RX_PASSTHROUGH = 0x020, SIG_TONE_RX_PASSTHROUGH = 0x040,
SIG_TONE_UPDATE_REQUEST = 0x100 /*! 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. */ \return The number of samples unprocessed. */
SPAN_DECLARE(int) sig_tone_rx(sig_tone_rx_state_t *s, int16_t amp[], int len); 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. /*! Initialise a signaling tone receiver context.
\brief Initialise a signaling tone context. \brief Initialise a signaling tone context.
\param s The 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 sig_update Callback function to handle signaling updates.
\param user_data An opaque pointer. \param user_data An opaque pointer.
\return A pointer to the signalling tone context, or NULL if there was a problem. */ \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. /*! Release a signaling tone receiver context.
\brief 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. /*! Set the tone mode.
\brief Set the tone mode. \brief Set the tone mode.
\param s The signaling tone context. \param s The signaling tone context.
\param mode The new mode for the transmitted tones. */ \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 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. /*! Initialise a signaling tone transmitter context.
\brief Initialise a signaling tone 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 sig_update Callback function to handle signaling updates.
\param user_data An opaque pointer. \param user_data An opaque pointer.
\return A pointer to the signalling tone context, or NULL if there was a problem. */ \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. /*! Release a signaling tone transmitter context.
\brief Release a signaling tone transmitter context. \brief Release a signaling tone transmitter context.

View File

@ -22,7 +22,7 @@
* License along with this program; if not, write to the Free Software * License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 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_) #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); 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) #if defined(__cplusplus)
} }
#endif #endif

View File

@ -0,0 +1,59 @@
/*
* SpanDSP - a series of DSP components for telephony
*
* swept_tone.h - Swept tone generation
*
* Written by Steve Underwood <steveu@coppice.org>
*
* 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 ------------------------------------------------------------*/

View File

@ -22,7 +22,7 @@
* License along with this program; if not, write to the Free Software * License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 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 */ /*! \file */
@ -524,9 +524,9 @@ typedef struct
int pages_rx; int pages_rx;
/*! \brief The number of pages in the file (<0 if not known). */ /*! \brief The number of pages in the file (<0 if not known). */
int pages_in_file; 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; 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; int y_resolution;
/*! \brief The number of horizontal pixels in the most recent page. */ /*! \brief The number of horizontal pixels in the most recent page. */
int width; int width;

View File

@ -22,7 +22,7 @@
* License along with this program; if not, write to the Free Software * License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 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_) #if !defined(_SPANDSP_TIMING_H_)
@ -56,8 +56,8 @@ static __inline__ uint64_t rdtscll(void)
#elif defined(__x86_64__) #elif defined(__x86_64__)
static __inline__ uint64_t rdtscll(void) static __inline__ uint64_t rdtscll(void)
{ {
unsigned int a; uint32_t a;
unsigned int d; uint32_t d;
/* For x86_64 we need to merge the result in 2 32 bit registers /* For x86_64 we need to merge the result in 2 32 bit registers
into one clean 64 bit result. */ into one clean 64 bit result. */

View File

@ -30,9 +30,9 @@
/* The date and time of the version are in UTC form. */ /* The date and time of the version are in UTC form. */
#define SPANDSP_RELEASE_DATE 20090714 #define SPANDSP_RELEASE_DATE 20091005
#define SPANDSP_RELEASE_TIME 135534 #define SPANDSP_RELEASE_TIME 132812
#define SPANDSP_RELEASE_DATETIME_STRING "20090714 135534" #define SPANDSP_RELEASE_DATETIME_STRING "20091005 132812"
#endif #endif
/*- End of file ------------------------------------------------------------*/ /*- End of file ------------------------------------------------------------*/

View File

@ -0,0 +1,128 @@
/*
* SpanDSP - a series of DSP components for telephony
*
* swept_tone.c - Swept tone generation
*
* Written by Steve Underwood <steveu@coppice.org>
*
* 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 <stdlib.h>
#include <inttypes.h>
#include <string.h>
#include <stdio.h>
#if defined(HAVE_TGMATH_H)
#include <tgmath.h>
#endif
#if defined(HAVE_MATH_H)
#include <math.h>
#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 ------------------------------------------------------------*/

View File

@ -22,7 +22,7 @@
* License along with this program; if not, write to the Free Software * License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 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 */ /*! \file */
@ -421,7 +421,7 @@ static int tx_start_page(t30_state_t *s)
} }
s->ecm_block = 0; s->ecm_block = 0;
s->error_correcting_mode_retries = 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; return 0;
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
@ -431,7 +431,7 @@ static int tx_end_page(t30_state_t *s)
s->retries = 0; s->retries = 0;
if (t4_tx_end_page(&(s->t4)) == 0) if (t4_tx_end_page(&(s->t4)) == 0)
{ {
s->ecm_tx_page++; s->tx_page_number++;
s->ecm_block = 0; s->ecm_block = 0;
} }
return 0; return 0;
@ -470,7 +470,7 @@ static int rx_end_page(t30_state_t *s)
{ {
if (t4_rx_end_page(&(s->t4)) == 0) if (t4_rx_end_page(&(s->t4)) == 0)
{ {
s->ecm_rx_page++; s->rx_page_number++;
s->ecm_block = 0; s->ecm_block = 0;
} }
return 0; return 0;
@ -1042,7 +1042,7 @@ static int send_pps_frame(t30_state_t *s)
frame[1] = CONTROL_FIELD_FINAL_FRAME; frame[1] = CONTROL_FIELD_FINAL_FRAME;
frame[2] = (uint8_t) (T30_PPS | s->dis_received); 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[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[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)); 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])); 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 --------------------------------------------------------*/ /*- 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) 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); 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 --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
static void unexpected_final_frame(t30_state_t *s, const uint8_t *msg, int len) 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); 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;
send_dcn(s); send_dcn(s);
} }
/*- End of function --------------------------------------------------------*/ /*- 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) 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); 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); send_dcn(s);
} }
/*- End of function --------------------------------------------------------*/ /*- 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); 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) 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) 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: case T30_DIS:
/* TODO: This is a fudge to allow for starting up in T.38, where the other end has /* 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) 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: case T30_DCN:
/* Just ignore any DCN's which appear at this stage. */ /* 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) 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: case T30_DCN:
/* Just ignore any DCN's which appear at this stage. */ /* 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) 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 */ /* We should be sending the DCS sequence right now */
switch (msg[2] & 0xFE) fcf = msg[2] & 0xFE;
switch (fcf)
{ {
case T30_DCN: case T30_DCN:
s->current_status = T30_ERR_TX_BADDCS; 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) 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 */ /* We should be sending the TCF data right now */
switch (msg[2] & 0xFE) fcf = msg[2] & 0xFE;
switch (fcf)
{ {
case T30_DCN: case T30_DCN:
s->current_status = T30_ERR_TX_BADDCS; 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) 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: case T30_CFR:
/* Trainability test succeeded. Send the document. */ /* 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) 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 */ /* We should be receiving TCF right now, not HDLC messages */
switch (msg[2] & 0xFE) fcf = msg[2] & 0xFE;
switch (fcf)
{ {
case T30_CRP: case T30_CRP:
repeat_last_command(s); 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) 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 */ /* We're waiting for a response to the CFR we sent */
switch (msg[2] & 0xFE) fcf = msg[2] & 0xFE;
switch (fcf)
{ {
case T30_DCS: case T30_DCS:
/* If we received another DCS, they must have missed our CFR */ /* 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) 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 */ /* We're waiting for a response to the FTT we sent */
switch (msg[2] & 0xFE) fcf = msg[2] & 0xFE;
switch (fcf)
{ {
case T30_DCS: case T30_DCS:
process_rx_dcs(s, msg, len); 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) 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 /* If we are getting HDLC messages, and we have not moved to the _POST_DOC_NON_ECM
state, it looks like either: state, it looks like either:
- we didn't see the image data carrier properly, or - 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 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. */ - 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: case T30_DIS:
process_rx_dis_dtc(s, msg, len); 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: case T30_MPS:
/* Treat this as a bad quality page. */ /* Treat this as a bad quality page. */
if (s->phase_d_handler) 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; s->next_rx_step = msg[2] & 0xFE;
queue_phase(s, T30_PHASE_D_TX); queue_phase(s, T30_PHASE_D_TX);
set_state(s, T30_STATE_III_Q_RTN); 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. */ /* Treat this as a bad quality page. */
if (s->phase_d_handler) 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->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
} }
s->next_rx_step = msg[2] & 0xFE; 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: case T30_EOS:
/* Treat this as a bad quality page. */ /* Treat this as a bad quality page. */
if (s->phase_d_handler) 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; s->next_rx_step = msg[2] & 0xFE;
/* Return to phase B */ /* Return to phase B */
queue_phase(s, T30_PHASE_B_TX); 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. */ /* Treat this as a bad quality page. */
if (s->phase_d_handler) 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->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
} }
s->next_rx_step = T30_PRI_EOM; 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: case T30_EOP:
/* Treat this as a bad quality page. */ /* Treat this as a bad quality page. */
if (s->phase_d_handler) 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; s->next_rx_step = msg[2] & 0xFE;
queue_phase(s, T30_PHASE_D_TX); queue_phase(s, T30_PHASE_D_TX);
set_state(s, T30_STATE_III_Q_RTN); 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. */ /* Treat this as a bad quality page. */
if (s->phase_d_handler) 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->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
} }
s->next_rx_step = msg[2] & 0xFE; 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; break;
default: default:
/* We don't know what to do with this. */ /* We don't know what to do with this. */
s->current_status = T30_ERR_RX_INVALCMD;
unexpected_final_frame(s, msg, len); unexpected_final_frame(s, msg, len);
break; 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) 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: case T30_MPS:
if (s->phase_d_handler) 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; s->next_rx_step = fcf;
queue_phase(s, T30_PHASE_D_TX); queue_phase(s, T30_PHASE_D_TX);
switch (copy_quality(s)) 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: case T30_PRI_MPS:
if (s->phase_d_handler) 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->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
} }
s->next_rx_step = msg[2] & 0xFE; s->next_rx_step = fcf;
switch (copy_quality(s)) switch (copy_quality(s))
{ {
case T30_COPY_QUALITY_PERFECT: 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_EOM:
case T30_EOS: case T30_EOS:
if (s->phase_d_handler) 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; s->next_rx_step = fcf;
/* Return to phase B */ /* Return to phase B */
queue_phase(s, T30_PHASE_B_TX); queue_phase(s, T30_PHASE_B_TX);
switch (copy_quality(s)) 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: case T30_PRI_EOM:
if (s->phase_d_handler) 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->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
} }
s->next_rx_step = msg[2] & 0xFE; s->next_rx_step = fcf;
switch (copy_quality(s)) switch (copy_quality(s))
{ {
case T30_COPY_QUALITY_PERFECT: 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; break;
case T30_EOP: case T30_EOP:
if (s->phase_d_handler) 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; s->next_rx_step = fcf;
queue_phase(s, T30_PHASE_D_TX); queue_phase(s, T30_PHASE_D_TX);
switch (copy_quality(s)) 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: case T30_PRI_EOP:
if (s->phase_d_handler) 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->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
} }
s->next_rx_step = msg[2] & 0xFE; s->next_rx_step = fcf;
switch (copy_quality(s)) switch (copy_quality(s))
{ {
case T30_COPY_QUALITY_PERFECT: 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; break;
default: default:
/* We don't know what to do with this. */ /* We don't know what to do with this. */
s->current_status = T30_ERR_RX_INVALCMD;
unexpected_final_frame(s, msg, len); unexpected_final_frame(s, msg, len);
break; 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) 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; uint8_t fcf2;
/* This actually handles 2 states - _DOC_ECM and _POST_DOC_ECM - as they are very similar */ /* 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: case T30_DIS:
process_rx_dis_dtc(s, msg, len); 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; break;
default: default:
/* We don't know what to do with this. */ /* We don't know what to do with this. */
s->current_status = T30_ERR_RX_INVALCMD;
unexpected_final_frame(s, msg, len); unexpected_final_frame(s, msg, len);
break; 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) 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: case T30_CRP:
repeat_last_command(s); 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) 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: case T30_CRP:
repeat_last_command(s); 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) 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: case T30_RR:
if (s->receiver_not_ready_count > 0) 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) 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: case T30_DIS:
process_rx_dis_dtc(s, msg, len); 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) 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: case T30_DIS:
process_rx_dis_dtc(s, msg, len); 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) 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: case T30_CRP:
repeat_last_command(s); 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) 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: case T30_CRP:
repeat_last_command(s); 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) static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len)
{ {
t4_stats_t stats; t4_stats_t stats;
uint8_t fcf;
switch (msg[2] & 0xFE) fcf = msg[2] & 0xFE;
switch (fcf)
{ {
case T30_MCF: case T30_MCF:
switch (s->next_tx_step) 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: case T30_PRI_MPS:
tx_end_page(s); tx_end_page(s);
if (s->phase_d_handler) 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)) if (tx_start_page(s))
{ {
/* TODO: recover */ /* 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: case T30_EOS:
tx_end_page(s); tx_end_page(s);
if (s->phase_d_handler) 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)); t4_tx_release(&(s->t4));
s->operation_in_progress = OPERATION_IN_PROGRESS_NONE; s->operation_in_progress = OPERATION_IN_PROGRESS_NONE;
if (span_log_test(&s->logging, SPAN_LOG_FLOW)) 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: case T30_PRI_EOP:
tx_end_page(s); tx_end_page(s);
if (s->phase_d_handler) 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)); t4_tx_release(&(s->t4));
s->operation_in_progress = OPERATION_IN_PROGRESS_NONE; s->operation_in_progress = OPERATION_IN_PROGRESS_NONE;
send_dcn(s); send_dcn(s);
@ -3488,13 +3542,16 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len)
} }
break; break;
case T30_RTP: case T30_RTP:
#if 0
s->rtp_events++;
#endif
switch (s->next_tx_step) switch (s->next_tx_step)
{ {
case T30_MPS: case T30_MPS:
case T30_PRI_MPS: case T30_PRI_MPS:
tx_end_page(s); tx_end_page(s);
if (s->phase_d_handler) 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)) if (tx_start_page(s))
{ {
/* TODO: recover */ /* 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: case T30_EOS:
tx_end_page(s); tx_end_page(s);
if (s->phase_d_handler) 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)); t4_tx_release(&(s->t4));
/* TODO: should go back to T, and resend */ /* TODO: should go back to T, and resend */
return_to_phase_b(s, TRUE); 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: case T30_PRI_EOP:
tx_end_page(s); tx_end_page(s);
if (s->phase_d_handler) 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)); t4_tx_release(&(s->t4));
s->current_status = T30_ERR_TX_INVALRSP;
send_dcn(s); send_dcn(s);
break; break;
} }
break; break;
case T30_RTN: case T30_RTN:
#if 0
s->rtn_events++;
#endif
switch (s->next_tx_step) switch (s->next_tx_step)
{ {
case T30_MPS: case T30_MPS:
case T30_PRI_MPS: case T30_PRI_MPS:
s->retries = 0; s->retries = 0;
if (s->phase_d_handler) if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, T30_RTN); s->phase_d_handler(s, s->phase_d_user_data, fcf);
/* Send fresh training, and then repeat the last page */ #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) if (step_fallback_entry(s) < 0)
{ {
/* We have fallen back as far as we can go. Give up. */ /* 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: case T30_EOS:
s->retries = 0; s->retries = 0;
if (s->phase_d_handler) if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, T30_RTN); s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->current_status = T30_ERR_TX_INVALRSP; #if 0
return_to_phase_b(s, TRUE); if (s->retransmit_capable)
{
/* Wait for DIS */
}
else
#endif
{
return_to_phase_b(s, TRUE);
}
break; break;
case T30_EOP: case T30_EOP:
case T30_PRI_EOP: case T30_PRI_EOP:
s->retries = 0; s->retries = 0;
if (s->phase_d_handler) if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, T30_RTN); s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->current_status = T30_ERR_TX_INVALRSP; #if 0
send_dcn(s); 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;
} }
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; s->retries = 0;
if (s->phase_d_handler) 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); s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
} }
break; break;
@ -3584,7 +3680,7 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len)
s->retries = 0; s->retries = 0;
if (s->phase_d_handler) 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); s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
} }
break; break;
@ -3613,6 +3709,7 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len)
break; break;
default: default:
/* We don't know what to do with this. */ /* We don't know what to do with this. */
s->current_status = T30_ERR_TX_INVALRSP;
unexpected_final_frame(s, msg, len); unexpected_final_frame(s, msg, len);
break; 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) 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_EOP:
case T30_EOM: 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) 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_EOP:
case T30_EOM: 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) 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_EOP:
case T30_EOM: 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) 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: case T30_CRP:
repeat_last_command(s); 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) static void process_state_iv_pps_null(t30_state_t *s, const uint8_t *msg, int len)
{ {
t4_stats_t stats; t4_stats_t stats;
uint8_t fcf;
switch (msg[2] & 0xFE) fcf = msg[2] & 0xFE;
switch (fcf)
{ {
case T30_MCF: case T30_MCF:
s->retries = 0; 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: case T30_PRI_MPS:
tx_end_page(s); tx_end_page(s);
if (s->phase_d_handler) 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)) if (tx_start_page(s))
{ {
/* TODO: recover */ /* 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: case T30_EOS:
tx_end_page(s); tx_end_page(s);
if (s->phase_d_handler) 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)); t4_tx_release(&(s->t4));
s->operation_in_progress = OPERATION_IN_PROGRESS_NONE; s->operation_in_progress = OPERATION_IN_PROGRESS_NONE;
if (span_log_test(&s->logging, SPAN_LOG_FLOW)) 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: case T30_PRI_EOP:
tx_end_page(s); tx_end_page(s);
if (s->phase_d_handler) 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)); t4_tx_release(&(s->t4));
s->operation_in_progress = OPERATION_IN_PROGRESS_NONE; s->operation_in_progress = OPERATION_IN_PROGRESS_NONE;
send_dcn(s); 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) static void process_state_iv_pps_q(t30_state_t *s, const uint8_t *msg, int len)
{ {
t4_stats_t stats; t4_stats_t stats;
uint8_t fcf;
switch (msg[2] & 0xFE) fcf = msg[2] & 0xFE;
switch (fcf)
{ {
case T30_MCF: case T30_MCF:
s->retries = 0; 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: case T30_PRI_MPS:
tx_end_page(s); tx_end_page(s);
if (s->phase_d_handler) 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)) if (tx_start_page(s))
{ {
/* TODO: recover */ /* 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: case T30_EOS:
tx_end_page(s); tx_end_page(s);
if (s->phase_d_handler) 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)); t4_tx_release(&(s->t4));
s->operation_in_progress = OPERATION_IN_PROGRESS_NONE; s->operation_in_progress = OPERATION_IN_PROGRESS_NONE;
if (span_log_test(&s->logging, SPAN_LOG_FLOW)) 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: case T30_PRI_EOP:
tx_end_page(s); tx_end_page(s);
if (s->phase_d_handler) 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)); t4_tx_release(&(s->t4));
s->operation_in_progress = OPERATION_IN_PROGRESS_NONE; s->operation_in_progress = OPERATION_IN_PROGRESS_NONE;
send_dcn(s); 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; s->retries = 0;
if (s->phase_d_handler) 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); s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
} }
break; 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; s->retries = 0;
if (s->phase_d_handler) 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); s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
} }
break; 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) static void process_state_iv_pps_rnr(t30_state_t *s, const uint8_t *msg, int len)
{ {
t4_stats_t stats; t4_stats_t stats;
uint8_t fcf;
switch (msg[2] & 0xFE) fcf = msg[2] & 0xFE;
switch (fcf)
{ {
case T30_MCF: case T30_MCF:
s->retries = 0; 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: case T30_PRI_MPS:
tx_end_page(s); tx_end_page(s);
if (s->phase_d_handler) 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)) if (tx_start_page(s))
{ {
/* TODO: recover */ /* 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: case T30_EOS:
tx_end_page(s); tx_end_page(s);
if (s->phase_d_handler) 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)); t4_tx_release(&(s->t4));
s->operation_in_progress = OPERATION_IN_PROGRESS_NONE; s->operation_in_progress = OPERATION_IN_PROGRESS_NONE;
if (span_log_test(&s->logging, SPAN_LOG_FLOW)) 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: case T30_PRI_EOP:
tx_end_page(s); tx_end_page(s);
if (s->phase_d_handler) 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)); t4_tx_release(&(s->t4));
s->operation_in_progress = OPERATION_IN_PROGRESS_NONE; s->operation_in_progress = OPERATION_IN_PROGRESS_NONE;
send_dcn(s); 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; s->retries = 0;
if (s->phase_d_handler) 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); s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
} }
break; 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; s->retries = 0;
if (s->phase_d_handler) 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); s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
} }
break; 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) 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: case T30_CTR:
/* Valid response to a CTC received */ /* 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) 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: case T30_RNR:
if (s->timer_t5 == 0) 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; s->retries = 0;
if (s->phase_d_handler) 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); s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
} }
break; 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) 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: case T30_RNR:
if (s->timer_t5 == 0) 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; s->retries = 0;
if (s->phase_d_handler) 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); s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
} }
break; break;
@ -4257,7 +4381,7 @@ static void process_rx_control_msg(t30_state_t *s, const uint8_t *msg, int len)
} }
else else
{ {
unexpected_frame(s, msg, len); unexpected_non_final_frame(s, msg, len);
} }
break; break;
case (T30_SEP & 0xFE): 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 else
{ {
unexpected_frame(s, msg, len); unexpected_non_final_frame(s, msg, len);
} }
break; break;
case (T30_PSA & 0xFE): 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 else
{ {
unexpected_frame(s, msg, len); unexpected_non_final_frame(s, msg, len);
} }
break; break;
case (T30_CIA & 0xFE): 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 else
{ {
unexpected_frame(s, msg, len); unexpected_non_final_frame(s, msg, len);
} }
break; break;
case (T30_ISP & 0xFE): 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 else
{ {
unexpected_frame(s, msg, len); unexpected_non_final_frame(s, msg, len);
} }
break; break;
case (T30_TSI & 0xFE): 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 = s->error_correcting_mode;
t->error_correcting_mode_retries = s->error_correcting_mode_retries; t->error_correcting_mode_retries = s->error_correcting_mode_retries;
t4_get_transfer_statistics(&s->t4, &stats); t4_get_transfer_statistics(&s->t4, &stats);
t->pages_tx = s->ecm_tx_page; t->pages_tx = s->tx_page_number;
t->pages_rx = s->ecm_rx_page; t->pages_rx = s->rx_page_number;
t->pages_in_file = stats.pages_in_file; t->pages_in_file = stats.pages_in_file;
t->width = stats.width; t->width = stats.width;
t->length = stats.length; 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->encoding = stats.encoding;
t->image_size = stats.line_image_size; t->image_size = stats.line_image_size;
t->current_status = s->current_status; t->current_status = s->current_status;
#if 0
t->rtn_events = s->rtn_events;
t->rtp_events = s->rtp_events;
#endif
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
@ -6000,9 +6128,13 @@ SPAN_DECLARE(int) t30_restart(t30_state_t *s)
t30_build_dis_or_dtc(s); t30_build_dis_or_dtc(s);
memset(&s->rx_info, 0, sizeof(s->rx_info)); memset(&s->rx_info, 0, sizeof(s->rx_info));
release_resources(s); release_resources(s);
/* The ECM page number is only reset at call establishment */ /* The page number is only reset at call establishment */
s->ecm_rx_page = 0; s->rx_page_number = 0;
s->ecm_tx_page = 0; s->tx_page_number = 0;
#if 0
s->rtn_events = 0;
s->rtp_events = 0;
#endif
s->far_end_detected = FALSE; s->far_end_detected = FALSE;
s->timer_t0_t1 = ms_to_samples(DEFAULT_TIMER_T0); s->timer_t0_t1 = ms_to_samples(DEFAULT_TIMER_T0);
if (s->calling_party) if (s->calling_party)

View File

@ -25,7 +25,7 @@
* License along with this program; if not, write to the Free Software * License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 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 */ /*! \file */
@ -176,12 +176,15 @@ enum
static int restart_modem(t31_state_t *s, int new_modem); 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 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_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 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(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(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(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 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 int cng_rx(void *user_data, const int16_t amp[], int len);
static void non_ecm_put_bit(void *user_data, int bit); 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_signal_present = FALSE;
s->at_state.rx_trained = FALSE; s->at_state.rx_trained = FALSE;
s->rx_frame_received = 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; use_hdlc = FALSE;
switch (s->modem) 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 /* Do V.21/HDLC receive in parallel. The other end may send its
first message at any time. The CNG tone will continue until first message at any time. The CNG tone will continue until
we get a valid preamble. */ 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); t31_v21_rx(s);
set_tx_handler(s, (span_tx_handler_t *) &modem_connect_tones_tx, &t->connect_tx); 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); 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 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); t31_v21_rx(s);
silence_gen_set(&t->silence_gen, 0); silence_gen_set(&t->silence_gen, 0);
set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen); 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 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); t31_v21_rx(s);
} }
break; break;
@ -1652,7 +1655,7 @@ static int restart_modem(t31_state_t *s, int new_modem)
case FAX_MODEM_V17_RX: case FAX_MODEM_V17_RX:
if (!s->t38_mode) 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); v17_rx_restart(&t->v17_rx, s->bit_rate, s->short_train);
/* Allow for +FCERROR/+FRH:3 */ /* Allow for +FCERROR/+FRH:3 */
t31_v21_rx(s); t31_v21_rx(s);
@ -1689,7 +1692,7 @@ static int restart_modem(t31_state_t *s, int new_modem)
case FAX_MODEM_V27TER_RX: case FAX_MODEM_V27TER_RX:
if (!s->t38_mode) 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); v27ter_rx_restart(&t->v27ter_rx, s->bit_rate, FALSE);
/* Allow for +FCERROR/+FRH:3 */ /* Allow for +FCERROR/+FRH:3 */
t31_v21_rx(s); t31_v21_rx(s);
@ -1726,7 +1729,7 @@ static int restart_modem(t31_state_t *s, int new_modem)
case FAX_MODEM_V29_RX: case FAX_MODEM_V29_RX:
if (!s->t38_mode) 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); v29_rx_restart(&t->v29_rx, s->bit_rate, FALSE);
/* Allow for +FCERROR/+FRH:3 */ /* Allow for +FCERROR/+FRH:3 */
t31_v21_rx(s); t31_v21_rx(s);
@ -1752,7 +1755,7 @@ static int restart_modem(t31_state_t *s, int new_modem)
case FAX_MODEM_SILENCE_RX: case FAX_MODEM_SILENCE_RX:
if (!s->t38_mode) 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); silence_gen_set(&t->silence_gen, 0);
set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen); set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL); 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.rx_data_bytes = 0;
s->at_state.transmit = FALSE; s->at_state.transmit = FALSE;
s->modem = FAX_MODEM_SILENCE_TX; 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); t31_set_at_rx_mode(s, AT_MODE_OFFHOOK_COMMAND);
at_put_response_code(&s->at_state, AT_RESPONSE_CODE_OK); 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 --------------------------------------------------------*/ /*- 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; s->audio.modems.rx_user_data = user_data;
} }
/*- End of function --------------------------------------------------------*/ /*- 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 /* The fast modem has trained, so we no longer need to run the slow
one in parallel. */ 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)); 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 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 /* We have received something, and the fast modem has not trained. We must
be receiving valid V.21 */ 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)); 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; return len;
} }
/*- End of function --------------------------------------------------------*/ /*- 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) static int v27ter_v21_rx(void *user_data, const int16_t amp[], int len)
{ {
t31_state_t *t; 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 /* The fast modem has trained, so we no longer need to run the slow
one in parallel. */ 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)); 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 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 /* We have received something, and the fast modem has not trained. We must
be receiving valid V.21 */ 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)); 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; return len;
} }
/*- End of function --------------------------------------------------------*/ /*- 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) static int v29_v21_rx(void *user_data, const int16_t amp[], int len)
{ {
t31_state_t *t; 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 /* The fast modem has trained, so we no longer need to run the slow
one in parallel. */ 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)); 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 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 /* We have received something, and the fast modem has not trained. We must
be receiving valid V.21 */ 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)); 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; return len;
} }
/*- End of function --------------------------------------------------------*/ /*- 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) SPAN_DECLARE(int) t31_rx(t31_state_t *s, int16_t amp[], int len)
{ {
int i; int i;

View File

@ -22,7 +22,7 @@
* License along with this program; if not, write to the Free Software * License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 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 */ /*! \file */
@ -93,9 +93,9 @@
enum enum
{ {
T38_CHUNKING_MERGE_FCS_WITH_DATA = 0x0001, T38_CHUNKING_MERGE_FCS_WITH_DATA = 0x0001,
T38_CHUNKING_WHOLE_FRAMES = 0x0002, T38_CHUNKING_WHOLE_FRAMES = 0x0002,
T38_CHUNKING_ALLOW_TEP_TIME = 0x0004 T38_CHUNKING_ALLOW_TEP_TIME = 0x0004
}; };
enum enum

View File

@ -16,7 +16,7 @@
## along with this program; if not, write to the Free Software ## along with this program; if not, write to the Free Software
## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ## 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_CFLAGS = $(COMP_VENDOR_CFLAGS)
AM_LDFLAGS = $(COMP_VENDOR_LDFLAGS) AM_LDFLAGS = $(COMP_VENDOR_LDFLAGS)
@ -99,6 +99,7 @@ noinst_PROGRAMS = adsi_tests \
sig_tone_tests \ sig_tone_tests \
super_tone_rx_tests \ super_tone_rx_tests \
super_tone_tx_tests \ super_tone_tx_tests \
swept_tone_tests \
t4_tests \ t4_tests \
t31_tests \ t31_tests \
t38_core_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_SOURCES = super_tone_tx_tests.c
super_tone_tx_tests_LDADD = -L$(top_builddir)/spandsp-sim -lspandsp-sim $(LIBDIR) -lspandsp 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_SOURCES = t4_tests.c
t4_tests_LDADD = $(LIBDIR) -lspandsp t4_tests_LDADD = $(LIBDIR) -lspandsp

View File

@ -22,7 +22,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 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 /*! \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; type = fr[2] & 0xFE;
if (type == T30_DIS || type == T30_DTC || type == T30_DCS) if (type == T30_DIS || type == T30_DTC || type == T30_DCS)
t30_decode_dis_dtc_dcs(&t30_dummy, fr, frlen); 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)) if (t35_decode(&fr[3], frlen - 3, &country, &vendor, &model))
{ {

View File

@ -22,7 +22,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 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 /*! \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_NAME1 "line_model_test_in1.wav"
#define IN_FILE_NAME2 "line_model_test_in2.wav" #define IN_FILE_NAME2 "line_model_test_in2.wav"
#define OUT_FILE_NAME1 "line_model_one_way_test_out.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 channel_codec;
int rbs_pattern; 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); 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); if ((inhandle1 = sf_open_telephony_read(IN_FILE_NAME1, 1)) == NULL)
exit(2); {
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) 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); exit(2);
} }
} }
if (sf_close(inhandle1)) if (speech_test)
{ {
fprintf(stderr, " Cannot close audio file '%s'\n", IN_FILE_NAME1); if (sf_close(inhandle1))
exit(2); {
fprintf(stderr, " Cannot close audio file '%s'\n", IN_FILE_NAME1);
exit(2);
}
} }
if (sf_close(outhandle)) 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(&noise1, 1234567, -10.0f);
awgn_init_dbm0(&noise2, 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); if ((inhandle1 = sf_open_telephony_read(IN_FILE_NAME1, 1)) == NULL)
exit(2); {
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); inhandle1 =
exit(2); 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); exit(2);
} }
for (i = 0; i < 10000; i++) 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); exit(2);
} }
} }
if (sf_close(inhandle1)) if (speech_test)
{ {
fprintf(stderr, " Cannot close audio file '%s'\n", IN_FILE_NAME1); if (sf_close(inhandle1))
exit(2); {
} fprintf(stderr, " Cannot close audio file '%s'\n", IN_FILE_NAME1);
if (sf_close(inhandle2)) exit(2);
{ }
fprintf(stderr, " Cannot close audio file '%s'\n", IN_FILE_NAME2); if (sf_close(inhandle2))
exit(2); {
fprintf(stderr, " Cannot close audio file '%s'\n", IN_FILE_NAME2);
exit(2);
}
} }
if (sf_close(outhandle)) 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); exit(2);
} }
both_ways_line_model_release(model); both_ways_line_model_release(model);
} }
/*- End of function --------------------------------------------------------*/ /*- 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 main(int argc, char *argv[])
{ {
int line_model_no; int line_model_no;
@ -319,6 +392,7 @@ int main(int argc, char *argv[])
complexify_tests(); complexify_tests();
test_one_way_model(line_model_no, speech_test); test_one_way_model(line_model_no, speech_test);
test_both_ways_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 function --------------------------------------------------------*/
/*- End of file ------------------------------------------------------------*/ /*- End of file ------------------------------------------------------------*/

View File

@ -17,7 +17,7 @@
# License along with this program; if not, write to the Free Software # License along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # 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 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 completed OK
echo super_tone_tx_tests not enabled 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 ./t31_tests -r >$STDOUT_DEST 2>$STDERR_DEST
RETVAL=$? RETVAL=$?
if [ $RETVAL != 0 ] if [ $RETVAL != 0 ]

View File

@ -22,7 +22,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 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 */ /*! \file */
@ -58,112 +58,97 @@
static int sampleno = 0; static int sampleno = 0;
static int tone_1_present = 0; static int tone_1_present = 0;
static int tone_2_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 void tx_handler(void *user_data, int what, int level, int duration)
static int tx_handler(void *user_data, int what)
{ {
//printf("What - %d\n", what); sig_tone_tx_state_t *s;
if ((what & SIG_TONE_UPDATE_REQUEST))
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"); printf("Tx: update request\n");
/* The signaling processor wants to know what to do next */ /* The sig tone transmit side wants to know what to do next */
if (sampleno < ms_to_samples(100)) switch (tx_section)
{ {
/* 100ms off-hook */ case 0:
printf("100ms off-hook - %d samples\n", 800 - sampleno); printf("33ms break - %d samples\n", ms_to_samples(33));
return 0x02 | ((ms_to_samples(100) - sampleno) << 16); tx_section++;
} sig_tone_tx_set_mode(s, SIG_TONE_1_PRESENT, ms_to_samples(33));
else if (sampleno < ms_to_samples(600)) break;
{ case 1:
/* 500ms idle */ printf("67ms make - %d samples\n", ms_to_samples(67));
printf("500ms idle - %d samples\n", ms_to_samples(600) - sampleno); if (++dial_pulses == 9)
return 0x02 | SIG_TONE_1_PRESENT | ((ms_to_samples(600) - sampleno) << 16); tx_section++;
}
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);
}
else else
{ tx_section--;
printf("67ms make - %d samples\n", ms_to_samples(67)); sig_tone_tx_set_mode(s, 0, ms_to_samples(67));
ping = !ping; break;
return 0x02 | SIG_TONE_1_PRESENT | (ms_to_samples(67) << 16); case 2:
} tx_section++;
/*endif*/ 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 /*endswitch*/
{
return 0x02 | SIG_TONE_1_PRESENT | ((ms_to_samples(700) - sampleno) << 16) | SIG_TONE_TX_PASSTHROUGH;
}
/*endif*/
} }
/*endif*/ /*endif*/
return 0;
} }
/*- End of function --------------------------------------------------------*/ /*- 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)) if ((what & SIG_TONE_1_CHANGE))
{ {
tone_1_present = what & SIG_TONE_1_PRESENT; 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*/ /*endif*/
if ((what & SIG_TONE_2_CHANGE)) if ((what & SIG_TONE_2_CHANGE))
{ {
tone_2_present = what & SIG_TONE_2_PRESENT; 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*/ /*endif*/
return 0;
} }
/*- End of function --------------------------------------------------------*/ /*- 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]; int16_t buf[8192];
awgn_state_t noise_source;
int i; int i;
int f; int len;
uint32_t phase_acc; double sumin;
int32_t phase_rate; double sumout;
int32_t scaling; swept_tone_state_t *swept;
double sum;
/* Things like noise don't highlight the frequency response of the high Q notch /* 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. */ very well. We use a slowly swept frequency to check it. */
awgn_init_dbm0(&noise_source, 1234567, -10.0f); swept = swept_tone_init(NULL, 200.0f, 3900.0f, -10.0f, 120*SAMPLE_RATE, 0);
for (f = 1; f < 4000; f++) for (;;)
{ {
phase_rate = dds_phase_rate(f); if ((len = swept_tone(swept, buf, SAMPLES_PER_CHUNK)) <= 0)
scaling = dds_scaling_dbm0(-10); break;
phase_acc = 0; sumin = 0.0;
for (i = 0; i < 8192; i++) for (i = 0; i < len; i++)
buf[i] = dds_mod(&phase_acc, phase_rate, scaling, 0); 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*/ /*endfor*/
sig_tone_rx(s, buf, 8192); printf("%7.1f %f\n", swept_tone_current_frequency(swept), 10.0*log10(sumout/sumin));
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);
} }
/*endfor*/ /*endfor*/
swept_tone_free(swept);
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
@ -189,45 +174,56 @@ int main(int argc, char *argv[])
} }
/*endif*/ /*endif*/
awgn_init_dbm0(&noise_source, 1234567, -10.0f); awgn_init_dbm0(&noise_source, 1234567, -20.0f);
for (type = 1; type <= 3; type++) for (type = 1; type <= 3; type++)
{ {
sampleno = 0; sampleno = 0;
tone_1_present = 0; tone_1_present = 0;
tone_2_present = 0; tone_2_present = 0;
ping = 0; tx_section = 0;
munge = NULL; munge = NULL;
switch (type) switch (type)
{ {
case 1: case 1:
printf("2280Hz tests.\n"); printf("2280Hz tests.\n");
munge = codec_munge_init(MUNGE_CODEC_ALAW, 0); munge = codec_munge_init(MUNGE_CODEC_ALAW, 0);
sig_tone_tx_init(&tx_state, SIG_TONE_2280HZ, tx_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, NULL); sig_tone_rx_init(&rx_state, SIG_TONE_2280HZ, rx_handler, &rx_state);
rx_state.current_rx_tone |= SIG_TONE_RX_PASSTHROUGH; rx_state.current_rx_tone |= SIG_TONE_RX_PASSTHROUGH;
break; break;
case 2: case 2:
printf("26000Hz tests.\n"); printf("2600Hz tests.\n");
munge = codec_munge_init(MUNGE_CODEC_ULAW, 0); munge = codec_munge_init(MUNGE_CODEC_ULAW, 0);
sig_tone_tx_init(&tx_state, SIG_TONE_2600HZ, tx_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, NULL); sig_tone_rx_init(&rx_state, SIG_TONE_2600HZ, rx_handler, &rx_state);
rx_state.current_rx_tone |= SIG_TONE_RX_PASSTHROUGH; rx_state.current_rx_tone |= SIG_TONE_RX_PASSTHROUGH;
break; break;
case 3: case 3:
printf("2400Hz/26000Hz tests.\n"); printf("2400Hz/2600Hz tests.\n");
munge = codec_munge_init(MUNGE_CODEC_ULAW, 0); munge = codec_munge_init(MUNGE_CODEC_ULAW, 0);
sig_tone_tx_init(&tx_state, SIG_TONE_2400HZ_2600HZ, tx_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, NULL); sig_tone_rx_init(&rx_state, SIG_TONE_2400HZ_2600HZ, rx_handler, &rx_state);
rx_state.current_rx_tone |= SIG_TONE_RX_PASSTHROUGH; rx_state.current_rx_tone |= SIG_TONE_RX_PASSTHROUGH;
break; break;
} }
/*endswitch*/ /*endswitch*/
/* Set to the default of hook condition */
//map_frequency_response(&rx_state); 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++) for (i = 0; i < SAMPLES_PER_CHUNK; i++)
amp[i] = awgn(&noise_source); amp[i] = awgn(&noise_source);
/*endfor*/ /*endfor*/

View File

@ -0,0 +1,101 @@
/*
* SpanDSP - a series of DSP components for telephony
*
* swept_tone_tests.c
*
* Written by Steve Underwood <steveu@coppice.org>
*
* 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 <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <memory.h>
#include <sndfile.h>
#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 ------------------------------------------------------------*/