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
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# $Id: configure.ac,v 1.71 2009/07/12 09:29:18 steveu Exp $
# $Id: configure.ac,v 1.73 2009/10/03 04:37:25 steveu Exp $
# @start 1
@ -108,20 +108,20 @@ else
CXXFLAGS=${CXXFLAGS-"-g -O2"}
fi
AC_DEFUN([REMOVE_FROM_VAR],[
new_val=""
removed=0
for i in $$1; do
if test "x$i" != "x$2"; then
new_val="$new_val $i"
else
removed=1
fi
done
if test $removed = "1"; then
echo " removed \"$2\" from $1"
$1=$new_val
fi
AC_DEFUN([REMOVE_FROM_VAR],[
new_val=""
removed=0
for i in $$1; do
if test "x$i" != "x$2"; then
new_val="$new_val $i"
else
removed=1
fi
done
if test $removed = "1"; then
echo " removed \"$2\" from $1"
$1=$new_val
fi
])
AC_C_CONST
@ -146,9 +146,9 @@ AC_ARG_ENABLE(sse4_2, [ --enable-sse4-2 Enable SSE4.2 support])
AC_ARG_ENABLE(sse4a, [ --enable-sse4a Enable SSE4A support])
AC_ARG_ENABLE(sse5, [ --enable-sse5 Enable SSE5 support])
AC_ARG_ENABLE(fixed_point, [ --enable-fixed-point Enable fixed point support])
# The following is for MSVC, where we may be using a local copy of libtiff, built alongside spandsp
AC_ARG_ENABLE(builtin_tiff,
[AC_HELP_STRING([--enable-builtin-tiff],[build with builtin libtiff])],[enable_builtin_tiff="$enableval"],[enable_builtin_tiff="no"])
[AC_HELP_STRING([--enable-builtin-tiff],[build with builtin libtiff])],[enable_builtin_tiff="$enableval"],[enable_builtin_tiff="no"])
AC_FUNC_ERROR_AT_LINE
AC_FUNC_VPRINTF

View File

@ -22,7 +22,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id: line_model.c,v 1.12 2009/06/01 16:27:12 steveu Exp $
* $Id: line_model.c,v 1.14 2009/09/23 16:02:59 steveu Exp $
*/
#if defined(HAVE_CONFIG_H)
@ -54,7 +54,7 @@
#define NULL (void *) 0
#endif
float null_line_model[] =
static const float null_line_model[] =
{
0.0,
0.0,
@ -187,7 +187,7 @@ float null_line_model[] =
1.0
};
static float *models[] =
SPAN_DECLARE_DATA const float *line_models[] =
{
null_line_model, /* 0 */
proakis_line_model,
@ -225,7 +225,7 @@ static float calc_near_line_filter(one_way_line_model_state_t *s, float v)
s->near_buf_ptr = p;
/* Apply the filter */
sum = 0;
sum = 0.0f;
for (j = 0; j < s->near_filter_len; j++)
{
sum += s->near_filter[j]*s->near_buf[p];
@ -254,7 +254,7 @@ static float calc_far_line_filter(one_way_line_model_state_t *s, float v)
s->far_buf_ptr = p;
/* Apply the filter */
sum = 0;
sum = 0.0f;
for (j = 0; j < s->far_filter_len; j++)
{
sum += s->far_filter[j]*s->far_buf[p];
@ -479,10 +479,10 @@ SPAN_DECLARE(one_way_line_model_state_t *) one_way_line_model_init(int model, fl
s->munge = codec_munge_init(codec, rbs_pattern);
s->near_filter = models[model];
s->near_filter = line_models[model];
s->near_filter_len = 129;
s->far_filter = models[model];
s->far_filter = line_models[model];
s->far_filter_len = 129;
/* Put half the noise in each analogue section */
@ -526,14 +526,14 @@ SPAN_DECLARE(both_ways_line_model_state_t *) both_ways_line_model_init(int model
s->line1.bulk_delay_ptr = 0;
s->line2.bulk_delay_ptr = 0;
s->line1.near_filter = models[model1];
s->line1.near_filter = line_models[model1];
s->line1.near_filter_len = 129;
s->line2.near_filter = models[model2];
s->line2.near_filter = line_models[model2];
s->line2.near_filter_len = 129;
s->line1.far_filter = models[model1];
s->line1.far_filter = line_models[model1];
s->line1.far_filter_len = 129;
s->line2.far_filter = models[model2];
s->line2.far_filter = line_models[model2];
s->line2.far_filter_len = 129;
/* Put half the noise in each analogue section */

View File

@ -22,7 +22,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id: make_line_models.c,v 1.9 2009/02/10 17:49:20 steveu Exp $
* $Id: make_line_models.c,v 1.10 2009/09/23 16:02:59 steveu Exp $
*/
/*! \page make_line_models_page Telephony line model construction
@ -849,7 +849,8 @@ static void generate_ad_edd(void)
offset = (f - edd[l - 1].freq)/(edd[l].freq - edd[l - 1].freq);
delay = (1.0f - offset)*edd[l - 1].edd[k] + offset*edd[l].edd[k];
}
phase = 2.0f*M_PI*f*delay*0.001f;
//phase = 2.0f*M_PI*f*delay*0.001f;
phase = 0.0f;
#if defined(HAVE_FFTW3_H)
in[i][0] = amp*cosf(phase);
in[i][1] = amp*sinf(phase);
@ -874,7 +875,7 @@ static void generate_ad_edd(void)
fprintf(outfile, "/* V.56bis AD-%d, EDD%d */\n", (j == 0) ? 1 : j + 4, k + 1);
fprintf(outfile, "float ad_%d_edd_%d_model[] =\n", (j == 0) ? 1 : j + 4, k + 1);
fprintf(outfile, "const float ad_%d_edd_%d_model[] =\n", (j == 0) ? 1 : j + 4, k + 1);
fprintf(outfile, "{\n");
/* Normalise the filter's gain */
pw = 0.0f;
@ -955,7 +956,8 @@ static void generate_proakis(void)
/* Linear interpolation */
amp = ((1.0f - offset)*proakis[index].amp + offset*proakis[index + 1].amp)/2.3f;
delay = (1.0f - offset)*proakis[index].delay + offset*proakis[index + 1].delay;
phase = 2.0f*M_PI*f*delay*0.001f;
//phase = 2.0f*M_PI*f*delay*0.001f;
phase = 0.0f;
#if defined(HAVE_FFTW3_H)
in[i][0] = amp*cosf(phase);
in[i][1] = amp*sinf(phase);
@ -978,7 +980,7 @@ static void generate_proakis(void)
fprintf(outfile, "/* Medium range telephone line response\n");
fprintf(outfile, " (from p 537, Digital Communication, John G. Proakis */\n");
fprintf(outfile, "float proakis_line_model[] =\n");
fprintf(outfile, "const float proakis_line_model[] =\n");
fprintf(outfile, "{\n");
/* Normalise the filter's gain */
pw = 0.0f;

View File

@ -22,7 +22,7 @@
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id: line_model.h,v 1.6 2009/05/31 14:47:10 steveu Exp $
* $Id: line_model.h,v 1.7 2009/09/23 16:02:59 steveu Exp $
*/
/*! \file */
@ -132,6 +132,8 @@ extern "C"
{
#endif
SPAN_DECLARE_DATA extern const float *line_models[];
SPAN_DECLARE(void) both_ways_line_model(both_ways_line_model_state_t *s,
int16_t output1[],
const int16_t input1[],

View File

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

View File

@ -16,7 +16,7 @@
## License along with this program; if not, write to the Free Software
## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
##
## $Id: Makefile.am,v 1.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_LDFLAGS = $(COMP_VENDOR_LDFLAGS)
@ -110,6 +110,7 @@ libspandsp_la_SOURCES = adsi.c \
silence_gen.c \
super_tone_rx.c \
super_tone_tx.c \
swept_tone.c \
t4.c \
t30.c \
t30_api.c \
@ -188,6 +189,7 @@ nobase_include_HEADERS = spandsp/adsi.h \
spandsp/silence_gen.h \
spandsp/super_tone_rx.h \
spandsp/super_tone_tx.h \
spandsp/swept_tone.h \
spandsp/t4.h \
spandsp/t30.h \
spandsp/t30_api.h \
@ -226,6 +228,7 @@ nobase_include_HEADERS = spandsp/adsi.h \
spandsp/private/bert.h \
spandsp/private/bitstream.h \
spandsp/private/dtmf.h \
spandsp/private/echo.h \
spandsp/private/fax.h \
spandsp/private/fax_modems.h \
spandsp/private/fsk.h \
@ -238,6 +241,7 @@ nobase_include_HEADERS = spandsp/adsi.h \
spandsp/private/logging.h \
spandsp/private/lpc10.h \
spandsp/private/modem_connect_tones.h \
spandsp/private/modem_echo.h \
spandsp/private/noise.h \
spandsp/private/oki_adpcm.h \
spandsp/private/queue.h \
@ -246,6 +250,7 @@ nobase_include_HEADERS = spandsp/adsi.h \
spandsp/private/silence_gen.h \
spandsp/private/super_tone_rx.h \
spandsp/private/super_tone_tx.h \
spandsp/private/swept_tone.h \
spandsp/private/t30.h \
spandsp/private/t31.h \
spandsp/private/t38_core.h \

View File

@ -25,7 +25,7 @@
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id: 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 */
@ -80,7 +80,7 @@ enum
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,
/*.verbose =*/ TRUE,
/*.result_code_format =*/ ASCII_RESULT_CODES,

View File

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

View File

@ -23,7 +23,7 @@
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id: 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 */
@ -128,9 +128,13 @@ static void hdlc_underflow_handler(void *user_data)
}
/*- 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;
}
/*- End of function --------------------------------------------------------*/
@ -162,7 +166,7 @@ static int v17_v21_rx(void *user_data, const int16_t amp[], int len)
/* The fast modem has trained, so we no longer need to run the slow
one in parallel. */
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.17 + V.21 to V.17 (%.2fdBm0)\n", v17_rx_signal_power(&s->v17_rx));
set_rx_handler(t, (span_rx_handler_t *) &v17_rx, &s->v17_rx);
set_rx_handler(t, (span_rx_handler_t *) &v17_rx, (span_rx_fillin_handler_t *) &v17_rx_fillin, &s->v17_rx);
}
else
{
@ -172,13 +176,26 @@ static int v17_v21_rx(void *user_data, const int16_t amp[], int len)
/* We have received something, and the fast modem has not trained. We must
be receiving valid V.21 */
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.17 + V.21 to V.21 (%.2fdBm0)\n", fsk_rx_signal_power(&s->v21_rx));
set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, &s->v21_rx);
set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, (span_rx_fillin_handler_t *) &fsk_rx_fillin, &s->v21_rx);
}
}
return 0;
}
/*- End of function --------------------------------------------------------*/
static int v17_v21_rx_fillin(void *user_data, int len)
{
fax_state_t *t;
fax_modems_state_t *s;
t = (fax_state_t *) user_data;
s = &t->modems;
v17_rx_fillin(&s->v17_rx, len);
fsk_rx_fillin(&s->v21_rx, len);
return 0;
}
/*- End of function --------------------------------------------------------*/
static int v27ter_v21_rx(void *user_data, const int16_t amp[], int len)
{
fax_state_t *t;
@ -192,7 +209,7 @@ static int v27ter_v21_rx(void *user_data, const int16_t amp[], int len)
/* The fast modem has trained, so we no longer need to run the slow
one in parallel. */
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.27ter + V.21 to V.27ter (%.2fdBm0)\n", v27ter_rx_signal_power(&s->v27ter_rx));
set_rx_handler(t, (span_rx_handler_t *) &v27ter_rx, &s->v27ter_rx);
set_rx_handler(t, (span_rx_handler_t *) &v27ter_rx, (span_rx_fillin_handler_t *) &v27ter_rx_fillin, &s->v27ter_rx);
}
else
{
@ -202,13 +219,26 @@ static int v27ter_v21_rx(void *user_data, const int16_t amp[], int len)
/* We have received something, and the fast modem has not trained. We must
be receiving valid V.21 */
span_log(&s->logging, SPAN_LOG_FLOW, "Switching from V.27ter + V.21 to V.21 (%.2fdBm0)\n", fsk_rx_signal_power(&s->v21_rx));
set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, &s->v21_rx);
set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, (span_rx_fillin_handler_t *) &fsk_rx_fillin, &s->v21_rx);
}
}
return 0;
}
/*- End of function --------------------------------------------------------*/
static int v27ter_v21_rx_fillin(void *user_data, int len)
{
fax_state_t *t;
fax_modems_state_t *s;
t = (fax_state_t *) user_data;
s = &t->modems;
v27ter_rx_fillin(&s->v27ter_rx, len);
fsk_rx_fillin(&s->v21_rx, len);
return 0;
}
/*- End of function --------------------------------------------------------*/
static int v29_v21_rx(void *user_data, const int16_t amp[], int len)
{
fax_state_t *t;
@ -222,7 +252,7 @@ static int v29_v21_rx(void *user_data, const int16_t amp[], int len)
/* The fast modem has trained, so we no longer need to run the slow
one in parallel. */
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.29 + V.21 to V.29 (%.2fdBm0)\n", v29_rx_signal_power(&s->v29_rx));
set_rx_handler(t, (span_rx_handler_t *) &v29_rx, &s->v29_rx);
set_rx_handler(t, (span_rx_handler_t *) &v29_rx, (span_rx_fillin_handler_t *) &v29_rx_fillin, &s->v29_rx);
}
else
{
@ -232,13 +262,26 @@ static int v29_v21_rx(void *user_data, const int16_t amp[], int len)
/* We have received something, and the fast modem has not trained. We must
be receiving valid V.21 */
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.29 + V.21 to V.21 (%.2fdBm0)\n", fsk_rx_signal_power(&s->v21_rx));
set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, &s->v21_rx);
set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, (span_rx_fillin_handler_t *) &fsk_rx_fillin, &s->v21_rx);
}
}
return 0;
}
/*- End of function --------------------------------------------------------*/
static int v29_v21_rx_fillin(void *user_data, int len)
{
fax_state_t *t;
fax_modems_state_t *s;
t = (fax_state_t *) user_data;
s = &t->modems;
v29_rx_fillin(&s->v29_rx, len);
fsk_rx_fillin(&s->v21_rx, len);
return 0;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) fax_rx(fax_state_t *s, int16_t *amp, int len)
{
int i;
@ -276,26 +319,9 @@ SPAN_DECLARE(int) fax_rx_fillin(fax_state_t *s, int len)
write(s->modems.audio_rx_log, amp, len*sizeof(int16_t));
}
#endif
t30_timer_update(&s->t30, len);
/* Call the fillin function of the current modem (if there is one). */
switch (s->modems.current_rx_type)
{
case T30_MODEM_V21:
len = fsk_rx_fillin(&s->modems.v21_rx, len);
break;
case T30_MODEM_V27TER:
/* TODO: what about FSK in the early stages */
len = v27ter_rx_fillin(&s->modems.v27ter_rx, len);
break;
case T30_MODEM_V29:
/* TODO: what about FSK in the early stages */
len = v29_rx_fillin(&s->modems.v29_rx, len);
break;
case T30_MODEM_V17:
/* TODO: what about FSK in the early stages */
len = v17_rx_fillin(&s->modems.v17_rx, len);
break;
}
s->modems.rx_fillin_handler(s->modems.rx_user_data, len);
t30_timer_update(&s->t30, len);
return len;
}
/*- End of function --------------------------------------------------------*/
@ -399,27 +425,27 @@ static void fax_set_rx_type(void *user_data, int type, int bit_rate, int short_t
case T30_MODEM_V21:
fsk_rx_init(&t->v21_rx, &preset_fsk_specs[FSK_V21CH2], TRUE, (put_bit_func_t) hdlc_rx_put_bit, put_bit_user_data);
fsk_rx_signal_cutoff(&t->v21_rx, -45.5f);
set_rx_handler(s, (span_rx_handler_t *) &fsk_rx, &t->v21_rx);
set_rx_handler(s, (span_rx_handler_t *) &fsk_rx, (span_rx_fillin_handler_t *) &fsk_rx_fillin, &t->v21_rx);
break;
case T30_MODEM_V27TER:
v27ter_rx_restart(&t->v27ter_rx, bit_rate, FALSE);
v27ter_rx_set_put_bit(&t->v27ter_rx, put_bit_func, put_bit_user_data);
set_rx_handler(s, &v27ter_v21_rx, s);
set_rx_handler(s, &v27ter_v21_rx, &v27ter_v21_rx_fillin, s);
break;
case T30_MODEM_V29:
v29_rx_restart(&t->v29_rx, bit_rate, FALSE);
v29_rx_set_put_bit(&t->v29_rx, put_bit_func, put_bit_user_data);
set_rx_handler(s, &v29_v21_rx, s);
set_rx_handler(s, &v29_v21_rx, &v29_v21_rx_fillin, s);
break;
case T30_MODEM_V17:
v17_rx_restart(&t->v17_rx, bit_rate, short_train);
v17_rx_set_put_bit(&t->v17_rx, put_bit_func, put_bit_user_data);
set_rx_handler(s, &v17_v21_rx, s);
set_rx_handler(s, &v17_v21_rx, &v17_v21_rx_fillin, s);
break;
case T30_MODEM_DONE:
span_log(&s->logging, SPAN_LOG_FLOW, "FAX exchange complete\n");
default:
set_rx_handler(s, (span_rx_handler_t *) &span_dummy_rx, s);
set_rx_handler(s, (span_rx_handler_t *) &span_dummy_rx, (span_rx_fillin_handler_t *) &span_dummy_rx_fillin, s);
break;
}
}

