]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
update to spandsp snapshot 20091005
authorAnthony Minessale <anthony.minessale@gmail.com>
Mon, 5 Oct 2009 14:34:26 +0000 (14:34 +0000)
committerAnthony Minessale <anthony.minessale@gmail.com>
Mon, 5 Oct 2009 14:34:26 +0000 (14:34 +0000)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@15084 d0543943-73ff-0310-b7d9-9358b9ac24b2

46 files changed:
libs/spandsp/.update
libs/spandsp/configure.ac
libs/spandsp/spandsp-sim/line_model.c
libs/spandsp/spandsp-sim/make_line_models.c
libs/spandsp/spandsp-sim/spandsp/line_model.h
libs/spandsp/spandsp/fax-tests.dtd
libs/spandsp/src/Makefile.am
libs/spandsp/src/at_interpreter.c
libs/spandsp/src/echo.c
libs/spandsp/src/fax.c
libs/spandsp/src/fax_modems.c
libs/spandsp/src/libspandsp.2005.vcproj
libs/spandsp/src/libspandsp.2008.vcproj
libs/spandsp/src/libspandsp.dsp
libs/spandsp/src/make_modem_filter.c
libs/spandsp/src/modem_echo.c
libs/spandsp/src/msvc/spandsp.h
libs/spandsp/src/sig_tone.c
libs/spandsp/src/silence_gen.c
libs/spandsp/src/spandsp.h.in
libs/spandsp/src/spandsp/echo.h
libs/spandsp/src/spandsp/expose.h
libs/spandsp/src/spandsp/fast_convert.h
libs/spandsp/src/spandsp/modem_echo.h
libs/spandsp/src/spandsp/private/echo.h [new file with mode: 0644]
libs/spandsp/src/spandsp/private/fax_modems.h
libs/spandsp/src/spandsp/private/modem_echo.h [new file with mode: 0644]
libs/spandsp/src/spandsp/private/sig_tone.h
libs/spandsp/src/spandsp/private/swept_tone.h [new file with mode: 0644]
libs/spandsp/src/spandsp/private/t30.h
libs/spandsp/src/spandsp/sig_tone.h
libs/spandsp/src/spandsp/silence_gen.h
libs/spandsp/src/spandsp/swept_tone.h [new file with mode: 0644]
libs/spandsp/src/spandsp/t30.h
libs/spandsp/src/spandsp/timing.h
libs/spandsp/src/spandsp/version.h
libs/spandsp/src/swept_tone.c [new file with mode: 0644]
libs/spandsp/src/t30.c
libs/spandsp/src/t31.c
libs/spandsp/src/t38_terminal.c
libs/spandsp/tests/Makefile.am
libs/spandsp/tests/fax_decode.c
libs/spandsp/tests/line_model_tests.c
libs/spandsp/tests/regression_tests.sh
libs/spandsp/tests/sig_tone_tests.c
libs/spandsp/tests/swept_tone_tests.c [new file with mode: 0644]

index df0d5762bf60014ea74291b870ed9f6031e1d8b7..0c4f2f72a7b72fc7a2f0d6d97acf2aea75849f0e 100644 (file)
@@ -1 +1 @@
-Wed Oct  1 00:08:32 EDT 2008
+Mon Oct  5 09:33:55 CDT 2009
index d23c63016c9e045d362470c1482d9e0423ff67b2..58b7af50d0a6007c13fadeb6414a97473d611e3b 100644 (file)
@@ -16,7 +16,7 @@
 # License along with this program; if not, write to the Free Software
 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 #
-# $Id: 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
index 0c1e2564e0ed34c4fb5d0df1d2db8fbc6fc4a7c7..5e09b39fd12e88aa0dabdab50bfaced242b42c83 100644 (file)
@@ -22,7 +22,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: 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 */
index aabbfd2602ded7287db45f7006502fa837e9efe5..42fac11fa88148a524c9eb744fef257607620291 100644 (file)
@@ -22,7 +22,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: 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;
index ebe1592bcc8ce2336f88d895ceb3fc423f7cbece..a8131e2707a2f70583c920655969ef340ff49efa 100644 (file)
@@ -22,7 +22,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: 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[],
index 38dd7cd0d8e25407c8ffc7a310b025af1b06e5df..beb4eae3efa69ddd5adf6322004ca39b5565b64b 100644 (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
index 84dae2c53ace99e723d404fa738d104ce1217331..831e50ca68c54bab111de26e0b78f2c10cee5b46 100644 (file)
@@ -16,7 +16,7 @@
 ## License along with this program; if not, write to the Free Software
 ## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 ##
-## $Id: Makefile.am,v 1.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 \
index 602a737223345d8a74e15318448198b1390387f8..ffd39301ee0ac315b3126dfa7de848d20d1c74d1 100644 (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,
index 30c607ca54d114c89abd5cd6dd39cca6daf7d741..23bb868bbd162fab113f5ed77f369ef09cfd3a61 100644 (file)
@@ -27,7 +27,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: echo.c,v 1.32 2009/02/10 13:06:46 steveu Exp $
+ * $Id: echo.c,v 1.33 2009/09/22 13:11:04 steveu Exp $
  */
 
 /*! \file */
 #include "spandsp/bit_operations.h"
 #include "spandsp/echo.h"
 
+#include "spandsp/private/echo.h"
+
 #if !defined(NULL)
 #define NULL (void *) 0
 #endif
index 744f9df02d2829ec4086889a5223e97d177d325c..e656d377e59d11db2a10113bdd50b6d186ea2bc7 100644 (file)
@@ -23,7 +23,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: 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;
     }
 }
index 3ab3e3b15121fa32b389b19bdff89a68d7112ebe..740569e4e094191c0c265b21eb67dba9fce75e1f 100644 (file)
@@ -22,7 +22,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: 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;
index 5479159aab72ad86bc5d8453c6d0dcb54b163bcc..453f519b61c7463e69347a7765e2a069b1e2b5a7 100644 (file)
 <File RelativePath="silence_gen.c"></File>\r
 <File RelativePath="super_tone_rx.c"></File>\r
 <File RelativePath="super_tone_tx.c"></File>\r
+<File RelativePath="swept_tone.c"></File>\r
 <File RelativePath="t4.c"></File>\r
 <File RelativePath="t30.c"></File>\r
 <File RelativePath="t30_api.c"></File>\r
 <File RelativePath="spandsp/silence_gen.h"></File>\r
 <File RelativePath="spandsp/super_tone_rx.h"></File>\r
 <File RelativePath="spandsp/super_tone_tx.h"></File>\r
+<File RelativePath="spandsp/swept_tone.h"></File>\r
 <File RelativePath="spandsp/t4.h"></File>\r
 <File RelativePath="spandsp/t30.h"></File>\r
 <File RelativePath="spandsp/t30_api.h"></File>\r
 <File RelativePath="spandsp/private/bert.h"></File>\r
 <File RelativePath="spandsp/private/bitstream.h"></File>\r
 <File RelativePath="spandsp/private/dtmf.h"></File>\r
+<File RelativePath="spandsp/private/echo.h"></File>\r
 <File RelativePath="spandsp/private/fax.h"></File>\r
 <File RelativePath="spandsp/private/fax_modems.h"></File>\r
 <File RelativePath="spandsp/private/fsk.h"></File>\r
 <File RelativePath="spandsp/private/logging.h"></File>\r
 <File RelativePath="spandsp/private/lpc10.h"></File>\r
 <File RelativePath="spandsp/private/modem_connect_tones.h"></File>\r
+<File RelativePath="spandsp/private/modem_echo.h"></File>\r
 <File RelativePath="spandsp/private/noise.h"></File>\r
 <File RelativePath="spandsp/private/oki_adpcm.h"></File>\r
 <File RelativePath="spandsp/private/queue.h"></File>\r
 <File RelativePath="spandsp/private/silence_gen.h"></File>\r
 <File RelativePath="spandsp/private/super_tone_rx.h"></File>\r
 <File RelativePath="spandsp/private/super_tone_tx.h"></File>\r
+<File RelativePath="spandsp/private/swept_tone.h"></File>\r
 <File RelativePath="spandsp/private/t30.h"></File>\r
 <File RelativePath="spandsp/private/t31.h"></File>\r
 <File RelativePath="spandsp/private/t38_core.h"></File>\r