View File

@ -22,7 +22,7 @@
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id: fax_modems.c,v 1.5 2009/04/12 03:29:58 steveu Exp $
* $Id: fax_modems.c,v 1.6 2009/09/04 14:38:46 steveu Exp $
*/
/*! \file */
@ -101,6 +101,7 @@ SPAN_DECLARE(int) fax_modems_v17_v21_rx(void *user_data, const int16_t amp[], in
be receiving valid V.21 */
span_log(&s->logging, SPAN_LOG_FLOW, "Switching from V.17 + V.21 to V.21 (%.2fdBm0)\n", fsk_rx_signal_power(&s->v21_rx));
s->rx_handler = (span_rx_handler_t *) &fsk_rx;
s->rx_fillin_handler = (span_rx_fillin_handler_t *) &fsk_rx_fillin;
s->rx_user_data = &s->v21_rx;
}
return 0;
@ -131,6 +132,7 @@ SPAN_DECLARE(int) fax_modems_v27ter_v21_rx(void *user_data, const int16_t amp[],
be receiving valid V.21 */
span_log(&s->logging, SPAN_LOG_FLOW, "Switching from V.27ter + V.21 to V.21 (%.2fdBm0)\n", fsk_rx_signal_power(&s->v21_rx));
s->rx_handler = (span_rx_handler_t *) &fsk_rx;
s->rx_fillin_handler = (span_rx_fillin_handler_t *) &fsk_rx_fillin;
s->rx_user_data = &s->v21_rx;
}
return 0;
@ -161,6 +163,7 @@ SPAN_DECLARE(int) fax_modems_v29_v21_rx(void *user_data, const int16_t amp[], in
be receiving valid V.21 */
span_log(&s->logging, SPAN_LOG_FLOW, "Switching from V.29 + V.21 to V.21 (%.2fdBm0)\n", fsk_rx_signal_power(&s->v21_rx));
s->rx_handler = (span_rx_handler_t *) &fsk_rx;
s->rx_fillin_handler = (span_rx_fillin_handler_t *) &fsk_rx_fillin;
s->rx_user_data = &s->v21_rx;
}
return 0;
@ -196,6 +199,7 @@ static void v17_rx_status_handler(void *user_data, int status)
case SIG_STATUS_TRAINING_SUCCEEDED:
span_log(&s->logging, SPAN_LOG_FLOW, "Switching to V.17 (%.2fdBm0)\n", v17_rx_signal_power(&s->v17_rx));
s->rx_handler = (span_rx_handler_t *) &v17_rx;
s->rx_fillin_handler = (span_rx_fillin_handler_t *) &v17_rx_fillin;
s->rx_user_data = &s->v17_rx;
break;
}
@ -212,6 +216,7 @@ static void v27ter_rx_status_handler(void *user_data, int status)
case SIG_STATUS_TRAINING_SUCCEEDED:
span_log(&s->logging, SPAN_LOG_FLOW, "Switching to V.27ter (%.2fdBm0)\n", v27ter_rx_signal_power(&s->v27ter_rx));
s->rx_handler = (span_rx_handler_t *) &v27ter_rx;
s->rx_fillin_handler = (span_rx_fillin_handler_t *) &v27ter_rx_fillin;
s->rx_user_data = &s->v27ter_rx;
break;
}
@ -228,6 +233,7 @@ static void v29_rx_status_handler(void *user_data, int status)
case SIG_STATUS_TRAINING_SUCCEEDED:
span_log(&s->logging, SPAN_LOG_FLOW, "Switching to V.29 (%.2fdBm0)\n", v29_rx_signal_power(&s->v29_rx));
s->rx_handler = (span_rx_handler_t *) &v29_rx;
s->rx_fillin_handler = (span_rx_fillin_handler_t *) &v29_rx_fillin;
s->rx_user_data = &s->v29_rx;
break;
}
@ -300,6 +306,7 @@ SPAN_DECLARE(fax_modems_state_t *) fax_modems_init(fax_modems_state_t *s,
s->rx_signal_present = FALSE;
s->rx_handler = (span_rx_handler_t *) &span_dummy_rx;
s->rx_fillin_handler = (span_rx_fillin_handler_t *) &span_dummy_rx;
s->rx_user_data = NULL;
s->tx_handler = (span_tx_handler_t *) &silence_gen;
s->tx_user_data = &s->silence_gen;

View File

@ -142,6 +142,7 @@
<File RelativePath="silence_gen.c"></File>
<File RelativePath="super_tone_rx.c"></File>
<File RelativePath="super_tone_tx.c"></File>
<File RelativePath="swept_tone.c"></File>
<File RelativePath="t4.c"></File>
<File RelativePath="t30.c"></File>
<File RelativePath="t30_api.c"></File>
@ -219,6 +220,7 @@
<File RelativePath="spandsp/silence_gen.h"></File>
<File RelativePath="spandsp/super_tone_rx.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/t30.h"></File>
<File RelativePath="spandsp/t30_api.h"></File>
@ -257,6 +259,7 @@
<File RelativePath="spandsp/private/bert.h"></File>
<File RelativePath="spandsp/private/bitstream.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_modems.h"></File>
<File RelativePath="spandsp/private/fsk.h"></File>
@ -269,6 +272,7 @@
<File RelativePath="spandsp/private/logging.h"></File>
<File RelativePath="spandsp/private/lpc10.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/oki_adpcm.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/super_tone_rx.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/t31.h"></File>
<File RelativePath="spandsp/private/t38_core.h"></File>

View File

@ -212,6 +212,7 @@
<File RelativePath="silence_gen.c"></File>
<File RelativePath="super_tone_rx.c"></File>
<File RelativePath="super_tone_tx.c"></File>
<File RelativePath="swept_tone.c"></File>
<File RelativePath="t4.c"></File>
<File RelativePath="t30.c"></File>
<File RelativePath="t30_api.c"></File>
@ -289,6 +290,7 @@
<File RelativePath="spandsp/silence_gen.h"></File>
<File RelativePath="spandsp/super_tone_rx.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/t30.h"></File>
<File RelativePath="spandsp/t30_api.h"></File>
@ -327,6 +329,7 @@
<File RelativePath="spandsp/private/bert.h"></File>
<File RelativePath="spandsp/private/bitstream.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_modems.h"></File>
<File RelativePath="spandsp/private/fsk.h"></File>
@ -339,6 +342,7 @@
<File RelativePath="spandsp/private/logging.h"></File>
<File RelativePath="spandsp/private/lpc10.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/oki_adpcm.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/super_tone_rx.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/t31.h"></File>
<File RelativePath="spandsp/private/t38_core.h"></File>

View File

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

View File

@ -23,7 +23,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id: make_modem_filter.c,v 1.16 2009/07/10 13:15:56 steveu Exp $
* $Id: make_modem_filter.c,v 1.17 2009/10/03 04:37:25 steveu Exp $
*/
#if defined(HAVE_CONFIG_H)
@ -44,7 +44,7 @@
#include <stdio.h>
#include <time.h>
#include <fcntl.h>
#if defined(__sunos) || defined(__solaris) || defined(__sun)
#if defined(__sunos) || defined(__solaris) || defined(__sun)
#include <getopt.h>
#endif

View File

@ -22,7 +22,7 @@
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id: modem_echo.c,v 1.25 2009/02/03 16:28:39 steveu Exp $
* $Id: modem_echo.c,v 1.26 2009/09/22 13:11:04 steveu Exp $
*/
/*! \file */
@ -53,6 +53,8 @@
#include "spandsp/dc_restore.h"
#include "spandsp/modem_echo.h"
#include "spandsp/private/modem_echo.h"
SPAN_DECLARE(modem_echo_can_state_t *) modem_echo_can_create(int len)
{
modem_echo_can_state_t *ec;

View File

@ -22,7 +22,7 @@
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id: spandsp.h.in,v 1.18 2009/04/02 13:43:49 steveu Exp $
* $Id: spandsp.h.in,v 1.19 2009/09/22 13:11:04 steveu Exp $
*/
/*! \file */
@ -69,6 +69,7 @@
#include <spandsp/complex_filters.h>
#include <spandsp/dc_restore.h>
#include <spandsp/dds.h>
#include <spandsp/swept_tone.h>
#include <spandsp/echo.h>
#include <spandsp/modem_echo.h>
#include <spandsp/crc.h>

View File

@ -23,7 +23,7 @@
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id: sig_tone.c,v 1.32 2009/04/12 14:18:02 steveu Exp $
* $Id: sig_tone.c,v 1.33 2009/09/04 14:38:46 steveu Exp $
*/
/*! \file */
@ -44,14 +44,17 @@
#include "floating_fudge.h"
#include <memory.h>
#include <string.h>
#include <limits.h>
#undef SPANDSP_USE_FIXED_POINT
#include "spandsp/telephony.h"
#include "spandsp/fast_convert.h"
#include "spandsp/dc_restore.h"
#include "spandsp/saturated.h"
#include "spandsp/vector_int.h"
#include "spandsp/complex.h"
#include "spandsp/dds.h"
#include "spandsp/super_tone_rx.h"
#include "spandsp/sig_tone.h"
#include "spandsp/private/sig_tone.h"
@ -67,12 +70,12 @@ sig_tone_descriptor_t sig_tones[4] =
{
/* 2280Hz (e.g. AC15, and many other European protocols) */
{2280, 0},
{-10, -20}, /* -10+-1 dBmO and -20+-1 dBm0 */
400*(SAMPLE_RATE/1000), /* 300ms to 550ms */
{{-10, -20}, {0, 0}}, /* -10+-1 dBmO and -20+-1 dBm0 */
ms_to_samples(400), /* 300ms to 550ms */
225*(SAMPLE_RATE/1000),
ms_to_samples(225),
225*(SAMPLE_RATE/1000),
ms_to_samples(225),
TRUE,
24,
@ -135,12 +138,12 @@ sig_tone_descriptor_t sig_tones[4] =
{
/* 2600Hz (e.g. many US protocols) */
{2600, 0},
{-8, -8},
400*(SAMPLE_RATE/1000),
{{-8, -8}, {0, 0}},
ms_to_samples(400),
225*(SAMPLE_RATE/1000),
ms_to_samples(225),
225*(SAMPLE_RATE/1000),
ms_to_samples(225),
FALSE,
24,
@ -202,13 +205,13 @@ sig_tone_descriptor_t sig_tones[4] =
},
{
/* 2400Hz/2600Hz (e.g. SS5 and SS5bis) */
{2400, 2600},
{-8, -8},
400*(SAMPLE_RATE/1000),
{2600, 2400},
{{-8, -8}, {-8, -8}},
ms_to_samples(400),
225*(SAMPLE_RATE/1000),
ms_to_samples(225),
225*(SAMPLE_RATE/1000),
ms_to_samples(225),
FALSE,
24,
@ -276,19 +279,40 @@ SPAN_DECLARE(int) sig_tone_tx(sig_tone_tx_state_t *s, int16_t amp[], int len)
int j;
int n;
int16_t tone;
int update;
int need_update;
int high_low;
for (i = 0; i < len; i += n)
{
if (s->current_tx_timeout < len - i)
n = s->current_tx_timeout;
if (s->current_tx_timeout)
{
if (s->current_tx_timeout <= len - i)
{
n = s->current_tx_timeout;
need_update = TRUE;
}
else
{
n = len - i;
need_update = FALSE;
}
s->current_tx_timeout -= n;
}
else
{
n = len - i;
need_update = FALSE;
}
if (!(s->current_tx_tone & SIG_TONE_TX_PASSTHROUGH))
vec_zeroi16(&amp[i], n);
/*endif*/
if ((s->current_tx_tone & (SIG_TONE_1_PRESENT || SIG_TONE_2_PRESENT)))
{
/* Are we in the early phase (high tone energy level), or the sustaining
phase (low tone energy level) of tone generation? */
/* This doesn't try to get the high/low timing precise, as there is no
value in doing so. It works block by block, and the blocks are normally
quite short. */
if (s->high_low_timer > 0)
{
if (n > s->high_low_timer)
@ -301,47 +325,30 @@ SPAN_DECLARE(int) sig_tone_tx(sig_tone_tx_state_t *s, int16_t amp[], int len)
high_low = 1;
}
/*endif*/
if (s->current_tx_tone & SIG_TONE_TX_PASSTHROUGH)
if ((s->current_tx_tone & SIG_TONE_1_PRESENT) && s->phase_rate[0])
{
for (j = i; j < i + n; j++)
{
tone = dds_mod(&(s->phase_acc[0]), s->phase_rate[0], s->tone_scaling[high_low], 0);
tone = dds_mod(&(s->phase_acc[0]), s->phase_rate[0], s->tone_scaling[0][high_low], 0);
amp[j] = saturate(amp[j] + tone);
}
/*endfor*/
}
else
/*endif*/
if ((s->current_tx_tone & SIG_TONE_2_PRESENT) && s->phase_rate[1])
{
for (j = i; j < i + n; j++)
amp[j] = dds_mod(&(s->phase_acc[0]), s->phase_rate[0], s->tone_scaling[high_low], 0);
{
tone = dds_mod(&(s->phase_acc[1]), s->phase_rate[1], s->tone_scaling[1][high_low], 0);
amp[j] = saturate(amp[j] + tone);
}
/*endfor*/
}
/*endif*/
}
else
{
/* There is no tone. We either leave the audio in the buffer, or silence it. */
if (!(s->current_tx_tone & SIG_TONE_TX_PASSTHROUGH))
{
/* Zap any audio in the buffer */
memset(amp + i, 0, sizeof(int16_t)*n);
}
/*endif*/
}
/*endif*/
if ((s->current_tx_timeout -= n) <= 0)
{
if (s->sig_update)
{
update = s->sig_update(s->user_data, SIG_TONE_UPDATE_REQUEST);
if ((update & 0x03) == 0x03)
s->high_low_timer = s->desc->high_low_timeout;
/*endif*/
s->current_tx_tone = update & 0xFFFF;
s->current_tx_timeout = (update >> 16) & 0xFFFF;
}
/*endif*/
}
if (need_update && s->sig_update)
s->sig_update(s->user_data, SIG_TONE_TX_UPDATE_REQUEST, 0, 0);
/*endif*/
}
/*endfor*/
@ -349,17 +356,22 @@ SPAN_DECLARE(int) sig_tone_tx(sig_tone_tx_state_t *s, int16_t amp[], int len)
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(void) sig_tone_tx_set_mode(sig_tone_tx_state_t *s, int mode)
SPAN_DECLARE(void) sig_tone_tx_set_mode(sig_tone_tx_state_t *s, int mode, int duration)
{
if ((mode & 0x03) == 0x03 && !(s->current_tx_tone & SIG_TONE_1_PRESENT))
int old_tones;
int new_tones;
old_tones = s->current_tx_tone & (SIG_TONE_1_PRESENT | SIG_TONE_2_PRESENT);
new_tones = mode & (SIG_TONE_1_PRESENT | SIG_TONE_2_PRESENT);
if (new_tones && old_tones != new_tones)
s->high_low_timer = s->desc->high_low_timeout;
/*endif*/
s->current_tx_tone = mode & 0xFFFF;
s->current_tx_timeout = (mode >> 16) & 0xFFFF;
s->current_tx_tone = mode;
s->current_tx_timeout = duration;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(sig_tone_tx_state_t *) sig_tone_tx_init(sig_tone_tx_state_t *s, int tone_type, sig_tone_func_t sig_update, void *user_data)
SPAN_DECLARE(sig_tone_tx_state_t *) sig_tone_tx_init(sig_tone_tx_state_t *s, int tone_type, tone_report_func_t sig_update, void *user_data)
{
int i;
@ -385,7 +397,8 @@ SPAN_DECLARE(sig_tone_tx_state_t *) sig_tone_tx_init(sig_tone_tx_state_t *s, int
s->phase_rate[i] = dds_phase_rate((float) s->desc->tone_freq[i]);
else
s->phase_rate[i] = 0;
s->tone_scaling[i] = dds_scaling_dbm0((float) s->desc->tone_amp[i]);
s->tone_scaling[i][0] = dds_scaling_dbm0((float) s->desc->tone_amp[i][0]);
s->tone_scaling[i][1] = dds_scaling_dbm0((float) s->desc->tone_amp[i][1]);
}
return s;
}
@ -404,6 +417,7 @@ SPAN_DECLARE(int) sig_tone_tx_free(sig_tone_tx_state_t *s)
return 0;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) sig_tone_rx(sig_tone_rx_state_t *s, int16_t amp[], int len)
{
#if defined(SPANDSP_USE_FIXED_POINT)
@ -422,7 +436,7 @@ SPAN_DECLARE(int) sig_tone_rx(sig_tone_rx_state_t *s, int16_t amp[], int len)
for (i = 0; i < len; i++)
{
if (s->signaling_state_duration < 0xFFFF)
if (s->signaling_state_duration < INT_MAX)
s->signaling_state_duration++;
/*endif*/
notched_signal = 0;
@ -529,7 +543,7 @@ SPAN_DECLARE(int) sig_tone_rx(sig_tone_rx_state_t *s, int16_t amp[], int len)
if (!s->tone_present)
{
if (s->sig_update)
s->sig_update(s->user_data, SIG_TONE_1_CHANGE | (s->signaling_state_duration << 16));
s->sig_update(s->user_data, SIG_TONE_1_CHANGE, 0, s->signaling_state_duration);
/*endif*/
s->signaling_state_duration = 0;
}
@ -541,15 +555,15 @@ SPAN_DECLARE(int) sig_tone_rx(sig_tone_rx_state_t *s, int16_t amp[], int len)
if (s->tone_present)
{
if (s->sig_update)
s->sig_update(s->user_data, SIG_TONE_1_CHANGE | SIG_TONE_1_PRESENT | (s->signaling_state_duration << 16));
s->sig_update(s->user_data, SIG_TONE_1_CHANGE | SIG_TONE_1_PRESENT, 0, s->signaling_state_duration);
/*endif*/
s->signaling_state_duration = 0;
}
/*endif*/
}
/*endif*/
/* Notch insertion logic */
/* Notch insertion logic */
/* tone_present and tone_on are equivalent in flat mode */
if (s->tone_present)
{
@ -590,7 +604,7 @@ SPAN_DECLARE(int) sig_tone_rx(sig_tone_rx_state_t *s, int16_t amp[], int len)
s->tone_persistence_timeout = s->desc->tone_off_check_time;
s->notch_insertion_timeout = s->desc->notch_lag_time;
if (s->sig_update)
s->sig_update(s->user_data, SIG_TONE_1_CHANGE | SIG_TONE_1_PRESENT | (s->signaling_state_duration << 16));
s->sig_update(s->user_data, SIG_TONE_1_CHANGE | SIG_TONE_1_PRESENT, 0, s->signaling_state_duration);
/*endif*/
s->signaling_state_duration = 0;
}
@ -626,7 +640,7 @@ SPAN_DECLARE(int) sig_tone_rx(sig_tone_rx_state_t *s, int16_t amp[], int len)
s->tone_present = FALSE;
s->tone_persistence_timeout = s->desc->tone_on_check_time;
if (s->sig_update)
s->sig_update(s->user_data, SIG_TONE_1_CHANGE | (s->signaling_state_duration << 16));
s->sig_update(s->user_data, SIG_TONE_1_CHANGE, 0, s->signaling_state_duration);
/*endif*/
s->signaling_state_duration = 0;
}
@ -648,7 +662,7 @@ SPAN_DECLARE(int) sig_tone_rx(sig_tone_rx_state_t *s, int16_t amp[], int len)
if ((s->current_rx_tone & SIG_TONE_RX_PASSTHROUGH))
{
if (s->notch_enabled)
if ((s->current_rx_tone & SIG_TONE_RX_FILTER_TONE) || s->notch_enabled)
amp[i] = (int16_t) notched_signal;
/*endif*/
}
@ -663,7 +677,13 @@ SPAN_DECLARE(int) sig_tone_rx(sig_tone_rx_state_t *s, int16_t amp[], int len)
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(sig_tone_rx_state_t *) sig_tone_rx_init(sig_tone_rx_state_t *s, int tone_type, sig_tone_func_t sig_update, void *user_data)
SPAN_DECLARE(void) sig_tone_rx_set_mode(sig_tone_rx_state_t *s, int mode, int duration)
{
s->current_rx_tone = mode;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(sig_tone_rx_state_t *) sig_tone_rx_init(sig_tone_rx_state_t *s, int tone_type, tone_report_func_t sig_update, void *user_data)
{
if (sig_update == NULL || tone_type < 1 || tone_type > 3)
return NULL;

View File

@ -22,7 +22,7 @@
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id: silence_gen.c,v 1.22 2009/06/02 16:03:56 steveu Exp $
* $Id: silence_gen.c,v 1.23 2009/09/04 14:38:46 steveu Exp $
*/
/*! \file */
@ -158,4 +158,10 @@ SPAN_DECLARE(int) span_dummy_mod(void *user_data, int16_t amp[], int len)
return len;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE_NONSTD(int) span_dummy_rx_fillin(void *user_data, int len)
{
return 0;
}
/*- End of function --------------------------------------------------------*/
/*- End of file ------------------------------------------------------------*/

View File

@ -22,7 +22,7 @@
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id: spandsp.h.in,v 1.18 2009/04/02 13:43:49 steveu Exp $
* $Id: spandsp.h.in,v 1.19 2009/09/22 13:11:04 steveu Exp $
*/
/*! \file */
@ -66,6 +66,7 @@
#include <spandsp/complex_filters.h>
#include <spandsp/dc_restore.h>
#include <spandsp/dds.h>
#include <spandsp/swept_tone.h>
#include <spandsp/echo.h>
#include <spandsp/modem_echo.h>
#include <spandsp/crc.h>

View File

@ -24,7 +24,7 @@
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id: echo.h,v 1.19 2009/02/10 13:06:47 steveu Exp $
* $Id: echo.h,v 1.20 2009/09/22 13:11:04 steveu Exp $
*/
/*! \file */
@ -133,59 +133,7 @@ enum
G.168 echo canceller descriptor. This defines the working state for a line
echo canceller.
*/
typedef struct
{
int tx_power[4];
int rx_power[3];
int clean_rx_power;
int rx_power_threshold;
int nonupdate_dwell;
int curr_pos;
int taps;
int tap_mask;
int adaption_mode;
int32_t supp_test1;
int32_t supp_test2;
int32_t supp1;
int32_t supp2;
int vad;
int cng;
int16_t geigel_max;
int geigel_lag;
int dtd_onset;
int tap_set;
int tap_rotate_counter;
int32_t latest_correction; /* Indication of the magnitude of the latest
adaption, or a code to indicate why adaption
was skipped, for test purposes */
int32_t last_acf[28];
int narrowband_count;
int narrowband_score;
fir16_state_t fir_state;
/*! Echo FIR taps (16 bit version) */
int16_t *fir_taps16[4];
/*! Echo FIR taps (32 bit version) */
int32_t *fir_taps32;
/* DC and near DC blocking filter states */
int32_t tx_hpf[2];
int32_t rx_hpf[2];
/* Parameters for the optional Hoth noise generator */
int cng_level;
int cng_rndnum;
int cng_filter;
/* Snapshot sample of coeffs used for development */
int16_t *snapshot;
} echo_can_state_t;
typedef struct echo_can_state_s echo_can_state_t;
#if defined(__cplusplus)
extern "C"

View File

@ -23,7 +23,7 @@
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id: expose.h,v 1.13 2009/05/16 03:34:45 steveu Exp $
* $Id: expose.h,v 1.14 2009/09/22 13:11:04 steveu Exp $
*/
/*! \file */
@ -56,6 +56,9 @@
#include <spandsp/private/super_tone_tx.h>
#include <spandsp/private/super_tone_rx.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/fsk.h>
#include <spandsp/private/v29rx.h>

View File

@ -22,7 +22,7 @@
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id: fast_convert.h,v 1.8 2009/07/10 13:15:56 steveu Exp $
* $Id: fast_convert.h,v 1.9 2009/10/03 04:37:25 steveu Exp $
*/
#if !defined(_SPANDSP_FAST_CONVERT_H_)
@ -150,7 +150,7 @@ extern "C"
);
return retval;
}
#elif defined(__GNUC__) || (__SUNPRO_C >= 0x0590)
#elif defined(__GNUC__) || (__SUNPRO_C >= 0x0590)
#if defined(__i386__)
/* These routines are guaranteed fast on an i386 machine. Using the built in
@ -403,7 +403,7 @@ extern "C"
the accuracy issues related to changing the rounding scheme are of little concern
to us. */
#if !defined(__sgi) && !defined(__sunos) && !defined(__solaris) && !defined(__sun)
#if !defined(__sgi) && !defined(__sunos) && !defined(__solaris) && !defined(__sun)
#warning "No usable lrint() and lrintf() functions available."
#warning "Replacing these functions with a simple C cast."
#endif

View File

@ -25,7 +25,7 @@
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id: modem_echo.h,v 1.13 2009/02/03 16:28:41 steveu Exp $
* $Id: modem_echo.h,v 1.14 2009/09/22 13:11:04 steveu Exp $
*/
/*! \file */
@ -84,22 +84,7 @@ minor burden.
Modem line echo canceller descriptor. This defines the working state for a line
echo canceller.
*/
typedef struct
{
int adapt;
int taps;
fir16_state_t fir_state;
/*! Echo FIR taps (16 bit version) */
int16_t *fir_taps16;
/*! Echo FIR taps (32 bit version) */
int32_t *fir_taps32;
int tx_power;
int rx_power;
int curr_pos;
} modem_echo_can_state_t;
typedef struct modem_echo_can_state_s modem_echo_can_state_t;
#if defined(__cplusplus)
extern "C"

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
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id: fax_modems.h,v 1.3 2009/03/23 14:17:42 steveu Exp $
* $Id: fax_modems.h,v 1.4 2009/09/04 14:38:47 steveu Exp $
*/
/*! \file */
@ -95,11 +95,9 @@ struct fax_modems_state_s
/*! The current receive signal handler */
span_rx_handler_t *rx_handler;
void *rx_user_data;
/*! The current receive missing signal fill-in handler */
span_rx_fillin_handler_t *rx_fillin_handler;
void *rx_fillin_user_data;
void *rx_user_data;
/*! The current transmit signal handler */
span_tx_handler_t *tx_handler;

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
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id: sig_tone.h,v 1.3 2009/04/12 14:18:02 steveu Exp $
* $Id: sig_tone.h,v 1.4 2009/09/04 14:38:47 steveu Exp $
*/
#if !defined(_SPANDSP_PRIVATE_SIG_TONE_H_)
@ -38,8 +38,8 @@ struct sig_tone_descriptor_s
{
/*! \brief The tones used. */
int tone_freq[2];
/*! \brief The high and low tone amplitudes. */
int tone_amp[2];
/*! \brief The high and low tone amplitudes for each of the tones. */
int tone_amp[2][2];
/*! \brief The delay, in audio samples, before the high level tone drops
to a low level tone. */
@ -80,7 +80,6 @@ struct sig_tone_descriptor_s
#endif
} tone[2];
#if defined(SPANDSP_USE_FIXED_POINT)
/*! \brief Flat mode bandpass bi-quad parameters */
int32_t broad_a[3];
@ -128,23 +127,23 @@ struct sig_tone_descriptor_s
struct sig_tone_tx_state_s
{
/*! \brief The callback function used to handle signaling changes. */
sig_tone_func_t sig_update;
tone_report_func_t sig_update;
/*! \brief A user specified opaque pointer passed to the callback function. */
void *user_data;
/*! \brief Tone descriptor */
sig_tone_descriptor_t *desc;
/*! The scaling values for the high and low level tones */
int16_t tone_scaling[2];
/*! The sample timer, used to switch between the high and low level tones. */
int high_low_timer;
/*! The phase rates for the one or two tones */
int32_t phase_rate[2];
/*! The phase accumulators for the one or two tones */
uint32_t phase_acc[2];
/*! The scaling values for the one or two tones, and the high and low level of each tone */
int16_t tone_scaling[2][2];
/*! The sample timer, used to switch between the high and low level tones. */
int high_low_timer;
/*! \brief Current transmit tone */
int current_tx_tone;
/*! \brief Current transmit timeout */
@ -159,7 +158,7 @@ struct sig_tone_tx_state_s
struct sig_tone_rx_state_s
{
/*! \brief The callback function used to handle signaling changes. */
sig_tone_func_t sig_update;
tone_report_func_t sig_update;
/*! \brief A user specified opaque pointer passed to the callback function. */
void *user_data;

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
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id: t30.h,v 1.4 2009/04/12 14:18:02 steveu Exp $
* $Id: t30.h,v 1.5 2009/09/20 13:42:29 steveu Exp $
*/
/*! \file */
@ -221,10 +221,10 @@ struct t30_state_s
/*! \brief A bit map of the OK ECM frames, constructed as a PPR frame. */
uint8_t ecm_frame_map[3 + 32];
/*! \brief The current page number for receiving, in ECM mode. This is reset at the start of a call. */
int ecm_rx_page;
/*! \brief The current page number for sending, in ECM mode. This is reset at the start of a call. */
int ecm_tx_page;
/*! \brief The current page number for receiving, in ECM or non-ECM mode. This is reset at the start of a call. */
int rx_page_number;
/*! \brief The current page number for sending, in ECM or non-ECM mode. This is reset at the start of a call. */
int tx_page_number;
/*! \brief The current block number, in ECM mode */
int ecm_block;
/*! \brief The number of frames in the current block number, in ECM mode */

View File

@ -23,7 +23,7 @@
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id: sig_tone.h,v 1.19 2009/04/12 14:18:02 steveu Exp $
* $Id: sig_tone.h,v 1.20 2009/09/04 14:38:46 steveu Exp $
*/
/*! \file */
@ -54,32 +54,39 @@ least supervisory information may be heard.
#if !defined(_SPANDSP_SIG_TONE_H_)
#define _SPANDSP_SIG_TONE_H_
typedef int (*sig_tone_func_t)(void *user_data, int what);
/* The optional tone sets */
enum
{
/*! European 2280Hz signaling tone */
/*! European 2280Hz signaling tone. Tone 1 is 2280Hz. Tone 2 is not used. */
SIG_TONE_2280HZ = 1,
/*! US 2600Hz signaling tone */
/*! US 2600Hz signaling tone. Tone 1 is 2600Hz. Tone 2 is not used. */
SIG_TONE_2600HZ,
/*! US 2400Hz + 2600Hz signaling tones */
/*! US 2400Hz + 2600Hz signaling tones. Tone 1 is 2600Hz. Tone 2 is 2400Hz. */
SIG_TONE_2400HZ_2600HZ
};
/* Mode control and report bits for transmit and receive */
enum
{
/*! Signaling tone 1 is present */
SIG_TONE_1_PRESENT = 0x001,
/*! Signaling tone 1 has changed state (ignored when setting tx mode) */
SIG_TONE_1_CHANGE = 0x002,
/*! Signaling tone 2 is present */
SIG_TONE_2_PRESENT = 0x004,
/*! Signaling tone 2 has changed state (ignored when setting tx mode) */
SIG_TONE_2_CHANGE = 0x008,
/*! The media signal is passing through. Tones might be added to it. */
SIG_TONE_TX_PASSTHROUGH = 0x010,
/*! The media signal is passing through. Tones might be extracted from it, if detected. */
SIG_TONE_RX_PASSTHROUGH = 0x020,
SIG_TONE_UPDATE_REQUEST = 0x100
SIG_TONE_RX_PASSTHROUGH = 0x040,
/*! Force filtering of the signaling tone, whether signaling is being detected or not.
This is mostly useful for test purposes. */
SIG_TONE_RX_FILTER_TONE = 0x080,
/*! Request an update of the transmit status, upon timeout of the previous status. */
SIG_TONE_TX_UPDATE_REQUEST = 0x100,
/*! Request an update of the receiver status, upon timeout of the previous status. */
SIG_TONE_RX_UPDATE_REQUEST = 0x200
};
/*!
@ -106,6 +113,14 @@ extern "C"
\return The number of samples unprocessed. */
SPAN_DECLARE(int) sig_tone_rx(sig_tone_rx_state_t *s, int16_t amp[], int len);
/*! Set the receive mode.
\brief Set the receive mode.
\param s The signaling tone context.
\param mode The new mode for the receiver.
\param duration The duration for this mode, before an update is requested.
A duration of zero means forever. */
SPAN_DECLARE(void) sig_tone_rx_set_mode(sig_tone_rx_state_t *s, int mode, int duration);
/*! Initialise a signaling tone receiver context.
\brief Initialise a signaling tone context.
\param s The signaling tone context.
@ -113,7 +128,7 @@ SPAN_DECLARE(int) sig_tone_rx(sig_tone_rx_state_t *s, int16_t amp[], int len);
\param sig_update Callback function to handle signaling updates.
\param user_data An opaque pointer.
\return A pointer to the signalling tone context, or NULL if there was a problem. */
SPAN_DECLARE(sig_tone_rx_state_t *) sig_tone_rx_init(sig_tone_rx_state_t *s, int tone_type, sig_tone_func_t sig_update, void *user_data);
SPAN_DECLARE(sig_tone_rx_state_t *) sig_tone_rx_init(sig_tone_rx_state_t *s, int tone_type, tone_report_func_t sig_update, void *user_data);
/*! Release a signaling tone receiver context.
\brief Release a signaling tone receiver context.
@ -138,8 +153,10 @@ SPAN_DECLARE(int) sig_tone_tx(sig_tone_tx_state_t *s, int16_t amp[], int len);
/*! Set the tone mode.
\brief Set the tone mode.
\param s The signaling tone context.
\param mode The new mode for the transmitted tones. */
SPAN_DECLARE(void) sig_tone_tx_set_mode(sig_tone_tx_state_t *s, int mode);
\param mode The new mode for the transmitted tones.
\param duration The duration for this mode, before an update is requested.
A duration of zero means forever. */
SPAN_DECLARE(void) sig_tone_tx_set_mode(sig_tone_tx_state_t *s, int mode, int duration);
/*! Initialise a signaling tone transmitter context.
\brief Initialise a signaling tone context.
@ -148,7 +165,7 @@ SPAN_DECLARE(void) sig_tone_tx_set_mode(sig_tone_tx_state_t *s, int mode);
\param sig_update Callback function to handle signaling updates.
\param user_data An opaque pointer.
\return A pointer to the signalling tone context, or NULL if there was a problem. */
SPAN_DECLARE(sig_tone_tx_state_t *) sig_tone_tx_init(sig_tone_tx_state_t *s, int tone_type, sig_tone_func_t sig_update, void *user_data);
SPAN_DECLARE(sig_tone_tx_state_t *) sig_tone_tx_init(sig_tone_tx_state_t *s, int tone_type, tone_report_func_t sig_update, void *user_data);
/*! Release a signaling tone transmitter context.
\brief Release a signaling tone transmitter context.

View File

@ -22,7 +22,7 @@
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id: silence_gen.h,v 1.18 2009/06/02 16:03:56 steveu Exp $
* $Id: silence_gen.h,v 1.19 2009/09/04 14:38:47 steveu Exp $
*/
#if !defined(_SPANDSP_SILENCE_GEN_H_)
@ -125,6 +125,16 @@ SPAN_DECLARE_NONSTD(int) span_dummy_rx(void *user_data, const int16_t amp[], int
*/
SPAN_DECLARE(int) span_dummy_mod(void *user_data, int16_t amp[], int len);
/*! A dummy routine to use as a receive fillin callback, when we aren't really
trying to process what is received. It just absorbs and ignores the
request.
\brief Dummy receive fillin callback.
\param user_data The context.
\param len The length of the signal buffer
\return 0.
*/
SPAN_DECLARE_NONSTD(int) span_dummy_rx_fillin(void *user_data, int len);
#if defined(__cplusplus)
}
#endif

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
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id: t30.h,v 1.125 2009/04/12 09:12:10 steveu Exp $
* $Id: t30.h,v 1.126 2009/09/21 15:52:39 steveu Exp $
*/
/*! \file */
@ -524,9 +524,9 @@ typedef struct
int pages_rx;
/*! \brief The number of pages in the file (<0 if not known). */
int pages_in_file;
/*! \brief The horizontal column-to-column resolution of the page, in pixels per metre */
/*! \brief The horizontal column-to-column resolution of the most recent page, in pixels per metre */
int x_resolution;
/*! \brief The vertical row-to-row resolution of the page, in pixels per metre */
/*! \brief The vertical row-to-row resolution of the most recent page, in pixels per metre */
int y_resolution;
/*! \brief The number of horizontal pixels in the most recent page. */
int width;

View File

@ -22,7 +22,7 @@
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id: timing.h,v 1.13 2008/04/17 14:27:01 steveu Exp $
* $Id: timing.h,v 1.14 2009/09/04 14:38:47 steveu Exp $
*/
#if !defined(_SPANDSP_TIMING_H_)
@ -56,8 +56,8 @@ static __inline__ uint64_t rdtscll(void)
#elif defined(__x86_64__)
static __inline__ uint64_t rdtscll(void)
{
unsigned int a;
unsigned int d;
uint32_t a;
uint32_t d;
/* For x86_64 we need to merge the result in 2 32 bit registers
into one clean 64 bit result. */

View File

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

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
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id: t30.c,v 1.301 2009/05/25 12:37:38 steveu Exp $
* $Id: t30.c,v 1.303 2009/09/21 15:51:18 steveu Exp $
*/
/*! \file */
@ -421,7 +421,7 @@ static int tx_start_page(t30_state_t *s)
}
s->ecm_block = 0;
s->error_correcting_mode_retries = 0;
span_log(&s->logging, SPAN_LOG_FLOW, "Starting page %d of transfer\n", s->ecm_tx_page + 1);
span_log(&s->logging, SPAN_LOG_FLOW, "Starting page %d of transfer\n", s->tx_page_number + 1);
return 0;
}
/*- End of function --------------------------------------------------------*/
@ -431,7 +431,7 @@ static int tx_end_page(t30_state_t *s)
s->retries = 0;
if (t4_tx_end_page(&(s->t4)) == 0)
{
s->ecm_tx_page++;
s->tx_page_number++;
s->ecm_block = 0;
}
return 0;
@ -470,7 +470,7 @@ static int rx_end_page(t30_state_t *s)
{
if (t4_rx_end_page(&(s->t4)) == 0)
{
s->ecm_rx_page++;
s->rx_page_number++;
s->ecm_block = 0;
}
return 0;
@ -1042,7 +1042,7 @@ static int send_pps_frame(t30_state_t *s)
frame[1] = CONTROL_FIELD_FINAL_FRAME;
frame[2] = (uint8_t) (T30_PPS | s->dis_received);
frame[3] = (s->ecm_at_page_end) ? ((uint8_t) (s->next_tx_step | s->dis_received)) : T30_NULL;
frame[4] = (uint8_t) (s->ecm_tx_page & 0xFF);
frame[4] = (uint8_t) (s->tx_page_number & 0xFF);
frame[5] = (uint8_t) (s->ecm_block & 0xFF);
frame[6] = (uint8_t) ((s->ecm_frames_this_tx_burst == 0) ? 0 : (s->ecm_frames_this_tx_burst - 1));
span_log(&s->logging, SPAN_LOG_FLOW, "Sending PPS + %s\n", t30_frametype(frame[3]));
@ -1957,30 +1957,19 @@ static int start_receiving_document(t30_state_t *s)
}
/*- End of function --------------------------------------------------------*/
static void unexpected_frame(t30_state_t *s, const uint8_t *msg, int len)
{
span_log(&s->logging, SPAN_LOG_FLOW, "Unexpected %s received in state %d\n", t30_frametype(msg[2]), s->state);
switch (s->state)
{
case T30_STATE_F_DOC_ECM:
case T30_STATE_F_DOC_NON_ECM:
s->current_status = T30_ERR_RX_INVALCMD;
break;
}
}
/*- End of function --------------------------------------------------------*/
static void unexpected_non_final_frame(t30_state_t *s, const uint8_t *msg, int len)
{
span_log(&s->logging, SPAN_LOG_FLOW, "Unexpected %s frame in state %d\n", t30_frametype(msg[2]), s->state);
s->current_status = T30_ERR_UNEXPECTED;
if (s->current_status == T30_ERR_OK)
s->current_status = T30_ERR_UNEXPECTED;
}
/*- End of function --------------------------------------------------------*/
static void unexpected_final_frame(t30_state_t *s, const uint8_t *msg, int len)
{
span_log(&s->logging, SPAN_LOG_FLOW, "Unexpected %s received in state %d\n", t30_frametype(msg[2]), s->state);
s->current_status = T30_ERR_UNEXPECTED;
span_log(&s->logging, SPAN_LOG_FLOW, "Unexpected %s frame in state %d\n", t30_frametype(msg[2]), s->state);
if (s->current_status == T30_ERR_OK)
s->current_status = T30_ERR_UNEXPECTED;
send_dcn(s);
}
/*- End of function --------------------------------------------------------*/
@ -1988,7 +1977,8 @@ static void unexpected_final_frame(t30_state_t *s, const uint8_t *msg, int len)
static void unexpected_frame_length(t30_state_t *s, const uint8_t *msg, int len)
{
span_log(&s->logging, SPAN_LOG_FLOW, "Unexpected %s frame length - %d\n", t30_frametype(msg[0]), len);
s->current_status = T30_ERR_UNEXPECTED;
if (s->current_status == T30_ERR_OK)
s->current_status = T30_ERR_UNEXPECTED;
send_dcn(s);
}
/*- End of function --------------------------------------------------------*/
@ -2372,9 +2362,9 @@ static int process_rx_pps(t30_state_t *s, const uint8_t *msg, int len)
}
}
span_log(&s->logging, SPAN_LOG_FLOW, "Received PPS + %s - page %d, block %d, %d frames\n", t30_frametype(msg[3]), page, block, frames);
if (page != s->ecm_rx_page)
if (page != s->rx_page_number)
{
span_log(&s->logging, SPAN_LOG_FLOW, "ECM rx page mismatch - expected %d, but received %d.\n", s->ecm_rx_page, page);
span_log(&s->logging, SPAN_LOG_FLOW, "ECM rx page mismatch - expected %d, but received %d.\n", s->rx_page_number, page);
}
if (block != s->ecm_block)
{
@ -2645,7 +2635,11 @@ static void process_rx_fnv(t30_state_t *s, const uint8_t *msg, int len)
static void process_state_answering(t30_state_t *s, const uint8_t *msg, int len)
{
switch (msg[2] & 0xFE)
uint8_t fcf;
/* We should be sending the TCF data right now */
fcf = msg[2] & 0xFE;
switch (fcf)
{
case T30_DIS:
/* TODO: This is a fudge to allow for starting up in T.38, where the other end has
@ -2675,7 +2669,11 @@ static void process_state_answering(t30_state_t *s, const uint8_t *msg, int len)
static void process_state_b(t30_state_t *s, const uint8_t *msg, int len)
{
switch (msg[2] & 0xFE)
uint8_t fcf;
/* We should be sending the TCF data right now */
fcf = msg[2] & 0xFE;
switch (fcf)
{
case T30_DCN:
/* Just ignore any DCN's which appear at this stage. */
@ -2696,7 +2694,10 @@ static void process_state_b(t30_state_t *s, const uint8_t *msg, int len)
static void process_state_c(t30_state_t *s, const uint8_t *msg, int len)
{
switch (msg[2] & 0xFE)
uint8_t fcf;
fcf = msg[2] & 0xFE;
switch (fcf)
{
case T30_DCN:
/* Just ignore any DCN's which appear at this stage. */
@ -2717,8 +2718,11 @@ static void process_state_c(t30_state_t *s, const uint8_t *msg, int len)
static void process_state_d(t30_state_t *s, const uint8_t *msg, int len)
{
uint8_t fcf;
/* We should be sending the DCS sequence right now */
switch (msg[2] & 0xFE)
fcf = msg[2] & 0xFE;
switch (fcf)
{
case T30_DCN:
s->current_status = T30_ERR_TX_BADDCS;
@ -2740,8 +2744,11 @@ static void process_state_d(t30_state_t *s, const uint8_t *msg, int len)
static void process_state_d_tcf(t30_state_t *s, const uint8_t *msg, int len)
{
uint8_t fcf;
/* We should be sending the TCF data right now */
switch (msg[2] & 0xFE)
fcf = msg[2] & 0xFE;
switch (fcf)
{
case T30_DCN:
s->current_status = T30_ERR_TX_BADDCS;
@ -2763,7 +2770,10 @@ static void process_state_d_tcf(t30_state_t *s, const uint8_t *msg, int len)
static void process_state_d_post_tcf(t30_state_t *s, const uint8_t *msg, int len)
{
switch (msg[2] & 0xFE)
uint8_t fcf;
fcf = msg[2] & 0xFE;
switch (fcf)
{
case T30_CFR:
/* Trainability test succeeded. Send the document. */
@ -2832,8 +2842,11 @@ static void process_state_d_post_tcf(t30_state_t *s, const uint8_t *msg, int len
static void process_state_f_tcf(t30_state_t *s, const uint8_t *msg, int len)
{
uint8_t fcf;
/* We should be receiving TCF right now, not HDLC messages */
switch (msg[2] & 0xFE)
fcf = msg[2] & 0xFE;
switch (fcf)
{
case T30_CRP:
repeat_last_command(s);
@ -2851,8 +2864,11 @@ static void process_state_f_tcf(t30_state_t *s, const uint8_t *msg, int len)
static void process_state_f_cfr(t30_state_t *s, const uint8_t *msg, int len)
{
uint8_t fcf;
/* We're waiting for a response to the CFR we sent */
switch (msg[2] & 0xFE)
fcf = msg[2] & 0xFE;
switch (fcf)
{
case T30_DCS:
/* If we received another DCS, they must have missed our CFR */
@ -2874,8 +2890,11 @@ static void process_state_f_cfr(t30_state_t *s, const uint8_t *msg, int len)
static void process_state_f_ftt(t30_state_t *s, const uint8_t *msg, int len)
{
uint8_t fcf;
/* We're waiting for a response to the FTT we sent */
switch (msg[2] & 0xFE)
fcf = msg[2] & 0xFE;
switch (fcf)
{
case T30_DCS:
process_rx_dcs(s, msg, len);
@ -2896,12 +2915,15 @@ static void process_state_f_ftt(t30_state_t *s, const uint8_t *msg, int len)
static void process_state_f_doc_non_ecm(t30_state_t *s, const uint8_t *msg, int len)
{
uint8_t fcf;
/* If we are getting HDLC messages, and we have not moved to the _POST_DOC_NON_ECM
state, it looks like either:
- we didn't see the image data carrier properly, or
- they didn't see our T30_CFR, and are repeating the DCS/TCF sequence.
- they didn't see out T30_MCF, and are repeating the end of page message. */
switch (msg[2] & 0xFE)
fcf = msg[2] & 0xFE;
switch (fcf)
{
case T30_DIS:
process_rx_dis_dtc(s, msg, len);
@ -2912,7 +2934,7 @@ static void process_state_f_doc_non_ecm(t30_state_t *s, const uint8_t *msg, int
case T30_MPS:
/* Treat this as a bad quality page. */
if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, msg[2] & 0xFE);
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->next_rx_step = msg[2] & 0xFE;
queue_phase(s, T30_PHASE_D_TX);
set_state(s, T30_STATE_III_Q_RTN);
@ -2922,7 +2944,7 @@ static void process_state_f_doc_non_ecm(t30_state_t *s, const uint8_t *msg, int
/* Treat this as a bad quality page. */
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, msg[2] & 0xFE);
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
s->next_rx_step = msg[2] & 0xFE;
@ -2932,7 +2954,7 @@ static void process_state_f_doc_non_ecm(t30_state_t *s, const uint8_t *msg, int
case T30_EOS:
/* Treat this as a bad quality page. */
if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, msg[2] & 0xFE);
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->next_rx_step = msg[2] & 0xFE;
/* Return to phase B */
queue_phase(s, T30_PHASE_B_TX);
@ -2943,7 +2965,7 @@ static void process_state_f_doc_non_ecm(t30_state_t *s, const uint8_t *msg, int
/* Treat this as a bad quality page. */
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, msg[2] & 0xFE);
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
s->next_rx_step = T30_PRI_EOM;
@ -2952,7 +2974,7 @@ static void process_state_f_doc_non_ecm(t30_state_t *s, const uint8_t *msg, int
case T30_EOP:
/* Treat this as a bad quality page. */
if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, msg[2] & 0xFE);
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->next_rx_step = msg[2] & 0xFE;
queue_phase(s, T30_PHASE_D_TX);
set_state(s, T30_STATE_III_Q_RTN);
@ -2962,7 +2984,7 @@ static void process_state_f_doc_non_ecm(t30_state_t *s, const uint8_t *msg, int
/* Treat this as a bad quality page. */
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, msg[2] & 0xFE);
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
s->next_rx_step = msg[2] & 0xFE;
@ -2980,6 +3002,7 @@ static void process_state_f_doc_non_ecm(t30_state_t *s, const uint8_t *msg, int
break;
default:
/* We don't know what to do with this. */
s->current_status = T30_ERR_RX_INVALCMD;
unexpected_final_frame(s, msg, len);
break;
}
@ -2988,12 +3011,15 @@ static void process_state_f_doc_non_ecm(t30_state_t *s, const uint8_t *msg, int
static void process_state_f_post_doc_non_ecm(t30_state_t *s, const uint8_t *msg, int len)
{
switch (msg[2] & 0xFE)
uint8_t fcf;
fcf = msg[2] & 0xFE;
switch (fcf)
{
case T30_MPS:
if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, msg[2] & 0xFE);
s->next_rx_step = msg[2] & 0xFE;
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->next_rx_step = fcf;
queue_phase(s, T30_PHASE_D_TX);
switch (copy_quality(s))
{
@ -3020,10 +3046,10 @@ static void process_state_f_post_doc_non_ecm(t30_state_t *s, const uint8_t *msg,
case T30_PRI_MPS:
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, msg[2] & 0xFE);
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
s->next_rx_step = msg[2] & 0xFE;
s->next_rx_step = fcf;
switch (copy_quality(s))
{
case T30_COPY_QUALITY_PERFECT:
@ -3049,8 +3075,8 @@ static void process_state_f_post_doc_non_ecm(t30_state_t *s, const uint8_t *msg,
case T30_EOM:
case T30_EOS:
if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, msg[2] & 0xFE);
s->next_rx_step = msg[2] & 0xFE;
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->next_rx_step = fcf;
/* Return to phase B */
queue_phase(s, T30_PHASE_B_TX);
switch (copy_quality(s))
@ -3078,10 +3104,10 @@ static void process_state_f_post_doc_non_ecm(t30_state_t *s, const uint8_t *msg,
case T30_PRI_EOM:
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, msg[2] & 0xFE);
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
s->next_rx_step = msg[2] & 0xFE;
s->next_rx_step = fcf;
switch (copy_quality(s))
{
case T30_COPY_QUALITY_PERFECT:
@ -3106,8 +3132,8 @@ static void process_state_f_post_doc_non_ecm(t30_state_t *s, const uint8_t *msg,
break;
case T30_EOP:
if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, msg[2] & 0xFE);
s->next_rx_step = msg[2] & 0xFE;
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->next_rx_step = fcf;
queue_phase(s, T30_PHASE_D_TX);
switch (copy_quality(s))
{
@ -3137,10 +3163,10 @@ static void process_state_f_post_doc_non_ecm(t30_state_t *s, const uint8_t *msg,
case T30_PRI_EOP:
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, msg[2] & 0xFE);
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
s->next_rx_step = msg[2] & 0xFE;
s->next_rx_step = fcf;
switch (copy_quality(s))
{
case T30_COPY_QUALITY_PERFECT:
@ -3175,6 +3201,7 @@ static void process_state_f_post_doc_non_ecm(t30_state_t *s, const uint8_t *msg,
break;
default:
/* We don't know what to do with this. */
s->current_status = T30_ERR_RX_INVALCMD;
unexpected_final_frame(s, msg, len);
break;
}
@ -3183,10 +3210,12 @@ static void process_state_f_post_doc_non_ecm(t30_state_t *s, const uint8_t *msg,
static void process_state_f_doc_and_post_doc_ecm(t30_state_t *s, const uint8_t *msg, int len)
{
uint8_t fcf;
uint8_t fcf2;
/* This actually handles 2 states - _DOC_ECM and _POST_DOC_ECM - as they are very similar */
switch (msg[2] & 0xFE)
fcf = msg[2] & 0xFE;
switch (fcf)
{
case T30_DIS:
process_rx_dis_dtc(s, msg, len);
@ -3267,6 +3296,7 @@ static void process_state_f_doc_and_post_doc_ecm(t30_state_t *s, const uint8_t *
break;
default:
/* We don't know what to do with this. */
s->current_status = T30_ERR_RX_INVALCMD;
unexpected_final_frame(s, msg, len);
break;
}
@ -3275,7 +3305,10 @@ static void process_state_f_doc_and_post_doc_ecm(t30_state_t *s, const uint8_t *
static void process_state_f_post_rcp_mcf(t30_state_t *s, const uint8_t *msg, int len)
{
switch (msg[2] & 0xFE)
uint8_t fcf;
fcf = msg[2] & 0xFE;
switch (fcf)
{
case T30_CRP:
repeat_last_command(s);
@ -3296,7 +3329,10 @@ static void process_state_f_post_rcp_mcf(t30_state_t *s, const uint8_t *msg, int
static void process_state_f_post_rcp_ppr(t30_state_t *s, const uint8_t *msg, int len)
{
switch (msg[2] & 0xFE)
uint8_t fcf;
fcf = msg[2] & 0xFE;
switch (fcf)
{
case T30_CRP:
repeat_last_command(s);
@ -3314,7 +3350,10 @@ static void process_state_f_post_rcp_ppr(t30_state_t *s, const uint8_t *msg, int
static void process_state_f_post_rcp_rnr(t30_state_t *s, const uint8_t *msg, int len)
{
switch (msg[2] & 0xFE)
uint8_t fcf;
fcf = msg[2] & 0xFE;
switch (fcf)
{
case T30_RR:
if (s->receiver_not_ready_count > 0)
@ -3345,7 +3384,10 @@ static void process_state_f_post_rcp_rnr(t30_state_t *s, const uint8_t *msg, int
static void process_state_r(t30_state_t *s, const uint8_t *msg, int len)
{
switch (msg[2] & 0xFE)
uint8_t fcf;
fcf = msg[2] & 0xFE;
switch (fcf)
{
case T30_DIS:
process_rx_dis_dtc(s, msg, len);
@ -3374,7 +3416,10 @@ static void process_state_r(t30_state_t *s, const uint8_t *msg, int len)
static void process_state_t(t30_state_t *s, const uint8_t *msg, int len)
{
switch (msg[2] & 0xFE)
uint8_t fcf;
fcf = msg[2] & 0xFE;
switch (fcf)
{
case T30_DIS:
process_rx_dis_dtc(s, msg, len);
@ -3400,7 +3445,10 @@ static void process_state_t(t30_state_t *s, const uint8_t *msg, int len)
static void process_state_i(t30_state_t *s, const uint8_t *msg, int len)
{
switch (msg[2] & 0xFE)
uint8_t fcf;
fcf = msg[2] & 0xFE;
switch (fcf)
{
case T30_CRP:
repeat_last_command(s);
@ -3418,7 +3466,10 @@ static void process_state_i(t30_state_t *s, const uint8_t *msg, int len)
static void process_state_ii(t30_state_t *s, const uint8_t *msg, int len)
{
switch (msg[2] & 0xFE)
uint8_t fcf;
fcf = msg[2] & 0xFE;
switch (fcf)
{
case T30_CRP:
repeat_last_command(s);
@ -3437,8 +3488,10 @@ static void process_state_ii(t30_state_t *s, const uint8_t *msg, int len)
static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len)
{
t4_stats_t stats;
uint8_t fcf;
switch (msg[2] & 0xFE)
fcf = msg[2] & 0xFE;
switch (fcf)
{
case T30_MCF:
switch (s->next_tx_step)
@ -3447,7 +3500,8 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len)
case T30_PRI_MPS:
tx_end_page(s);
if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, T30_MCF);
s->phase_d_handler(s, s->phase_d_user_data, fcf);
/* Transmit the next page */
if (tx_start_page(s))
{
/* TODO: recover */
@ -3461,7 +3515,7 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len)
case T30_EOS:
tx_end_page(s);
if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, T30_MCF);
s->phase_d_handler(s, s->phase_d_user_data, fcf);
t4_tx_release(&(s->t4));
s->operation_in_progress = OPERATION_IN_PROGRESS_NONE;
if (span_log_test(&s->logging, SPAN_LOG_FLOW))
@ -3475,7 +3529,7 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len)
case T30_PRI_EOP:
tx_end_page(s);
if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, T30_MCF);
s->phase_d_handler(s, s->phase_d_user_data, fcf);
t4_tx_release(&(s->t4));
s->operation_in_progress = OPERATION_IN_PROGRESS_NONE;
send_dcn(s);
@ -3488,13 +3542,16 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len)
}
break;
case T30_RTP:
#if 0
s->rtp_events++;
#endif
switch (s->next_tx_step)
{
case T30_MPS:
case T30_PRI_MPS:
tx_end_page(s);
if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, T30_RTP);
s->phase_d_handler(s, s->phase_d_user_data, fcf);
if (tx_start_page(s))
{
/* TODO: recover */
@ -3517,7 +3574,7 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len)
case T30_EOS:
tx_end_page(s);
if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, T30_RTP);
s->phase_d_handler(s, s->phase_d_user_data, fcf);
t4_tx_release(&(s->t4));
/* TODO: should go back to T, and resend */
return_to_phase_b(s, TRUE);
@ -3526,22 +3583,35 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len)
case T30_PRI_EOP:
tx_end_page(s);
if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, T30_RTP);
s->phase_d_handler(s, s->phase_d_user_data, fcf);
t4_tx_release(&(s->t4));
s->current_status = T30_ERR_TX_INVALRSP;
send_dcn(s);
break;
}
break;
case T30_RTN:
#if 0
s->rtn_events++;
#endif
switch (s->next_tx_step)
{
case T30_MPS:
case T30_PRI_MPS:
s->retries = 0;
if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, T30_RTN);
/* Send fresh training, and then repeat the last page */
s->phase_d_handler(s, s->phase_d_user_data, fcf);
#if 0
if (!s->retransmit_capable)
#endif
{
/* Send the next page, regardless of the problem with the current one. */
if (tx_start_page(s))
{
/* TODO: recover */
break;
}
}
/* Send fresh training */
if (step_fallback_entry(s) < 0)
{
/* We have fallen back as far as we can go. Give up. */
@ -3558,17 +3628,43 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len)
case T30_EOS:
s->retries = 0;
if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, T30_RTN);
s->current_status = T30_ERR_TX_INVALRSP;
return_to_phase_b(s, TRUE);
s->phase_d_handler(s, s->phase_d_user_data, fcf);
#if 0
if (s->retransmit_capable)
{
/* Wait for DIS */
}
else
#endif
{
return_to_phase_b(s, TRUE);
}
break;
case T30_EOP:
case T30_PRI_EOP:
s->retries = 0;
if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, T30_RTN);
s->current_status = T30_ERR_TX_INVALRSP;
send_dcn(s);
s->phase_d_handler(s, s->phase_d_user_data, fcf);
#if 0
if (s->retransmit_capable)
{
/* Send fresh training, and then repeat the last page */
if (step_fallback_entry(s) < 0)
{
/* We have fallen back as far as we can go. Give up. */
s->current_fallback = 0;
s->current_status = T30_ERR_CANNOT_TRAIN;
send_dcn(s);
break;
}
queue_phase(s, T30_PHASE_B_TX);
restart_sending_document(s);
}
else
#endif
{
send_dcn(s);
}
break;
}
break;
@ -3576,7 +3672,7 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len)
s->retries = 0;
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, T30_PIP);
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
break;
@ -3584,7 +3680,7 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len)
s->retries = 0;
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, T30_PIN);
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
break;
@ -3613,6 +3709,7 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len)
break;
default:
/* We don't know what to do with this. */
s->current_status = T30_ERR_TX_INVALRSP;
unexpected_final_frame(s, msg, len);
break;
}
@ -3621,7 +3718,10 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len)
static void process_state_iii_q_mcf(t30_state_t *s, const uint8_t *msg, int len)
{
switch (msg[2] & 0xFE)
uint8_t fcf;
fcf = msg[2] & 0xFE;
switch (fcf)
{
case T30_EOP:
case T30_EOM:
@ -3655,7 +3755,10 @@ static void process_state_iii_q_mcf(t30_state_t *s, const uint8_t *msg, int len)
static void process_state_iii_q_rtp(t30_state_t *s, const uint8_t *msg, int len)
{
switch (msg[2] & 0xFE)
uint8_t fcf;
fcf = msg[2] & 0xFE;
switch (fcf)
{
case T30_EOP:
case T30_EOM:
@ -3686,7 +3789,10 @@ static void process_state_iii_q_rtp(t30_state_t *s, const uint8_t *msg, int len)
static void process_state_iii_q_rtn(t30_state_t *s, const uint8_t *msg, int len)
{
switch (msg[2] & 0xFE)
uint8_t fcf;
fcf = msg[2] & 0xFE;
switch (fcf)
{
case T30_EOP:
case T30_EOM:
@ -3721,7 +3827,10 @@ static void process_state_iii_q_rtn(t30_state_t *s, const uint8_t *msg, int len)
static void process_state_iv(t30_state_t *s, const uint8_t *msg, int len)
{
switch (msg[2] & 0xFE)
uint8_t fcf;
fcf = msg[2] & 0xFE;
switch (fcf)
{
case T30_CRP:
repeat_last_command(s);
@ -3740,8 +3849,10 @@ static void process_state_iv(t30_state_t *s, const uint8_t *msg, int len)
static void process_state_iv_pps_null(t30_state_t *s, const uint8_t *msg, int len)
{
t4_stats_t stats;
uint8_t fcf;
switch (msg[2] & 0xFE)
fcf = msg[2] & 0xFE;
switch (fcf)
{
case T30_MCF:
s->retries = 0;
@ -3765,7 +3876,7 @@ static void process_state_iv_pps_null(t30_state_t *s, const uint8_t *msg, int le
case T30_PRI_MPS:
tx_end_page(s);
if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, T30_MCF);
s->phase_d_handler(s, s->phase_d_user_data, fcf);
if (tx_start_page(s))
{
/* TODO: recover */
@ -3783,7 +3894,7 @@ static void process_state_iv_pps_null(t30_state_t *s, const uint8_t *msg, int le
case T30_EOS:
tx_end_page(s);
if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, T30_MCF);
s->phase_d_handler(s, s->phase_d_user_data, fcf);
t4_tx_release(&(s->t4));
s->operation_in_progress = OPERATION_IN_PROGRESS_NONE;
if (span_log_test(&s->logging, SPAN_LOG_FLOW))
@ -3797,7 +3908,7 @@ static void process_state_iv_pps_null(t30_state_t *s, const uint8_t *msg, int le
case T30_PRI_EOP:
tx_end_page(s);
if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, T30_MCF);
s->phase_d_handler(s, s->phase_d_user_data, fcf);
t4_tx_release(&(s->t4));
s->operation_in_progress = OPERATION_IN_PROGRESS_NONE;
send_dcn(s);
@ -3842,8 +3953,10 @@ static void process_state_iv_pps_null(t30_state_t *s, const uint8_t *msg, int le
static void process_state_iv_pps_q(t30_state_t *s, const uint8_t *msg, int len)
{
t4_stats_t stats;
uint8_t fcf;
switch (msg[2] & 0xFE)
fcf = msg[2] & 0xFE;
switch (fcf)
{
case T30_MCF:
s->retries = 0;
@ -3867,7 +3980,7 @@ static void process_state_iv_pps_q(t30_state_t *s, const uint8_t *msg, int len)
case T30_PRI_MPS:
tx_end_page(s);
if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, T30_MCF);
s->phase_d_handler(s, s->phase_d_user_data, fcf);
if (tx_start_page(s))
{
/* TODO: recover */
@ -3885,7 +3998,7 @@ static void process_state_iv_pps_q(t30_state_t *s, const uint8_t *msg, int len)
case T30_EOS:
tx_end_page(s);
if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, T30_MCF);
s->phase_d_handler(s, s->phase_d_user_data, fcf);
t4_tx_release(&(s->t4));
s->operation_in_progress = OPERATION_IN_PROGRESS_NONE;
if (span_log_test(&s->logging, SPAN_LOG_FLOW))
@ -3899,7 +4012,7 @@ static void process_state_iv_pps_q(t30_state_t *s, const uint8_t *msg, int len)
case T30_PRI_EOP:
tx_end_page(s);
if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, T30_MCF);
s->phase_d_handler(s, s->phase_d_user_data, fcf);
t4_tx_release(&(s->t4));
s->operation_in_progress = OPERATION_IN_PROGRESS_NONE;
send_dcn(s);
@ -3923,7 +4036,7 @@ static void process_state_iv_pps_q(t30_state_t *s, const uint8_t *msg, int len)
s->retries = 0;
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, T30_PIP);
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
break;
@ -3931,7 +4044,7 @@ static void process_state_iv_pps_q(t30_state_t *s, const uint8_t *msg, int len)
s->retries = 0;
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, T30_PIN);
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
break;
@ -3960,8 +4073,10 @@ static void process_state_iv_pps_q(t30_state_t *s, const uint8_t *msg, int len)
static void process_state_iv_pps_rnr(t30_state_t *s, const uint8_t *msg, int len)
{
t4_stats_t stats;
uint8_t fcf;
switch (msg[2] & 0xFE)
fcf = msg[2] & 0xFE;
switch (fcf)
{
case T30_MCF:
s->retries = 0;
@ -3985,7 +4100,7 @@ static void process_state_iv_pps_rnr(t30_state_t *s, const uint8_t *msg, int len
case T30_PRI_MPS:
tx_end_page(s);
if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, T30_MCF);
s->phase_d_handler(s, s->phase_d_user_data, fcf);
if (tx_start_page(s))
{
/* TODO: recover */
@ -4003,7 +4118,7 @@ static void process_state_iv_pps_rnr(t30_state_t *s, const uint8_t *msg, int len
case T30_EOS:
tx_end_page(s);
if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, T30_MCF);
s->phase_d_handler(s, s->phase_d_user_data, fcf);
t4_tx_release(&(s->t4));
s->operation_in_progress = OPERATION_IN_PROGRESS_NONE;
if (span_log_test(&s->logging, SPAN_LOG_FLOW))
@ -4017,7 +4132,7 @@ static void process_state_iv_pps_rnr(t30_state_t *s, const uint8_t *msg, int len
case T30_PRI_EOP:
tx_end_page(s);
if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, T30_MCF);
s->phase_d_handler(s, s->phase_d_user_data, fcf);
t4_tx_release(&(s->t4));
s->operation_in_progress = OPERATION_IN_PROGRESS_NONE;
send_dcn(s);
@ -4041,7 +4156,7 @@ static void process_state_iv_pps_rnr(t30_state_t *s, const uint8_t *msg, int len
s->retries = 0;
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, T30_PIP);
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
break;
@ -4049,7 +4164,7 @@ static void process_state_iv_pps_rnr(t30_state_t *s, const uint8_t *msg, int len
s->retries = 0;
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, T30_PIN);
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
break;
@ -4073,7 +4188,10 @@ static void process_state_iv_pps_rnr(t30_state_t *s, const uint8_t *msg, int len
static void process_state_iv_ctc(t30_state_t *s, const uint8_t *msg, int len)
{
switch (msg[2] & 0xFE)
uint8_t fcf;
fcf = msg[2] & 0xFE;
switch (fcf)
{
case T30_CTR:
/* Valid response to a CTC received */
@ -4100,7 +4218,10 @@ static void process_state_iv_ctc(t30_state_t *s, const uint8_t *msg, int len)
static void process_state_iv_eor(t30_state_t *s, const uint8_t *msg, int len)
{
switch (msg[2] & 0xFE)
uint8_t fcf;
fcf = msg[2] & 0xFE;
switch (fcf)
{
case T30_RNR:
if (s->timer_t5 == 0)
@ -4113,7 +4234,7 @@ static void process_state_iv_eor(t30_state_t *s, const uint8_t *msg, int len)
s->retries = 0;
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, T30_PIN);
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
break;
@ -4138,7 +4259,10 @@ static void process_state_iv_eor(t30_state_t *s, const uint8_t *msg, int len)
static void process_state_iv_eor_rnr(t30_state_t *s, const uint8_t *msg, int len)
{
switch (msg[2] & 0xFE)
uint8_t fcf;
fcf = msg[2] & 0xFE;
switch (fcf)
{
case T30_RNR:
if (s->timer_t5 == 0)
@ -4151,7 +4275,7 @@ static void process_state_iv_eor_rnr(t30_state_t *s, const uint8_t *msg, int len
s->retries = 0;
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, T30_PIN);
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
break;
@ -4257,7 +4381,7 @@ static void process_rx_control_msg(t30_state_t *s, const uint8_t *msg, int len)
}
else
{
unexpected_frame(s, msg, len);
unexpected_non_final_frame(s, msg, len);
}
break;
case (T30_SEP & 0xFE):
@ -4269,7 +4393,7 @@ static void process_rx_control_msg(t30_state_t *s, const uint8_t *msg, int len)
}
else
{
unexpected_frame(s, msg, len);
unexpected_non_final_frame(s, msg, len);
}
break;
case (T30_PSA & 0xFE):
@ -4280,7 +4404,7 @@ static void process_rx_control_msg(t30_state_t *s, const uint8_t *msg, int len)
}
else
{
unexpected_frame(s, msg, len);
unexpected_non_final_frame(s, msg, len);
}
break;
case (T30_CIA & 0xFE):
@ -4291,7 +4415,7 @@ static void process_rx_control_msg(t30_state_t *s, const uint8_t *msg, int len)
}
else
{
unexpected_frame(s, msg, len);
unexpected_non_final_frame(s, msg, len);
}
break;
case (T30_ISP & 0xFE):
@ -4302,7 +4426,7 @@ static void process_rx_control_msg(t30_state_t *s, const uint8_t *msg, int len)
}
else
{
unexpected_frame(s, msg, len);
unexpected_non_final_frame(s, msg, len);
}
break;
case (T30_TSI & 0xFE):
@ -5956,8 +6080,8 @@ SPAN_DECLARE(void) t30_get_transfer_statistics(t30_state_t *s, t30_stats_t *t)
t->error_correcting_mode = s->error_correcting_mode;
t->error_correcting_mode_retries = s->error_correcting_mode_retries;
t4_get_transfer_statistics(&s->t4, &stats);
t->pages_tx = s->ecm_tx_page;
t->pages_rx = s->ecm_rx_page;
t->pages_tx = s->tx_page_number;
t->pages_rx = s->rx_page_number;
t->pages_in_file = stats.pages_in_file;
t->width = stats.width;
t->length = stats.length;
@ -5968,6 +6092,10 @@ SPAN_DECLARE(void) t30_get_transfer_statistics(t30_state_t *s, t30_stats_t *t)
t->encoding = stats.encoding;
t->image_size = stats.line_image_size;
t->current_status = s->current_status;
#if 0
t->rtn_events = s->rtn_events;
t->rtp_events = s->rtp_events;
#endif
}
/*- End of function --------------------------------------------------------*/
@ -6000,9 +6128,13 @@ SPAN_DECLARE(int) t30_restart(t30_state_t *s)
t30_build_dis_or_dtc(s);
memset(&s->rx_info, 0, sizeof(s->rx_info));
release_resources(s);
/* The ECM page number is only reset at call establishment */
s->ecm_rx_page = 0;
s->ecm_tx_page = 0;
/* The page number is only reset at call establishment */
s->rx_page_number = 0;
s->tx_page_number = 0;
#if 0
s->rtn_events = 0;
s->rtp_events = 0;
#endif
s->far_end_detected = FALSE;
s->timer_t0_t1 = ms_to_samples(DEFAULT_TIMER_T0);
if (s->calling_party)

View File

@ -25,7 +25,7 @@
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id: t31.c,v 1.151 2009/07/14 13:54:22 steveu Exp $
* $Id: t31.c,v 1.152 2009/09/04 14:38:46 steveu Exp $
*/
/*! \file */
@ -176,12 +176,15 @@ enum
static int restart_modem(t31_state_t *s, int new_modem);
static void hdlc_accept_frame(void *user_data, const uint8_t *msg, int len, int ok);
static void set_rx_handler(t31_state_t *s, span_rx_handler_t *handler, void *user_data);
static void set_rx_handler(t31_state_t *s, span_rx_handler_t *rx_handler, span_rx_fillin_handler_t *fillin_handler, void *user_data);
static void set_tx_handler(t31_state_t *s, span_tx_handler_t *handler, void *user_data);
static void set_next_tx_handler(t31_state_t *s, span_tx_handler_t *handler, void *user_data);
static int v17_v21_rx(void *user_data, const int16_t amp[], int len);
static int v17_v21_rx_fillin(void *user_data, int len);
static int v27ter_v21_rx(void *user_data, const int16_t amp[], int len);
static int v27ter_v21_rx_fillin(void *user_data, int len);
static int v29_v21_rx(void *user_data, const int16_t amp[], int len);
static int v29_v21_rx_fillin(void *user_data, int len);
static int silence_rx(void *user_data, const int16_t amp[], int len);
static int cng_rx(void *user_data, const int16_t amp[], int len);
static void non_ecm_put_bit(void *user_data, int bit);
@ -1527,7 +1530,7 @@ static int restart_modem(t31_state_t *s, int new_modem)
s->at_state.rx_signal_present = FALSE;
s->at_state.rx_trained = FALSE;
s->rx_frame_received = FALSE;
set_rx_handler(s, (span_rx_handler_t *) &span_dummy_rx, NULL);
set_rx_handler(s, (span_rx_handler_t *) &span_dummy_rx, (span_rx_fillin_handler_t *) &span_dummy_rx_fillin, NULL);
use_hdlc = FALSE;
switch (s->modem)
{
@ -1546,7 +1549,7 @@ static int restart_modem(t31_state_t *s, int new_modem)
/* Do V.21/HDLC receive in parallel. The other end may send its
first message at any time. The CNG tone will continue until
we get a valid preamble. */
set_rx_handler(s, (span_rx_handler_t *) &cng_rx, s);
set_rx_handler(s, (span_rx_handler_t *) &cng_rx, (span_rx_fillin_handler_t *) &span_dummy_rx_fillin, s);
t31_v21_rx(s);
set_tx_handler(s, (span_tx_handler_t *) &modem_connect_tones_tx, &t->connect_tx);
set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
@ -1559,7 +1562,7 @@ static int restart_modem(t31_state_t *s, int new_modem)
}
else
{
set_rx_handler(s, (span_rx_handler_t *) &cng_rx, s);
set_rx_handler(s, (span_rx_handler_t *) &cng_rx, (span_rx_fillin_handler_t *) &span_dummy_rx_fillin, s);
t31_v21_rx(s);
silence_gen_set(&t->silence_gen, 0);
set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
@ -1610,7 +1613,7 @@ static int restart_modem(t31_state_t *s, int new_modem)
}
else
{
set_rx_handler(s, (span_rx_handler_t *) &fsk_rx, &t->v21_rx);
set_rx_handler(s, (span_rx_handler_t *) &fsk_rx, (span_rx_fillin_handler_t *) &fsk_rx_fillin, &t->v21_rx);
t31_v21_rx(s);
}
break;
@ -1652,7 +1655,7 @@ static int restart_modem(t31_state_t *s, int new_modem)
case FAX_MODEM_V17_RX:
if (!s->t38_mode)
{
set_rx_handler(s, (span_rx_handler_t *) &v17_v21_rx, s);
set_rx_handler(s, (span_rx_handler_t *) &v17_v21_rx, (span_rx_fillin_handler_t *) &v17_v21_rx_fillin, s);
v17_rx_restart(&t->v17_rx, s->bit_rate, s->short_train);
/* Allow for +FCERROR/+FRH:3 */
t31_v21_rx(s);
@ -1689,7 +1692,7 @@ static int restart_modem(t31_state_t *s, int new_modem)
case FAX_MODEM_V27TER_RX:
if (!s->t38_mode)
{
set_rx_handler(s, (span_rx_handler_t *) &v27ter_v21_rx, s);
set_rx_handler(s, (span_rx_handler_t *) &v27ter_v21_rx, (span_rx_fillin_handler_t *) &v27ter_v21_rx_fillin, s);
v27ter_rx_restart(&t->v27ter_rx, s->bit_rate, FALSE);
/* Allow for +FCERROR/+FRH:3 */
t31_v21_rx(s);
@ -1726,7 +1729,7 @@ static int restart_modem(t31_state_t *s, int new_modem)
case FAX_MODEM_V29_RX:
if (!s->t38_mode)
{
set_rx_handler(s, (span_rx_handler_t *) &v29_v21_rx, s);
set_rx_handler(s, (span_rx_handler_t *) &v29_v21_rx, (span_rx_fillin_handler_t *) &v29_v21_rx_fillin, s);
v29_rx_restart(&t->v29_rx, s->bit_rate, FALSE);
/* Allow for +FCERROR/+FRH:3 */
t31_v21_rx(s);
@ -1752,7 +1755,7 @@ static int restart_modem(t31_state_t *s, int new_modem)
case FAX_MODEM_SILENCE_RX:
if (!s->t38_mode)
{
set_rx_handler(s, (span_rx_handler_t *) &silence_rx, s);
set_rx_handler(s, (span_rx_handler_t *) &silence_rx, (span_rx_fillin_handler_t *) &span_dummy_rx_fillin, s);
silence_gen_set(&t->silence_gen, 0);
set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
@ -2113,7 +2116,7 @@ SPAN_DECLARE(int) t31_at_rx(t31_state_t *s, const char *t, int len)
s->at_state.rx_data_bytes = 0;
s->at_state.transmit = FALSE;
s->modem = FAX_MODEM_SILENCE_TX;
set_rx_handler(s, (span_rx_handler_t *) &span_dummy_rx, NULL);
set_rx_handler(s, (span_rx_handler_t *) &span_dummy_rx, (span_rx_fillin_handler_t *) &span_dummy_rx_fillin, NULL);
t31_set_at_rx_mode(s, AT_MODE_OFFHOOK_COMMAND);
at_put_response_code(&s->at_state, AT_RESPONSE_CODE_OK);
}
@ -2136,9 +2139,13 @@ SPAN_DECLARE(int) t31_at_rx(t31_state_t *s, const char *t, int len)
}
/*- End of function --------------------------------------------------------*/
static void set_rx_handler(t31_state_t *s, span_rx_handler_t *handler, void *user_data)
static void set_rx_handler(t31_state_t *s,
span_rx_handler_t *rx_handler,
span_rx_fillin_handler_t *fillin_handler,
void *user_data)
{
s->audio.modems.rx_handler = handler;
s->audio.modems.rx_handler = rx_handler;
s->audio.modems.rx_fillin_handler = fillin_handler;
s->audio.modems.rx_user_data = user_data;
}
/*- End of function --------------------------------------------------------*/
@ -2208,7 +2215,7 @@ static int v17_v21_rx(void *user_data, const int16_t amp[], int len)
/* The fast modem has trained, so we no longer need to run the slow
one in parallel. */
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.17 + V.21 to V.17 (%.2fdBm0)\n", v17_rx_signal_power(&s->v17_rx));
set_rx_handler(t, (span_rx_handler_t *) &v17_rx, &s->v17_rx);
set_rx_handler(t, (span_rx_handler_t *) &v17_rx, (span_rx_fillin_handler_t *) &v17_rx_fillin, &s->v17_rx);
}
else
{
@ -2218,13 +2225,26 @@ static int v17_v21_rx(void *user_data, const int16_t amp[], int len)
/* We have received something, and the fast modem has not trained. We must
be receiving valid V.21 */
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.17 + V.21 to V.21 (%.2fdBm0)\n", fsk_rx_signal_power(&s->v21_rx));
set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, &s->v21_rx);
set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, (span_rx_fillin_handler_t *) &fsk_rx_fillin, &s->v21_rx);
}
}
return len;
}
/*- End of function --------------------------------------------------------*/
static int v17_v21_rx_fillin(void *user_data, int len)
{
t31_state_t *t;
fax_modems_state_t *s;
t = (t31_state_t *) user_data;
s = &t->audio.modems;
v17_rx_fillin(&s->v17_rx, len);
fsk_rx_fillin(&s->v21_rx, len);
return 0;
}
/*- End of function --------------------------------------------------------*/
static int v27ter_v21_rx(void *user_data, const int16_t amp[], int len)
{
t31_state_t *t;
@ -2238,7 +2258,7 @@ static int v27ter_v21_rx(void *user_data, const int16_t amp[], int len)
/* The fast modem has trained, so we no longer need to run the slow
one in parallel. */
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.27ter + V.21 to V.27ter (%.2fdBm0)\n", v27ter_rx_signal_power(&s->v27ter_rx));
set_rx_handler(t, (span_rx_handler_t *) &v27ter_rx, &s->v27ter_rx);
set_rx_handler(t, (span_rx_handler_t *) &v27ter_rx, (span_rx_fillin_handler_t *) &v27ter_rx_fillin, &s->v27ter_rx);
}
else
{
@ -2248,13 +2268,26 @@ static int v27ter_v21_rx(void *user_data, const int16_t amp[], int len)
/* We have received something, and the fast modem has not trained. We must
be receiving valid V.21 */
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.27ter + V.21 to V.21 (%.2fdBm0)\n", fsk_rx_signal_power(&s->v21_rx));
set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, &s->v21_rx);
set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, (span_rx_fillin_handler_t *) &fsk_rx_fillin, &s->v21_rx);
}
}
return len;
}
/*- End of function --------------------------------------------------------*/
static int v27ter_v21_rx_fillin(void *user_data, int len)
{
t31_state_t *t;
fax_modems_state_t *s;
t = (t31_state_t *) user_data;
s = &t->audio.modems;
v17_rx_fillin(&s->v27ter_rx, len);
fsk_rx_fillin(&s->v21_rx, len);
return 0;
}
/*- End of function --------------------------------------------------------*/
static int v29_v21_rx(void *user_data, const int16_t amp[], int len)
{
t31_state_t *t;
@ -2268,7 +2301,7 @@ static int v29_v21_rx(void *user_data, const int16_t amp[], int len)
/* The fast modem has trained, so we no longer need to run the slow
one in parallel. */
span_log(&s->logging, SPAN_LOG_FLOW, "Switching from V.29 + V.21 to V.29 (%.2fdBm0)\n", v29_rx_signal_power(&s->v29_rx));
set_rx_handler(t, (span_rx_handler_t *) &v29_rx, &s->v29_rx);
set_rx_handler(t, (span_rx_handler_t *) &v29_rx, (span_rx_fillin_handler_t *) &v29_rx_fillin, &s->v29_rx);
}
else
{
@ -2278,13 +2311,26 @@ static int v29_v21_rx(void *user_data, const int16_t amp[], int len)
/* We have received something, and the fast modem has not trained. We must
be receiving valid V.21 */
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.29 + V.21 to V.21 (%.2fdBm0)\n", fsk_rx_signal_power(&s->v21_rx));
set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, &s->v21_rx);
set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, (span_rx_fillin_handler_t *) &fsk_rx_fillin, &s->v21_rx);
}
}
return len;
}
/*- End of function --------------------------------------------------------*/
static int v29_v21_rx_fillin(void *user_data, int len)
{
t31_state_t *t;
fax_modems_state_t *s;
t = (t31_state_t *) user_data;
s = &t->audio.modems;
v29_rx_fillin(&s->v29_rx, len);
fsk_rx_fillin(&s->v21_rx, len);
return 0;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) t31_rx(t31_state_t *s, int16_t amp[], int len)
{
int i;

View File

@ -22,7 +22,7 @@
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id: t38_terminal.c,v 1.127 2009/07/14 13:54:22 steveu Exp $
* $Id: t38_terminal.c,v 1.128 2009/09/04 14:38:46 steveu Exp $
*/
/*! \file */
@ -93,9 +93,9 @@
enum
{
T38_CHUNKING_MERGE_FCS_WITH_DATA = 0x0001,
T38_CHUNKING_WHOLE_FRAMES = 0x0002,
T38_CHUNKING_ALLOW_TEP_TIME = 0x0004
T38_CHUNKING_MERGE_FCS_WITH_DATA = 0x0001,
T38_CHUNKING_WHOLE_FRAMES = 0x0002,
T38_CHUNKING_ALLOW_TEP_TIME = 0x0004
};
enum

View File

@ -16,7 +16,7 @@
## along with this program; if not, write to the Free Software
## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
##
## $Id: Makefile.am,v 1.116 2009/05/30 15:23:13 steveu Exp $
## $Id: Makefile.am,v 1.117 2009/09/22 13:11:04 steveu Exp $
AM_CFLAGS = $(COMP_VENDOR_CFLAGS)
AM_LDFLAGS = $(COMP_VENDOR_LDFLAGS)
@ -99,6 +99,7 @@ noinst_PROGRAMS = adsi_tests \
sig_tone_tests \
super_tone_rx_tests \
super_tone_tx_tests \
swept_tone_tests \
t4_tests \
t31_tests \
t38_core_tests \
@ -273,6 +274,9 @@ super_tone_rx_tests_LDADD = -L$(top_builddir)/spandsp-sim -lspandsp-sim $(LIBDIR
super_tone_tx_tests_SOURCES = super_tone_tx_tests.c
super_tone_tx_tests_LDADD = -L$(top_builddir)/spandsp-sim -lspandsp-sim $(LIBDIR) -lspandsp
swept_tone_tests_SOURCES = swept_tone_tests.c
swept_tone_tests_LDADD = -L$(top_builddir)/spandsp-sim -lspandsp-sim $(LIBDIR) -lspandsp
t4_tests_SOURCES = t4_tests.c
t4_tests_LDADD = $(LIBDIR) -lspandsp

View File

@ -22,7 +22,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id: fax_decode.c,v 1.56 2009/05/30 15:23:13 steveu Exp $
* $Id: fax_decode.c,v 1.57 2009/09/15 14:01:53 steveu Exp $
*/
/*! \page fax_decode_page FAX decoder
@ -124,7 +124,7 @@ static void print_frame(const char *io, const uint8_t *fr, int frlen)
type = fr[2] & 0xFE;
if (type == T30_DIS || type == T30_DTC || type == T30_DCS)
t30_decode_dis_dtc_dcs(&t30_dummy, fr, frlen);
if (type == T30_NSF)
if (type == T30_NSF || type == T30_NSS || type == T30_NSC)
{
if (t35_decode(&fr[3], frlen - 3, &country, &vendor, &model))
{

View File

@ -22,7 +22,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id: line_model_tests.c,v 1.27 2009/05/30 15:23:14 steveu Exp $
* $Id: line_model_tests.c,v 1.28 2009/09/23 16:02:59 steveu Exp $
*/
/*! \page line_model_tests_page Telephony line model tests
@ -62,7 +62,7 @@
#define IN_FILE_NAME1 "line_model_test_in1.wav"
#define IN_FILE_NAME2 "line_model_test_in2.wav"
#define OUT_FILE_NAME1 "line_model_one_way_test_out.wav"
#define OUT_FILE_NAME "line_model_test_out.wav"
#define OUT_FILE_NAME2 "line_model_two_way_test_out.wav"
int channel_codec;
int rbs_pattern;
@ -128,10 +128,17 @@ static void test_one_way_model(int line_model_no, int speech_test)
awgn_init_dbm0(&noise1, 1234567, -10.0f);
if ((inhandle1 = sf_open_telephony_read(IN_FILE_NAME1, 1)) == NULL)
if (speech_test)
{
fprintf(stderr, " Cannot open audio file '%s'\n", IN_FILE_NAME1);
exit(2);
if ((inhandle1 = sf_open_telephony_read(IN_FILE_NAME1, 1)) == NULL)
{
fprintf(stderr, " Cannot open audio file '%s'\n", IN_FILE_NAME1);
exit(2);
}
}
else
{
inhandle1 = NULL;
}
if ((outhandle = sf_open_telephony_write(OUT_FILE_NAME1, 1)) == NULL)
{
@ -167,10 +174,13 @@ static void test_one_way_model(int line_model_no, int speech_test)
exit(2);
}
}
if (sf_close(inhandle1))
if (speech_test)
{
fprintf(stderr, " Cannot close audio file '%s'\n", IN_FILE_NAME1);
exit(2);
if (sf_close(inhandle1))
{
fprintf(stderr, " Cannot close audio file '%s'\n", IN_FILE_NAME1);
exit(2);
}
}
if (sf_close(outhandle))
{
@ -208,19 +218,27 @@ static void test_both_ways_model(int line_model_no, int speech_test)
awgn_init_dbm0(&noise1, 1234567, -10.0f);
awgn_init_dbm0(&noise2, 1234567, -10.0f);
if ((inhandle1 = sf_open_telephony_read(IN_FILE_NAME1, 1)) == NULL)
if (speech_test)
{
fprintf(stderr, " Cannot open audio file '%s'\n", IN_FILE_NAME1);
exit(2);
if ((inhandle1 = sf_open_telephony_read(IN_FILE_NAME1, 1)) == NULL)
{
fprintf(stderr, " Cannot open audio file '%s'\n", IN_FILE_NAME1);
exit(2);
}
if ((inhandle2 = sf_open_telephony_read(IN_FILE_NAME2, 1)) == NULL)
{
fprintf(stderr, " Cannot open audio file '%s'\n", IN_FILE_NAME2);
exit(2);
}
}
if ((inhandle2 = sf_open_telephony_read(IN_FILE_NAME2, 1)) == NULL)
else
{
fprintf(stderr, " Cannot open audio file '%s'\n", IN_FILE_NAME2);
exit(2);
inhandle1 =
inhandle2 = NULL;
}
if ((outhandle = sf_open_telephony_write(OUT_FILE_NAME, 2)) == NULL)
if ((outhandle = sf_open_telephony_write(OUT_FILE_NAME2, 2)) == NULL)
{
fprintf(stderr, " Cannot create audio file '%s'\n", OUT_FILE_NAME);
fprintf(stderr, " Cannot create audio file '%s'\n", OUT_FILE_NAME2);
exit(2);
}
for (i = 0; i < 10000; i++)
@ -261,25 +279,80 @@ static void test_both_ways_model(int line_model_no, int speech_test)
exit(2);
}
}
if (sf_close(inhandle1))
if (speech_test)
{
fprintf(stderr, " Cannot close audio file '%s'\n", IN_FILE_NAME1);
exit(2);
}
if (sf_close(inhandle2))
{
fprintf(stderr, " Cannot close audio file '%s'\n", IN_FILE_NAME2);
exit(2);
if (sf_close(inhandle1))
{
fprintf(stderr, " Cannot close audio file '%s'\n", IN_FILE_NAME1);
exit(2);
}
if (sf_close(inhandle2))
{
fprintf(stderr, " Cannot close audio file '%s'\n", IN_FILE_NAME2);
exit(2);
}
}
if (sf_close(outhandle))
{
fprintf(stderr, " Cannot close audio file '%s'\n", OUT_FILE_NAME);
fprintf(stderr, " Cannot close audio file '%s'\n", OUT_FILE_NAME2);
exit(2);
}
both_ways_line_model_release(model);
}
/*- End of function --------------------------------------------------------*/
static void test_line_filter(int line_model_no)
{
float out;
double sumin;
double sumout;
int i;
int j;
int p;
int ptr;
int len;
swept_tone_state_t *s;
float filter[129];
int16_t buf[BLOCK_LEN];
s = swept_tone_init(NULL, 200.0f, 3900.0f, -10.0f, 120*SAMPLE_RATE, 0);
for (j = 0; j < 129; j++)
filter[j] = 0.0f;
ptr = 0;
for (;;)
{
if ((len = swept_tone(s, buf, BLOCK_LEN)) <= 0)
break;
sumin = 0.0;
sumout = 0.0;
for (i = 0; i < len; i++)
{
/* Add the sample in the filter buffer */
p = ptr;
filter[p] = buf[i];
if (++p == 129)
p = 0;
ptr = p;
/* Apply the filter */
out = 0.0f;
for (j = 0; j < 129; j++)
{
out += line_models[line_model_no][128 - j]*filter[p];
if (++p >= 129)
p = 0;
}
sumin += buf[i]*buf[i];
sumout += out*out;
}
/*endfor*/
printf("%7.1f %f\n", swept_tone_current_frequency(s), 10.0*log10(sumout/sumin));
}
/*endfor*/
swept_tone_free(s);
}
/*- End of function --------------------------------------------------------*/
int main(int argc, char *argv[])
{
int line_model_no;
@ -319,6 +392,7 @@ int main(int argc, char *argv[])
complexify_tests();
test_one_way_model(line_model_no, speech_test);
test_both_ways_model(line_model_no, speech_test);
test_line_filter(line_model_no);
}
/*- End of function --------------------------------------------------------*/
/*- End of file ------------------------------------------------------------*/

View File

@ -17,7 +17,7 @@
# License along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# $Id: regression_tests.sh,v 1.58 2009/05/19 14:47:02 steveu Exp $
# $Id: regression_tests.sh,v 1.59 2009/09/22 13:28:18 steveu Exp $
#
ITUTESTS_TIF=../test-data/itu/fax/itutests.tif
@ -468,6 +468,16 @@ echo super_tone_rx_tests not enabled
#echo super_tone_tx_tests completed OK
echo super_tone_tx_tests not enabled
#./swept_tone_tests >$STDOUT_DEST 2>$STDERR_DEST
#RETVAL=$?
#if [ $RETVAL != 0 ]
#then
# echo swept_tone_tests failed!
# exit $RETVAL
#fi
#echo swept_tone_tests completed OK
echo swept_tone_tests not enabled
./t31_tests -r >$STDOUT_DEST 2>$STDERR_DEST
RETVAL=$?
if [ $RETVAL != 0 ]

View File

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

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 ------------------------------------------------------------*/