index 8b1878957954b70327ea280b0edf09be5fd437fd..c0bb6f77e94f4323c55bea4d8dc5b8eca5bd3a6d 100644 (file)
 <File RelativePath="silence_gen.c"></File>\r
 <File RelativePath="super_tone_rx.c"></File>\r
 <File RelativePath="super_tone_tx.c"></File>\r
+<File RelativePath="swept_tone.c"></File>\r
 <File RelativePath="t4.c"></File>\r
 <File RelativePath="t30.c"></File>\r
 <File RelativePath="t30_api.c"></File>\r
 <File RelativePath="spandsp/silence_gen.h"></File>\r
 <File RelativePath="spandsp/super_tone_rx.h"></File>\r
 <File RelativePath="spandsp/super_tone_tx.h"></File>\r
+<File RelativePath="spandsp/swept_tone.h"></File>\r
 <File RelativePath="spandsp/t4.h"></File>\r
 <File RelativePath="spandsp/t30.h"></File>\r
 <File RelativePath="spandsp/t30_api.h"></File>\r
 <File RelativePath="spandsp/private/bert.h"></File>\r
 <File RelativePath="spandsp/private/bitstream.h"></File>\r
 <File RelativePath="spandsp/private/dtmf.h"></File>\r
+<File RelativePath="spandsp/private/echo.h"></File>\r
 <File RelativePath="spandsp/private/fax.h"></File>\r
 <File RelativePath="spandsp/private/fax_modems.h"></File>\r
 <File RelativePath="spandsp/private/fsk.h"></File>\r
 <File RelativePath="spandsp/private/logging.h"></File>\r
 <File RelativePath="spandsp/private/lpc10.h"></File>\r
 <File RelativePath="spandsp/private/modem_connect_tones.h"></File>\r
+<File RelativePath="spandsp/private/modem_echo.h"></File>\r
 <File RelativePath="spandsp/private/noise.h"></File>\r
 <File RelativePath="spandsp/private/oki_adpcm.h"></File>\r
 <File RelativePath="spandsp/private/queue.h"></File>\r
 <File RelativePath="spandsp/private/silence_gen.h"></File>\r
 <File RelativePath="spandsp/private/super_tone_rx.h"></File>\r
 <File RelativePath="spandsp/private/super_tone_tx.h"></File>\r
+<File RelativePath="spandsp/private/swept_tone.h"></File>\r
 <File RelativePath="spandsp/private/t30.h"></File>\r
 <File RelativePath="spandsp/private/t31.h"></File>\r
 <File RelativePath="spandsp/private/t38_core.h"></File>\r
index 6c062168bb67bb69aab84a1f541597a216b76beb..96f955ebf4142ce4e082b3bb2ef8e2c61004faab 100644 (file)
@@ -293,6 +293,10 @@ SOURCE=.\super_tone_tx.c
 # End Source File\r
 # Begin Source File\r
 \r
+SOURCE=.\swept_tone.c\r
+# End Source File\r
+# Begin Source File\r
+\r
 SOURCE=.\t4.c\r
 # End Source File\r
 # Begin Source File\r
@@ -599,6 +603,10 @@ SOURCE=.\spandsp/super_tone_tx.h
 # End Source File\r
 # Begin Source File\r
 \r
+SOURCE=.\spandsp/swept_tone.h\r
+# End Source File\r
+# Begin Source File\r
+\r
 SOURCE=.\spandsp/t4.h\r
 # End Source File\r
 # Begin Source File\r
@@ -751,6 +759,10 @@ SOURCE=.\spandsp/private/dtmf.h
 # End Source File\r
 # Begin Source File\r
 \r
+SOURCE=.\spandsp/private/echo.h\r
+# End Source File\r
+# Begin Source File\r
+\r
 SOURCE=.\spandsp/private/fax.h\r
 # End Source File\r
 # Begin Source File\r
@@ -799,6 +811,10 @@ SOURCE=.\spandsp/private/modem_connect_tones.h
 # End Source File\r
 # Begin Source File\r
 \r
+SOURCE=.\spandsp/private/modem_echo.h\r
+# End Source File\r
+# Begin Source File\r
+\r
 SOURCE=.\spandsp/private/noise.h\r
 # End Source File\r
 # Begin Source File\r
@@ -831,6 +847,10 @@ SOURCE=.\spandsp/private/super_tone_tx.h
 # End Source File\r
 # Begin Source File\r
 \r
+SOURCE=.\spandsp/private/swept_tone.h\r
+# End Source File\r
+# Begin Source File\r
+\r
 SOURCE=.\spandsp/private/t30.h\r
 # End Source File\r
 # Begin Source File\r
index ce659b30c3ea181d0a78493db4aedde12d868400..b158f413c879e7160acfb0d09bdd42cf5969c8c4 100644 (file)
@@ -23,7 +23,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: make_modem_filter.c,v 1.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
 
index 8ed03c983b8ed9275a910caf9a1bae0f8e1efe81..c31d4cba3182da213f479c4a81726a30203526d8 100644 (file)
@@ -22,7 +22,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: 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;
index 81b74f172f57afda29915a64e6e038fe4dc38ed1..25f705f5ab7d5d91745cc4256c80d2590467375c 100644 (file)
@@ -22,7 +22,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: spandsp.h.in,v 1.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>
index dea3ed79f3697b2beb9304399f675c7daf8504c5..0183dadedbd526138be6304580041b2be56b41f5 100644 (file)
@@ -23,7 +23,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: sig_tone.c,v 1.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 */
 #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;
index fa6529021aedd1b8bfd50c9fe1e180400422dad9..4998f8bc0ec2ca5ddc027f222289502a0aed9bf0 100644 (file)
@@ -22,7 +22,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: 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 ------------------------------------------------------------*/
index f5b7b0fe88f0d36e18f3fce3bac1e72f200a3676..59122b654f64d99b4507a7796b0ec19ba0245609 100644 (file)
@@ -22,7 +22,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: spandsp.h.in,v 1.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>
index eb423dd0f7e27694e2e7487107c2d25b705b1bd5..b4769091815551b3f5bada973866dbe4dc2525c2 100644 (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"
index 25b671827cf0f920a0fc18a05981c455f585c44f..44a3c5c7b57c46bad6364544551a00ed5408a729 100644 (file)
@@ -23,7 +23,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: 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>
index 1620042c2a8d6fb8e0c07b25f4fcf061c9019b78..ccf275aaf3e13b600b26027d65891a4eb30e4e59 100644 (file)
@@ -22,7 +22,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: 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
index cc9f06e45e215b8cf1f400e1e559cfedc84ea929..77ffe6b535057d9b8e0616a7360ad214087b7432 100644 (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"
diff --git a/libs/spandsp/src/spandsp/private/echo.h b/libs/spandsp/src/spandsp/private/echo.h
new file mode 100644 (file)
index 0000000..4a91798
--- /dev/null
@@ -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 ------------------------------------------------------------*/
index 1eec1c9bbc47dbd51b453255a874bb0cc61e91ef..a46749c0cfd868e8878f5ecfe80fb539707f0552 100644 (file)
@@ -22,7 +22,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: fax_modems.h,v 1.3 2009/03/23 14:17:42 steveu Exp $
+ * $Id: fax_modems.h,v 1.4 2009/09/04 14:38:47 steveu Exp $
  */
 
 /*! \file */
@@ -95,11 +95,9 @@ struct fax_modems_state_s
 
     /*! The current receive signal handler */
     span_rx_handler_t *rx_handler;
-    void *rx_user_data;
-
     /*! The current receive missing signal fill-in handler */
     span_rx_fillin_handler_t *rx_fillin_handler;
-    void *rx_fillin_user_data;
+    void *rx_user_data;
 
     /*! The current transmit signal handler */
     span_tx_handler_t *tx_handler;
diff --git a/libs/spandsp/src/spandsp/private/modem_echo.h b/libs/spandsp/src/spandsp/private/modem_echo.h
new file mode 100644 (file)
index 0000000..082cb8d
--- /dev/null
@@ -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 ------------------------------------------------------------*/
index a98c8b16b44d35bc9de1686655d6e882ee497621..edf7a68bb7063d80a8d4f158ca65effaaf4f1f7c 100644 (file)
@@ -23,7 +23,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: sig_tone.h,v 1.3 2009/04/12 14:18:02 steveu Exp $
+ * $Id: sig_tone.h,v 1.4 2009/09/04 14:38:47 steveu Exp $
  */
 
 #if !defined(_SPANDSP_PRIVATE_SIG_TONE_H_)
@@ -38,8 +38,8 @@ struct sig_tone_descriptor_s
 {
     /*! \brief The tones used. */
     int tone_freq[2];
-    /*! \brief The high and low tone amplitudes. */
-    int tone_amp[2];
+    /*! \brief The high and low tone amplitudes for each of the tones. */
+    int tone_amp[2][2];
 
     /*! \brief The delay, in audio samples, before the high level tone drops
                to a low level tone. */
@@ -80,7 +80,6 @@ struct sig_tone_descriptor_s
 #endif
     } tone[2];
 
-
 #if defined(SPANDSP_USE_FIXED_POINT)
     /*! \brief Flat mode bandpass bi-quad parameters */
     int32_t broad_a[3];
@@ -128,23 +127,23 @@ struct sig_tone_descriptor_s
 struct sig_tone_tx_state_s
 {
     /*! \brief The callback function used to handle signaling changes. */
-    sig_tone_func_t sig_update;
+    tone_report_func_t sig_update;
     /*! \brief A user specified opaque pointer passed to the callback function. */
     void *user_data;
 
     /*! \brief Tone descriptor */
     sig_tone_descriptor_t *desc;
 
-    /*! The scaling values for the high and low level tones */
-    int16_t tone_scaling[2];
-    /*! The sample timer, used to switch between the high and low level tones. */
-    int high_low_timer;
-
     /*! The phase rates for the one or two tones */
     int32_t phase_rate[2];
     /*! The phase accumulators for the one or two tones */
     uint32_t phase_acc[2];
 
+    /*! The scaling values for the one or two tones, and the high and low level of each tone */
+    int16_t tone_scaling[2][2];
+    /*! The sample timer, used to switch between the high and low level tones. */
+    int high_low_timer;
+
     /*! \brief Current transmit tone */
     int current_tx_tone;
     /*! \brief Current transmit timeout */
@@ -159,7 +158,7 @@ struct sig_tone_tx_state_s
 struct sig_tone_rx_state_s
 {
     /*! \brief The callback function used to handle signaling changes. */
-    sig_tone_func_t sig_update;
+    tone_report_func_t sig_update;
     /*! \brief A user specified opaque pointer passed to the callback function. */
     void *user_data;
 
diff --git a/libs/spandsp/src/spandsp/private/swept_tone.h b/libs/spandsp/src/spandsp/private/swept_tone.h
new file mode 100644 (file)
index 0000000..ce8e5a6
--- /dev/null
@@ -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 ------------------------------------------------------------*/
index 00dbeabff0b7d2c595c2e12dd9c31db92c99e00f..958a553c89d98168183072883dbb32e929ad2ede 100644 (file)
@@ -22,7 +22,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: 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 */
index eecbfdd4382686b834dcf70b4ee135125f390ac1..64bcd6f4224206c950de6ecd17d1cc17587b133a 100644 (file)
@@ -23,7 +23,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: sig_tone.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.
index c7300ec4aa0b69ba30263b375cf63c6790e05980..467408d75ba1456f20b40abe03e61b4efd80ffe3 100644 (file)
@@ -22,7 +22,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: silence_gen.h,v 1.18 2009/06/02 16:03:56 steveu Exp $
+ * $Id: silence_gen.h,v 1.19 2009/09/04 14:38:47 steveu Exp $
  */
 
 #if !defined(_SPANDSP_SILENCE_GEN_H_)
@@ -125,6 +125,16 @@ SPAN_DECLARE_NONSTD(int) span_dummy_rx(void *user_data, const int16_t amp[], int
 */
 SPAN_DECLARE(int) span_dummy_mod(void *user_data, int16_t amp[], int len);
 
+/*! A dummy routine to use as a receive fillin callback, when we aren't really
+    trying to process what is received. It just absorbs and ignores the
+    request.
+    \brief Dummy receive fillin callback.
+    \param user_data The context.
+    \param len The length of the signal buffer
+    \return 0.
+*/
+SPAN_DECLARE_NONSTD(int) span_dummy_rx_fillin(void *user_data, int len);
+
 #if defined(__cplusplus)
 }
 #endif
diff --git a/libs/spandsp/src/spandsp/swept_tone.h b/libs/spandsp/src/spandsp/swept_tone.h
new file mode 100644 (file)
index 0000000..414f951
--- /dev/null
@@ -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 ------------------------------------------------------------*/
index dbd3dec1e294fcdb6b58c3ec5c2e9aee180bbbcd..d0d71f674db65d5eae07233a48393fed15c56a7a 100644 (file)
@@ -22,7 +22,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: 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;
index 735471659ff82f75997a9d630ffca07788e88300..85f3ce5f43eabdb1f76e98c04b0f2509ff073ef8 100644 (file)
@@ -22,7 +22,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: 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. */
index 88a8ab76dfe879693297cacefd7f43378b8e4cc2..fe4e70aa73f9b74c05e8f615ae20fd3621b5b68a 100644 (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 ------------------------------------------------------------*/
diff --git a/libs/spandsp/src/swept_tone.c b/libs/spandsp/src/swept_tone.c
new file mode 100644 (file)
index 0000000..78555ab
--- /dev/null
@@ -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 ------------------------------------------------------------*/
index 6640fd8294086ca87f26753c13d453438fe912aa..a112dd9fac4012549804985287822216f1ab0ef4 100644 (file)
@@ -22,7 +22,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: 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)
index c9871a19b209a2e28a6860c8bf682f760aff4426..307a2c38daff73eb06d572a96da0b64aec8edc89 100644 (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;
index 4ea4dd4579b8be6c623ce2527b0c2e0fc2c59db8..1e9c70926f00a2985c6fb31dcfe62a2b13c2bac1 100644 (file)
@@ -22,7 +22,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: 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
index 07083318f4d47b28ceaa230149aa03fb7662e0f5..253d398d315b2e866adacbc6767b8aacc80aa775 100644 (file)
@@ -16,7 +16,7 @@
 ## along with this program; if not, write to the Free Software
 ## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 ##
-## $Id: Makefile.am,v 1.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
 
index 131244db2373314c6fe47d6ae4d3d36db4dbc1cb..ec5a493f4c9fa3baaf4f8005798fd4f766b6e4e6 100644 (file)
@@ -22,7 +22,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: 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))
         {
index b769e717e62fb830f4c2aabf6ed92781303a9a3d..309e2e7890758569457206cc4bf934e0377ee5c9 100644 (file)
@@ -22,7 +22,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: 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 ------------------------------------------------------------*/
index 4f77c9c54a34de71c82fda4c79e481fb28b77dd5..efd02619fb8eacf5e1c3b615e34e182aca52bb95 100755 (executable)
@@ -17,7 +17,7 @@
 # License along with this program; if not, write to the Free Software
 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 #
-# $Id: regression_tests.sh,v 1.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 ]
index e795fc87f9ad0e61354856542ef05ac03d99b2b2..e2afea4a3d0249ba3a007565c92387ca3c4d4a22 100644 (file)
@@ -22,7 +22,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: 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 */
 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))
-        {
-            /* 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))
+        /* The sig tone transmit side wants to know what to do next */
+        switch (tx_section)
         {
-            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*/
-        }
-        else
-        {
-            return 0x02 | SIG_TONE_1_PRESENT | ((ms_to_samples(700) - sampleno) << 16) | SIG_TONE_TX_PASSTHROUGH;
+                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;
         }
-        /*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);
-        /*endfor*/
-        sig_tone_rx(s, buf, 8192);
-        sum = 0.0;
-        for (i = 1000;  i < 8192;  i++)
-            sum += (double) buf[i]*(double) buf[i];
+        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*/
-        sum = sqrt(sum);
-        printf("%7d %f\n", f, sum);
+        printf("%7.1f %f\n", swept_tone_current_frequency(swept), 10.0*log10(sumout/sumin));
     }
     /*endfor*/
+    swept_tone_free(swept);
 }
 /*- End of function --------------------------------------------------------*/
 
@@ -189,45 +174,56 @@ int main(int argc, char *argv[])
     }
     /*endif*/
 
-    awgn_init_dbm0(&noise_source, 1234567, -10.0f);
+    awgn_init_dbm0(&noise_source, 1234567, -20.0f);
 
     for (type = 1;  type <= 3;  type++)
     {
         sampleno = 0;
         tone_1_present = 0;
         tone_2_present = 0;
-        ping = 0;
+        tx_section = 0;
         munge = NULL;
         switch (type)
         {
         case 1:
             printf("2280Hz tests.\n");
             munge = codec_munge_init(MUNGE_CODEC_ALAW, 0);
-            sig_tone_tx_init(&tx_state, SIG_TONE_2280HZ, tx_handler, NULL);
-            sig_tone_rx_init(&rx_state, SIG_TONE_2280HZ, rx_handler, NULL);
+            sig_tone_tx_init(&tx_state, SIG_TONE_2280HZ, tx_handler, &tx_state);
+            sig_tone_rx_init(&rx_state, SIG_TONE_2280HZ, rx_handler, &rx_state);
             rx_state.current_rx_tone |= SIG_TONE_RX_PASSTHROUGH;
             break;
         case 2:
-            printf("26000Hz tests.\n");
+            printf("2600Hz tests.\n");
             munge = codec_munge_init(MUNGE_CODEC_ULAW, 0);
-            sig_tone_tx_init(&tx_state, SIG_TONE_2600HZ, tx_handler, NULL);
-            sig_tone_rx_init(&rx_state, SIG_TONE_2600HZ, rx_handler, NULL);
+            sig_tone_tx_init(&tx_state, SIG_TONE_2600HZ, tx_handler, &tx_state);
+            sig_tone_rx_init(&rx_state, SIG_TONE_2600HZ, rx_handler, &rx_state);
             rx_state.current_rx_tone |= SIG_TONE_RX_PASSTHROUGH;
             break;
         case 3:
-            printf("2400Hz/26000Hz tests.\n");
+            printf("2400Hz/2600Hz tests.\n");
             munge = codec_munge_init(MUNGE_CODEC_ULAW, 0);
-            sig_tone_tx_init(&tx_state, SIG_TONE_2400HZ_2600HZ, tx_handler, NULL);
-            sig_tone_rx_init(&rx_state, SIG_TONE_2400HZ_2600HZ, rx_handler, NULL);
+            sig_tone_tx_init(&tx_state, SIG_TONE_2400HZ_2600HZ, tx_handler, &tx_state);
+            sig_tone_rx_init(&rx_state, SIG_TONE_2400HZ_2600HZ, rx_handler, &rx_state);
             rx_state.current_rx_tone |= SIG_TONE_RX_PASSTHROUGH;
             break;
         }
         /*endswitch*/
-    
-        //map_frequency_response(&rx_state);
+        /* Set to the default of hook condition */
+        sig_tone_rx_set_mode(&rx_state, SIG_TONE_RX_PASSTHROUGH | SIG_TONE_RX_FILTER_TONE, 0);
+        sig_tone_tx_set_mode(&tx_state, SIG_TONE_1_PRESENT | SIG_TONE_2_PRESENT | SIG_TONE_TX_PASSTHROUGH, 0);
 
-        for (sampleno = 0;  sampleno < 20000;  sampleno += SAMPLES_PER_CHUNK)
+        map_frequency_response(&rx_state);
+
+        sig_tone_rx_set_mode(&rx_state, SIG_TONE_RX_PASSTHROUGH, 0);
+        for (sampleno = 0;  sampleno < 30000;  sampleno += SAMPLES_PER_CHUNK)
         {
+            if (sampleno == 8000)
+            {
+                /* 100ms seize */
+                printf("100ms seize - %d samples\n", ms_to_samples(100));
+                dial_pulses = 0;
+                sig_tone_tx_set_mode(&tx_state, 0, ms_to_samples(100));
+            }
             for (i = 0;  i < SAMPLES_PER_CHUNK;  i++)
                 amp[i] = awgn(&noise_source);
             /*endfor*/
diff --git a/libs/spandsp/tests/swept_tone_tests.c b/libs/spandsp/tests/swept_tone_tests.c
new file mode 100644 (file)
index 0000000..010fbcd
--- /dev/null
@@ -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 ------------------------------------------------------------*/